Skip to content

Commit 88b33dc

Browse files
authored
🧪 WIF test suites (#1441)
* 🧹 Update spelling list to include envsubst and gettext * 🧪 WIF test suite - GKE (GCP) * 🧹Moving GKE tests into separate `gke` directory to enable other testing on other platforms * 🧪 WIF test suite - EKS (AWS) * 🧪 Add AKS Workload Identity support in deployment handler tests and resource definitions * 🐛 Add Azure CLI login with federated token for AKS Workload Identity * 🧪 WIF test suite - AKS (Azure)
1 parent 6bb3e7f commit 88b33dc

57 files changed

Lines changed: 2140 additions & 303 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/spelling/expect.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
AAD
12
AADSTS
3+
ACR
24
artifactory
35
bak
46
bitnami
@@ -8,13 +10,16 @@ deepcopy
810
deletecollection
911
dockerconfigjson
1012
eksctl
13+
envsubst
1114
fullname
15+
gettext
1216
iamidentitymapping
1317
irsa
1418
kustomization
1519
mcr
1620
mondoooperatorconfig
1721
nginx
22+
NSG
1823
oidc
1924
openssl
2025
psat
@@ -27,4 +32,5 @@ SResources
2732
SVIDs
2833
tekton
2934
tpl
35+
westeurope
3036
wif

.gitignore

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ terraform.tfvars
6363
terraform.tfstate.backup
6464

6565
# tests artifacts
66-
tests/e2e/terraform/kubeconfig
67-
tests/e2e/terraform/kubeconfig-target
68-
tests/e2e/terraform/gke_gcloud_auth_plugin_cache
69-
tests/e2e/terraform/mondoo.json
66+
tests/e2e/**/kubeconfig
67+
tests/e2e/**/kubeconfig-target
68+
tests/e2e/**/gke_gcloud_auth_plugin_cache
69+
tests/e2e/**/mondoo.json

controllers/k8s_scan/deployment_handler_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,56 @@ func (s *DeploymentHandlerSuite) TestReconcile_ExternalCluster_WorkloadIdentity_
401401
s.Contains(initContainers[0].Image, "google-cloud-cli")
402402
}
403403

404+
func (s *DeploymentHandlerSuite) TestReconcile_ExternalCluster_WorkloadIdentity_AKS() {
405+
// Configure external cluster with AKS Workload Identity
406+
s.auditConfig.Spec.KubernetesResources.ExternalClusters = []mondoov1alpha2.ExternalCluster{
407+
{
408+
Name: "aks-prod",
409+
WorkloadIdentity: &mondoov1alpha2.WorkloadIdentityConfig{
410+
Provider: mondoov1alpha2.CloudProviderAKS,
411+
AKS: &mondoov1alpha2.AKSWorkloadIdentity{
412+
SubscriptionID: "sub-123",
413+
ResourceGroup: "my-rg",
414+
ClusterName: "prod-cluster",
415+
ClientID: "client-123",
416+
TenantID: "tenant-456",
417+
},
418+
},
419+
},
420+
}
421+
422+
d := s.createDeploymentHandler()
423+
s.NoError(d.KubeClient.Create(s.ctx, &s.auditConfig))
424+
425+
result, err := d.Reconcile(s.ctx)
426+
s.NoError(err)
427+
s.True(result.IsZero())
428+
429+
// Verify WIF ServiceAccount was created with correct annotation and label
430+
wifSA := &corev1.ServiceAccount{}
431+
wifSA.Name = WIFServiceAccountName(s.auditConfig.Name, "aks-prod")
432+
wifSA.Namespace = s.auditConfig.Namespace
433+
s.NoError(d.KubeClient.Get(s.ctx, client.ObjectKeyFromObject(wifSA), wifSA))
434+
s.Equal("client-123", wifSA.Annotations["azure.workload.identity/client-id"])
435+
s.Equal("true", wifSA.Labels["azure.workload.identity/use"])
436+
437+
// Verify external cluster CronJob was created with init container
438+
externalCronJob := &batchv1.CronJob{}
439+
externalCronJob.Name = ExternalClusterCronJobName(s.auditConfig.Name, "aks-prod")
440+
externalCronJob.Namespace = s.auditConfig.Namespace
441+
s.NoError(d.KubeClient.Get(s.ctx, client.ObjectKeyFromObject(externalCronJob), externalCronJob))
442+
443+
// Verify init container exists and uses azure-cli
444+
initContainers := externalCronJob.Spec.JobTemplate.Spec.Template.Spec.InitContainers
445+
s.Len(initContainers, 1)
446+
s.Equal("generate-kubeconfig", initContainers[0].Name)
447+
s.Contains(initContainers[0].Image, "azure-cli")
448+
449+
// Verify pod template has the AKS WI label for webhook injection
450+
podLabels := externalCronJob.Spec.JobTemplate.Spec.Template.Labels
451+
s.Equal("true", podLabels["azure.workload.identity/use"])
452+
}
453+
404454
func (s *DeploymentHandlerSuite) TestReconcile_ExternalCluster_SPIFFE() {
405455
// Create trust bundle secret for remote cluster CA
406456
trustBundleSecret := &corev1.Secret{

controllers/k8s_scan/resources.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@ func ExternalClusterCronJob(image string, cluster v1alpha2.ExternalCluster, m *v
340340

341341
initContainers = append(initContainers, wifInitContainer(cluster))
342342

343+
// AKS Workload Identity webhook uses a pod-level objectSelector matching
344+
// the label "azure.workload.identity/use: true" to inject federated token
345+
// env vars and projected volume. Add it to the pod template labels.
346+
if cluster.WorkloadIdentity.Provider == v1alpha2.CloudProviderAKS {
347+
ls["azure.workload.identity/use"] = "true"
348+
}
349+
343350
case cluster.SPIFFEAuth != nil:
344351
// SPIFFE auth: use sidecar to fetch certificates, generate kubeconfig
345352
serviceAccountName = m.Spec.Scanner.ServiceAccountName
@@ -695,6 +702,9 @@ retry gcloud container clusters get-credentials "$CLUSTER_NAME" \
695702
--project "$PROJECT_ID" \
696703
--location "$CLUSTER_LOCATION"
697704
cp ~/.kube/config /etc/opt/mondoo/kubeconfig/kubeconfig
705+
echo "=== DEBUG: generated kubeconfig ==="
706+
cat /etc/opt/mondoo/kubeconfig/kubeconfig
707+
echo "=== END DEBUG ==="
698708
`
699709
env = []corev1.EnvVar{
700710
{Name: "HOME", Value: "/tmp"},
@@ -710,6 +720,9 @@ retry aws eks update-kubeconfig \
710720
--name "$CLUSTER_NAME" \
711721
--region "$AWS_REGION" \
712722
--kubeconfig /etc/opt/mondoo/kubeconfig/kubeconfig
723+
echo "=== DEBUG: generated kubeconfig ==="
724+
cat /etc/opt/mondoo/kubeconfig/kubeconfig
725+
echo "=== END DEBUG ==="
713726
`
714727
env = []corev1.EnvVar{
715728
{Name: "HOME", Value: "/tmp"},
@@ -720,6 +733,13 @@ retry aws eks update-kubeconfig \
720733
case v1alpha2.CloudProviderAKS:
721734
image = AzureCLIImage
722735
script = retryWrapper + `
736+
# Azure CLI requires explicit login with the federated token injected by the
737+
# AKS Workload Identity webhook (AZURE_CLIENT_ID, AZURE_TENANT_ID,
738+
# AZURE_FEDERATED_TOKEN_FILE are set as env vars by the webhook).
739+
retry az login --federated-token "$(cat "$AZURE_FEDERATED_TOKEN_FILE")" \
740+
--service-principal \
741+
-u "$AZURE_CLIENT_ID" \
742+
-t "$AZURE_TENANT_ID"
723743
retry az aks get-credentials \
724744
--resource-group "$RESOURCE_GROUP" \
725745
--name "$CLUSTER_NAME" \
@@ -741,10 +761,11 @@ retry az aks get-credentials \
741761
}
742762

743763
return corev1.Container{
744-
Name: "generate-kubeconfig",
745-
Image: image,
746-
Command: []string{"/bin/sh", "-c", script},
747-
Env: env,
764+
Name: "generate-kubeconfig",
765+
Image: image,
766+
ImagePullPolicy: corev1.PullIfNotPresent,
767+
Command: []string{"/bin/sh", "-c", script},
768+
Env: env,
748769
VolumeMounts: []corev1.VolumeMount{
749770
{Name: "kubeconfig", MountPath: "/etc/opt/mondoo/kubeconfig"},
750771
{Name: "temp", MountPath: "/tmp"},
@@ -863,9 +884,10 @@ kill $HELPER_PID 2>/dev/null || true
863884
`
864885

865886
return corev1.Container{
866-
Name: "fetch-spiffe-certs",
867-
Image: SPIFFEHelperImage,
868-
Command: []string{"/bin/sh", "-c", script},
887+
Name: "fetch-spiffe-certs",
888+
Image: SPIFFEHelperImage,
889+
ImagePullPolicy: corev1.PullIfNotPresent,
890+
Command: []string{"/bin/sh", "-c", script},
869891
Env: []corev1.EnvVar{
870892
{Name: "SOCKET_FILE", Value: socketFile},
871893
{Name: "K8S_SERVER", Value: cluster.SPIFFEAuth.Server},

0 commit comments

Comments
 (0)