Parcourir la source

feat: implement azure pushsecret ifnotexist updatepolicy via secretExists function (#3361)

Signed-off-by: rohautl <lu.rohaut@laposte.net>
Co-authored-by: Gustavo Fernandes de Carvalho <gusfcarvalho@gmail.com>
rohautl il y a 2 ans
Parent
commit
e0bdcd0d97

+ 26 - 2
pkg/provider/azure/keyvault/keyvault.go

@@ -310,8 +310,32 @@ func (a *Azure) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushSecret
 	}
 }
 
-func (a *Azure) SecretExists(_ context.Context, _ esv1beta1.PushSecretRemoteRef) (bool, error) {
-	return false, fmt.Errorf("not implemented")
+func (a *Azure) SecretExists(ctx context.Context, remoteRef esv1beta1.PushSecretRemoteRef) (bool, error) {
+	objectType, secretName := getObjType(esv1beta1.ExternalSecretDataRemoteRef{Key: remoteRef.GetRemoteKey()})
+
+	var err error
+	switch objectType {
+	case defaultObjType:
+		_, err = a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "")
+	case objectTypeCert:
+		_, err = a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, secretName, "")
+	case objectTypeKey:
+		_, err = a.baseClient.GetKey(ctx, *a.provider.VaultURL, secretName, "")
+	default:
+		errMsg := fmt.Sprintf("secret type '%v' is not supported", objectType)
+		return false, errors.New(errMsg)
+	}
+
+	err = parseError(err)
+	if err != nil {
+		var noSecretErr esv1beta1.NoSecretError
+		if errors.As(err, &noSecretErr) {
+			return false, nil
+		}
+		return false, err
+	}
+
+	return true, nil
 }
 
 func getCertificateFromValue(value []byte) (*x509.Certificate, error) {

+ 73 - 0
pkg/provider/azure/keyvault/keyvault_test.go

@@ -62,6 +62,8 @@ type secretManagerTestCase struct {
 	expectedSecret string
 	// for testing secretmap
 	expectedData map[string][]byte
+
+	expectedExistence bool
 }
 
 func makeValidSecretManagerTestCase() *secretManagerTestCase {
@@ -1620,3 +1622,74 @@ func TestValidateStore(t *testing.T) {
 		})
 	}
 }
+
+func TestAzureKeyVaultSecretExists(t *testing.T) {
+	unsupportedType := func(smtc *secretManagerTestCase) {
+		smtc.pushData = testingfake.PushSecretData{
+			RemoteKey: "yadayada/foo",
+		}
+		smtc.expectError = "secret type 'yadayada' is not supported"
+	}
+
+	secretFound := func(smtc *secretManagerTestCase) {
+		smtc.pushData = testingfake.PushSecretData{
+			RemoteKey: secretName,
+		}
+		smtc.secretOutput = keyvault.SecretBundle{
+			Tags: map[string]*string{
+				"managed-by": pointer.To("external-secrets"),
+			},
+			Value: pointer.To("foo"),
+		}
+		smtc.expectedExistence = true
+	}
+
+	secretFoundNoUsefulTags := func(smtc *secretManagerTestCase) {
+		smtc.pushData = testingfake.PushSecretData{
+			RemoteKey: secretName,
+		}
+		smtc.secretOutput = keyvault.SecretBundle{
+			Tags: map[string]*string{
+				"someTag": pointer.To("someUselessValue"),
+			},
+			Value: pointer.To("foo"),
+		}
+		smtc.expectedExistence = true
+	}
+
+	secretNotFound := func(smtc *secretManagerTestCase) {
+		smtc.pushData = testingfake.PushSecretData{
+			RemoteKey: secretName,
+		}
+		smtc.apiErr = autorest.DetailedError{StatusCode: 404, Method: "GET", Message: "Not Found"}
+		smtc.expectedExistence = false
+	}
+
+	testCases := []*secretManagerTestCase{
+		makeValidSecretManagerTestCaseCustom(unsupportedType),
+		makeValidSecretManagerTestCaseCustom(secretFound),
+		makeValidSecretManagerTestCaseCustom(secretFoundNoUsefulTags),
+		makeValidSecretManagerTestCaseCustom(secretNotFound),
+	}
+
+	sm := Azure{
+		provider: &esv1beta1.AzureKVProvider{VaultURL: pointer.To(fakeURL)},
+	}
+
+	for k, tc := range testCases {
+		sm.baseClient = tc.mockClient
+		exists, err := sm.SecretExists(context.Background(), tc.pushData)
+
+		if !utils.ErrorContains(err, tc.expectError) {
+			if err == nil {
+				t.Errorf("[%d] unexpected error: <nil>, expected: '%s'", k, tc.expectError)
+			} else {
+				t.Errorf("[%d] unexpected error: '%s', expected: '%s'", k, err.Error(), tc.expectError)
+			}
+		}
+
+		if exists != tc.expectedExistence {
+			t.Errorf("[%d] unexpected existence result: expected %t, got %t", k, tc.expectedExistence, exists)
+		}
+	}
+}