Skip to content

Commit

Permalink
PRD Securely signed releases (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndriiMysko authored and vitalie committed Jul 10, 2023
1 parent 4238c34 commit 45ede98
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/travis/scheduler/record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
require 'travis/scheduler/record/branch'
require 'travis/scheduler/record/build'
require 'travis/scheduler/record/commit'
require 'travis/scheduler/record/custom_key'
require 'travis/scheduler/record/installation'
require 'travis/scheduler/record/job'
require 'travis/scheduler/record/log'
require 'travis/scheduler/record/membership'
require 'travis/scheduler/record/organization'
require 'travis/scheduler/record/permission'
require 'travis/scheduler/record/pull_request'
Expand Down
7 changes: 7 additions & 0 deletions lib/travis/scheduler/record/custom_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'travis/support/encrypted_column'
require 'travis/support/secure_config'

class CustomKey < ActiveRecord::Base
serialize :private_key, Travis::EncryptedColumn.new
belongs_to :owner, polymorphic: true
end
4 changes: 4 additions & 0 deletions lib/travis/scheduler/record/membership.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Membership < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
35 changes: 34 additions & 1 deletion lib/travis/scheduler/serialize/worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def data
vm_size: job.vm_size,
queue: job.queue,
config: job.decrypted_config,
env_vars: job.env_vars,
env_vars: env_vars_with_custom_keys,
job: job_data,
host: Travis::Scheduler.config.host,
source: build_data,
Expand Down Expand Up @@ -238,6 +238,39 @@ def allowed_repositories
def travis_vcs_proxy?
repo.vcs_type == 'TravisproxyRepository'
end

def env_vars_with_custom_keys
job.env_vars + custom_keys
end

def custom_keys
return [] if job.decrypted_config[:keys].blank?

if job.source.event_type == 'pull_request' && job.source.request.pull_request.head_repo_slug != job.source.request.pull_request.base_repo_slug
base_repo_owner_name, base_repo_name = job.source.request.pull_request.base_repo_slug.to_s.split('/')
return [] unless base_repo_owner_name && base_repo_name


base_repo = ::Repository.find_by(owner_name: base_repo_owner_name, name: base_repo_name)
return [] unless base_repo && base_repo.settings.share_ssh_keys_with_forks?

end

job.decrypted_config[:keys].map do |key|
custom_key = CustomKey.where(name: key, owner_id: build.sender_id, owner_type: 'User').first
if custom_key.nil?
org_ids = Membership.where(user_id: build.sender_id).map(&:organization_id)
if !base_repo.nil? && base_repo.owner_type == 'Organization'
org_ids.reject! { |id| id != base_repo.owner_id }
elsif repo.owner_type == 'Organization'
org_ids.reject! { |id| id != repo.owner_id }
end

custom_key = CustomKey.where(name: key, owner_id: org_ids, owner_type: 'Organization').first unless org_ids.empty?
end
custom_key.nil? ? nil : { name: "TRAVIS_#{key}", value: Base64.strict_encode64(custom_key.private_key), public: false, branch: nil }
end.compact
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions lib/travis/scheduler/serialize/worker/repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ def travis_vcs_proxy?
vcs_type == 'TravisproxyRepository'
end

def owner_type
repo.owner_type
end

def owner_id
repo.owner_id
end

private

# If the repo does not have a custom timeout, look to the repo's
Expand Down
9 changes: 9 additions & 0 deletions spec/support/factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,14 @@ def public=(value)
author_name 'Sven Fuchs'
author_email 'me@svenfuchs.com'
end

factory :membership do
association :organization
association :user
end

factory :custom_key, :class => 'CustomKey' do
name 'key'
end
end

41 changes: 41 additions & 0 deletions spec/travis/scheduler/serialize/worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,45 @@ def encrypted(value)
it { expect(data[:keep_netrc]).to be false }
end
end

context 'custom_keys' do
let!(:organization1) {FactoryGirl.create(:org, login: "org1", id: 1)}
let!(:organization2) {FactoryGirl.create(:org, login: "org2", id: 2)}
let!(:repo) { FactoryGirl.create(:repo, default_branch: 'main') }
let!(:membership1) {FactoryGirl.create(:membership, user: repo.owner, organization: organization1) }
let!(:membership2) {FactoryGirl.create(:membership, user: repo.owner, organization: organization2) }
let!(:custom_key1) {FactoryGirl.create(:custom_key, name: 'key1', owner_id: organization1.id, owner_type: 'Organization', private_key: 'abc')}
let!(:custom_key2) {FactoryGirl.create(:custom_key, name: 'key1', owner_id: organization2.id, owner_type: 'Organization', private_key: 'def')}

describe 'when two organization have the same key name' do
before {
build.update(sender_id: repo.owner.id)
job.update(config: {:keys => ['key1']})
repo.update_attributes(owner: organization2, owner_name: 'org2')
}

it { expect(data[:env_vars]).to include({:name=>"TRAVIS_key1", :value=>"ZGVm", :public=>false, :branch=>nil})}
end

describe 'when user has no access to organization' do
let!(:organization3) {FactoryGirl.create(:org, login: "org3", id: 3)}
let!(:custom_key3) {FactoryGirl.create(:custom_key, name: 'key1', owner_id: organization3.id, owner_type: 'Organization', private_key: 'ghi')}
let(:raw_settings) do
{
env_vars: nil,
timeout_hard_limit: 180,
timeout_log_silence: 20,
share_ssh_keys_with_forks: false
}
end

before {
build.update(sender_id: repo.owner.id)
job.update(config: {:keys => ['key1']})
repo.update_attributes(owner: organization3, owner_name: 'org3')
}

it { expect(data[:env_vars]).to eq([])}
end
end
end

0 comments on commit 45ede98

Please sign in to comment.