debian-mirror-gitlab/app/models/key.rb

194 lines
5.2 KiB
Ruby
Raw Normal View History

2018-11-18 11:00:15 +05:30
# frozen_string_literal: true
2019-07-07 11:18:12 +05:30
class Key < ApplicationRecord
2018-03-17 18:26:18 +05:30
include AfterCommitQueue
2015-04-26 12:48:37 +05:30
include Sortable
2022-07-16 23:28:13 +05:30
include ShaAttribute
2020-04-08 14:13:33 +05:30
include Expirable
2021-09-04 01:27:46 +05:30
include FromUnion
2020-01-01 13:55:28 +05:30
sha256_attribute :fingerprint_sha256
2014-09-02 18:07:02 +05:30
2017-08-17 22:00:37 +05:30
belongs_to :user
2014-09-02 18:07:02 +05:30
2023-04-23 21:23:45 +05:30
has_many :ssh_signatures, class_name: 'CommitSignatures::SshSignature'
2017-08-17 22:00:37 +05:30
before_validation :generate_fingerprint
validates :title,
presence: true,
length: { maximum: 255 }
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
validates :key,
presence: true,
length: { maximum: 5000 },
2022-03-02 08:16:31 +05:30
format: { with: /\A(#{Gitlab::SSHPublicKey.supported_algorithms.join('|')})/ }
2018-03-17 18:26:18 +05:30
2022-06-21 17:19:12 +05:30
validates :fingerprint_sha256,
uniqueness: true,
2022-07-16 23:28:13 +05:30
presence: { message: 'cannot be generated' }
2014-09-02 18:07:02 +05:30
2018-03-17 18:26:18 +05:30
validate :key_meets_restrictions
2022-07-16 23:28:13 +05:30
validate :expiration, on: :create
2022-08-13 15:12:31 +05:30
validate :banned_key, if: :key_changed?
2018-03-17 18:26:18 +05:30
2014-09-02 18:07:02 +05:30
delegate :name, :email, to: :user, prefix: true
2023-03-04 22:38:38 +05:30
enum usage_type: {
auth_and_signing: 0,
auth: 1,
signing: 2
}
2015-04-26 12:48:37 +05:30
after_create :post_create_hook
2018-03-17 18:26:18 +05:30
after_create :refresh_user_cache
2015-04-26 12:48:37 +05:30
after_destroy :post_destroy_hook
2018-03-17 18:26:18 +05:30
after_destroy :refresh_user_cache
2023-03-04 22:38:38 +05:30
after_commit :add_to_authorized_keys, on: :create
after_commit :remove_from_authorized_keys, on: :destroy
2014-09-02 18:07:02 +05:30
2020-01-01 13:55:28 +05:30
alias_attribute :fingerprint_md5, :fingerprint
2022-08-27 11:52:29 +05:30
alias_attribute :name, :title
2020-01-01 13:55:28 +05:30
scope :preload_users, -> { preload(:user) }
scope :for_user, -> (user) { where(user: user) }
2022-06-21 17:19:12 +05:30
scope :order_last_used_at_desc, -> { reorder(arel_table[:last_used_at].desc.nulls_last) }
2023-03-04 22:38:38 +05:30
scope :auth, -> { where(usage_type: [:auth, :auth_and_signing]) }
scope :signing, -> { where(usage_type: [:signing, :auth_and_signing]) }
2021-09-04 01:27:46 +05:30
# Date is set specifically in this scope to improve query time.
2021-12-11 22:18:48 +05:30
scope :expired_today_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') = CURRENT_DATE AND expiry_notification_delivered_at IS NULL"]) }
2021-04-29 21:17:54 +05:30
scope :expiring_soon_and_not_notified, -> { where(["date(expires_at AT TIME ZONE 'UTC') > CURRENT_DATE AND date(expires_at AT TIME ZONE 'UTC') < ? AND before_expiry_notification_delivered_at IS NULL", DAYS_TO_EXPIRE.days.from_now.to_date]) }
2020-01-01 13:55:28 +05:30
2018-12-13 13:39:08 +05:30
def self.regular_keys
where(type: ['Key', nil])
end
2017-08-17 22:00:37 +05:30
def key=(value)
2018-03-27 19:54:05 +05:30
write_attribute(:key, value.present? ? Gitlab::SSHPublicKey.sanitize(value) : nil)
2018-03-17 18:26:18 +05:30
@public_key = nil
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
def publishable_key
2016-09-13 17:45:13 +05:30
# Strip out the keys comment so we don't leak email addresses
# Replace with simple ident of user_name (hostname)
self.key.split[0..1].push("#{self.user_name} (#{Gitlab.config.gitlab.host})").join(' ')
2015-09-11 14:41:01 +05:30
end
2014-09-02 18:07:02 +05:30
# projects that has this key
def projects
user.authorized_projects
end
def shell_id
"key-#{id}"
end
2019-09-04 21:01:54 +05:30
# EE overrides this
def can_delete?
true
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ServiceClass
2017-08-17 22:00:37 +05:30
def update_last_used_at
2023-07-09 08:55:56 +05:30
Keys::LastUsedService.new(self).execute_async
2017-08-17 22:00:37 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ServiceClass
2017-08-17 22:00:37 +05:30
2020-04-08 14:13:33 +05:30
def add_to_authorized_keys
return unless Gitlab::CurrentSettings.authorized_keys_enabled?
AuthorizedKeysWorker.perform_async(:add_key, shell_id, key)
2014-09-02 18:07:02 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ServiceClass
2015-04-26 12:48:37 +05:30
def post_create_hook
SystemHooksService.new.execute_hooks_for(self, :create)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ServiceClass
2015-04-26 12:48:37 +05:30
2020-04-08 14:13:33 +05:30
def remove_from_authorized_keys
return unless Gitlab::CurrentSettings.authorized_keys_enabled?
AuthorizedKeysWorker.perform_async(:remove_key, shell_id)
2014-09-02 18:07:02 +05:30
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ServiceClass
2018-03-17 18:26:18 +05:30
def refresh_user_cache
return unless user
Users::KeysCountService.new(user).refresh_cache
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ServiceClass
2018-03-17 18:26:18 +05:30
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ServiceClass
2015-04-26 12:48:37 +05:30
def post_destroy_hook
SystemHooksService.new.execute_hooks_for(self, :destroy)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ServiceClass
2015-04-26 12:48:37 +05:30
2018-03-17 18:26:18 +05:30
def public_key
@public_key ||= Gitlab::SSHPublicKey.new(key)
end
2022-08-13 15:12:31 +05:30
def ensure_sha256_fingerprint!
return if self.fingerprint_sha256
save if generate_fingerprint
end
2023-04-23 21:23:45 +05:30
def signing?
super || auth_and_signing?
end
2014-09-02 18:07:02 +05:30
private
2015-04-26 12:48:37 +05:30
def generate_fingerprint
2014-09-02 18:07:02 +05:30
self.fingerprint = nil
2020-01-01 13:55:28 +05:30
self.fingerprint_sha256 = nil
2015-04-26 12:48:37 +05:30
2018-03-27 19:54:05 +05:30
return unless public_key.valid?
2015-04-26 12:48:37 +05:30
2022-06-21 17:19:12 +05:30
self.fingerprint_md5 = public_key.fingerprint unless Gitlab::FIPS.enabled?
2022-04-04 11:22:00 +05:30
self.fingerprint_sha256 = public_key.fingerprint_sha256.gsub("SHA256:", "")
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
def key_meets_restrictions
restriction = Gitlab::CurrentSettings.key_restriction_for(public_key.type)
if restriction == ApplicationSetting::FORBIDDEN_KEY_VALUE
errors.add(:key, forbidden_key_type_message)
elsif public_key.bits < restriction
errors.add(:key, "must be at least #{restriction} bits")
end
end
2022-07-23 23:45:48 +05:30
def banned_key
return unless public_key.banned?
help_page_url = Rails.application.routes.url_helpers.help_page_url(
'security/ssh_keys_restrictions',
anchor: 'block-banned-or-compromised-keys'
)
errors.add(
:key,
_('cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one.'),
help_page_url: help_page_url
)
end
2018-03-17 18:26:18 +05:30
def forbidden_key_type_message
2020-03-13 15:44:24 +05:30
allowed_types = Gitlab::CurrentSettings.allowed_key_types.map(&:upcase)
2018-03-17 18:26:18 +05:30
2020-03-13 15:44:24 +05:30
"type is forbidden. Must be #{Gitlab::Utils.to_exclusive_sentence(allowed_types)}"
2017-08-17 22:00:37 +05:30
end
2022-07-16 23:28:13 +05:30
def expiration
errors.add(:key, message: 'has expired') if expired?
end
2014-09-02 18:07:02 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
Key.prepend_mod_with('Key')