omnibus-gitlab/files/gitlab-cookbooks/gitlab-pages/libraries/gitlab_pages.rb

174 lines
7.5 KiB
Ruby

#
# 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 '../../gitlab/libraries/helpers/authorizer_helper'
require_relative '../../package/libraries/helpers/shell_out_helper'
require_relative '../../package/libraries/helpers/logging_helper'
module GitlabPages
class << self
include ShellOutHelper
include AuthorizeHelper
def parse_variables
parse_pages_external_url
parse_gitlab_pages_daemon
# Only call parse_secrets when not generating a defaults secrets file.
parse_secrets unless Gitlab['node'][SecretsHelper::SECRETS_FILE_CHEF_ATTR]
parse_automatic_oauth_registration
parse_namespace_in_path
end
def parse_pages_external_url
return unless Gitlab['pages_external_url']
Gitlab['gitlab_rails']['pages_enabled'] = true if Gitlab['gitlab_rails']['pages_enabled'].nil?
Gitlab['gitlab_pages']['enable'] = true if Gitlab['gitlab_pages']['enable'].nil?
uri = URI(Gitlab['pages_external_url'].to_s)
raise "GitLab Pages external URL must include a schema and FQDN, e.g. http://pages.example.com/" unless uri.host
Gitlab['gitlab_rails']['pages_host'] = uri.host
Gitlab['gitlab_rails']['pages_port'] = uri.port
case uri.scheme
when "http"
Gitlab['gitlab_rails']['pages_https'] = false
Nginx.parse_proxy_headers('pages_nginx', false)
when "https"
Gitlab['gitlab_rails']['pages_https'] = true
Gitlab['pages_nginx']['ssl_certificate'] ||= "/etc/gitlab/ssl/#{uri.host}.crt"
Gitlab['pages_nginx']['ssl_certificate_key'] ||= "/etc/gitlab/ssl/#{uri.host}.key"
Nginx.parse_proxy_headers('pages_nginx', true)
else
raise "Unsupported GitLab Pages external URL scheme: #{uri.scheme}"
end
raise "Unsupported GitLab Pages external URL path: #{uri.path}" unless ["", "/"].include?(uri.path)
# FQDN are prepared to be used as regexp: the dot is escaped
Gitlab['pages_nginx']['fqdn_regex'] = uri.host.gsub('.', '\.')
end
def parse_gitlab_pages_daemon
return unless Gitlab['gitlab_pages']['enable']
Gitlab['gitlab_pages']['domain'] = Gitlab['gitlab_rails']['pages_host']
if Gitlab['gitlab_pages']['external_https'] || Gitlab['gitlab_pages']['external_https_proxyv2']
Gitlab['gitlab_pages']['cert'] ||= "/etc/gitlab/ssl/#{Gitlab['gitlab_pages']['domain']}.crt"
Gitlab['gitlab_pages']['cert_key'] ||= "/etc/gitlab/ssl/#{Gitlab['gitlab_pages']['domain']}.key"
end
Gitlab['gitlab_pages']['pages_root'] ||= (Gitlab['gitlab_rails']['pages_path'] || File.join(Gitlab['gitlab_rails']['shared_path'], 'pages'))
Gitlab['gitlab_pages']['gitlab_server'] ||= Gitlab['external_url']
Gitlab['gitlab_pages']['artifacts_server_url'] ||= Gitlab['gitlab_pages']['gitlab_server'].chomp('/') + '/api/v4'
parse_auth_redirect_uri
end
def parse_auth_redirect_uri
return unless Gitlab['gitlab_pages']['access_control']
return if Gitlab['gitlab_pages']['auth_redirect_uri']
pages_uri = URI(Gitlab['pages_external_url'].to_s)
parsed_port = [80, 443].include?(pages_uri.port) ? "" : ":#{pages_uri.port}"
Gitlab['gitlab_pages']['auth_redirect_uri'] = if Gitlab['gitlab_pages']['namespace_in_path']
"#{pages_uri.scheme}://#{pages_uri.host}#{parsed_port}/projects/auth"
else
"#{pages_uri.scheme}://projects.#{pages_uri.host}#{parsed_port}/auth"
end
end
def authorize_with_gitlab
redirect_uri = Gitlab['gitlab_pages']['auth_redirect_uri']
app_name = 'GitLab Pages'
oauth_uid = Gitlab['gitlab_pages']['gitlab_id']
oauth_secret = Gitlab['gitlab_pages']['gitlab_secret']
o = query_gitlab_rails(redirect_uri, app_name, oauth_uid, oauth_secret)
if o.exitstatus.zero?
Gitlab['gitlab_pages']['register_as_oauth_app'] = false
SecretsHelper.write_to_gitlab_secrets
info('Updated the gitlab-secrets.json file.')
else
warn('Something went wrong while executing gitlab-rails runner command to get or create the app ID and secret.')
end
end
def parse_secrets
Gitlab['gitlab_pages']['auth_secret'] ||= SecretsHelper.generate_hex(64) if Gitlab['gitlab_pages']['access_control']
Gitlab['gitlab_pages']['gitlab_id'] ||= SecretsHelper.generate_urlsafe_base64
Gitlab['gitlab_pages']['gitlab_secret'] ||= SecretsHelper.generate_urlsafe_base64
Gitlab['gitlab_pages']['api_secret_key'] ||= Base64.strict_encode64(SecureRandom.random_bytes(32))
end
def validate_secrets
return unless Gitlab['gitlab_pages']['api_secret_key']
# Pages and GitLab expects exactly 32 bytes, encoded with base64
bytes = Base64.strict_decode64(Gitlab['gitlab_pages']['api_secret_key'])
raise "gitlab_pages['api_secret_key'] should be exactly 32 bytes" if bytes.length != 32
end
def parse_automatic_oauth_registration
# If GitLab Pages isn't enabled, do nothing.
return unless Gitlab['gitlab_pages']['enable']
# If writing to gitlab-secrets.json file is not explicitly disabled, do
# nothing.
return if Gitlab['package']['generate_secrets_json_file'] != false
Gitlab['gitlab_pages']['register_as_oauth_app'] = false
LoggingHelper.warning("Writing secrets to `gitlab-secrets.json` file is disabled. Hence, not automatically registering GitLab Pages as an Oauth App. So, GitLab SSO will not be available as a login option.")
end
def parse_namespace_in_path
# If GitLab Pages isn't enabled or namespace_in_path is isn't enabled, do nothing.
return unless Gitlab['gitlab_pages']['enable'] && Gitlab['gitlab_pages']['namespace_in_path']
Gitlab['pages_nginx']['namespace_in_path'] = Gitlab['gitlab_pages']['namespace_in_path']
url_scheme = Gitlab['gitlab_rails']['pages_https'] ? 'https' : 'http'
pages_port = Gitlab['gitlab_rails']['pages_port']
redirect_uri = Gitlab['gitlab_pages']['auth_redirect_uri'].gsub('.', '\.')
# Add the following when pages_port is not 80 or 443
Gitlab['pages_nginx']['proxy_redirect'] =
if [80, 443].include?(pages_port)
{
"~^(#{redirect_uri})(.*)$" => "$1$2",
"~^#{url_scheme}://([^/]*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']})/(.*)$" => "#{url_scheme}://$2/$1/$3",
"~^//([^/]*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']})/(.*)$" => "/$1/$3",
"~^/(.*)$" => "/$namespace/$1",
}
else
{
"~^(#{redirect_uri})(.*)$" => "$1$2",
"~^#{url_scheme}://([^/]*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']}:#{pages_port})/(.*)$" => "#{url_scheme}://$2/$1/$3",
"~^//([^/]*)\\.(#{Gitlab['pages_nginx']['fqdn_regex']}:#{pages_port})/(.*)$" => "/$1/$3",
"~^/(.*)$" => "/$namespace/$1",
}
end
end
end
end