files/gitlab-cookbooks/gitlab/libraries/registry.rb (103 lines of code) (raw):
#
# Copyright:: Copyright (c) 2016 GitLab Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative 'nginx.rb'
module Registry
class << self
def parse_variables
# first registry_external_url
parse_registry_external_url
# Enable the registry automatically if appropriate
auto_enable
# before this gitlab_rails[registry_path] needs to be parsed
parse_registry
# parsing the registry notifications
parse_registry_notifications
end
##
# If registry_external_url is not set, we're using Let's Encrypt integration,
# and the registry isn't explicitly disabled, we automatically enable the registry
def auto_enable
# If this is not nil, then it has been explicitly set and we should honor that
return unless Gitlab['registry']['enable'].nil?
# If registry_external_url is not nil, it has been explicitly set, and we should honor that
return unless Gitlab['registry_external_url'].nil?
# If Let's Encrypt is not enabled, we don't want to run
return unless Gitlab['letsencrypt']['enable']
uri = URI(Gitlab['external_url'].to_s)
# Don't auto enable for relative urls
return unless Gitlab['gitlab_rails']['gitlab_relative_url'].nil?
Gitlab['registry']['enable'] = true
Gitlab['registry_nginx']['listen_port'] ||= '5050'
Gitlab['registry_nginx']['redirect_http_to_https'] = false
Gitlab['registry_nginx']['fqdn'] = uri.host
Gitlab['gitlab_rails']['registry_port'] ||= Gitlab['registry_nginx']['listen_port']
set_ssl(uri.to_s)
parse_defaults(uri)
end
def parse_secrets
Gitlab['registry']['http_secret'] ||= SecretsHelper.generate_hex(64)
gitlab_registry_crt, gitlab_registry_key = Registry.generate_registry_keypair
Gitlab['registry']['internal_certificate'] ||= gitlab_registry_crt
Gitlab['registry']['internal_key'] ||= gitlab_registry_key
end
def parse_registry_external_url
return unless Gitlab['registry_external_url']
uri = URI(Gitlab['registry_external_url'].to_s)
raise "GitLab Container Registry external URL must include a schema and FQDN, e.g. https://registry.example.com/" unless uri.host
Gitlab['registry']['enable'] = true if Gitlab['registry']['enable'].nil?
parse_defaults(uri)
set_ssl(uri.to_s)
LetsEncryptHelper.add_service_alt_name("registry")
end
def parse_defaults(uri)
Gitlab['gitlab_rails']['registry_enabled'] = true if Gitlab['registry']['enable']
Gitlab['gitlab_rails']['registry_host'] = uri.host
Gitlab['registry_nginx']['listen_port'] ||= uri.port
Gitlab['registry']['registry_http_addr'] ||= "127.0.0.1:5000"
Gitlab['registry']['registry_http_addr'].gsub(/^https?\:\/\/(www.)?/, '')
Gitlab['registry']['token_realm'] ||= Gitlab['external_url']
Gitlab['gitlab_rails']['registry_api_url'] ||= "http://#{Gitlab['registry']['registry_http_addr']}"
end
def set_ssl(url)
uri = URI(url)
case uri.scheme
when "http"
Gitlab['registry_nginx']['https'] ||= false
Nginx.parse_proxy_headers('registry_nginx', false)
when "https"
Gitlab['registry_nginx']['https'] ||= true
Gitlab['registry_nginx']['ssl_certificate'] ||= "/etc/gitlab/ssl/#{uri.host}.crt"
Gitlab['registry_nginx']['ssl_certificate_key'] ||= "/etc/gitlab/ssl/#{uri.host}.key"
Nginx.parse_proxy_headers('registry_nginx', true)
else
raise "Unsupported GitLab Registry external URL scheme: #{uri.scheme}"
end
raise "Unsupported GitLab Registry external URL path: #{uri.path}" unless ["", "/"].include?(uri.path)
# Docker versions before 1.13 will fail to authenticate/push with the
# registry if Registry URL contained :80 or :443. So, we don't set the
# port in gitlab.yml.
Gitlab['gitlab_rails']['registry_port'] = uri.port unless [80, 443].include?(uri.port)
end
def parse_registry
return unless Gitlab['registry']['enable']
Gitlab['gitlab_rails']['registry_path'] = "#{Gitlab['gitlab_rails']['shared_path']}/registry" if Gitlab['gitlab_rails']['registry_path'].nil?
Gitlab['registry']['storage_delete_enabled'] = true if Gitlab['registry']['storage_delete_enabled'].nil?
Gitlab['registry']['health_storagedriver_enabled'] = true if Gitlab['registry']['health_storagedriver_enabled'].nil?
Gitlab['registry']['storage'] ||= {
'filesystem' => { 'rootdirectory' => Gitlab['gitlab_rails']['registry_path'] }
}
Gitlab['registry']['storage']['cache'] ||= { 'blobdescriptor' => 'inmemory' }
Gitlab['registry']['storage']['delete'] ||= { 'enabled' => Gitlab['registry']['storage_delete_enabled'] }
end
def parse_registry_notifications
return unless Gitlab['registry']['notifications']
user_configuration = Gitlab['registry']
gitlab_configuration = Gitlab['node']['registry']
# Use the registry defaults configured by the user but use the defaults from gitlab if they were not set
user_configuration['default_notifications_timeout'] ||= gitlab_configuration['default_notifications_timeout']
user_configuration['default_notifications_threshold'] ||= gitlab_configuration['default_notifications_threshold']
user_configuration['default_notifications_maxretries'] ||= gitlab_configuration['default_notifications_maxretries']
user_configuration['default_notifications_backoff'] ||= gitlab_configuration['default_notifications_backoff']
user_configuration['default_notifications_headers'] ||= gitlab_configuration['default_notifications_headers']
Gitlab['registry']['notifications'].each do |endpoint|
# Get the values from default if they are not set
endpoint['timeout'] ||= user_configuration['default_notifications_timeout']
endpoint['threshold'] ||= user_configuration['default_notifications_threshold']
endpoint['maxretries'] ||= user_configuration['default_notifications_maxretries']
endpoint['backoff'] ||= user_configuration['default_notifications_backoff']
# And merge the default headers with the ones specific to this endpoint
endpoint['headers'] = user_configuration['default_notifications_headers'].merge(endpoint['headers'] || {})
# As we set notification secret in gitlab.rb for registry we don't have to make user
# fill it in separately for GitLab application
Gitlab['gitlab_rails']['registry_notification_secret'] ||= endpoint['headers']['Authorization'].last if endpoint['name'] == 'geo_event'
end
end
def generate_registry_keypair
key, cert = SecretsHelper.generate_keypair(
bits: 4096,
subject: "/C=USA/O=GitLab/OU=Container/CN=Registry",
validity: 365 * 10 # ten years from now
)
[cert.to_pem, key.to_pem]
end
end
end