Commit 42fd2ebf authored by Pablo Carranza's avatar Pablo Carranza

Add InsecureKeyFingerprint that calculates the fingerprint without shelling out

parent 1d8d249b
...@@ -56,7 +56,10 @@ module API ...@@ -56,7 +56,10 @@ module API
# Get a ssh key using the fingerprint # Get a ssh key using the fingerprint
# #
get "/authorized_keys" do get "/authorized_keys" do
key = Key.find_by(fingerprint: params[:fingerprint]) fingerprint = params.fetch(:fingerprint) {
Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
}
key = Key.find_by(fingerprint: fingerprint)
not_found!("Key") if key.nil? not_found!("Key") if key.nil?
present key, with: Entities::SSHKey present key, with: Entities::SSHKey
end end
......
...@@ -49,7 +49,29 @@ module Gitlab ...@@ -49,7 +49,29 @@ module Gitlab
required_version_info = Gitlab::VersionInfo.new(6, 8) required_version_info = Gitlab::VersionInfo.new(6, 8)
version_info >= required_version_info version_info >= required_version_info
end
end
#
# Calculates the fingerprint of a given key without using
# openssh key validations. For this reason, only use
# for calculating the fingerprint to find the key with it.
#
# DO NOT use it for checking the validity of a ssh key.
#
class InsecureKeyFingerprint
attr_accessor :key
#
# Gets the base64 encoded string representing a rsa or dsa key
#
def initialize(key_base64)
@key = key_base64
end
def fingerprint
OpenSSL::Digest::MD5.hexdigest(Base64.decode64(@key)).scan(/../).join(':')
end end
end end
end end
require "spec_helper" require "spec_helper"
describe Gitlab::KeyFingerprint, lib: true do context do
let(:key) { "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" } let(:key) { "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" }
let(:fingerprint) { "3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b" } let(:fingerprint) { "3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b" }
describe "#fingerprint" do describe Gitlab::KeyFingerprint, lib: true do
it "generates the key's fingerprint" do describe "#fingerprint" do
expect(Gitlab::KeyFingerprint.new(key).fingerprint).to eq(fingerprint) it "generates the key's fingerprint" do
expect(Gitlab::KeyFingerprint.new(key).fingerprint).to eq(fingerprint)
end
end
end
describe Gitlab::InsecureKeyFingerprint, lib: true do
describe "#fingerprint" do
it "generates the key's fingerprint" do
expect(Gitlab::InsecureKeyFingerprint.new(key.split[1]).fingerprint).to eq(fingerprint)
end
end end
end end
end end
...@@ -49,7 +49,7 @@ describe API::API, api: true do ...@@ -49,7 +49,7 @@ describe API::API, api: true do
end end
describe "GET /internal/authorized_keys" do describe "GET /internal/authorized_keys" do
context "existing key" do context "unsing an existing key's fingerprint" do
it "finds the key" do it "finds the key" do
get(api('/internal/authorized_keys'), fingerprint: key.fingerprint, secret_token: secret_token) get(api('/internal/authorized_keys'), fingerprint: key.fingerprint, secret_token: secret_token)
...@@ -58,21 +58,42 @@ describe API::API, api: true do ...@@ -58,21 +58,42 @@ describe API::API, api: true do
end end
end end
context "non existing key" do context "non existing key's fingerprint" do
it "returns 404" do it "returns 404" do
get(api('/internal/authorized_keys'), fingerprint: "not-valid", secret_token: secret_token) get(api('/internal/authorized_keys'), fingerprint: "no:t-:va:li:d0", secret_token: secret_token)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
context "partial key match" do context "using a partial fingerprint" do
it "returns 404" do it "returns 404" do
get(api('/internal/authorized_keys'), fingerprint: "#{key.fingerprint[0..5]}%", secret_token: secret_token) get(api('/internal/authorized_keys'), fingerprint: "#{key.fingerprint[0..5]}%", secret_token: secret_token)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
end end
context "sending the key" do
it "finds the key" do
get(api('/internal/authorized_keys'), key: key.key.split[1], secret_token: secret_token)
expect(response.status).to eq(200)
expect(json_response["key"]).to eq(key.key)
end
it "returns 404 with a partial key" do
get(api('/internal/authorized_keys'), key: key.key.split[1][0...-3], secret_token: secret_token)
expect(response.status).to eq(404)
end
it "returns 404 with an not valid base64 string" do
get(api('/internal/authorized_keys'), key: "whatever!", secret_token: secret_token)
expect(response.status).to eq(404)
end
end
end end
describe "POST /internal/allowed" do describe "POST /internal/allowed" do
......
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