Commit 3c42d730 authored by Alexis Reigel's avatar Alexis Reigel
Browse files

add primary keyid attribute to gpg keys

parent d5580440b90f
......@@ -20,7 +20,14 @@ class GpgKey < ActiveRecord::Base
# the error about the fingerprint
unless: -> { errors.has_key?(:key) }
before_validation :extract_fingerprint
validates :primary_keyid,
presence: true,
uniqueness: true,
# only validate when the `key` is valid, as we don't want the user to show
# the error about the fingerprint
unless: -> { errors.has_key?(:key) }
before_validation :extract_fingerprint, :extract_primary_keyid
after_create :notify_user
def key=(value)
......@@ -49,6 +56,12 @@ def extract_fingerprint
self.fingerprint = Gitlab::Gpg.fingerprints_from_key(key).first
end
def extract_primary_keyid
# we can assume that the result only contains one item as the validation
# only allows one key
self.primary_keyid = Gitlab::Gpg.primary_keyids_from_key(key).first
end
def notify_user
run_after_commit { NotificationService.new.new_gpg_key(self) }
end
......
class AddPrimaryKeyidToGpgKeys < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_column :gpg_keys, :primary_keyid, :string
add_concurrent_index :gpg_keys, :primary_keyid
end
def down
remove_concurrent_index :gpg_keys, :primary_keyid if index_exists?(:gpg_keys, :primary_keyid)
remove_column :gpg_keys, :primary_keyid, :string
end
end
......@@ -546,8 +546,10 @@
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "primary_keyid"
end
add_index "gpg_keys", ["primary_keyid"], name: "index_gpg_keys_on_primary_keyid", using: :btree
add_index "gpg_keys", ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
create_table "identities", force: :cascade do |t|
......
......@@ -12,6 +12,18 @@ def fingerprints_from_key(key)
end
end
def primary_keyids_from_key(key)
using_tmp_keychain do
import = GPGME::Key.import(key)
return [] if import.imported == 0
fingerprints = import.imports.map(&:fingerprint)
GPGME::Key.find(:public, fingerprints).map { |raw_key| raw_key.primary_subkey.keyid }
end
end
def emails_from_key(key)
using_tmp_keychain do
import = GPGME::Key.import(key)
......
......@@ -220,8 +220,8 @@
Dir.mktmpdir do |dir|
FileUtils.cd dir do
`git clone --quiet #{remote_path} .`
`git commit --quiet -S#{GpgHelpers::User1.key_id} --allow-empty -m "signed commit, verified key/email"`
`git commit --quiet -S#{GpgHelpers::User2.key_id} --allow-empty -m "signed commit, unverified key/email"`
`git commit --quiet -S#{GpgHelpers::User1.primary_keyid} --allow-empty -m "signed commit, verified key/email"`
`git commit --quiet -S#{GpgHelpers::User2.primary_keyid} --allow-empty -m "signed commit, unverified key/email"`
`git push --quiet`
end
end
......
......@@ -15,6 +15,20 @@
end
end
describe '.primary_keyids_from_key' do
it 'returns the keyid' do
expect(
described_class.primary_keyids_from_key(GpgHelpers::User1.public_key)
).to eq [GpgHelpers::User1.primary_keyid]
end
it 'returns an empty array when the key is invalid' do
expect(
described_class.primary_keyids_from_key('bogus')
).to eq []
end
end
describe '.emails_from_key' do
it 'returns the emails' do
expect(
......
......@@ -21,6 +21,14 @@
expect(gpg_key.fingerprint).to eq GpgHelpers::User1.fingerprint
end
end
describe 'extract_primary_keyid' do
it 'extracts the primary keyid from the gpg key' do
gpg_key = described_class.new(key: GpgHelpers::User1.public_key)
gpg_key.valid?
expect(gpg_key.primary_keyid).to eq GpgHelpers::User1.primary_keyid
end
end
end
describe '#key=' do
......
......@@ -90,8 +90,8 @@ def public_key
KEY
end
def key_id
'00AC8B1D'
def primary_keyid
fingerprint[-16..-1]
end
def fingerprint
......@@ -179,8 +179,8 @@ def public_key
KEY
end
def key_id
'911EFD65'
def primary_keyid
fingerprint[-16..-1]
end
def fingerprint
......
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