Skip to content

Commit 5964764

Browse files
Merge pull request #1805 from RomanBednar/gcp-wif
STOR-1988: support GCP WIF in credentials request controller
2 parents 695e391 + f73b516 commit 5964764

File tree

2 files changed

+165
-4
lines changed

2 files changed

+165
-4
lines changed

pkg/operator/csi/credentialsrequestcontroller/credentials_request_controller.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package credentialsrequestcontroller
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/klog/v2"
67
"os"
78
"strings"
89
"time"
@@ -89,13 +90,11 @@ func (c CredentialsRequestController) sync(ctx context.Context, syncContext fact
8990
return err
9091
}
9192

92-
clusterCloudCredential, err := c.operatorLister.Get(clusterCloudCredentialName)
93+
sync, err := shouldSync(c.operatorLister)
9394
if err != nil {
9495
return err
9596
}
96-
97-
// if clusterCloudCredential is in manual mode without STS, do not sync cloud credentials
98-
if clusterCloudCredential.Spec.CredentialsMode == opv1.CloudCredentialsModeManual && os.Getenv("ROLEARN") == "" {
97+
if !sync {
9998
return nil
10099
}
101100

@@ -193,3 +192,29 @@ func isProvisioned(cr *unstructured.Unstructured) (bool, error) {
193192

194193
return provisionedValBool, nil
195194
}
195+
196+
func shouldSync(cloudCredentialLister operatorv1lister.CloudCredentialLister) (bool, error) {
197+
clusterCloudCredential, err := cloudCredentialLister.Get(clusterCloudCredentialName)
198+
if err != nil {
199+
klog.Errorf("Failed to get cluster cloud credential: %v", err)
200+
return false, err
201+
}
202+
203+
isManualMode := clusterCloudCredential.Spec.CredentialsMode == opv1.CloudCredentialsModeManual
204+
205+
isAWSSTSEnabled := os.Getenv("ROLEARN") != ""
206+
207+
poolID := os.Getenv("POOL_ID")
208+
providerID := os.Getenv("PROVIDER_ID")
209+
serviceAccountEmail := os.Getenv("SERVICE_ACCOUNT_EMAIL")
210+
projectNumber := os.Getenv("PROJECT_NUMBER")
211+
212+
isGCPWIFEnabled := poolID != "" && providerID != "" && serviceAccountEmail != "" && projectNumber != ""
213+
214+
// If cluster is in manual mode without short-term credentials enabled, do not sync cloud credentials.
215+
if isManualMode && !isAWSSTSEnabled && !isGCPWIFEnabled {
216+
return false, nil
217+
}
218+
219+
return true, nil
220+
}

pkg/operator/csi/credentialsrequestcontroller/credentials_request_controller_test.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"os"
78
"reflect"
89
"strconv"
910
"testing"
@@ -319,3 +320,138 @@ func (fake *fakeDynamicClient) Apply(ctx context.Context, name string, obj *unst
319320
func (fake *fakeDynamicClient) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error) {
320321
return nil, errors.New("not implemented")
321322
}
323+
324+
func TestShouldSync(t *testing.T) {
325+
tests := []struct {
326+
name string
327+
cloudCredential *opv1.CloudCredential
328+
envVars map[string]string
329+
expectedShouldSync bool
330+
expectedError bool
331+
}{
332+
{
333+
name: "Default mode",
334+
cloudCredential: &opv1.CloudCredential{
335+
ObjectMeta: metav1.ObjectMeta{
336+
Name: clusterCloudCredentialName,
337+
},
338+
Spec: opv1.CloudCredentialSpec{
339+
CredentialsMode: opv1.CloudCredentialsModeDefault,
340+
},
341+
},
342+
expectedShouldSync: true,
343+
expectedError: false,
344+
},
345+
{
346+
name: "Manual mode without short-term credentials",
347+
cloudCredential: &opv1.CloudCredential{
348+
ObjectMeta: metav1.ObjectMeta{
349+
Name: clusterCloudCredentialName,
350+
},
351+
Spec: opv1.CloudCredentialSpec{
352+
CredentialsMode: opv1.CloudCredentialsModeManual,
353+
},
354+
},
355+
expectedShouldSync: false,
356+
expectedError: false,
357+
},
358+
{
359+
name: "Manual mode with AWS STS enabled",
360+
cloudCredential: &opv1.CloudCredential{
361+
ObjectMeta: metav1.ObjectMeta{
362+
Name: clusterCloudCredentialName,
363+
},
364+
Spec: opv1.CloudCredentialSpec{
365+
CredentialsMode: opv1.CloudCredentialsModeManual,
366+
},
367+
},
368+
envVars: map[string]string{
369+
"ROLEARN": "arn:aws:iam::123456789012:role/test-role",
370+
},
371+
expectedShouldSync: true,
372+
expectedError: false,
373+
},
374+
{
375+
name: "Manual mode with GCP WIF enabled",
376+
cloudCredential: &opv1.CloudCredential{
377+
ObjectMeta: metav1.ObjectMeta{
378+
Name: clusterCloudCredentialName,
379+
},
380+
Spec: opv1.CloudCredentialSpec{
381+
CredentialsMode: opv1.CloudCredentialsModeManual,
382+
},
383+
},
384+
envVars: map[string]string{
385+
"POOL_ID": "test-pool",
386+
"PROVIDER_ID": "test-provider",
387+
"SERVICE_ACCOUNT_EMAIL": "[email protected]",
388+
"PROJECT_NUMBER": "123456789",
389+
},
390+
expectedShouldSync: true,
391+
expectedError: false,
392+
},
393+
{
394+
name: "Manual mode with partial GCP WIF configuration",
395+
cloudCredential: &opv1.CloudCredential{
396+
ObjectMeta: metav1.ObjectMeta{
397+
Name: clusterCloudCredentialName,
398+
},
399+
Spec: opv1.CloudCredentialSpec{
400+
CredentialsMode: opv1.CloudCredentialsModeManual,
401+
},
402+
},
403+
envVars: map[string]string{
404+
"POOL_ID": "test-pool",
405+
"PROVIDER_ID": "test-provider",
406+
"SERVICE_ACCOUNT_EMAIL": "[email protected]",
407+
},
408+
expectedShouldSync: false,
409+
expectedError: false,
410+
},
411+
{
412+
name: "Error getting cloud credential",
413+
cloudCredential: nil,
414+
expectedShouldSync: false,
415+
expectedError: true,
416+
},
417+
}
418+
419+
for _, tc := range tests {
420+
t.Run(tc.name, func(t *testing.T) {
421+
// Setup
422+
typedVersionedOperatorClient := fakeoperatorv1client.NewSimpleClientset()
423+
cloudCredentialInformer := operatorinformer.NewSharedInformerFactory(typedVersionedOperatorClient, 1*time.Minute)
424+
425+
if tc.cloudCredential != nil {
426+
err := cloudCredentialInformer.Operator().V1().CloudCredentials().Informer().GetStore().Add(tc.cloudCredential)
427+
if err != nil {
428+
t.Fatalf("Failed to add cloud credential to store: %v", err)
429+
}
430+
}
431+
432+
// Set environment variables
433+
for k, v := range tc.envVars {
434+
os.Setenv(k, v)
435+
}
436+
defer func() {
437+
for k := range tc.envVars {
438+
os.Unsetenv(k)
439+
}
440+
}()
441+
442+
// Act
443+
shouldSync, err := shouldSync(cloudCredentialInformer.Operator().V1().CloudCredentials().Lister())
444+
445+
// Assert
446+
if tc.expectedError && err == nil {
447+
t.Error("Expected an error, but got none")
448+
}
449+
if !tc.expectedError && err != nil {
450+
t.Errorf("Unexpected error: %v", err)
451+
}
452+
if shouldSync != tc.expectedShouldSync {
453+
t.Errorf("Expected shouldSync to be %v, but got %v", tc.expectedShouldSync, shouldSync)
454+
}
455+
})
456+
}
457+
}

0 commit comments

Comments
 (0)