Skip to content

Commit 2087558

Browse files
committed
Add IRSA injection
1 parent f949e87 commit 2087558

File tree

3 files changed

+109
-2
lines changed

3 files changed

+109
-2
lines changed

charts/k8s-service/templates/deployment.yaml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ Similarly, we need to decide whether or not there are environment variables to a
1313
We need this because certain sections are omitted if there are no volumes or environment variables to add.
1414
*/ -}}
1515
{{/* Go Templates do not support variable updating, so we simulate it using dictionaries */}}
16-
{{- $hasInjectionTypes := dict "hasVolume" false "hasEnvVars" false -}}
16+
{{- $hasInjectionTypes := dict "hasVolume" false "hasEnvVars" false "hasIRSA" false -}}
1717
{{- if .Values.envVars -}}
1818
{{- $_ := set $hasInjectionTypes "hasEnvVars" true -}}
1919
{{- end -}}
20+
{{- if gt (len .Values.aws.irsa.role_arn) 0 -}}
21+
{{- $_ := set $hasInjectionTypes "hasEnvVars" true -}}
22+
{{- $_ := set $hasInjectionTypes "hasVolume" true -}}
23+
{{- $_ := set $hasInjectionTypes "hasIRSA" true -}}
24+
{{- end -}}
2025
{{- $allSecrets := values .Values.secrets -}}
2126
{{- range $allSecrets -}}
2227
{{- if eq (index . "as") "volume" -}}
@@ -163,6 +168,12 @@ spec:
163168
{{- if index $hasInjectionTypes "hasEnvVars" }}
164169
env:
165170
{{- end }}
171+
{{- if index $hasInjectionTypes "hasIRSA" }}
172+
- name: AWS_ROLE_ARN
173+
value: "{{ .Values.aws.irsa.role_arn }}"
174+
- name: AWS_WEB_IDENTITY_TOKEN_FILE
175+
value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
176+
{{- end }}
166177
{{- range $key, $value := .Values.envVars }}
167178
- name: {{ $key }}
168179
value: {{ quote $value }}
@@ -195,6 +206,11 @@ spec:
195206
{{- if index $hasInjectionTypes "hasVolume" }}
196207
volumeMounts:
197208
{{- end }}
209+
{{- if index $hasInjectionTypes "hasIRSA" }}
210+
- name: aws-iam-token
211+
mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
212+
readOnly: true
213+
{{- end }}
198214
{{- range $name, $value := .Values.configMaps }}
199215
{{- if eq $value.as "volume" }}
200216
- name: {{ $name }}-volume
@@ -227,6 +243,16 @@ spec:
227243
{{- if index $hasInjectionTypes "hasVolume" }}
228244
volumes:
229245
{{- end }}
246+
{{- if index $hasInjectionTypes "hasIRSA" }}
247+
- name: aws-iam-token
248+
projected:
249+
defaultMode: 420
250+
sources:
251+
- serviceAccountToken:
252+
audience: sts.amazonaws.com
253+
expirationSeconds: 86400
254+
path: token
255+
{{- end }}
230256
{{- range $name, $value := .Values.configMaps }}
231257
{{- if eq $value.as "volume" }}
232258
- name: {{ $name }}-volume

charts/k8s-service/values.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,35 @@ tolerations: []
359359
# list is a string that corresponds to the Secret name.
360360
imagePullSecrets: []
361361

362+
#----------------------------------------------------------------------------------------------------------------------
363+
# AWS SPECIFIC VALUES
364+
# These input values relate to AWS specific features, such as those relating to EKS and the AWS ALB Ingress Controller.
365+
#----------------------------------------------------------------------------------------------------------------------
366+
aws:
367+
# irsa can be used to configure the projected tokens used in the IAM Roles for Service Accounts feature. This is
368+
# useful if you are manually annotating the projected tokens into your Pods, instead of relying on the mutating
369+
# admission hook.
370+
#
371+
# irsa is a map and expects the following keys:
372+
# - role_arn (string) (required) : The AWS ARN that the Service Account associated with the Pod should assume.
373+
# Note that the projected token will not be mounted and the environment
374+
# variables will not be set if this is an empty string (the default).
375+
#
376+
# Note that you can not use any role with the IRSA feature. It must have the proper assume role IAM policy to allow
377+
# the Service Account of the Pod to assume that role. See
378+
# https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html for more
379+
# information.
380+
#
381+
# EXAMPLE:
382+
#
383+
# aws:
384+
# irsa:
385+
# role_arn: "arn:aws:iam::123456789012:role/role-for-pod"
386+
#
387+
irsa:
388+
role_arn: ""
389+
390+
362391
#----------------------------------------------------------------------------------------------------------------------
363392
# GOOGLE SPECIFIC VALUES
364393
# google specifies Google (GKE) specific configuration to be set via arguments/env. variables

test/k8s_service_template_test.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func TestK8SServiceSecurityContextAnnotationRenderCorrectly(t *testing.T) {
142142
t,
143143
map[string]string{
144144
"securityContext.privileged": "true",
145-
"securityContext.runAsUser": "1000",
145+
"securityContext.runAsUser": "1000",
146146
},
147147
)
148148
renderedContainers := deployment.Spec.Template.Spec.Containers
@@ -524,6 +524,58 @@ func TestK8SServiceWithContainerCommandHasCommandSpec(t *testing.T) {
524524
assert.Equal(t, appContainer.Command, []string{"echo", "Hello world"})
525525
}
526526

527+
// Test that omitting aws.irsa.role_arn does not render the IRSA vars
528+
func TestK8SServiceWithoutIRSA(t *testing.T) {
529+
t.Parallel()
530+
531+
deployment := renderK8SServiceDeploymentWithSetValues(
532+
t,
533+
map[string]string{},
534+
)
535+
renderedPodSpec := deployment.Spec.Template.Spec
536+
assert.Equal(t, len(renderedPodSpec.Volumes), 0)
537+
renderedPodContainers := renderedPodSpec.Containers
538+
require.Equal(t, len(renderedPodContainers), 1)
539+
appContainer := renderedPodContainers[0]
540+
assert.Equal(t, len(appContainer.Env), 0)
541+
}
542+
543+
// Test that setting aws.irsa.role_arn renders the IRSA vars
544+
func TestK8SServiceWithIRSA(t *testing.T) {
545+
t.Parallel()
546+
547+
testRoleArn := "arn:aws:iam::123456789012:role/test-role"
548+
deployment := renderK8SServiceDeploymentWithSetValues(
549+
t,
550+
map[string]string{
551+
"aws.irsa.role_arn": testRoleArn,
552+
},
553+
)
554+
renderedPodSpec := deployment.Spec.Template.Spec
555+
556+
// Verify projected volume
557+
require.Equal(t, len(renderedPodSpec.Volumes), 1)
558+
volume := renderedPodSpec.Volumes[0]
559+
assert.Equal(t, volume.Name, "aws-iam-token")
560+
require.NotNil(t, volume.VolumeSource.Projected)
561+
projectedVolume := volume.VolumeSource.Projected
562+
require.Equal(t, len(projectedVolume.Sources), 1)
563+
projectedVolumeSource := projectedVolume.Sources[0]
564+
require.NotNil(t, projectedVolumeSource.ServiceAccountToken)
565+
assert.Equal(t, projectedVolumeSource.ServiceAccountToken.Audience, "sts.amazonaws.com")
566+
567+
// Verify injected env vars
568+
renderedPodContainers := renderedPodSpec.Containers
569+
require.Equal(t, len(renderedPodContainers), 1)
570+
appContainer := renderedPodContainers[0]
571+
assert.Equal(t, len(appContainer.Env), 2)
572+
roleArnEnv := appContainer.Env[0]
573+
assert.Equal(t, roleArnEnv.Name, "AWS_ROLE_ARN")
574+
assert.Equal(t, roleArnEnv.Value, testRoleArn)
575+
tokenEnv := appContainer.Env[1]
576+
assert.Equal(t, tokenEnv.Name, "AWS_WEB_IDENTITY_TOKEN_FILE")
577+
assert.Equal(t, tokenEnv.Value, "/var/run/secrets/eks.amazonaws.com/serviceaccount/token")
578+
}
527579

528580
// Test that providing tls configuration to Ingress renders correctly
529581
func TestK8SServiceIngressMultiCert(t *testing.T) {

0 commit comments

Comments
 (0)