diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 18:14:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-24 18:14:19 +0300 |
commit | b8d516a6876de74b68a800c5b69af9448b0de140 (patch) | |
tree | 3a56c8af8b36d03c20e9de4298f30b08cba0ea5a /app/controllers | |
parent | 77b8390171a55d4593e3730551751d8348992f80 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/controllers')
5 files changed, 144 insertions, 36 deletions
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index 32de9e69c85..15a261f572a 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -280,7 +280,10 @@ class Clusters::ClustersController < Clusters::BaseController end def generate_gcp_authorize_url - state = generate_session_key_redirect(clusterable.new_path(provider: :gcp).to_s) + new_path = clusterable.new_path(provider: :gcp).to_s + error_path = @project ? project_clusters_path(@project) : new_path + + state = generate_session_key_redirect(new_path, error_path) @authorize_url = GoogleApi::CloudPlatform::Client.new( nil, callback_google_api_auth_url, @@ -339,9 +342,10 @@ class Clusters::ClustersController < Clusters::BaseController session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] end - def generate_session_key_redirect(uri) + def generate_session_key_redirect(uri, error_uri) GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key| session[key] = uri + session[:error_uri] = error_uri end end diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb index 76a1c43dfa3..b9c5e87c69c 100644 --- a/app/controllers/google_api/authorizations_controller.rb +++ b/app/controllers/google_api/authorizations_controller.rb @@ -8,19 +8,36 @@ module GoogleApi feature_category :kubernetes_management + ## + # handle the response from google after the user + # goes through authentication and authorization process def callback - token, expires_at = GoogleApi::CloudPlatform::Client - .new(nil, callback_google_api_auth_url) - .get_token(params[:code]) - - session[GoogleApi::CloudPlatform::Client.session_key_for_token] = token - session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] = - expires_at.to_s - + redirect_uri = redirect_uri_from_session + ## + # when the user declines authorizations + # `error` param is returned + if params[:error] + flash[:alert] = _('Google Cloud authorizations required') + redirect_uri = session[:error_uri] + ## + # on success, the `code` param is returned + elsif params[:code] + token, expires_at = GoogleApi::CloudPlatform::Client + .new(nil, callback_google_api_auth_url) + .get_token(params[:code]) + + session[GoogleApi::CloudPlatform::Client.session_key_for_token] = token + session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] = expires_at.to_s + redirect_uri = redirect_uri_from_session + end + ## + # or google may just timeout rescue ::Faraday::TimeoutError, ::Faraday::ConnectionFailed flash[:alert] = _('Timeout connecting to the Google API. Please try again.') + ## + # regardless, we redirect the user appropriately ensure - redirect_to redirect_uri_from_session + redirect_to redirect_uri end private diff --git a/app/controllers/projects/google_cloud/base_controller.rb b/app/controllers/projects/google_cloud/base_controller.rb new file mode 100644 index 00000000000..2a9e89a445b --- /dev/null +++ b/app/controllers/projects/google_cloud/base_controller.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class Projects::GoogleCloud::BaseController < Projects::ApplicationController + feature_category :google_cloud + + before_action :admin_project_google_cloud! + before_action :google_oauth2_enabled! + before_action :feature_flag_enabled! + + private + + def admin_project_google_cloud! + access_denied! unless can?(current_user, :admin_project_google_cloud, project) + end + + def google_oauth2_enabled! + config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2') + if config.app_id.blank? || config.app_secret.blank? + access_denied! 'This GitLab instance not configured for Google Oauth2.' + end + end + + def feature_flag_enabled! + access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud) + end +end diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb new file mode 100644 index 00000000000..21b096a6c66 --- /dev/null +++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::BaseController + before_action :validate_gcp_token! + + def index + @google_cloud_path = project_google_cloud_index_path(project) + google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil) + gcp_projects = google_api_client.list_projects + + if gcp_projects.empty? + @js_data = {}.to_json + render status: :unauthorized, template: 'projects/google_cloud/errors/no_gcp_projects' + else + @js_data = { + gcpProjects: gcp_projects, + environments: project.environments, + cancelPath: project_google_cloud_index_path(project) + }.to_json + end + rescue Google::Apis::ClientError => error + handle_gcp_error(error, project) + end + + def create + google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil) + service_accounts_service = GoogleCloud::ServiceAccountsService.new(project) + gcp_project = params[:gcp_project] + environment = params[:environment] + generated_name = "GitLab :: #{@project.name} :: #{environment}" + generated_desc = "GitLab generated service account for project '#{@project.name}' and environment '#{environment}'" + + service_account = google_api_client.create_service_account(gcp_project, generated_name, generated_desc) + service_account_key = google_api_client.create_service_account_key(gcp_project, service_account.unique_id) + + service_accounts_service.add_for_project( + environment, + service_account.project_id, + service_account.to_json, + service_account_key.to_json + ) + + redirect_to project_google_cloud_index_path(project), notice: _('Service account generated successfully') + rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error + handle_gcp_error(error, project) + end + + private + + def validate_gcp_token! + is_token_valid = GoogleApi::CloudPlatform::Client.new(token_in_session, nil) + .validate_token(expires_at_in_session) + + return if is_token_valid + + return_url = project_google_cloud_service_accounts_path(project) + state = generate_session_key_redirect(request.url, return_url) + @authorize_url = GoogleApi::CloudPlatform::Client.new(nil, + callback_google_api_auth_url, + state: state).authorize_url + redirect_to @authorize_url + end + + def generate_session_key_redirect(uri, error_uri) + GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key| + session[key] = uri + session[:error_uri] = error_uri + end + end + + def token_in_session + session[GoogleApi::CloudPlatform::Client.session_key_for_token] + end + + def expires_at_in_session + session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] + end + + def handle_gcp_error(error, project) + Gitlab::ErrorTracking.track_exception(error, project_id: project.id) + @js_data = { error: error.to_s }.to_json + render status: :unauthorized, template: 'projects/google_cloud/errors/gcp_error' + end +end diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb index 7257ed1ef6f..6cc67391d6c 100644 --- a/app/controllers/projects/google_cloud_controller.rb +++ b/app/controllers/projects/google_cloud_controller.rb @@ -1,34 +1,11 @@ # frozen_string_literal: true -class Projects::GoogleCloudController < Projects::ApplicationController - feature_category :google_cloud - - before_action :admin_project_google_cloud? - before_action :google_oauth2_enabled? - before_action :feature_flag_enabled? - +class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController def index @js_data = { serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project, - createServiceAccountUrl: '#mocked-url-create-service', + createServiceAccountUrl: project_google_cloud_service_accounts_path(project), emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg') }.to_json end - - private - - def admin_project_google_cloud? - access_denied! unless can?(current_user, :admin_project_google_cloud, project) - end - - def google_oauth2_enabled? - config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2') - if config.app_id.blank? || config.app_secret.blank? - access_denied! 'This GitLab instance not configured for Google Oauth2.' - end - end - - def feature_flag_enabled? - access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud) - end end |