Don't add add IAM vars to manifest if service account is not being created

In the case IRSA is optional for an addon, we shouldn't unconditinally add the IRSA bits to the manifest.
This is also a clean up. We no longer need to expand the list of well-known SAs as we already know which roles are being built
This commit is contained in:
Ole Markus With 2022-09-04 08:28:32 +02:00
parent 3518182e44
commit 6548ca6ca7
14 changed files with 27 additions and 159 deletions

View File

@ -26,21 +26,12 @@ import (
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/kubemanifest"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/model/components/addonmanifests/awscloudcontrollermanager"
"k8s.io/kops/pkg/model/components/addonmanifests/awsebscsidriver"
"k8s.io/kops/pkg/model/components/addonmanifests/awsloadbalancercontroller"
"k8s.io/kops/pkg/model/components/addonmanifests/certmanager"
"k8s.io/kops/pkg/model/components/addonmanifests/clusterautoscaler"
"k8s.io/kops/pkg/model/components/addonmanifests/dnscontroller"
"k8s.io/kops/pkg/model/components/addonmanifests/externaldns"
"k8s.io/kops/pkg/model/components/addonmanifests/karpenter"
"k8s.io/kops/pkg/model/components/addonmanifests/kuberouter"
"k8s.io/kops/pkg/model/components/addonmanifests/nodeterminationhandler"
"k8s.io/kops/pkg/model/iam"
"k8s.io/kops/upup/pkg/fi"
)
func RemapAddonManifest(addon *addonsapi.AddonSpec, context *model.KopsModelContext, assetBuilder *assets.AssetBuilder, manifest []byte) ([]byte, error) {
func RemapAddonManifest(addon *addonsapi.AddonSpec, context *model.KopsModelContext, assetBuilder *assets.AssetBuilder, manifest []byte, serviceAccounts map[string]iam.Subject) ([]byte, error) {
name := fi.StringValue(addon.Name)
{
@ -60,7 +51,7 @@ func RemapAddonManifest(addon *addonsapi.AddonSpec, context *model.KopsModelCont
return nil, fmt.Errorf("failed to annotate %q: %w", name, err)
}
err = addServiceAccountRole(context, objects)
err = addServiceAccountRole(context, objects, serviceAccounts)
if err != nil {
return nil, fmt.Errorf("failed to add service account for %q: %w", name, err)
}
@ -83,7 +74,7 @@ func RemapAddonManifest(addon *addonsapi.AddonSpec, context *model.KopsModelCont
return manifest, nil
}
func addServiceAccountRole(context *model.KopsModelContext, objects kubemanifest.ObjectList) error {
func addServiceAccountRole(context *model.KopsModelContext, objects kubemanifest.ObjectList, serviceAccounts map[string]iam.Subject) error {
if !context.UseServiceAccountExternalPermissions() {
return nil
}
@ -98,7 +89,7 @@ func addServiceAccountRole(context *model.KopsModelContext, objects kubemanifest
return fmt.Errorf("failed to parse spec.template.spec from Deployment: %v", err)
}
sa := podSpec.ServiceAccountName
subject := getWellknownServiceAccount(sa)
subject := serviceAccounts[sa]
if subject == nil {
continue
}
@ -115,31 +106,6 @@ func addServiceAccountRole(context *model.KopsModelContext, objects kubemanifest
return nil
}
func getWellknownServiceAccount(name string) iam.Subject {
switch name {
case "aws-load-balancer-controller":
return &awsloadbalancercontroller.ServiceAccount{}
case "cluster-autoscaler":
return &clusterautoscaler.ServiceAccount{}
case "ebs-csi-controller-sa":
return &awsebscsidriver.ServiceAccount{}
case "aws-node-termination-handler":
return &nodeterminationhandler.ServiceAccount{}
case "aws-cloud-controller-manager":
return &awscloudcontrollermanager.ServiceAccount{}
case "external-dns":
return &externaldns.ServiceAccount{}
case "karpenter":
return &karpenter.ServiceAccount{}
case "kube-router":
return &kuberouter.ServiceAccount{}
case "cert-manager":
return &certmanager.ServiceAccount{}
default:
return nil
}
}
func addLabels(addon *addonsapi.AddonSpec, objects kubemanifest.ObjectList) error {
for _, object := range objects {
meta := &metav1.ObjectMeta{}

View File

@ -41,7 +41,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -48,7 +48,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -55,7 +55,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -55,7 +55,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -55,7 +55,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -48,7 +48,7 @@ spec:
version: 9.99.0
- id: k8s-1.16
manifest: certmanager.io/k8s-1.16.yaml
manifestHash: 60a0383cd2ee4081dc072ce69c0bae3d7f05ebcad91e0b141bfbee3e140200ef
manifestHash: 79bc70f8f9b7a91e97830ecaa8968a51e0c5b78318444cb5a44935e8f9f73aa1
name: certmanager.io
selector: null
version: 9.99.0

View File

@ -9553,10 +9553,6 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: AWS_ROLE_ARN
value: arn:aws-test:iam::123456789012:role/cert-manager.kube-system.sa.minimal.example.com
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/amazonaws.com/token
image: quay.io/jetstack/cert-manager-controller:v1.9.1
imagePullPolicy: IfNotPresent
name: cert-manager
@ -9567,13 +9563,9 @@ spec:
resources: {}
securityContext:
allowPrivilegeEscalation: false
volumeMounts:
- mountPath: /var/run/secrets/amazonaws.com/
name: token-amazonaws-com
readOnly: true
nodeSelector: null
priorityClassName: system-cluster-critical
securityContext:
fsGroup: 10001
runAsNonRoot: true
serviceAccountName: cert-manager
tolerations:
@ -9581,15 +9573,6 @@ spec:
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
volumes:
- name: token-amazonaws-com
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: amazonaws.com
expirationSeconds: 86400
path: token
---

View File

@ -100,7 +100,7 @@ func NewBootstrapChannelBuilder(modelContext *model.KopsModelContext,
// Build is responsible for adding the addons to the channel
func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error {
addons, err := b.buildAddons(c)
addons, serviceAccounts, err := b.buildAddons(c)
if err != nil {
return err
}
@ -130,7 +130,7 @@ func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error {
}
// Go through any transforms that are best expressed as code
remapped, err := addonmanifests.RemapAddonManifest(a.Spec, b.KopsModelContext, b.assetBuilder, manifestBytes)
remapped, err := addonmanifests.RemapAddonManifest(a.Spec, b.KopsModelContext, b.assetBuilder, manifestBytes, serviceAccounts)
if err != nil {
klog.Infof("invalid manifest: %s", string(manifestBytes))
return fmt.Errorf("error remapping manifest %s: %v", manifestPath, err)
@ -180,7 +180,7 @@ func (b *BootstrapChannelBuilder) Build(c *fi.ModelBuilderContext) error {
manifestPath := "addons/" + *a.Spec.Manifest
// Go through any transforms that are best expressed as code
manifestBytes, err := addonmanifests.RemapAddonManifest(&a.Spec, b.KopsModelContext, b.assetBuilder, a.Manifest)
manifestBytes, err := addonmanifests.RemapAddonManifest(&a.Spec, b.KopsModelContext, b.assetBuilder, a.Manifest, serviceAccounts)
if err != nil {
klog.Infof("invalid manifest: %s", string(a.Manifest))
return fmt.Errorf("error remapping manifest %s: %v", manifestPath, err)
@ -324,7 +324,7 @@ type Addon struct {
BuildPrune bool
}
func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*AddonList, error) {
func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*AddonList, map[string]iam.Subject, error) {
addons := &AddonList{}
serviceAccountRoles := []iam.Subject{}
@ -1016,7 +1016,7 @@ func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*Addon
err := addCiliumAddon(b, addons)
if err != nil {
return nil, fmt.Errorf("failed to add cilium addon: %w", err)
return nil, nil, fmt.Errorf("failed to add cilium addon: %w", err)
}
authenticationSelector := map[string]string{"role.kubernetes.io/authentication": "1"}
@ -1173,6 +1173,8 @@ func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*Addon
})
}
serviceAccounts := make(map[string]iam.Subject)
if b.Cluster.Spec.GetCloudProvider() == kops.CloudProviderAWS && b.Cluster.Spec.KubeAPIServer.ServiceAccountIssuer != nil {
awsModelContext := &awsmodel.AWSModelContext{
KopsModelContext: b.KopsModelContext,
@ -1183,9 +1185,11 @@ func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*Addon
_, err := iamModelBuilder.BuildServiceAccountRoleTasks(serviceAccountRole, c)
if err != nil {
return nil, err
return nil, nil, err
}
sa, _ := serviceAccountRole.ServiceAccount()
serviceAccounts[sa.Name] = serviceAccountRole
}
}
return addons, nil
return addons, serviceAccounts, nil
}