1# frozen_string_literal: true
2
3module Clusters
4  module Aws
5    class FetchCredentialsService
6      attr_reader :provision_role
7
8      MissingRoleError = Class.new(StandardError)
9
10      def initialize(provision_role, provider: nil)
11        @provision_role = provision_role
12        @provider = provider
13        @region = provider&.region || provision_role&.region || Clusters::Providers::Aws::DEFAULT_REGION
14      end
15
16      def execute
17        raise MissingRoleError, 'AWS provisioning role not configured' unless provision_role.present?
18
19        ::Aws::AssumeRoleCredentials.new(
20          client: client,
21          role_arn: provision_role.role_arn,
22          role_session_name: session_name,
23          external_id: provision_role.role_external_id,
24          policy: session_policy
25        ).credentials
26      end
27
28      private
29
30      attr_reader :provider, :region
31
32      def client
33        ::Aws::STS::Client.new(**client_args)
34      end
35
36      def client_args
37        { region: region, credentials: gitlab_credentials }.compact
38      end
39
40      def gitlab_credentials
41        # These are not needed for IAM instance profiles
42        return unless access_key_id.present? && secret_access_key.present?
43
44        ::Aws::Credentials.new(access_key_id, secret_access_key)
45      end
46
47      def access_key_id
48        Gitlab::CurrentSettings.eks_access_key_id
49      end
50
51      def secret_access_key
52        Gitlab::CurrentSettings.eks_secret_access_key
53      end
54
55      ##
56      # If we haven't created a provider record yet,
57      # we restrict ourselves to read-only access so
58      # that we can safely expose credentials to the
59      # frontend (to be used when populating the
60      # creation form).
61      def session_policy
62        if provider.nil?
63          File.read(read_only_policy)
64        end
65      end
66
67      def read_only_policy
68        Rails.root.join('vendor', 'aws', 'iam', "eks_cluster_read_only_policy.json")
69      end
70
71      def session_name
72        if provider.present?
73          "gitlab-eks-cluster-#{provider.cluster_id}-user-#{provision_role.user_id}"
74        else
75          "gitlab-eks-autofill-user-#{provision_role.user_id}"
76        end
77      end
78    end
79  end
80end
81