Commit 62d54034 authored by Rubén Dávila's avatar Rubén Dávila

Process and create subkeys when a new GPG key is created

parent 5ae8e378
...@@ -9,6 +9,7 @@ class GpgKey < ActiveRecord::Base ...@@ -9,6 +9,7 @@ class GpgKey < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :gpg_signatures has_many :gpg_signatures
has_many :subkeys, class_name: 'GpgKey', foreign_key: :parent_id, dependent: :destroy
validates :user, presence: true validates :user, presence: true
...@@ -18,7 +19,8 @@ class GpgKey < ActiveRecord::Base ...@@ -18,7 +19,8 @@ class GpgKey < ActiveRecord::Base
format: { format: {
with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX})(?!#{KEY_SUFFIX}).)+#{KEY_SUFFIX}\Z/m, with: /\A#{KEY_PREFIX}((?!#{KEY_PREFIX})(?!#{KEY_SUFFIX}).)+#{KEY_SUFFIX}\Z/m,
message: "is invalid. A valid public GPG key begins with '#{KEY_PREFIX}' and ends with '#{KEY_SUFFIX}'" message: "is invalid. A valid public GPG key begins with '#{KEY_PREFIX}' and ends with '#{KEY_SUFFIX}'"
} },
unless: :parent_id?
validates :fingerprint, validates :fingerprint,
presence: true, presence: true,
...@@ -34,8 +36,9 @@ class GpgKey < ActiveRecord::Base ...@@ -34,8 +36,9 @@ class GpgKey < ActiveRecord::Base
# the error about the fingerprint # the error about the fingerprint
unless: -> { errors.has_key?(:key) } unless: -> { errors.has_key?(:key) }
before_validation :extract_fingerprint, :extract_primary_keyid before_validation :extract_fingerprint, :extract_primary_keyid, unless: :parent_id?
after_commit :update_invalid_gpg_signatures, on: :create after_commit :update_invalid_gpg_signatures, on: :create
after_save :generate_subkeys, unless: :parent_id?
def primary_keyid def primary_keyid
super&.upcase super&.upcase
...@@ -106,4 +109,18 @@ class GpgKey < ActiveRecord::Base ...@@ -106,4 +109,18 @@ class GpgKey < ActiveRecord::Base
# only allows one key # only allows one key
self.primary_keyid = Gitlab::Gpg.primary_keyids_from_key(key).first self.primary_keyid = Gitlab::Gpg.primary_keyids_from_key(key).first
end end
def generate_subkeys
gpg_subkeys = Gitlab::Gpg.subkeys_from_key(key)
gpg_subkeys[primary_keyid].each do |subkey_data|
unless subkeys.where(fingerprint: subkey_data[:fingerprint]).exists?
subkeys.create!(
user: user,
primary_keyid: subkey_data[:keyid],
fingerprint: subkey_data[:fingerprint]
)
end
end
end
end end
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddParentIdToGpgKeys < ActiveRecord::Migration
DOWNTIME = false
def change
add_column :gpg_keys, :parent_id, :integer
end
end
...@@ -586,6 +586,7 @@ ActiveRecord::Schema.define(version: 20171004121444) do ...@@ -586,6 +586,7 @@ ActiveRecord::Schema.define(version: 20171004121444) do
t.binary "primary_keyid" t.binary "primary_keyid"
t.binary "fingerprint" t.binary "fingerprint"
t.text "key" t.text "key"
t.integer "parent_id"
end end
add_index "gpg_keys", ["fingerprint"], name: "index_gpg_keys_on_fingerprint", unique: true, using: :btree add_index "gpg_keys", ["fingerprint"], name: "index_gpg_keys_on_fingerprint", unique: true, using: :btree
......
...@@ -34,6 +34,27 @@ module Gitlab ...@@ -34,6 +34,27 @@ module Gitlab
end end
end end
def subkeys_from_key(key)
using_tmp_keychain do
fingerprints = CurrentKeyChain.fingerprints_from_key(key)
raw_keys = GPGME::Key.find(:public, fingerprints)
grouped_subkeys = Hash.new { |h, k| h[k] = [] }
raw_keys.each_with_object(grouped_subkeys).each do |raw_key, subkeys|
primary_subkey_id = raw_key.primary_subkey.keyid
raw_key.subkeys.each do |subkey|
# Skip if current subkey is a master key
next if primary_subkey_id == subkey.keyid
# Skip if it isn't a sign key
next if subkey.capability.exclude?(:sign)
subkeys[primary_subkey_id] << { keyid: subkey.keyid, fingerprint: subkey.fingerprint }
end
end
end
end
def user_infos_from_key(key) def user_infos_from_key(key)
using_tmp_keychain do using_tmp_keychain do
fingerprints = CurrentKeyChain.fingerprints_from_key(key) fingerprints = CurrentKeyChain.fingerprints_from_key(key)
......
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