From 3c2b4a1cede956d5160ccf08d0a561bf31248161 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Mon, 22 Jul 2019 16:56:40 +0200 Subject: Enable serving static objects from an external storage It consists of two parts: 1. Redirecting users to the configured external storage 1. Allowing the external storage to request the static object(s) on behalf of the user by means of specific tokens Part of https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/6829 --- .../concerns/sessionless_authentication.rb | 4 ++-- .../concerns/static_object_external_storage.rb | 24 ++++++++++++++++++++++ app/controllers/profiles_controller.rb | 9 ++++++++ .../projects/repositories_controller.rb | 4 ++++ 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 app/controllers/concerns/static_object_external_storage.rb (limited to 'app/controllers') diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb index 4304b8565ce..ba06384a37a 100644 --- a/app/controllers/concerns/sessionless_authentication.rb +++ b/app/controllers/concerns/sessionless_authentication.rb @@ -2,10 +2,10 @@ # == SessionlessAuthentication # -# Controller concern to handle PAT and RSS token authentication methods +# Controller concern to handle PAT, RSS, and static objects token authentication methods # module SessionlessAuthentication - # This filter handles personal access tokens, and atom requests with rss tokens + # This filter handles personal access tokens, atom requests with rss tokens, and static object tokens def authenticate_sessionless_user!(request_format) user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user(request_format) diff --git a/app/controllers/concerns/static_object_external_storage.rb b/app/controllers/concerns/static_object_external_storage.rb new file mode 100644 index 00000000000..dbfe0ed3adf --- /dev/null +++ b/app/controllers/concerns/static_object_external_storage.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module StaticObjectExternalStorage + extend ActiveSupport::Concern + + included do + include ApplicationHelper + end + + def redirect_to_external_storage + return if external_storage_request? + + redirect_to external_storage_url_or_path(request.fullpath, project) + end + + def external_storage_request? + header_token = request.headers['X-Gitlab-External-Storage-Token'] + return false unless header_token.present? + + external_storage_token = Gitlab::CurrentSettings.static_objects_external_storage_auth_token + ActiveSupport::SecurityUtils.secure_compare(header_token, external_storage_token) || + raise(Gitlab::Access::AccessDeniedError) + end +end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 1d16ddb1608..958a24b6c0e 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -46,6 +46,15 @@ class ProfilesController < Profiles::ApplicationController redirect_to profile_personal_access_tokens_path end + def reset_static_object_token + Users::UpdateService.new(current_user, user: @user).execute! do |user| + user.reset_static_object_token! + end + + redirect_to profile_personal_access_tokens_path, + notice: s_('Profiles|Static object token was successfully reset') + end + # rubocop: disable CodeReuse/ActiveRecord def audit_log @events = AuditEvent.where(entity_type: "User", entity_id: current_user.id) diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb index a51759641e4..d69f9e65874 100644 --- a/app/controllers/projects/repositories_controller.rb +++ b/app/controllers/projects/repositories_controller.rb @@ -2,6 +2,9 @@ class Projects::RepositoriesController < Projects::ApplicationController include ExtractsPath + include StaticObjectExternalStorage + + prepend_before_action(only: [:archive]) { authenticate_sessionless_user!(:archive) } # Authorize before_action :require_non_empty_project, except: :create @@ -9,6 +12,7 @@ class Projects::RepositoriesController < Projects::ApplicationController before_action :assign_append_sha, only: :archive before_action :authorize_download_code! before_action :authorize_admin_project!, only: :create + before_action :redirect_to_external_storage, only: :archive, if: :static_objects_external_storage_enabled? def create @project.create_repository -- cgit v1.2.3