From ab813fd6c83848775a5861d99f6beddfcae9ca68 Mon Sep 17 00:00:00 2001 From: calvix Date: Thu, 2 Nov 2023 16:42:33 +0100 Subject: [PATCH] create-irsa-role-for-ebs-driver (#212) * create-irsa-role-for-ebs-driver * create-irsa-role-for-ebs-driver * fix-tests * fix-tests2 * fix3 --- CHANGELOG.md | 1 + .../awsmachinetemplate_controller_test.go | 1 + controllers/common_test.go | 160 ++++++++++++++++++ pkg/iam/ebs_csi_driver_template.go | 135 +++++++++++++++ pkg/iam/iam.go | 7 +- pkg/iam/template.go | 5 + 6 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 pkg/iam/ebs_csi_driver_template.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 18d4d74f..fe70a491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add tags from `AWSCluster.Spec.AdditionalTags` and `AWSManagedControlPlane.Spec.AdditionalTags` to all created resources. +- Add IRSA role for EBS CSI driver. ## [0.11.0] - 2023-11-01 diff --git a/controllers/awsmachinetemplate_controller_test.go b/controllers/awsmachinetemplate_controller_test.go index c75b8565..ffe9bad2 100644 --- a/controllers/awsmachinetemplate_controller_test.go +++ b/controllers/awsmachinetemplate_controller_test.go @@ -331,6 +331,7 @@ var _ = Describe("AWSMachineTemplateReconciler", func() { externalDnsRoleInfo, certManagerRoleInfo, ALBControllerRoleInfo, + ebsCsiDriverRoleInfo, } expectedIAMTags := []*iam.Tag{ diff --git a/controllers/common_test.go b/controllers/common_test.go index 43a76770..7e499f82 100644 --- a/controllers/common_test.go +++ b/controllers/common_test.go @@ -374,3 +374,163 @@ var ALBControllerRoleInfo = RoleInfo{ ReturnRoleArn: "arn:aws:iam::55554444:role/test-cluster-ALBController-Role", } + +var ebsCsiDriverRoleInfo = RoleInfo{ + ExpectedName: "test-cluster-ebs-csi-driver-role", + + ExpectedAssumeRolePolicyDocument: `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::012345678901:oidc-provider/irsa.test.gaws.gigantic.io" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "irsa.test.gaws.gigantic.io:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa" + } + } + } + ] +} +`, + + ExpectedPolicyName: "control-plane-test-cluster-policy", + ExpectedPolicyDocument: `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:CreateSnapshot", + "ec2:AttachVolume", + "ec2:DetachVolume", + "ec2:ModifyVolume", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateTags" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*" + ], + "Condition": { + "StringEquals": { + "ec2:CreateAction": [ + "CreateVolume", + "CreateSnapshot" + ] + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteTags" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "aws:RequestTag/ebs.csi.aws.com/cluster": "true" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "aws:RequestTag/CSIVolumeName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/kubernetes.io/created-for/pvc/name": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteSnapshot" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeSnapshotName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteSnapshot" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + } + } + ] +}`, + + ReturnRoleArn: "arn:aws:iam::55554444:role/test-cluster-ebs-csi-driver", +} diff --git a/pkg/iam/ebs_csi_driver_template.go b/pkg/iam/ebs_csi_driver_template.go new file mode 100644 index 00000000..cb124a3a --- /dev/null +++ b/pkg/iam/ebs_csi_driver_template.go @@ -0,0 +1,135 @@ +package iam + +const EBSCSIDriverPolicyTemplate = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:CreateSnapshot", + "ec2:AttachVolume", + "ec2:DetachVolume", + "ec2:ModifyVolume", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateTags" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*" + ], + "Condition": { + "StringEquals": { + "ec2:CreateAction": [ + "CreateVolume", + "CreateSnapshot" + ] + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteTags" + ], + "Resource": [ + "arn:aws:ec2:*:*:volume/*", + "arn:aws:ec2:*:*:snapshot/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "aws:RequestTag/ebs.csi.aws.com/cluster": "true" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "aws:RequestTag/CSIVolumeName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteVolume" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/kubernetes.io/created-for/pvc/name": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteSnapshot" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeSnapshotName": "*" + } + } + }, + { + "Effect": "Allow", + "Action": [ + "ec2:DeleteSnapshot" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + } + } + ] +}` diff --git a/pkg/iam/iam.go b/pkg/iam/iam.go index 9f2cc21c..11426d1b 100644 --- a/pkg/iam/iam.go +++ b/pkg/iam/iam.go @@ -24,6 +24,7 @@ const ( IRSARole = "irsa-role" CertManagerRole = "cert-manager-role" ALBConrollerRole = "ALBController-Role" + EBSCSIDriverRole = "ebs-csi-driver-role" IAMControllerOwnedTag = "capi-iam-controller/owned" ClusterIDTag = "sigs.k8s.io/cluster-api-provider-aws/cluster/%s" @@ -156,7 +157,7 @@ func (s *IAMService) ReconcileKiamRole() error { func (s *IAMService) ReconcileRolesForIRSA(awsAccountID string, cloudFrontDomain string) error { s.log.Info("reconciling IAM roles for IRSA") - for _, roleTypeToReconcile := range []string{Route53Role, CertManagerRole, ALBConrollerRole} { + for _, roleTypeToReconcile := range []string{Route53Role, CertManagerRole, ALBConrollerRole, EBSCSIDriverRole} { var params Route53RoleParams params, err := s.generateRoute53RoleParams(roleTypeToReconcile, awsAccountID, cloudFrontDomain) if err != nil { @@ -667,7 +668,9 @@ func getServiceAccount(role string) (string, error) { return "external-dns", nil } else if role == ALBConrollerRole { return "aws-load-balancer-controller", nil + } else if role == EBSCSIDriverRole { + return "ebs-csi-controller-sa", nil } - return "", fmt.Errorf("Cannot get service account for specified role - %s", role) + return "", fmt.Errorf("cannot get service account for specified role - %s", role) } diff --git a/pkg/iam/template.go b/pkg/iam/template.go index 56718dc7..b568cfc3 100644 --- a/pkg/iam/template.go +++ b/pkg/iam/template.go @@ -53,6 +53,8 @@ func getInlinePolicyTemplate(roleType string) string { return route53RolePolicyTemplateForCertManager case ALBConrollerRole: return ALBControllerPolicyTemplate + case EBSCSIDriverRole: + return EBSCSIDriverPolicyTemplate default: return "" } @@ -76,6 +78,9 @@ func getTrustPolicyTemplate(roleType string) string { return trustIdentityPolicyKIAMAndIRSA case ALBConrollerRole: return trustIdentityPolicyKIAMAndIRSA + case EBSCSIDriverRole: + return trustIdentityPolicyKIAMAndIRSA + default: return "" }