summaryrefslogtreecommitdiff
path: root/app/models/remote_mirror.rb
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2018-11-12 10:52:48 +0000
committerNick Thomas <nick@gitlab.com>2018-11-19 11:46:39 +0000
commitf1bc7b6eb5cb9beab55e4edac87cc5e0b7ceb069 (patch)
tree2e5aedd22e2fd05909c1e97c5bc52602feadc825 /app/models/remote_mirror.rb
parentb1b4c94484b0613a6a457e32218d4f62b9eb2029 (diff)
downloadgitlab-ce-f1bc7b6eb5cb9beab55e4edac87cc5e0b7ceb069.tar.gz
SSH public-key authentication for push mirroring
Diffstat (limited to 'app/models/remote_mirror.rb')
-rw-r--r--app/models/remote_mirror.rb45
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