diff options
author | Nick Thomas <nick@gitlab.com> | 2017-08-21 13:30:03 +0300 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2017-08-30 22:50:44 +0300 |
commit | b0f982fbdf69c292ab4530c0aaaf1ab42f4e7a01 (patch) | |
tree | 0d76c74fb6260de1e3c9694a8501491b2eb486ef /spec/lib | |
parent | 81f08d30e641dc1a6666022ab1f5d36dbcdced7e (diff) |
Add settings for minimum key strength and allowed key type
This is an amalgamation of:
* Cory Hinshaw: Initial implementation !5552
* Rémy Coutable: Updates !9350
* Nick Thomas: Resolve conflicts and add ED25519 support !13712
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/gitlab/git_access_spec.rb | 42 | ||||
-rw-r--r-- | spec/lib/gitlab/key_fingerprint_spec.rb | 82 | ||||
-rw-r--r-- | spec/lib/gitlab/ssh_public_key_spec.rb | 132 |
3 files changed, 174 insertions, 82 deletions
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 295a979da76..a67902c7209 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -155,6 +155,48 @@ describe Gitlab::GitAccess do end end + shared_examples '#check with a key that is not valid' do + before do + project.add_master(user) + end + + context 'key is too small' do + before do + stub_application_setting(minimum_rsa_bits: 4096) + end + + it 'does not allow keys which are too small' do + aggregate_failures do + expect(actor).not_to be_valid + expect { pull_access_check }.to raise_unauthorized('Your SSH key length must be at least 4096 bits.') + expect { push_access_check }.to raise_unauthorized('Your SSH key length must be at least 4096 bits.') + end + end + end + + context 'key type is not allowed' do + before do + stub_application_setting(allowed_key_types: ['ecdsa']) + end + + it 'does not allow keys which are too small' do + aggregate_failures do + expect(actor).not_to be_valid + expect { pull_access_check }.to raise_unauthorized('Your SSH key type is not allowed. Must be ECDSA.') + expect { push_access_check }.to raise_unauthorized('Your SSH key type is not allowed. Must be ECDSA.') + end + end + end + end + + it_behaves_like '#check with a key that is not valid' do + let(:actor) { build(:rsa_key_2048, user: user) } + end + + it_behaves_like '#check with a key that is not valid' do + let(:actor) { build(:rsa_deploy_key_2048, user: user) } + end + describe '#check_project_moved!' do before do project.add_master(user) diff --git a/spec/lib/gitlab/key_fingerprint_spec.rb b/spec/lib/gitlab/key_fingerprint_spec.rb deleted file mode 100644 index d643dc5342d..00000000000 --- a/spec/lib/gitlab/key_fingerprint_spec.rb +++ /dev/null @@ -1,82 +0,0 @@ -require 'spec_helper' - -describe Gitlab::KeyFingerprint, lib: true do - KEYS = { - rsa: - 'example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5z65PwQ1GE6foJgwk' \ - '9rmQi/glaXbUeVa5uvQpnZ3Z5+forcI7aTngh3aZ/H2UDP2L70TGy7kKNyp0J3a8/OdG' \ - 'Z08y5yi3JlbjFARO1NyoFEjw2H1SJxeJ43L6zmvTlu+hlK1jSAlidl7enS0ufTlzEEj4' \ - 'iJcuTPKdVzKRgZuTRVm9woWNVKqIrdRC0rJiTinERnfSAp/vNYERMuaoN4oJt8p/NEek' \ - 'rmFoDsQOsyDW5RAnCnjWUU+jFBKDpfkJQ1U2n6BjJewC9dl6ODK639l3yN4WOLZEk4tN' \ - 'UysfbGeF3rmMeflaD6O1Jplpv3YhwVGFNKa7fMq6k3Z0tszTJPYh', - ecdsa: - 'example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAI' \ - 'bmlzdHAyNTYAAABBBKTJy43NZzJSfNxpv/e2E6Zy3qoHoTQbmOsU5FEfpWfWa1MdTeXQ' \ - 'YvKOi+qz/1AaNx6BK421jGu74JCDJtiZWT8=', - ed25519: - '@revoked example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjq' \ - 'uxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf', - dss: - 'example.com ssh-dss AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdS' \ - 'PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f' \ - '6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iID' \ - 'GZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhX' \ - 'uXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwW' \ - 'eotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6A' \ - 'e1UlZAFMO/7PSSoAAACBAJcQ4JODqhuGbXIEpqxetm7PWbdbCcr3y/GzIZ066pRovpL6' \ - 'qm3qCVIym4cyChxWwb8qlyCIi+YRUUWm1z/wiBYT2Vf3S4FXBnyymCkKEaV/EY7+jd4X' \ - '1bXI58OD2u+bLCB/sInM4fGB8CZUIWT9nJH0Ve9jJUge2ms348/QOJ1+' - }.freeze - - MD5_FINGERPRINTS = { - rsa: '06:b2:8a:92:df:0e:11:2c:ca:7b:8f:a4:ba:6e:4b:fd', - ecdsa: '45:ff:5b:98:9a:b6:8a:41:13:c1:30:8b:09:5e:7b:4e', - ed25519: '2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16', - dss: '57:98:86:02:5f:9c:f4:9b:ad:5a:1e:51:92:0e:fd:2b' - }.freeze - - BIT_COUNTS = { - rsa: 2048, - ecdsa: 256, - ed25519: 256, - dss: 1024 - }.freeze - - describe '#type' do - KEYS.each do |type, key| - it "calculates the type of #{type} keys" do - calculated_type = described_class.new(key).type - - expect(calculated_type).to eq(type.to_s.upcase) - end - end - end - - describe '#fingerprint' do - KEYS.each do |type, key| - it "calculates the MD5 fingerprint for #{type} keys" do - fp = described_class.new(key).fingerprint - - expect(fp).to eq(MD5_FINGERPRINTS[type]) - end - end - end - - describe '#bits' do - KEYS.each do |type, key| - it "calculates the number of bits in #{type} keys" do - bits = described_class.new(key).bits - - expect(bits).to eq(BIT_COUNTS[type]) - end - end - end - - describe '#key' do - it 'carries the unmodified key data' do - key = described_class.new(KEYS[:rsa]).key - - expect(key).to eq(KEYS[:rsa]) - end - end -end diff --git a/spec/lib/gitlab/ssh_public_key_spec.rb b/spec/lib/gitlab/ssh_public_key_spec.rb new file mode 100644 index 00000000000..d3314552d31 --- /dev/null +++ b/spec/lib/gitlab/ssh_public_key_spec.rb @@ -0,0 +1,132 @@ +require 'spec_helper' + +describe Gitlab::SSHPublicKey, lib: true do + let(:key) { attributes_for(:rsa_key_2048)[:key] } + let(:public_key) { described_class.new(key) } + + describe '.technology_names' do + it 'returns the available technology names' do + expect(described_class.technology_names).to eq(%w[rsa dsa ecdsa ed25519]) + end + end + + describe '.allowed_sizes(name)' do + where(:name, :sizes) do + [ + ['rsa', [1024, 2048, 3072, 4096]], + ['dsa', [1024, 2048, 3072]], + ['ecdsa', [256, 384, 521]], + ['ed25519', [256]] + ] + end + + subject { described_class.allowed_sizes(name) } + + with_them do + it { is_expected.to eq(sizes) } + end + end + + describe '.allowed_type?' do + it 'determines the key type' do + expect(described_class.allowed_type?('foo')).to be(false) + end + end + + describe '#valid?' do + subject { public_key } + + context 'with a valid SSH key' do + it { is_expected.to be_valid } + end + + context 'with an invalid SSH key' do + let(:key) { 'this is not a key' } + + it { is_expected.not_to be_valid } + end + end + + describe '#type' do + subject { public_key.type } + + where(:factory, :type) do + [ + [:rsa_key_2048, :rsa], + [:dsa_key_2048, :dsa], + [:ecdsa_key_256, :ecdsa], + [:ed25519_key_256, :ed25519] + ] + end + + with_them do + let(:key) { attributes_for(factory)[:key] } + + it { is_expected.to eq(type) } + end + + context 'with an invalid SSH key' do + let(:key) { 'this is not a key' } + + it { is_expected.to be_nil } + end + end + + describe '#bits' do + subject { public_key.bits } + + where(:factory, :bits) do + [ + [:rsa_key_2048, 2048], + [:dsa_key_2048, 2048], + [:ecdsa_key_256, 256], + [:ed25519_key_256, 256] + ] + end + + with_them do + let(:key) { attributes_for(factory)[:key] } + + it { is_expected.to eq(bits) } + end + + context 'with an invalid SSH key' do + let(:key) { 'this is not a key' } + + it { is_expected.to be_nil } + end + end + + describe '#fingerprint' do + subject { public_key.fingerprint } + + where(:factory, :fingerprint) do + [ + [:rsa_key_2048, '2e:ca:dc:e0:37:29:ed:fc:f0:1d:bf:66:d4:cd:51:b1'], + [:dsa_key_2048, 'bc:c1:a4:be:7e:8c:84:56:b3:58:93:53:c6:80:78:8c'], + [:ecdsa_key_256, '67:a3:a9:7d:b8:e1:15:d4:80:40:21:34:bb:ed:97:38'], + [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73'] + ] + end + + with_them do + let(:key) { attributes_for(factory)[:key] } + + it { is_expected.to eq(fingerprint) } + end + + context 'with an invalid SSH key' do + let(:key) { 'this is not a key' } + + it { is_expected.to be_nil } + end + end + + describe '#key_text' do + let(:key) { 'this is not a key' } + + it 'carries the unmodified key data' do + expect(public_key.key_text).to eq(key) + end + end +end |