# # 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 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' Gitlab['pages_nginx']['namespace_in_path'] = Gitlab['gitlab_pages']['namespace_in_path'] if Gitlab['gitlab_pages']['namespace_in_path'] 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 end end