Skip to content
This repository was archived by the owner on May 10, 2018. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions lib/travis/model/repository/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ class EnvVar < Travis::Settings::Model
class SshKey < Travis::Settings::Model
class NotAPrivateKeyError < StandardError; end

KEY_CLASSES = [
OpenSSL::PKey::RSA,
OpenSSL::PKey::DSA,
OpenSSL::PKey::EC,
]

attribute :description, String
attribute :value, Travis::Settings::EncryptedValue
attribute :repository_id, Integer
Expand All @@ -28,18 +34,24 @@ class NotAPrivateKeyError < StandardError; end

def validate_correctness
return unless value.decrypt
key = OpenSSL::PKey::RSA.new(value.decrypt, '')
raise NotAPrivateKeyError unless key.private?
rescue OpenSSL::PKey::RSAError, NotAPrivateKeyError
# it seems there is no easy way to check if key
# needs a pass phrase with ruby's openssl bindings,
# that's why we need to manually check that
if value.decrypt.to_s =~ /ENCRYPTED/
errors.add(:value, :key_with_a_passphrase)
else
errors.add(:value, :not_a_private_key)

unless KEY_CLASSES.any? { |pkey_class| validate_pkey(pkey_class, value.decrypt) }
if value.decrypt.to_s =~ /ENCRYPTED/
errors.add(:value, :key_with_a_passphrase)
else
errors.add(:value, :not_a_private_key)
end
end
end

private

def validate_pkey(pkey_class, key_string)
key = pkey_class.new(key_string, '')
key.respond_to?(:private_key?) ? key.private_key? : key.private?
rescue OpenSSL::PKey::PKeyError
false
end
end

class EnvVars < Collection
Expand Down
42 changes: 42 additions & 0 deletions spec/travis/model/repository/settings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,48 @@
require 'spec_helper'

describe Repository::Settings do
describe Repository::Settings::SshKey do
# We're generating insecure keys to make the tests go fast. This test is
# just verifying that the keys are valid, so that shouldn't be an issue.
# Don't use these commands if you want to make your own secure keys, though.

it 'validates RSA keys' do
rsa_key = OpenSSL::PKey::RSA.generate(1024)

ssh_key = Repository::Settings::SshKey.new
ssh_key.value = rsa_key.to_pem

ssh_key.should be_valid
end

it 'validates DSA keys' do
dsa_key = OpenSSL::PKey::DSA.generate(1024)

ssh_key = Repository::Settings::SshKey.new
ssh_key.value = dsa_key.to_pem

ssh_key.should be_valid
end

it 'does not validate invalid keys' do
ssh_key = Repository::Settings::SshKey.new
ssh_key.value = "-----BEGIN RSA PRIVATE KEY-----\nThisisnotavalidkey\n-----END RSA PRIVATE KEY-----\n"

ssh_key.should_not be_valid
ssh_key.errors[:value].should == [:not_a_private_key]
end

it 'does not validate password protected keys' do
rsa_key = OpenSSL::PKey::RSA.generate(1024)

ssh_key = Repository::Settings::SshKey.new
ssh_key.value = rsa_key.to_pem(OpenSSL::Cipher.new("AES-128-CBC"), "passphrase")

ssh_key.should_not be_valid
ssh_key.errors[:value].should == [:key_with_a_passphrase]
end
end

describe 'env_vars' do
it 'can be filtered to get only public vars' do
settings = Repository::Settings.load(env_vars: [
Expand Down