diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2016-03-29 13:32:17 +0000 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2016-03-29 13:32:17 +0000 |
commit | fda23577b96bc1fcb50e0b6e7c41df729ece68dd (patch) | |
tree | 1aa59a1778b367d406de919d1e20dc5e3eb13b21 | |
parent | 91e722550b40bbd8214e54a01b2183b27b95bde1 (diff) | |
parent | 38b8600f93ebe40eb9211051ef64b1013d053132 (diff) | |
download | gitlab-shell-fda23577b96bc1fcb50e0b6e7c41df729ece68dd.tar.gz |
Merge branch 'use-ssh-key-internal-api' into 'master'
Use ssh key internal api to build the authorized-keys command on openssh 6.9
See merge request !42
-rw-r--r-- | CHANGELOG | 3 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rwxr-xr-x | bin/authorized_keys | 25 | ||||
-rw-r--r-- | lib/gitlab_authorized_keys.rb | 0 | ||||
-rw-r--r-- | lib/gitlab_keys.rb | 26 | ||||
-rw-r--r-- | lib/gitlab_net.rb | 7 | ||||
-rw-r--r-- | spec/gitlab_net_spec.rb | 36 | ||||
-rw-r--r-- | spec/vcr_cassettes/ssh-key-not-found.yml | 50 | ||||
-rw-r--r-- | spec/vcr_cassettes/ssh-key-not-implemented.yml | 50 | ||||
-rw-r--r-- | spec/vcr_cassettes/ssh-key-ok.yml | 40 |
10 files changed, 224 insertions, 15 deletions
@@ -1,3 +1,6 @@ +v2.6.14 + - Add support for ssh AuthorizedKeysCommand query by key + v2.6.13 - Add push-branches command - Add delete-remote-branches command @@ -1 +1 @@ -2.6.13 +2.6.14 diff --git a/bin/authorized_keys b/bin/authorized_keys new file mode 100755 index 0000000..6aab4a5 --- /dev/null +++ b/bin/authorized_keys @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +# +# GitLab shell authorized_keys. Query GitLab API to get the authorized command for a given ssh key fingerprint +# +# Ex. +# /bin/authorized_keys BASE64-KEY +# +# Returns +# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQA... +# + +key = ARGV[0] +abort "# No key provided" if key.nil? || key.empty? + +require_relative "../lib/gitlab_init" +require_relative "../lib/gitlab_net" +require_relative "../lib/gitlab_keys" + +authorized_key = GitlabNet.new.authorized_key(key) +if authorized_key.nil? + puts "# No key was found for #{key}" +else + puts GitlabKey.new.key_line("key-#{authorized_key['id']}", authorized_key["key"]) +end diff --git a/lib/gitlab_authorized_keys.rb b/lib/gitlab_authorized_keys.rb new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/lib/gitlab_authorized_keys.rb diff --git a/lib/gitlab_keys.rb b/lib/gitlab_keys.rb index 3710f96..f17e6b7 100644 --- a/lib/gitlab_keys.rb +++ b/lib/gitlab_keys.rb @@ -11,6 +11,7 @@ class GitlabKeys @key_id = ARGV.shift @key = ARGV.shift @auth_file = GitlabConfig.new.auth_file + @gitlab_key = GitlabKey.new end def exec @@ -32,7 +33,7 @@ class GitlabKeys def add_key lock do $logger.info "Adding key #{@key_id} => #{@key.inspect}" - auth_line = key_line(@key_id, @key) + auth_line = @gitlab_key.key_line(@key_id, @key) open(auth_file, 'a') { |file| file.puts(auth_line) } end true @@ -59,7 +60,7 @@ class GitlabKeys abort("#{$0}: invalid input #{input.inspect}") unless tokens.count == 2 key_id, public_key = tokens $logger.info "Adding key #{key_id} => #{public_key.inspect}" - file.puts(key_line(key_id, public_key)) + file.puts(@gitlab_key.key_line(key_id, public_key)) end end end @@ -70,20 +71,12 @@ class GitlabKeys $stdin end - def key_command(key_id) - "#{ROOT_PATH}/bin/gitlab-shell #{key_id}" - end - - def key_line(key_id, public_key) - auth_line = "command=\"#{key_command(key_id)}\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #{public_key}" - end - def rm_key lock do $logger.info "Removing key #{@key_id}" open(auth_file, 'r+') do |f| while line = f.gets do - next unless line.start_with?("command=\"#{key_command(@key_id)}\"") + next unless line.start_with?("command=\"#{@gitlab_key.command(@key_id)}\"") f.seek(-line.length, IO::SEEK_CUR) # Overwrite the line with #'s. Because the 'line' variable contains # a terminating '\n', we write line.length - 1 '#' characters. @@ -115,3 +108,14 @@ class GitlabKeys @lock_file ||= auth_file + '.lock' end end + + +class GitlabKey + def command(key_id) + "#{ROOT_PATH}/bin/gitlab-shell #{key_id}" + end + + def key_line(key_id, public_key) + "command=\"#{command(key_id)}\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #{public_key}" + end +end diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb index 71e113b..8b6d33b 100644 --- a/lib/gitlab_net.rb +++ b/lib/gitlab_net.rb @@ -56,6 +56,13 @@ class GitlabNet get("#{host}/check", read_timeout: CHECK_TIMEOUT) end + def authorized_key(key) + resp = get("#{host}/authorized_keys?key=#{URI.escape(key, '+/=')}") + JSON.parse(resp.body) if resp.code == "200" + rescue + nil + end + protected def config diff --git a/spec/gitlab_net_spec.rb b/spec/gitlab_net_spec.rb index 2d9b544..e4dee33 100644 --- a/spec/gitlab_net_spec.rb +++ b/spec/gitlab_net_spec.rb @@ -8,8 +8,8 @@ describe GitlabNet, vcr: true do let(:changes) { ['0000000000000000000000000000000000000000 92d0970eefd7acb6d548878925ce2208cfe2d2ec refs/heads/branch4'] } before do - gitlab_net.stub!(:host).and_return('https://dev.gitlab.org/api/v3/internal') - gitlab_net.stub!(:secret_token).and_return('a123') + gitlab_net.stub(:host).and_return('https://dev.gitlab.org/api/v3/internal') + gitlab_net.stub(:secret_token).and_return('a123') end describe :check do @@ -76,6 +76,36 @@ describe GitlabNet, vcr: true do end end + describe :authorized_key do + let (:ssh_key) { "AAAAB3NzaC1yc2EAAAADAQABAAACAQDPKPqqnqQ9PDFw65cO7iHXrKw6ucSZg8Bd2CZ150Yy1YRDPJOWeRNCnddS+M/Lk" } + + it "should return nil when the resource is not implemented" do + VCR.use_cassette("ssh-key-not-implemented") do + result = gitlab_net.authorized_key("whatever") + result.should be_nil + end + end + + it "should return nil when the fingerprint is not found" do + VCR.use_cassette("ssh-key-not-found") do + result = gitlab_net.authorized_key("whatever") + result.should be_nil + end + end + + it "should return a ssh key with a valid fingerprint" do + VCR.use_cassette("ssh-key-ok") do + result = gitlab_net.authorized_key(ssh_key) + result.should eq({ + "created_at" => "2016-03-04T18:27:36.959Z", + "id" => 2, + "key" => "ssh-rsa a-made=up-rsa-key dummy@gitlab.com", + "title" => "some key title" + }) + end + end + end + describe :check_access do context 'ssh key with access to project' do it 'should allow pull access for dev.gitlab.org' do @@ -142,7 +172,7 @@ describe GitlabNet, vcr: true do describe :http_client_for do subject { gitlab_net.send :http_client_for, URI('https://localhost/') } before do - gitlab_net.stub! :cert_store + gitlab_net.stub :cert_store gitlab_net.send(:config).stub(:http_settings) { {'self_signed_cert' => true} } end diff --git a/spec/vcr_cassettes/ssh-key-not-found.yml b/spec/vcr_cassettes/ssh-key-not-found.yml new file mode 100644 index 0000000..55e5b4f --- /dev/null +++ b/spec/vcr_cassettes/ssh-key-not-found.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://dev.gitlab.org/api/v3/internal/authorized_keys?key=whatever + body: + encoding: US-ASCII + string: secret_token=a123 + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 404 + message: Not Found + headers: + Server: + - nginx + Date: + - Mon, 07 Mar 2016 12:09:59 GMT + Content-Type: + - text/html; charset=utf-8 + Connection: + - keep-alive + Cache-Control: + - no-cache + Set-Cookie: + - _gitlab_session=a924e63729e538c9efe10fa8338077d7; path=/; expires=Mon, 14 + Mar 2016 12:09:59 -0000; secure; HttpOnly + Status: + - 404 Not Found + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - 275ad011-515f-4239-80be-e537fd7c9086 + X-Runtime: + - '2.169401' + X-Xss-Protection: + - 1; mode=block + http_version: + recorded_at: Mon, 07 Mar 2016 12:10:00 GMT +recorded_with: VCR 2.4.0 diff --git a/spec/vcr_cassettes/ssh-key-not-implemented.yml b/spec/vcr_cassettes/ssh-key-not-implemented.yml new file mode 100644 index 0000000..98c3c00 --- /dev/null +++ b/spec/vcr_cassettes/ssh-key-not-implemented.yml @@ -0,0 +1,50 @@ +--- +http_interactions: +- request: + method: get + uri: https://dev.gitlab.org/api/v3/internal/authorized_keys?key=whatever + body: + encoding: US-ASCII + string: secret_token=a123 + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 501 + message: Not Implemented + headers: + Server: + - nginx + Date: + - Mon, 07 Mar 2016 12:09:59 GMT + Content-Type: + - text/html; charset=utf-8 + Connection: + - keep-alive + Cache-Control: + - no-cache + Set-Cookie: + - _gitlab_session=a924e63729e538c9efe10fa8338077d7; path=/; expires=Mon, 14 + Mar 2016 12:09:59 -0000; secure; HttpOnly + Status: + - 501 Not Implemented + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Request-Id: + - 275ad011-515f-4239-80be-e537fd7c9086 + X-Runtime: + - '2.169401' + X-Xss-Protection: + - 1; mode=block + http_version: + recorded_at: Mon, 07 Mar 2016 12:10:00 GMT +recorded_with: VCR 2.4.0 diff --git a/spec/vcr_cassettes/ssh-key-ok.yml b/spec/vcr_cassettes/ssh-key-ok.yml new file mode 100644 index 0000000..87817d1 --- /dev/null +++ b/spec/vcr_cassettes/ssh-key-ok.yml @@ -0,0 +1,40 @@ +--- +http_interactions: +- request: + method: get + uri: https://dev.gitlab.org/api/v3/internal/authorized_keys?key=AAAAB3NzaC1yc2EAAAADAQABAAACAQDPKPqqnqQ9PDFw65cO7iHXrKw6ucSZg8Bd2CZ150Yy1YRDPJOWeRNCnddS+M/Lk + body: + encoding: US-ASCII + string: secret_token=a123 + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/x-www-form-urlencoded + response: + status: + code: 200 + message: OK + headers: + Server: + - nginx/1.1.19 + Date: + - Wed, 03 Sep 2014 11:27:35 GMT + Content-Type: + - application/json + Connection: + - keep-alive + Status: + - 200 OK + Cache-Control: + - max-age=0, private, must-revalidate + body: + encoding: UTF-8 + string: '{"id":2, "title":"some key title", "key":"ssh-rsa a-made=up-rsa-key dummy@gitlab.com", "created_at":"2016-03-04T18:27:36.959Z"}' + http_version: + recorded_at: Mon, 07 Mar 2016 12:10:00 GMT +recorded_with: VCR 2.4.0 |