Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/gpg_key.rb21
-rw-r--r--db/migrate/20170926050624_add_parent_id_to_gpg_keys.rb10
-rw-r--r--db/schema.rb1
-rw-r--r--lib/gitlab/gpg.rb21
4 files changed, 51 insertions, 2 deletions
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index 54bd5b68777..cbf01183969 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -9,6 +9,7 @@ class GpgKey < ActiveRecord::Base
belongs_to :user
has_many :gpg_signatures
+ has_many :subkeys, class_name: 'GpgKey', foreign_key: :parent_id, dependent: :destroy
validates :user, presence: true
@@ -18,7 +19,8 @@ class GpgKey < ActiveRecord::Base
format: {
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}'"
- }
+ },
+ unless: :parent_id?
validates :fingerprint,
presence: true,
@@ -34,8 +36,9 @@ class GpgKey < ActiveRecord::Base
# the error about the fingerprint
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_save :generate_subkeys, unless: :parent_id?
def primary_keyid
super&.upcase
@@ -106,4 +109,18 @@ class GpgKey < ActiveRecord::Base
# only allows one key
self.primary_keyid = Gitlab::Gpg.primary_keyids_from_key(key).first
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
diff --git a/db/migrate/20170926050624_add_parent_id_to_gpg_keys.rb b/db/migrate/20170926050624_add_parent_id_to_gpg_keys.rb
new file mode 100644
index 00000000000..ef7675be106
--- /dev/null
+++ b/db/migrate/20170926050624_add_parent_id_to_gpg_keys.rb
@@ -0,0 +1,10 @@
+# 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
diff --git a/db/schema.rb b/db/schema.rb
index 17be774e9de..9b1457c9a03 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -586,6 +586,7 @@ ActiveRecord::Schema.define(version: 20171004121444) do
t.binary "primary_keyid"
t.binary "fingerprint"
t.text "key"
+ t.integer "parent_id"
end
add_index "gpg_keys", ["fingerprint"], name: "index_gpg_keys_on_fingerprint", unique: true, using: :btree
diff --git a/lib/gitlab/gpg.rb b/lib/gitlab/gpg.rb
index 0d5039ddf5f..be22a9e0fe2 100644
--- a/lib/gitlab/gpg.rb
+++ b/lib/gitlab/gpg.rb
@@ -34,6 +34,27 @@ module Gitlab
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)
using_tmp_keychain do
fingerprints = CurrentKeyChain.fingerprints_from_key(key)