Skip to content

Commit bf35178

Browse files
Grant ec2:DescribeSecurityGroups to the IPv6 VPC CNI role (#8837)
fix: Grant ec2:DescribeSecurityGroups to the IPv6 VPC CNI role Subnet discovery in the VPC CNI needs two EC2 permissions, not one. 52148b4 granted ec2:DescribeSubnets; this grants the other half. Reported in #8768, where an IPv6 cluster hit both denials in sequence. The first surfaced as a MissingIAMPermissions pod event: Unauthorized operation: failed to call ec2:DescribeSubnets due to missing permissions. Once that was granted the CNI got further and failed on the second, which appears only in /var/log/aws-routed-eni/ipamd.log because the container writes nothing about it to stdout: Initialization failure: unable to describe security groups: operation error EC2: DescribeSecurityGroups, StatusCode: 403, api error UnauthorizedOperation: ... no identity-based policy allows the ec2:DescribeSecurityGroups action The upstream CNI documents both as required for subnet discovery since v1.22.1, and subnet discovery is on by default: aws/amazon-vpc-cni-k8s#3709 Only IPv6 clusters are affected. The IPv4 path attaches the AWS-managed AmazonEKS_CNI_Policy, whose current version (v6) already grants both ec2:DescribeSubnets and ec2:DescribeSecurityGroups. The IPv6 path uses this hand-written inline policy instead, so each action has to be granted explicitly. Both callers of makeIPv6VPCCNIPolicyDocument are affected: the IRSA path via addon.AttachPolicy, and the pod identity path via PodIdentityAssociation.PermissionPolicy. The existing pod identity test only asserted the document was non-empty, so it would not have caught a missing action; it now asserts both subnet discovery permissions, as the IRSA test already did for ec2:DescribeSubnets. With this change the IPv6 policy matches the upstream IPv6 policy exactly, with no missing and no extra actions.
1 parent 8b60f9d commit bf35178

2 files changed

Lines changed: 17 additions & 6 deletions

File tree

pkg/actions/addon/create.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,15 @@ func makeIPv6VPCCNIPolicyDocument(partition string) map[string]interface{} {
490490
"ec2:DescribeTags",
491491
"ec2:DescribeNetworkInterfaces",
492492
"ec2:DescribeInstanceTypes",
493-
// Required by the VPC CNI's subnet discovery, which is enabled
494-
// by default. Without it ipamd fails to initialise, aws-node
495-
// crash-loops and nodes never become ready. The IPv4 path gets
496-
// this from the AWS-managed AmazonEKS_CNI_Policy; the IPv6
497-
// path uses this inline policy, so it must be granted here.
493+
// Both of these are required by the VPC CNI's subnet discovery,
494+
// which is enabled by default since VPC CNI v1.22.1. Without
495+
// them ipamd fails to initialise, aws-node crash-loops and nodes
496+
// never become ready. The IPv4 path gets them from the
497+
// AWS-managed AmazonEKS_CNI_Policy; the IPv6 path uses this
498+
// inline policy, so they must be granted here. See
499+
// https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/iam-policy.md
498500
"ec2:DescribeSubnets",
501+
"ec2:DescribeSecurityGroups",
499502
},
500503
"Resource": "*",
501504
},

pkg/actions/addon/create_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package addon_test
33
import (
44
"bytes"
55
"context"
6+
"encoding/json"
67
"fmt"
78
"os"
89
"time"
@@ -988,6 +989,12 @@ var _ = Describe("Create", func() {
988989
Expect(args[1]).To(BeAssignableToTypeOf(&api.PodIdentityAssociation{}))
989990
Expect(args[1].(*api.PodIdentityAssociation).ServiceAccountName).To(Equal("aws-node"))
990991
Expect(args[1].(*api.PodIdentityAssociation).PermissionPolicy).NotTo(BeEmpty())
992+
// The pod identity path shares the IPv6 CNI policy document with
993+
// the IRSA path; subnet discovery permissions must reach both.
994+
policy, err := json.Marshal(args[1].(*api.PodIdentityAssociation).PermissionPolicy)
995+
Expect(err).NotTo(HaveOccurred())
996+
Expect(string(policy)).To(ContainSubstring("ec2:DescribeSubnets"))
997+
Expect(string(policy)).To(ContainSubstring("ec2:DescribeSecurityGroups"))
991998
}).
992999
Return("arn:aws:iam::111122223333:role/aws-node", nil).
9931000
Once()
@@ -1168,9 +1175,10 @@ var _ = Describe("Create", func() {
11681175
Expect(err).NotTo(HaveOccurred())
11691176
Expect(string(output)).To(ContainSubstring("AssignIpv6Addresses"))
11701177
// Subnet discovery is on by default in the VPC CNI; without
1171-
// this permission ipamd fails to initialise and nodes never
1178+
// these permissions ipamd fails to initialise and nodes never
11721179
// become ready.
11731180
Expect(string(output)).To(ContainSubstring("DescribeSubnets"))
1181+
Expect(string(output)).To(ContainSubstring("DescribeSecurityGroups"))
11741182
rsr.(*builder.IAMRoleResourceSet).OutputRole = "arn:aws:iam::111122223333:role/role-name-1"
11751183
return nil
11761184
}

0 commit comments

Comments
 (0)