diff options
author | Nick Thomas <nick@gitlab.com> | 2017-08-21 11:30:03 +0100 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2017-08-30 20:50:44 +0100 |
commit | b0f982fbdf69c292ab4530c0aaaf1ab42f4e7a01 (patch) | |
tree | 0d76c74fb6260de1e3c9694a8501491b2eb486ef /app/models/key.rb | |
parent | 81f08d30e641dc1a6666022ab1f5d36dbcdced7e (diff) | |
download | gitlab-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.rb | 45 |
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 |