summaryrefslogtreecommitdiff
path: root/app/models/key.rb
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2017-08-21 11:30:03 +0100
committerNick Thomas <nick@gitlab.com>2017-08-30 20:50:44 +0100
commitb0f982fbdf69c292ab4530c0aaaf1ab42f4e7a01 (patch)
tree0d76c74fb6260de1e3c9694a8501491b2eb486ef /app/models/key.rb
parent81f08d30e641dc1a6666022ab1f5d36dbcdced7e (diff)
downloadgitlab-ce-b0f982fbdf69c292ab4530c0aaaf1ab42f4e7a01.tar.gz
Add settings for minimum key strength and allowed key type
This is an amalgamation of: * Cory Hinshaw: Initial implementation !5552 * Rémy Coutable: Updates !9350 * Nick Thomas: Resolve conflicts and add ED25519 support !13712
Diffstat (limited to 'app/models/key.rb')
-rw-r--r--app/models/key.rb45
1 files changed, 44 insertions, 1 deletions
diff --git a/app/models/key.rb b/app/models/key.rb
index 49bc26122fa..27c91679ec9 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -1,6 +1,8 @@
require 'digest/md5'
class Key < ActiveRecord::Base
+ include AfterCommitQueue
+ include Gitlab::CurrentSettings
include Sortable
LAST_USED_AT_REFRESH_TIME = 1.day.to_i
@@ -12,14 +14,18 @@ class Key < ActiveRecord::Base
validates :title,
presence: true,
length: { maximum: 255 }
+
validates :key,
presence: true,
length: { maximum: 5000 },
format: { with: /\A(ssh|ecdsa)-.*\Z/ }
+
validates :fingerprint,
uniqueness: true,
presence: { message: 'cannot be generated' }
+ validate :key_meets_minimum_bit_length, :key_type_is_allowed
+
delegate :name, :email, to: :user, prefix: true
after_commit :add_to_shell, on: :create
@@ -80,6 +86,10 @@ class Key < ActiveRecord::Base
SystemHooksService.new.execute_hooks_for(self, :destroy)
end
+ def public_key
+ @public_key ||= Gitlab::SSHPublicKey.new(key)
+ end
+
private
def generate_fingerprint
@@ -87,7 +97,40 @@ class Key < ActiveRecord::Base
return unless self.key.present?
- self.fingerprint = Gitlab::KeyFingerprint.new(self.key).fingerprint
+ self.fingerprint = public_key.fingerprint
+ end
+
+ def key_meets_minimum_bit_length
+ case public_key.type
+ when :rsa
+ if public_key.bits < current_application_settings.minimum_rsa_bits
+ errors.add(:key, "length must be at least #{current_application_settings.minimum_rsa_bits} bits")
+ end
+ when :dsa
+ if public_key.bits < current_application_settings.minimum_dsa_bits
+ errors.add(:key, "length must be at least #{current_application_settings.minimum_dsa_bits} bits")
+ end
+ when :ecdsa
+ if public_key.bits < current_application_settings.minimum_ecdsa_bits
+ errors.add(:key, "elliptic curve size must be at least #{current_application_settings.minimum_ecdsa_bits} bits")
+ end
+ when :ed25519
+ if public_key.bits < current_application_settings.minimum_ed25519_bits
+ errors.add(:key, "length must be at least #{current_application_settings.minimum_ed25519_bits} bits")
+ end
+ end
+ end
+
+ def key_type_is_allowed
+ unless current_application_settings.allowed_key_types.include?(public_key.type.to_s)
+ allowed_types =
+ current_application_settings
+ .allowed_key_types
+ .map(&:upcase)
+ .to_sentence(last_word_connector: ', or ', two_words_connector: ' or ')
+
+ errors.add(:key, "type is not allowed. Must be #{allowed_types}")
+ end
end
def notify_user