diff options
author | Nick Thomas <nick@gitlab.com> | 2018-11-12 13:52:48 +0300 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2018-11-19 14:46:39 +0300 |
commit | f1bc7b6eb5cb9beab55e4edac87cc5e0b7ceb069 (patch) | |
tree | 2e5aedd22e2fd05909c1e97c5bc52602feadc825 /app/models/remote_mirror.rb | |
parent | b1b4c94484b0613a6a457e32218d4f62b9eb2029 (diff) |
SSH public-key authentication for push mirroring
Diffstat (limited to 'app/models/remote_mirror.rb')
-rw-r--r-- | app/models/remote_mirror.rb | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb index c1f53b5da4f..a3415a4a14c 100644 --- a/app/models/remote_mirror.rb +++ b/app/models/remote_mirror.rb @@ -2,6 +2,7 @@ class RemoteMirror < ActiveRecord::Base include AfterCommitQueue + include MirrorAuthentication PROTECTED_BACKOFF_DELAY = 1.minute UNPROTECTED_BACKOFF_DELAY = 5.minutes @@ -28,6 +29,8 @@ class RemoteMirror < ActiveRecord::Base after_commit :remove_remote, on: :destroy + before_validation :store_credentials + scope :enabled, -> { where(enabled: true) } scope :started, -> { with_update_status(:started) } scope :stuck, -> { started.where('last_update_at < ? OR (last_update_at IS NULL AND updated_at < ?)', 1.day.ago, 1.day.ago) } @@ -84,7 +87,21 @@ class RemoteMirror < ActiveRecord::Base end def update_repository(options) - raw.update(options) + if ssh_mirror_url? + if ssh_key_auth? && ssh_private_key.present? + options[:ssh_key] = ssh_private_key + end + + if ssh_known_hosts.present? + options[:known_hosts] = ssh_known_hosts + end + end + + Gitlab::Git::RemoteMirror.new( + project.repository.raw, + remote_name, + **options + ).update end def sync? @@ -128,7 +145,8 @@ class RemoteMirror < ActiveRecord::Base super(value) && return unless Gitlab::UrlSanitizer.valid?(value) mirror_url = Gitlab::UrlSanitizer.new(value) - self.credentials = mirror_url.credentials + self.credentials ||= {} + self.credentials = self.credentials.merge(mirror_url.credentials) super(mirror_url.sanitized_url) end @@ -152,17 +170,28 @@ class RemoteMirror < ActiveRecord::Base def ensure_remote! return unless project - return unless remote_name && url + return unless remote_name && remote_url # If this fails or the remote already exists, we won't know due to # https://gitlab.com/gitlab-org/gitaly/issues/1317 - project.repository.add_remote(remote_name, url) + project.repository.add_remote(remote_name, remote_url) end private - def raw - @raw ||= Gitlab::Git::RemoteMirror.new(project.repository.raw, remote_name) + def store_credentials + # This is a necessary workaround for attr_encrypted, which doesn't otherwise + # notice that the credentials have changed + self.credentials = self.credentials + end + + # The remote URL omits any password if SSH public-key authentication is in use + def remote_url + return url unless ssh_key_auth? && password.present? + + Gitlab::UrlSanitizer.new(read_attribute(:url), credentials: { user: user }).full_url + rescue + super end def fallback_remote_name @@ -214,7 +243,7 @@ class RemoteMirror < ActiveRecord::Base project.repository.async_remove_remote(prev_remote_name) end - project.repository.add_remote(remote_name, url) + project.repository.add_remote(remote_name, remote_url) end def remove_remote @@ -224,6 +253,6 @@ class RemoteMirror < ActiveRecord::Base end def mirror_url_changed? - url_changed? || encrypted_credentials_changed? + url_changed? || credentials_changed? end end |