From c9fac154cd99233c9a6f1cbb88316a476fffc3ad Mon Sep 17 00:00:00 2001 From: Pablo Carranza <pcarranza@gmail.com> Date: Tue, 8 Mar 2016 17:49:22 +0000 Subject: [PATCH] Add authorized keys bin script to find keys by fingerprint --- bin/authorized_keys | 25 +++++++++++++++++++++++++ lib/gitlab_authorized_keys.rb | 0 lib/gitlab_keys.rb | 26 +++++++++++++++----------- lib/gitlab_net.rb | 6 ++++-- spec/gitlab_net_spec.rb | 8 ++++---- 5 files changed, 48 insertions(+), 17 deletions(-) create mode 100755 bin/authorized_keys create mode 100644 lib/gitlab_authorized_keys.rb diff --git a/bin/authorized_keys b/bin/authorized_keys new file mode 100755 index 0000000..6f9880c --- /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 e6:17:f2:f3:b7 +# +# Returns +# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQA... +# + +fingerprint = ARGV[0] +abort "# No fingerprint provided" if fingerprint.nil? + +require_relative "../lib/gitlab_init" +require_relative "../lib/gitlab_net" +require_relative "../lib/gitlab_keys" + +authorized_key = GitlabNet.new.authorized_key(fingerprint) +unless authorized_key.nil? + puts GitlabKey.new.key_line(authorized_key["id"], authorized_key["key"]) +else + puts "# No key was found with fingerprint #{fingerprint}" +end diff --git a/lib/gitlab_authorized_keys.rb b/lib/gitlab_authorized_keys.rb new file mode 100644 index 0000000..e69de29 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 ddf2a06..503a267 100644 --- a/lib/gitlab_net.rb +++ b/lib/gitlab_net.rb @@ -56,9 +56,11 @@ class GitlabNet get("#{host}/check", read_timeout: CHECK_TIMEOUT) end - def ssh_key(fingerprint) + def authorized_key(fingerprint) resp = get("#{host}/ssh-key?fingerprint=#{fingerprint}") - JSON.parse(resp.body) rescue nil + JSON.parse(resp.body) if resp.code == "200" + rescue + nil end protected diff --git a/spec/gitlab_net_spec.rb b/spec/gitlab_net_spec.rb index 964e398..786316d 100644 --- a/spec/gitlab_net_spec.rb +++ b/spec/gitlab_net_spec.rb @@ -76,24 +76,24 @@ describe GitlabNet, vcr: true do end end - describe :ssh_key do + describe :authorized_key do it "should return nil when the resource is not implemented" do VCR.use_cassette("ssh-key-not-implemented") do - result = gitlab_net.ssh_key("whatever") + 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.ssh_key("whatever") + 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.ssh_key("42:18:16") + result = gitlab_net.authorized_key("42:18:16") result.should eq({ "created_at" => "2016-03-04T18:27:36.959Z", "id" => 2, -- 2.30.9