Commit c9fac154 authored by Pablo Carranza's avatar Pablo Carranza

Add authorized keys bin script to find keys by fingerprint

parent 1f2bef76
#!/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
...@@ -11,6 +11,7 @@ class GitlabKeys ...@@ -11,6 +11,7 @@ class GitlabKeys
@key_id = ARGV.shift @key_id = ARGV.shift
@key = ARGV.shift @key = ARGV.shift
@auth_file = GitlabConfig.new.auth_file @auth_file = GitlabConfig.new.auth_file
@gitlab_key = GitlabKey.new
end end
def exec def exec
...@@ -32,7 +33,7 @@ class GitlabKeys ...@@ -32,7 +33,7 @@ class GitlabKeys
def add_key def add_key
lock do lock do
$logger.info "Adding key #{@key_id} => #{@key.inspect}" $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) } open(auth_file, 'a') { |file| file.puts(auth_line) }
end end
true true
...@@ -59,7 +60,7 @@ class GitlabKeys ...@@ -59,7 +60,7 @@ class GitlabKeys
abort("#{$0}: invalid input #{input.inspect}") unless tokens.count == 2 abort("#{$0}: invalid input #{input.inspect}") unless tokens.count == 2
key_id, public_key = tokens key_id, public_key = tokens
$logger.info "Adding key #{key_id} => #{public_key.inspect}" $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 end
end end
...@@ -70,20 +71,12 @@ class GitlabKeys ...@@ -70,20 +71,12 @@ class GitlabKeys
$stdin $stdin
end 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 def rm_key
lock do lock do
$logger.info "Removing key #{@key_id}" $logger.info "Removing key #{@key_id}"
open(auth_file, 'r+') do |f| open(auth_file, 'r+') do |f|
while line = f.gets do 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) f.seek(-line.length, IO::SEEK_CUR)
# Overwrite the line with #'s. Because the 'line' variable contains # Overwrite the line with #'s. Because the 'line' variable contains
# a terminating '\n', we write line.length - 1 '#' characters. # a terminating '\n', we write line.length - 1 '#' characters.
...@@ -115,3 +108,14 @@ class GitlabKeys ...@@ -115,3 +108,14 @@ class GitlabKeys
@lock_file ||= auth_file + '.lock' @lock_file ||= auth_file + '.lock'
end end
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
...@@ -56,9 +56,11 @@ class GitlabNet ...@@ -56,9 +56,11 @@ class GitlabNet
get("#{host}/check", read_timeout: CHECK_TIMEOUT) get("#{host}/check", read_timeout: CHECK_TIMEOUT)
end end
def ssh_key(fingerprint) def authorized_key(fingerprint)
resp = get("#{host}/ssh-key?fingerprint=#{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 end
protected protected
......
...@@ -76,24 +76,24 @@ describe GitlabNet, vcr: true do ...@@ -76,24 +76,24 @@ describe GitlabNet, vcr: true do
end end
end end
describe :ssh_key do describe :authorized_key do
it "should return nil when the resource is not implemented" do it "should return nil when the resource is not implemented" do
VCR.use_cassette("ssh-key-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 result.should be_nil
end end
end end
it "should return nil when the fingerprint is not found" do it "should return nil when the fingerprint is not found" do
VCR.use_cassette("ssh-key-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 result.should be_nil
end end
end end
it "should return a ssh key with a valid fingerprint" do it "should return a ssh key with a valid fingerprint" do
VCR.use_cassette("ssh-key-ok") 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({ result.should eq({
"created_at" => "2016-03-04T18:27:36.959Z", "created_at" => "2016-03-04T18:27:36.959Z",
"id" => 2, "id" => 2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment