Skip to content

Commit d7cf41b

Browse files
committed
e2e tests for access entries
1 parent 19a93ed commit d7cf41b

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
apiVersion: cluster.x-k8s.io/v1beta1
3+
kind: Cluster
4+
metadata:
5+
name: "${CLUSTER_NAME}"
6+
spec:
7+
clusterNetwork:
8+
pods:
9+
cidrBlocks: ["192.168.0.0/16"]
10+
infrastructureRef:
11+
kind: AWSManagedControlPlane
12+
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
13+
name: "${CLUSTER_NAME}-control-plane"
14+
controlPlaneRef:
15+
kind: AWSManagedControlPlane
16+
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
17+
name: "${CLUSTER_NAME}-control-plane"
18+
---
19+
kind: AWSManagedControlPlane
20+
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
21+
metadata:
22+
name: "${CLUSTER_NAME}-control-plane"
23+
spec:
24+
region: "${AWS_REGION}"
25+
sshKeyName: "${AWS_SSH_KEY_NAME}"
26+
version: "${KUBERNETES_VERSION}"
27+
accessConfig:
28+
authenticationMode: API
29+
accessEntries:
30+
- principalARN: "arn:aws:iam::123456789012:role/KubernetesAdmin"
31+
type: STANDARD
32+
username: kubernetes-admin
33+
kubernetesGroups:
34+
- system:masters
35+
accessPolicies:
36+
- policyARN: "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
37+
accessScope:
38+
type: "cluster"
39+
- principalARN: "arn:aws:iam::123456789012:role/DeveloperRole"
40+
type: STANDARD
41+
username: developer
42+
kubernetesGroups:
43+
- developers
44+
accessPolicies:
45+
- policyARN: "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy"
46+
accessScope:
47+
type: "namespace"
48+
namespaces: ["default"]
49+
identityRef:
50+
kind: AWSClusterStaticIdentity
51+
name: e2e-account

test/e2e/suites/managed/eks_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,56 @@ var _ = ginkgo.Describe("[managed] [general] EKS cluster tests", func() {
165165
}
166166
})
167167

168+
ginkgo.By("should create a cluster with access entries")
169+
ManagedClusterSpec(ctx, func() ManagedClusterSpecInput {
170+
return ManagedClusterSpecInput{
171+
E2EConfig: e2eCtx.E2EConfig,
172+
ConfigClusterFn: defaultConfigCluster,
173+
BootstrapClusterProxy: e2eCtx.Environment.BootstrapClusterProxy,
174+
AWSSession: e2eCtx.BootstrapUserAWSSession,
175+
AWSSessionV2: e2eCtx.BootstrapUserAWSSessionV2,
176+
Namespace: namespace,
177+
ClusterName: clusterName,
178+
Flavour: EKSControlPlaneOnlyWithAccessEntriesFlavor,
179+
ControlPlaneMachineCount: 1, // NOTE: this cannot be zero as clusterctl returns an error
180+
WorkerMachineCount: 0,
181+
}
182+
})
183+
184+
ginkgo.By("should have created the expected access entries")
185+
expectedEntries := []ekscontrolplanev1.AccessEntry{
186+
{
187+
PrincipalARN: "arn:aws:iam::123456789012:role/KubernetesAdmin",
188+
Type: "STANDARD",
189+
Username: "kubernetes-admin",
190+
KubernetesGroups: []string{"system:masters"},
191+
AccessPolicies: []ekscontrolplanev1.AccessPolicyReference{
192+
{
193+
PolicyARN: "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy",
194+
AccessScope: ekscontrolplanev1.AccessScope{
195+
Type: "cluster",
196+
},
197+
},
198+
},
199+
},
200+
{
201+
PrincipalARN: "arn:aws:iam::123456789012:role/DeveloperRole",
202+
Type: "STANDARD",
203+
Username: "developer",
204+
KubernetesGroups: []string{"developers"},
205+
AccessPolicies: []ekscontrolplanev1.AccessPolicyReference{
206+
{
207+
PolicyARN: "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy",
208+
AccessScope: ekscontrolplanev1.AccessScope{
209+
Type: "namespace",
210+
Namespaces: []string{"default"},
211+
},
212+
},
213+
},
214+
},
215+
}
216+
verifyAccessEntries(ctx, eksClusterName, expectedEntries, e2eCtx.BootstrapUserAWSSessionV2)
217+
168218
ginkgo.By(fmt.Sprintf("getting cluster with name %s", clusterName))
169219
cluster := framework.GetClusterByName(ctx, framework.GetClusterByNameInput{
170220
Getter: e2eCtx.Environment.BootstrapClusterProxy.GetClient(),

test/e2e/suites/managed/helpers.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package managed
2222
import (
2323
"context"
2424
"fmt"
25+
"slices"
2526
"time"
2627

2728
"github.com/aws/aws-sdk-go-v2/aws"
@@ -35,6 +36,7 @@ import (
3536
crclient "sigs.k8s.io/controller-runtime/pkg/client"
3637

3738
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
39+
ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/eks/api/v1beta2"
3840
"sigs.k8s.io/cluster-api/test/framework/clusterctl"
3941
)
4042

@@ -49,6 +51,7 @@ const (
4951
EKSMachinePoolOnlyFlavor = "eks-machinepool-only"
5052
EKSIPv6ClusterFlavor = "eks-ipv6-cluster"
5153
EKSControlPlaneOnlyLegacyFlavor = "eks-control-plane-only-legacy"
54+
EKSControlPlaneOnlyWithAccessEntriesFlavor = "eks-control-plane-only-with-accessentries"
5255
)
5356

5457
const (
@@ -231,3 +234,68 @@ func verifyASG(eksClusterName, asgName string, checkOwned bool, cfg *aws.Config)
231234
Expect(found).To(BeTrue(), "expecting the cluster owned tag to exist")
232235
}
233236
}
237+
238+
func verifyAccessEntries(ctx context.Context, eksClusterName string, expectedEntries []ekscontrolplanev1.AccessEntry, cfg *aws.Config) {
239+
eksClient := eks.NewFromConfig(*cfg)
240+
241+
listOutput, err := eksClient.ListAccessEntries(ctx, &eks.ListAccessEntriesInput{
242+
ClusterName: &eksClusterName,
243+
})
244+
Expect(err).ToNot(HaveOccurred(), "failed to list access entries")
245+
246+
expectedEntriesMap := make(map[string]ekscontrolplanev1.AccessEntry, len(expectedEntries))
247+
for _, entry := range expectedEntries {
248+
expectedEntriesMap[entry.PrincipalARN] = entry
249+
}
250+
251+
for _, principalARN := range listOutput.AccessEntries {
252+
expectedEntry, exists := expectedEntriesMap[principalARN]
253+
Expect(exists).To(BeTrue(), fmt.Sprintf("unexpected access entry: %s", principalARN))
254+
255+
describeOutput, err := eksClient.DescribeAccessEntry(ctx, &eks.DescribeAccessEntryInput{
256+
ClusterName: &eksClusterName,
257+
PrincipalArn: &principalARN,
258+
})
259+
Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to describe access entry: %s", principalARN))
260+
261+
Expect(describeOutput.AccessEntry.Type).To(Equal(expectedEntry.Type), "access entry type does not match")
262+
Expect(describeOutput.AccessEntry.Username).To(Equal(expectedEntry.Username), "access entry username does not match")
263+
264+
if len(expectedEntry.KubernetesGroups) > 0 {
265+
slices.Sort(expectedEntry.KubernetesGroups)
266+
slices.Sort(describeOutput.AccessEntry.KubernetesGroups)
267+
Expect(describeOutput.AccessEntry.KubernetesGroups).To(Equal(expectedEntry.KubernetesGroups), "access entry kubernetes groups do not match")
268+
}
269+
270+
if len(expectedEntry.AccessPolicies) > 0 {
271+
listOutput, err := eksClient.ListAssociatedAccessPolicies(ctx, &eks.ListAssociatedAccessPoliciesInput{
272+
ClusterName: &eksClusterName,
273+
PrincipalArn: &principalARN,
274+
})
275+
Expect(err).ToNot(HaveOccurred(), "failed to list access policies")
276+
277+
expectedPolicies := make(map[string]ekscontrolplanev1.AccessPolicyReference, len(expectedEntry.AccessPolicies))
278+
for _, policy := range expectedEntry.AccessPolicies {
279+
expectedPolicies[policy.PolicyARN] = policy
280+
}
281+
282+
for _, policy := range listOutput.AssociatedAccessPolicies {
283+
expectedPolicy, exists := expectedPolicies[*policy.PolicyArn]
284+
Expect(exists).To(BeTrue(), fmt.Sprintf("unexpected access policy: %s", *policy.PolicyArn))
285+
286+
Expect(policy.AccessScope.Type).To(Equal(expectedPolicy.AccessScope.Type), "access policy scope type does not match")
287+
288+
if expectedPolicy.AccessScope.Type == "namespace" {
289+
slices.Sort(expectedPolicy.AccessScope.Namespaces)
290+
slices.Sort(policy.AccessScope.Namespaces)
291+
Expect(policy.AccessScope.Namespaces).To(Equal(expectedPolicy.AccessScope.Namespaces), "access policy scope namespaces do not match")
292+
}
293+
294+
delete(expectedPolicies, *policy.PolicyArn)
295+
}
296+
Expect(expectedPolicies).To(BeEmpty(), "not all expected access policies were found")
297+
}
298+
delete(expectedEntriesMap, principalARN)
299+
}
300+
Expect(expectedEntriesMap).To(BeEmpty(), "not all expected access entries were found")
301+
}

0 commit comments

Comments
 (0)