Skip to content

Commit 3d011de

Browse files
authored
Inject GSA email to root-reconciler when using FWI (#856) (#857)
It also updates the unit test to validate the injection.
1 parent 025b19d commit 3d011de

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

pkg/reconcilermanager/controllers/reposync_controller_test.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"encoding/json"
2020
"fmt"
21+
"path/filepath"
2122
"reflect"
2223
"strconv"
2324
"strings"
@@ -2800,13 +2801,40 @@ func TestMapObjectToRepoSync(t *testing.T) {
28002801
}
28012802
}
28022803

2804+
func validateContainerEnv(container, key, expectedValue string) validateFunc {
2805+
return func(deployment *appsv1.Deployment) error {
2806+
hasContainer := false
2807+
var envVars []corev1.EnvVar
2808+
for _, c := range deployment.Spec.Template.Spec.Containers {
2809+
if c.Name == container {
2810+
hasContainer = true
2811+
envVars = c.Env
2812+
}
2813+
}
2814+
if !hasContainer {
2815+
return fmt.Errorf("the container %q is not found in the deployment %q/%q", container, deployment.Namespace, deployment.Name)
2816+
}
2817+
2818+
for _, env := range envVars {
2819+
if env.Name == key {
2820+
if env.Value == expectedValue {
2821+
return nil
2822+
}
2823+
return fmt.Errorf("the value for ENV %q in the %q container is expected to be %q, but got %q", key, container, expectedValue, env.Value)
2824+
}
2825+
}
2826+
return fmt.Errorf("the ENV %q is not found in the %q container", key, container)
2827+
}
2828+
}
2829+
28032830
func TestInjectFleetWorkloadIdentityCredentialsToRepoSync(t *testing.T) {
28042831
// Mock out parseDeployment for testing.
28052832
parseDeployment = parsedDeployment
28062833

28072834
rs := repoSyncWithGit(reposyncNs, reposyncName, reposyncRef(gitRevision), reposyncBranch(branch), reposyncSecretType(configsync.AuthGCPServiceAccount), reposyncGCPSAEmail(gcpSAEmail))
28082835
reqNamespacedName := namespacedName(rs.Name, rs.Namespace)
28092836
fakeClient, fakeDynamicClient, testReconciler := setupNSReconciler(t, rs, secretObj(t, reposyncSSHKey, configsync.AuthSSH, v1beta1.GitSource, core.Namespace(rs.Namespace)))
2837+
// The membership doesn't have WorkloadIdentityPool and IdentityProvider specified, so FWI creds won't be injected.
28102838
testReconciler.membership = &hubv1.Membership{
28112839
Spec: hubv1.MembershipSpec{
28122840
Owner: hubv1.MembershipOwner{
@@ -2842,6 +2870,7 @@ func TestInjectFleetWorkloadIdentityCredentialsToRepoSync(t *testing.T) {
28422870
workloadIdentityPool := "test-gke-dev.svc.id.goog"
28432871
testReconciler.membership = &hubv1.Membership{
28442872
Spec: hubv1.MembershipSpec{
2873+
// Configuring WorkloadIdentityPool and IdentityProvider to validate if FWI creds are injected.
28452874
WorkloadIdentityPool: workloadIdentityPool,
28462875
IdentityProvider: "https://container.googleapis.com/v1/projects/test-gke-dev/locations/us-central1-c/clusters/fleet-workload-identity-test-cluster",
28472876
},
@@ -2865,7 +2894,11 @@ func TestInjectFleetWorkloadIdentityCredentialsToRepoSync(t *testing.T) {
28652894
wantDeployments = map[core.ID]*appsv1.Deployment{core.IDOf(repoDeployment): repoDeployment}
28662895

28672896
// compare Deployment.
2868-
if err := validateDeployments(wantDeployments, fakeDynamicClient); err != nil {
2897+
if err := validateDeployments(wantDeployments, fakeDynamicClient,
2898+
// Validate the credentials are injected in the askpass container
2899+
validateContainerEnv(reconcilermanager.GCENodeAskpassSidecar, gsaEmailEnvKey, gcpSAEmail),
2900+
validateContainerEnv(reconcilermanager.GCENodeAskpassSidecar, googleApplicationCredentialsEnvKey, filepath.Join(gcpKSATokenDir, googleApplicationCredentialsFile)),
2901+
); err != nil {
28692902
t.Errorf("Deployment validation failed. err: %v", err)
28702903
}
28712904
if t.Failed() {
@@ -3808,8 +3841,10 @@ func validateClusterRoleBinding(want *rbacv1.ClusterRoleBinding, fakeClient *syn
38083841
return nil
38093842
}
38103843

3844+
type validateFunc func(*appsv1.Deployment) error
3845+
38113846
// validateDeployments validates that important fields in the `wants` deployments match those same fields in the current deployments found in the unstructured Map
3812-
func validateDeployments(wants map[core.ID]*appsv1.Deployment, fakeDynamicClient *syncerFake.DynamicClient) error {
3847+
func validateDeployments(wants map[core.ID]*appsv1.Deployment, fakeDynamicClient *syncerFake.DynamicClient, validations ...validateFunc) error {
38133848
ctx := context.Background()
38143849
for id, want := range wants {
38153850
uObj, err := fakeDynamicClient.Resource(kinds.DeploymentResource()).
@@ -3928,6 +3963,12 @@ func validateDeployments(wants map[core.ID]*appsv1.Deployment, fakeDynamicClient
39283963
if diff := cmp.Diff(want.ResourceVersion, got.ResourceVersion); diff != "" {
39293964
return errors.Errorf("Unexpected Deployment ResourceVersion found for %q. Diff (- want, + got): %v", id, diff)
39303965
}
3966+
3967+
for _, v := range validations {
3968+
if err := v(got); err != nil {
3969+
return err
3970+
}
3971+
}
39313972
}
39323973
return nil
39333974
}

pkg/reconcilermanager/controllers/rootsync_controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,9 @@ func (r *RootSyncReconciler) populateContainerEnvs(ctx context.Context, rs *v1be
674674
noSSLVerify: rs.Spec.Git.NoSSLVerify,
675675
caCertSecretRef: v1beta1.GetSecretName(rs.Spec.Git.CACertSecretRef),
676676
})
677+
if enableAskpassSidecar(rs.Spec.SourceType, rs.Spec.Git.Auth) {
678+
result[reconcilermanager.GCENodeAskpassSidecar] = gceNodeAskPassSidecarEnvs(rs.Spec.GCPServiceAccountEmail)
679+
}
677680
case v1beta1.OciSource:
678681
result[reconcilermanager.OciSync] = ociSyncEnvs(rs.Spec.Oci.Image, rs.Spec.Oci.Auth, v1beta1.GetPeriodSecs(rs.Spec.Oci.Period, configsync.DefaultReconcilerPollingPeriodSeconds))
679682
case v1beta1.HelmSource:

pkg/reconcilermanager/controllers/rootsync_controller_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2297,6 +2297,7 @@ func TestInjectFleetWorkloadIdentityCredentialsToRootSync(t *testing.T) {
22972297
rs := rootSyncWithGit(rootsyncName, rootsyncRef(gitRevision), rootsyncBranch(branch), rootsyncSecretType(configsync.AuthGCPServiceAccount), rootsyncGCPSAEmail(gcpSAEmail))
22982298
reqNamespacedName := namespacedName(rs.Name, rs.Namespace)
22992299
fakeClient, fakeDynamicClient, testReconciler := setupRootReconciler(t, rs, secretObj(t, rootsyncSSHKey, configsync.AuthSSH, v1beta1.GitSource, core.Namespace(rs.Namespace)))
2300+
// The membership doesn't have WorkloadIdentityPool and IdentityProvider specified, so FWI creds won't be injected.
23002301
testReconciler.membership = &hubv1.Membership{
23012302
Spec: hubv1.MembershipSpec{
23022303
Owner: hubv1.MembershipOwner{
@@ -2331,6 +2332,7 @@ func TestInjectFleetWorkloadIdentityCredentialsToRootSync(t *testing.T) {
23312332
workloadIdentityPool := "test-gke-dev.svc.id.goog"
23322333
testReconciler.membership = &hubv1.Membership{
23332334
Spec: hubv1.MembershipSpec{
2335+
// Configuring WorkloadIdentityPool and IdentityProvider to validate if FWI creds are injected.
23342336
WorkloadIdentityPool: workloadIdentityPool,
23352337
IdentityProvider: "https://container.googleapis.com/v1/projects/test-gke-dev/locations/us-central1-c/clusters/fleet-workload-identity-test-cluster",
23362338
},
@@ -2352,7 +2354,11 @@ func TestInjectFleetWorkloadIdentityCredentialsToRootSync(t *testing.T) {
23522354
wantDeployments = map[core.ID]*appsv1.Deployment{core.IDOf(rootDeployment): rootDeployment}
23532355

23542356
// compare Deployment.
2355-
if err := validateDeployments(wantDeployments, fakeDynamicClient); err != nil {
2357+
if err := validateDeployments(wantDeployments, fakeDynamicClient,
2358+
// Validate the credentials are injected in the askpass container
2359+
validateContainerEnv(reconcilermanager.GCENodeAskpassSidecar, gsaEmailEnvKey, gcpSAEmail),
2360+
validateContainerEnv(reconcilermanager.GCENodeAskpassSidecar, googleApplicationCredentialsEnvKey, filepath.Join(gcpKSATokenDir, googleApplicationCredentialsFile)),
2361+
); err != nil {
23562362
t.Errorf("Deployment validation failed. err: %v", err)
23572363
}
23582364
if t.Failed() {

0 commit comments

Comments
 (0)