Class: KubesAws::IamRole

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Includes:
Prebaked, Logging, Services
Defined in:
lib/kubes_aws/iam_role.rb,
lib/kubes_aws/iam_role/prebaked.rb

Defined Under Namespace

Modules: Prebaked

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Prebaked

#prebaked_policies, #secrets_read_only

Methods included from Logging

#logger

Methods included from Services

#eks, #iam, #secrets, #ssm

Constructor Details

#initialize(app:, cluster: nil, namespace: nil, managed_policies: [], inline_policies: [], role_name: nil, ksa: nil) ⇒ IamRole

Returns a new instance of IamRole.



14
15
16
17
18
19
20
21
22
# File 'lib/kubes_aws/iam_role.rb', line 14

def initialize(app:, cluster:nil, namespace:nil, managed_policies: [], inline_policies: [], role_name: nil, ksa: nil)
  @app, @cluster, @managed_policies, @inline_policies = app, cluster, managed_policies, inline_policies

  # conventional names
  @ksa = ksa || @app                               # convention: app
  @namespace = namespace || "#{@app}-#{Kubes.env}" # convention: app-env
  @role_name = role_name || "#{@app}-#{Kubes.env}" # convention: app-env
  @cluster ||= infer_cluster
end

Instance Attribute Details

#role_nameObject (readonly)

public method to keep: role_name



13
14
15
# File 'lib/kubes_aws/iam_role.rb', line 13

def role_name
  @role_name
end

Instance Method Details

#add_inline_policiesObject



49
50
51
52
53
54
# File 'lib/kubes_aws/iam_role.rb', line 49

def add_inline_policies
  @inline_policies.each do |policy|
    params = normalize_inline_policy(policy)
    iam.put_role_policy(params)
  end
end

#add_mananged_policiesObject



85
86
87
88
89
90
91
92
93
94
# File 'lib/kubes_aws/iam_role.rb', line 85

def add_mananged_policies
  @managed_policies.each do |policy|
    policy_arn = normalize_managed_policy(policy)
    iam.attach_role_policy(
      role_name: @role_name,
      policy_arn: policy_arn,
    )
  end
  logger.debug "IAM Policies added to #{@role_name}"
end

#arnObject

public method to keep: arn



113
114
115
# File 'lib/kubes_aws/iam_role.rb', line 113

def arn
  "arn:aws:iam::#{}:role/#{@role_name}"
end

#awsObject



152
153
154
# File 'lib/kubes_aws/iam_role.rb', line 152

def aws
  AwsData.new
end

#aws_accountObject

public method to keep: aws_account



118
119
120
# File 'lib/kubes_aws/iam_role.rb', line 118

def 
  aws.
end

#callObject



24
25
26
27
28
29
# File 'lib/kubes_aws/iam_role.rb', line 24

def call
  create_open_id_connect_provider
  create_iam_role
  add_mananged_policies
  add_inline_policies
end

#create_iam_roleObject



76
77
78
79
80
81
82
83
# File 'lib/kubes_aws/iam_role.rb', line 76

def create_iam_role
  return if role_exist?
  iam.create_role(
    role_name: @role_name,
    assume_role_policy_document: trust_policy,
  )
  logger.debug "Created IAM Role #{@role_name}"
end

#create_open_id_connect_providerObject



71
72
73
74
# File 'lib/kubes_aws/iam_role.rb', line 71

def create_open_id_connect_provider
  open_id = OpenId.new(@cluster)
  open_id.create_provider
end

#infer_clusterObject

Attempts to infer the EKS cluster name using kubectl



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/kubes_aws/iam_role.rb', line 32

def infer_cluster
  command = "kubectl config view --minify --output 'jsonpath={..contexts..context.cluster}'"
  out = `#{command}`
  success = $?.success?
  name = out.split('/').last
  if !success or name.blank?
    logger.error <<~EOL.color(:red)
      ERROR: unable to determine EKS cluster name. Please specify it in:

          KubesAws::IamRole.new

    EOL
    exit 1
  end
  name
end

#issuer_urlObject



146
147
148
149
# File 'lib/kubes_aws/iam_role.rb', line 146

def issuer_url
  resp = eks.describe_cluster(name: @cluster)
  resp.cluster.identity.oidc.issuer
end

#normalize_inline_policy(policy) ⇒ Object

resp = client.put_role_policy(

policy_document: "{\"Version\":\"2012-10-17\",\"Statement\":{\"Effect\":\"Allow\",\"Action\":\"s3:*\",\"Resource\":\"*\"}}",
policy_name: "S3AccessPolicy",
role_name: "S3Access",

)



61
62
63
64
65
66
67
68
69
# File 'lib/kubes_aws/iam_role.rb', line 61

def normalize_inline_policy(policy)
  prebaked = prebaked_policies[policy]
  policy = prebaked if prebaked

  policy_document = policy[:policy_document]
  policy[:policy_document] = JSON.dump(policy_document) if policy_document.is_a?(Hash)
  policy[:role_name] = @role_name
  policy
end

#normalize_managed_policy(policy) ⇒ Object

AmazonS3ReadOnlyAccess => arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess



97
98
99
100
101
102
103
# File 'lib/kubes_aws/iam_role.rb', line 97

def normalize_managed_policy(policy)
  if policy.include?("arn:")
    policy
  else
    "arn:aws:iam::aws:policy/#{policy}"
  end
end

#role_exist?Boolean

Returns:

  • (Boolean)


105
106
107
108
109
110
# File 'lib/kubes_aws/iam_role.rb', line 105

def role_exist?
  iam.get_role(role_name: @role_name)
  true
rescue Aws::IAM::Errors::NoSuchEntity
  false
end

#trust_policyObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/kubes_aws/iam_role.rb', line 122

def trust_policy
  issuer_host = issuer_url.sub('https://','')
  provider_arn = "arn:aws:iam::#{}:oidc-provider/#{issuer_host}"
  <<~JSON
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Federated": "#{provider_arn}"
        },
        "Action": "sts:AssumeRoleWithWebIdentity",
        "Condition": {
          "StringEquals": {
            "#{issuer_host}:sub": "system:serviceaccount:#{@namespace}:#{@ksa}"
          }
        }
      }
    ]
  }
  JSON
end