diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-13 09:06:38 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-13 09:06:38 +0300 |
commit | 213ce7805856f2cc1d019a03c76ae0d098337c26 (patch) | |
tree | e97e9e02515dd83a2a5decd66ae8553ebb93b350 /app/services/clusters | |
parent | d41c040fa25a8b4092843b84bf7d839591b6ee09 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services/clusters')
-rw-r--r-- | app/services/clusters/aws/fetch_credentials_service.rb | 18 | ||||
-rw-r--r-- | app/services/clusters/aws/provision_service.rb | 12 | ||||
-rw-r--r-- | app/services/clusters/aws/proxy_service.rb | 134 |
3 files changed, 155 insertions, 9 deletions
diff --git a/app/services/clusters/aws/fetch_credentials_service.rb b/app/services/clusters/aws/fetch_credentials_service.rb index 29442208c62..2724d4b657b 100644 --- a/app/services/clusters/aws/fetch_credentials_service.rb +++ b/app/services/clusters/aws/fetch_credentials_service.rb @@ -3,11 +3,13 @@ module Clusters module Aws class FetchCredentialsService - attr_reader :provider + attr_reader :provision_role MissingRoleError = Class.new(StandardError) - def initialize(provider) + def initialize(provision_role, region:, provider: nil) + @provision_role = provision_role + @region = region @provider = provider end @@ -24,12 +26,10 @@ module Clusters private - def provision_role - provider.created_by_user.aws_role - end + attr_reader :provider, :region def client - ::Aws::STS::Client.new(credentials: gitlab_credentials, region: provider.region) + ::Aws::STS::Client.new(credentials: gitlab_credentials, region: region) end def gitlab_credentials @@ -45,7 +45,11 @@ module Clusters end def session_name - "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provider.created_by_user_id}" + if provider.present? + "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provision_role.user_id}" + else + "gitlab-eks-autofill-user-#{provision_role.user_id}" + end end end end diff --git a/app/services/clusters/aws/provision_service.rb b/app/services/clusters/aws/provision_service.rb index 6a3b0dffae2..35fe8433b4d 100644 --- a/app/services/clusters/aws/provision_service.rb +++ b/app/services/clusters/aws/provision_service.rb @@ -21,7 +21,7 @@ module Clusters end rescue Clusters::Aws::FetchCredentialsService::MissingRoleError provider.make_errored!('Amazon role is not configured') - rescue ::Aws::Errors::MissingCredentialsError, Settingslogic::MissingSetting + rescue ::Aws::Errors::MissingCredentialsError provider.make_errored!('Amazon credentials are not configured') rescue ::Aws::STS::Errors::ServiceError => e provider.make_errored!("Amazon authentication failed; #{e.message}") @@ -31,8 +31,16 @@ module Clusters private + def provision_role + provider.created_by_user&.aws_role + end + def credentials - @credentials ||= Clusters::Aws::FetchCredentialsService.new(provider).execute + @credentials ||= Clusters::Aws::FetchCredentialsService.new( + provision_role, + provider: provider, + region: provider.region + ).execute end def configure_provider_credentials diff --git a/app/services/clusters/aws/proxy_service.rb b/app/services/clusters/aws/proxy_service.rb new file mode 100644 index 00000000000..df8fc480005 --- /dev/null +++ b/app/services/clusters/aws/proxy_service.rb @@ -0,0 +1,134 @@ +# frozen_string_literal: true + +module Clusters + module Aws + class ProxyService + DEFAULT_REGION = 'us-east-1' + + BadRequest = Class.new(StandardError) + Response = Struct.new(:status, :body) + + def initialize(role, params:) + @role = role + @params = params + end + + def execute + api_response = request_from_api! + + Response.new(:ok, api_response.to_hash) + rescue *service_errors + Response.new(:bad_request, {}) + end + + private + + attr_reader :role, :params + + def request_from_api! + case requested_resource + when 'key_pairs' + ec2_client.describe_key_pairs + + when 'instance_types' + instance_types + + when 'roles' + iam_client.list_roles + + when 'regions' + ec2_client.describe_regions + + when 'security_groups' + raise BadRequest unless vpc_id.present? + + ec2_client.describe_security_groups(vpc_filter) + + when 'subnets' + raise BadRequest unless vpc_id.present? + + ec2_client.describe_subnets(vpc_filter) + + when 'vpcs' + ec2_client.describe_vpcs + + else + raise BadRequest + end + end + + def requested_resource + params[:resource] + end + + def vpc_id + params[:vpc_id] + end + + def region + params[:region] || DEFAULT_REGION + end + + def vpc_filter + { + filters: [{ + name: "vpc-id", + values: [vpc_id] + }] + } + end + + ## + # Unfortunately the EC2 API doesn't provide a list of + # possible instance types. There is a workaround, using + # the Pricing API, but instead of requiring the + # user to grant extra permissions for this we use the + # values that validate the CloudFormation template. + def instance_types + { + instance_types: cluster_stack_instance_types.map { |type| Hash(instance_type_name: type) } + } + end + + def cluster_stack_instance_types + YAML.safe_load(stack_template).dig('Parameters', 'NodeInstanceType', 'AllowedValues') + end + + def stack_template + File.read(Rails.root.join('vendor', 'aws', 'cloudformation', 'eks_cluster.yaml')) + end + + def ec2_client + ::Aws::EC2::Client.new(client_options) + end + + def iam_client + ::Aws::IAM::Client.new(client_options) + end + + def credentials + Clusters::Aws::FetchCredentialsService.new(role, region: region).execute + end + + def client_options + { + credentials: credentials, + region: region, + http_open_timeout: 5, + http_read_timeout: 10 + } + end + + def service_errors + [ + BadRequest, + Clusters::Aws::FetchCredentialsService::MissingRoleError, + ::Aws::Errors::MissingCredentialsError, + ::Aws::EC2::Errors::ServiceError, + ::Aws::IAM::Errors::ServiceError, + ::Aws::STS::Errors::ServiceError + ] + end + end + end +end |