mirror of
https://github.com/external-secrets/external-secrets.git
synced 2024-12-14 11:57:59 +00:00
Merge pull request #217 from ContainerSolutions/gcp_property
feat: add property feature to gcp
This commit is contained in:
commit
f4dd6d547a
14 changed files with 146 additions and 10 deletions
3
.github/codecov.yml
vendored
3
.github/codecov.yml
vendored
|
@ -1,2 +1,5 @@
|
|||
ignore:
|
||||
- pkg/provider/**/fake
|
||||
coverage:
|
||||
round: down
|
||||
precision: 2
|
||||
|
|
|
@ -31,5 +31,5 @@ To create a kubernetes secret from the GCP Secret Manager secret a `Kind=Externa
|
|||
|
||||
The operator will fetch the GCP Secret Manager secret and inject it as a `Kind=Secret`
|
||||
```
|
||||
kubectl get secret secret-to-be-created -n <namespace> | -o jsonpath='{.data.example-externalsecret-key}' | base64 -d
|
||||
kubectl get secret secret-to-be-created -n <namespace> | -o jsonpath='{.data.dev-secret-test}' | base64 -d
|
||||
```
|
||||
|
|
|
@ -134,7 +134,7 @@ var _ = Describe("[aws] ", func() {
|
|||
})
|
||||
|
||||
It("should sync secrets with dataFrom", func() {
|
||||
By("creating a GCP SM Secret")
|
||||
By("creating a AWS SM Secret")
|
||||
secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
|
||||
targetSecretKey1 := "name"
|
||||
targetSecretValue1 := "great-name"
|
||||
|
@ -174,7 +174,7 @@ var _ = Describe("[aws] ", func() {
|
|||
})
|
||||
|
||||
It("should sync secrets and get inner keys", func() {
|
||||
By("creating a GCP SM Secret")
|
||||
By("creating a AWS SM Secret")
|
||||
secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
|
||||
targetSecretKey1 := "firstname"
|
||||
targetSecretValue1 := "Tom"
|
||||
|
|
|
@ -29,6 +29,10 @@ import (
|
|||
"github.com/external-secrets/external-secrets/e2e/framework"
|
||||
)
|
||||
|
||||
const (
|
||||
targetSecret = "target-secret"
|
||||
)
|
||||
|
||||
var _ = Describe("[gcp] ", func() {
|
||||
f := framework.New("eso-gcp")
|
||||
var secretStore *esv1alpha1.SecretStore
|
||||
|
@ -77,7 +81,6 @@ var _ = Describe("[gcp] ", func() {
|
|||
By("creating a GCP SM Secret")
|
||||
secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
|
||||
secretValue := "great-value-test"
|
||||
targetSecret := "target-secret"
|
||||
secret, err := createGCPSecretsManagerSecret(
|
||||
projectID,
|
||||
secretKey1, secretValue, []byte(credentials))
|
||||
|
@ -123,7 +126,6 @@ var _ = Describe("[gcp] ", func() {
|
|||
targetSecretKey2 := "surname"
|
||||
targetSecretValue2 := "great-surname"
|
||||
secretValue := fmt.Sprintf("{ \"%s\": \"%s\", \"%s\": \"%s\" }", targetSecretKey1, targetSecretValue1, targetSecretKey2, targetSecretValue2)
|
||||
targetSecret := "target-secret"
|
||||
secret, err := createGCPSecretsManagerSecret(
|
||||
projectID,
|
||||
secretKey1, secretValue, []byte(credentials))
|
||||
|
@ -159,4 +161,67 @@ var _ = Describe("[gcp] ", func() {
|
|||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
It("should sync secrets and get inner keys", func() {
|
||||
By("creating a GCP SM Secret")
|
||||
secretKey1 := fmt.Sprintf("%s-%s", f.Namespace.Name, "one")
|
||||
targetSecretKey1 := "firstname"
|
||||
targetSecretValue1 := "Tom"
|
||||
targetSecretKey2 := "first_friend"
|
||||
targetSecretValue2 := "Roger"
|
||||
secretValue := fmt.Sprintf(
|
||||
`{
|
||||
"name": {"first": "%s", "last": "Anderson"},
|
||||
"friends":
|
||||
[
|
||||
{"first": "Dale", "last": "Murphy"},
|
||||
{"first": "%s", "last": "Craig"},
|
||||
{"first": "Jane", "last": "Murphy"}
|
||||
]
|
||||
}`, targetSecretValue1, targetSecretValue2)
|
||||
secret, err := createGCPSecretsManagerSecret(
|
||||
projectID,
|
||||
secretKey1, secretValue, []byte(credentials))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = f.CRClient.Create(context.Background(), &esv1alpha1.ExternalSecret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "datafrom-sync",
|
||||
Namespace: f.Namespace.Name,
|
||||
},
|
||||
Spec: esv1alpha1.ExternalSecretSpec{
|
||||
SecretStoreRef: esv1alpha1.SecretStoreRef{
|
||||
Name: f.Namespace.Name,
|
||||
},
|
||||
Target: esv1alpha1.ExternalSecretTarget{
|
||||
Name: targetSecret,
|
||||
},
|
||||
Data: []esv1alpha1.ExternalSecretData{
|
||||
{
|
||||
SecretKey: targetSecretKey1,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: secretKey1,
|
||||
Property: "name.first",
|
||||
},
|
||||
},
|
||||
{
|
||||
SecretKey: targetSecretKey2,
|
||||
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: secretKey1,
|
||||
Property: "friends.1.first",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
_, err = f.WaitForSecretValue(f.Namespace.Name, targetSecret, map[string][]byte{
|
||||
targetSecretKey1: []byte(targetSecretValue1),
|
||||
targetSecretKey2: []byte(targetSecretValue2),
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = deleteGCPSecretsManagerSecret(secret.Name, []byte(credentials))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
})
|
||||
|
|
|
@ -294,6 +294,11 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient p
|
|||
providerData[secretRef.SecretKey] = secretData
|
||||
}
|
||||
|
||||
err := providerClient.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error closing the connection: %w", err)
|
||||
}
|
||||
|
||||
return providerData, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -89,3 +89,7 @@ func (pm *ParameterStore) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
|
|||
}
|
||||
return secretData, nil
|
||||
}
|
||||
|
||||
func (pm *ParameterStore) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -102,3 +102,7 @@ func (sm *SecretsManager) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
|
|||
}
|
||||
return secretData, nil
|
||||
}
|
||||
|
||||
func (sm *SecretsManager) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -225,3 +225,7 @@ func (a *Azure) secretKeyRef(ctx context.Context, namespace string, secretRef sm
|
|||
value := strings.TrimSpace(string(keyBytes))
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (a *Azure) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ func (v *Client) WithGetSecret(secData []byte, err error) *Client {
|
|||
func (v *Client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
|
||||
return v.GetSecretMapFn(ctx, ref)
|
||||
}
|
||||
func (v *Client) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithGetSecretMap wraps the secret data map returned by this fake provider.
|
||||
func (v *Client) WithGetSecretMap(secData map[string][]byte, err error) *Client {
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
secretmanager "cloud.google.com/go/secretmanager/apiv1"
|
||||
"github.com/googleapis/gax-go"
|
||||
"github.com/tidwall/gjson"
|
||||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/option"
|
||||
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
|
||||
|
@ -38,6 +39,7 @@ const (
|
|||
|
||||
errGCPSMStore = "received invalid GCPSM SecretStore resource"
|
||||
errGCPSMCredSecretName = "invalid GCPSM SecretStore resource: missing GCP Secret Access Key"
|
||||
errClientClose = "unable to close SecretManager client: %w"
|
||||
errInvalidClusterStoreMissingSAKNamespace = "invalid ClusterSecretStore: missing GCP SecretAccessKey Namespace"
|
||||
errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
|
||||
errMissingSAK = "missing SecretAccessKey"
|
||||
|
@ -45,7 +47,6 @@ const (
|
|||
errUnableCreateGCPSMClient = "failed to create GCP secretmanager client: %w"
|
||||
errUninitalizedGCPProvider = "provider GCP is not initialized"
|
||||
errClientGetSecretAccess = "unable to access Secret from SecretManager Client: %w"
|
||||
errClientClose = "unable to close SecretManager client: %w"
|
||||
errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
|
||||
)
|
||||
|
||||
|
@ -153,12 +154,21 @@ func (sm *ProviderGCP) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSec
|
|||
return nil, fmt.Errorf(errClientGetSecretAccess, err)
|
||||
}
|
||||
|
||||
err = sm.SecretManagerClient.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(errClientClose, err)
|
||||
if ref.Property == "" {
|
||||
if result.Payload.Data != nil {
|
||||
return result.Payload.Data, nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid secret received. no secret string for key: %s", ref.Key)
|
||||
}
|
||||
|
||||
return result.Payload.Data, nil
|
||||
var payload string
|
||||
if result.Payload.Data != nil {
|
||||
payload = string(result.Payload.Data)
|
||||
}
|
||||
|
||||
val := gjson.Get(payload, ref.Property)
|
||||
|
||||
return []byte(val.String()), nil
|
||||
}
|
||||
|
||||
// GetSecretMap returns multiple k/v pairs from the provider.
|
||||
|
@ -186,6 +196,14 @@ func (sm *ProviderGCP) GetSecretMap(ctx context.Context, ref esv1alpha1.External
|
|||
return secretData, nil
|
||||
}
|
||||
|
||||
func (sm *ProviderGCP) Close() error {
|
||||
err := sm.SecretManagerClient.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf(errClientClose, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
schema.Register(&ProviderGCP{}, &esv1alpha1.SecretStoreProvider{
|
||||
GCPSM: &esv1alpha1.GCPSMProvider{},
|
||||
|
|
|
@ -103,6 +103,26 @@ func TestSecretManagerGetSecret(t *testing.T) {
|
|||
smtc.expectedSecret = "testtesttest"
|
||||
}
|
||||
|
||||
// good case: ref with
|
||||
setCustomRef := func(smtc *secretManagerTestCase) {
|
||||
smtc.ref = &esv1alpha1.ExternalSecretDataRemoteRef{
|
||||
Key: "/baz",
|
||||
Version: "default",
|
||||
Property: "name.first",
|
||||
}
|
||||
smtc.apiInput.Name = "projects/default/secrets//baz/versions/default"
|
||||
smtc.apiOutput.Payload.Data = []byte(
|
||||
`{
|
||||
"name": {"first": "Tom", "last": "Anderson"},
|
||||
"friends": [
|
||||
{"first": "Dale", "last": "Murphy"},
|
||||
{"first": "Roger", "last": "Craig"},
|
||||
{"first": "Jane", "last": "Murphy"}
|
||||
]
|
||||
}`)
|
||||
smtc.expectedSecret = "Tom"
|
||||
}
|
||||
|
||||
// good case: custom version set
|
||||
setCustomVersion := func(smtc *secretManagerTestCase) {
|
||||
smtc.ref.Version = "1234"
|
||||
|
@ -116,6 +136,7 @@ func TestSecretManagerGetSecret(t *testing.T) {
|
|||
makeValidSecretManagerTestCaseCustom(setSecretString),
|
||||
makeValidSecretManagerTestCaseCustom(setCustomVersion),
|
||||
makeValidSecretManagerTestCaseCustom(setAPIErr),
|
||||
makeValidSecretManagerTestCaseCustom(setCustomRef),
|
||||
}
|
||||
|
||||
sm := ProviderGCP{}
|
||||
|
|
|
@ -35,4 +35,5 @@ type SecretsClient interface {
|
|||
|
||||
// GetSecretMap returns multiple k/v pairs from the provider
|
||||
GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error)
|
||||
Close() error
|
||||
}
|
||||
|
|
|
@ -41,6 +41,10 @@ func (p *PP) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretData
|
|||
return map[string][]byte{}, nil
|
||||
}
|
||||
|
||||
func (p *PP) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestRegister tests if the Register function
|
||||
// (1) panics if it tries to register something invalid
|
||||
// (2) stores the correct provider.
|
||||
|
|
|
@ -149,6 +149,10 @@ func (v *client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecret
|
|||
return v.readSecret(ctx, ref.Key, ref.Version)
|
||||
}
|
||||
|
||||
func (v *client) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *client) readSecret(ctx context.Context, path, version string) (map[string][]byte, error) {
|
||||
kvPath := v.store.Path
|
||||
|
||||
|
|
Loading…
Reference in a new issue