1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Modified CRD according to the discussion

This commit is contained in:
Sebastian Gomez 2022-01-24 15:54:34 -05:00
parent e24baa9db5
commit f4d1b8dd22
28 changed files with 487 additions and 278 deletions

View file

@ -118,25 +118,18 @@ type ExternalSecretData struct {
// ExternalSecretDataRemoteRef defines Provider data location.
type ExternalSecretDataRemoteRef struct {
// Used to select a specific version and property from the secret
// +optional
Extract ExternalSecretExtract `json:"extract,omitempty"`
// Used to find secrets based on tags or regular expressions
Find ExternalSecretFind `json:"find,omitempty"`
}
type ExternalSecretExtract struct {
// Key is the key used in the Provider
// +optional
Key string `json:"key,omitempty"`
// Used to select multiple secrets based on a pattern
// +optional
MatchKey string `json:"matchKey,omitempty"`
// List of tags used to filter the secrets
Tags map[string]string `json:"tags,omitempty"`
// Used to select multiple secrets based on the name
// +optional
Name string `json:"name,omitempty"`
// Used to select multiple secrets based on a regular expression of the name
// +optional
RegExp string `json:"regexp,omitempty"`
// Used to select a specific version of the Provider value, if supported
// +optional
Version string `json:"version,omitempty"`
@ -146,14 +139,21 @@ type ExternalSecretDataRemoteRef struct {
Property string `json:"property,omitempty"`
}
// type ExternalSecretDataRemoteMatchKey struct {
type ExternalSecretFind struct {
// Key is the key used in the Provider
// +optional
Name FindName `json:"name,omitempty"`
// //A regular expression used to get the secrets
// //Name string `json:"name,omitempty"`
// Used to select a specific version of the Provider value, if supported
// +optional
Tags map[string]string `json:"tags,omitempty"`
}
// // List of tags used to filter the secrets
// Tags map[string]string `json:"tags,omitempty"`
// }
type FindName struct {
// Used to select multiple secrets based on a regular expression of the name
// +optional
RegExp string `json:"regexp,omitempty"`
}
// ExternalSecretSpec defines the desired state of ExternalSecret.
type ExternalSecretSpec struct {

View file

@ -405,6 +405,39 @@ func (in *ExternalSecretData) DeepCopy() *ExternalSecretData {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalSecretDataRemoteRef) DeepCopyInto(out *ExternalSecretDataRemoteRef) {
*out = *in
out.Extract = in.Extract
in.Find.DeepCopyInto(&out.Find)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretDataRemoteRef.
func (in *ExternalSecretDataRemoteRef) DeepCopy() *ExternalSecretDataRemoteRef {
if in == nil {
return nil
}
out := new(ExternalSecretDataRemoteRef)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalSecretExtract) DeepCopyInto(out *ExternalSecretExtract) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretExtract.
func (in *ExternalSecretExtract) DeepCopy() *ExternalSecretExtract {
if in == nil {
return nil
}
out := new(ExternalSecretExtract)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalSecretFind) DeepCopyInto(out *ExternalSecretFind) {
*out = *in
out.Name = in.Name
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make(map[string]string, len(*in))
@ -414,12 +447,12 @@ func (in *ExternalSecretDataRemoteRef) DeepCopyInto(out *ExternalSecretDataRemot
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretDataRemoteRef.
func (in *ExternalSecretDataRemoteRef) DeepCopy() *ExternalSecretDataRemoteRef {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretFind.
func (in *ExternalSecretFind) DeepCopy() *ExternalSecretFind {
if in == nil {
return nil
}
out := new(ExternalSecretDataRemoteRef)
out := new(ExternalSecretFind)
in.DeepCopyInto(out)
return out
}
@ -610,6 +643,21 @@ func (in *ExternalSecretTemplateMetadata) DeepCopy() *ExternalSecretTemplateMeta
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FindName) DeepCopyInto(out *FindName) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FindName.
func (in *FindName) DeepCopy() *FindName {
if in == nil {
return nil
}
out := new(FindName)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GCPSMAuth) DeepCopyInto(out *GCPSMAuth) {
*out = *in

View file

@ -59,34 +59,41 @@ spec:
description: ExternalSecretDataRemoteRef defines Provider data
location.
properties:
key:
description: Key is the key used in the Provider
type: string
matchKey:
description: Used to select multiple secrets based on a
pattern
type: string
name:
description: Used to select multiple secrets based on the
name
type: string
property:
description: Used to select a specific property of the Provider
value (if a map), if supported
type: string
regexp:
description: Used to select multiple secrets based on a
regular expression of the name
type: string
tags:
additionalProperties:
type: string
description: List of tags used to filter the secrets
extract:
description: Used to select a specific version and property
from the secret
properties:
key:
description: Key is the key used in the Provider
type: string
property:
description: Used to select a specific property of the
Provider value (if a map), if supported
type: string
version:
description: Used to select a specific version of the
Provider value, if supported
type: string
type: object
find:
description: Used to find secrets based on tags or regular
expressions
properties:
name:
description: Key is the key used in the Provider
properties:
regexp:
description: Used to select multiple secrets based
on a regular expression of the name
type: string
type: object
tags:
additionalProperties:
type: string
description: Used to select a specific version of the
Provider value, if supported
type: object
type: object
version:
description: Used to select a specific version of the Provider
value, if supported
type: string
type: object
secretKey:
type: string
@ -102,32 +109,40 @@ spec:
items:
description: ExternalSecretDataRemoteRef defines Provider data location.
properties:
key:
description: Key is the key used in the Provider
type: string
matchKey:
description: Used to select multiple secrets based on a pattern
type: string
name:
description: Used to select multiple secrets based on the name
type: string
property:
description: Used to select a specific property of the Provider
value (if a map), if supported
type: string
regexp:
description: Used to select multiple secrets based on a regular
expression of the name
type: string
tags:
additionalProperties:
type: string
description: List of tags used to filter the secrets
extract:
description: Used to select a specific version and property
from the secret
properties:
key:
description: Key is the key used in the Provider
type: string
property:
description: Used to select a specific property of the Provider
value (if a map), if supported
type: string
version:
description: Used to select a specific version of the Provider
value, if supported
type: string
type: object
find:
description: Used to find secrets based on tags or regular expressions
properties:
name:
description: Key is the key used in the Provider
properties:
regexp:
description: Used to select multiple secrets based on
a regular expression of the name
type: string
type: object
tags:
additionalProperties:
type: string
description: Used to select a specific version of the Provider
value, if supported
type: object
type: object
version:
description: Used to select a specific version of the Provider
value, if supported
type: string
type: object
type: array
refreshInterval:

View file

@ -393,15 +393,15 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient p
// If tags were added get all secret by tags
// Also if a regular expression was entered
if len(remoteRef.Tags) > 0 || len(remoteRef.RegExp) > 0 {
if len(remoteRef.Find.Tags) > 0 || len(remoteRef.Find.Name.RegExp) > 0 {
secretMap, err = providerClient.GetAllSecrets(ctx, remoteRef)
if err != nil {
return nil, fmt.Errorf(errGetSecretKey, remoteRef.Key, externalSecret.Name, err)
return nil, fmt.Errorf(errGetSecretKey, remoteRef.Extract.Key, externalSecret.Name, err)
}
} else {
secretMap, err = providerClient.GetSecretMap(ctx, remoteRef)
if err != nil {
return nil, fmt.Errorf(errGetSecretKey, remoteRef.Key, externalSecret.Name, err)
return nil, fmt.Errorf(errGetSecretKey, remoteRef.Extract.Key, externalSecret.Name, err)
}
}
providerData = utils.MergeByteMap(providerData, secretMap)
@ -410,7 +410,7 @@ func (r *Reconciler) getProviderSecretData(ctx context.Context, providerClient p
for _, secretRef := range externalSecret.Spec.Data {
secretData, err := providerClient.GetSecret(ctx, secretRef.RemoteRef)
if err != nil {
return nil, fmt.Errorf(errGetSecretKey, secretRef.RemoteRef.Key, externalSecret.Name, err)
return nil, fmt.Errorf(errGetSecretKey, secretRef.RemoteRef.Extract.Key, externalSecret.Name, err)
}
providerData[secretRef.SecretKey] = secretData

View file

@ -218,8 +218,10 @@ var _ = Describe("ExternalSecret controller", func() {
{
SecretKey: targetProp,
RemoteRef: esv1alpha1.ExternalSecretDataRemoteRef{
Key: remoteKey,
Property: remoteProperty,
Extract: esv1alpha1.ExternalSecretExtract{
Key: remoteKey,
Property: remoteProperty,
},
},
},
},
@ -482,7 +484,9 @@ var _ = Describe("ExternalSecret controller", func() {
}
tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
{
Key: "datamap",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "datamap",
},
},
}
fakeProvider.WithGetSecret([]byte(secretVal), nil)
@ -648,7 +652,9 @@ var _ = Describe("ExternalSecret controller", func() {
tc.externalSecret.Spec.Data = nil
tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
{
Key: remoteKey,
Extract: esv1alpha1.ExternalSecretExtract{
Key: remoteKey,
},
},
}
fakeProvider.WithGetSecretMap(map[string][]byte{
@ -675,7 +681,9 @@ var _ = Describe("ExternalSecret controller", func() {
tc.externalSecret.Spec.DataFrom = []esv1alpha1.ExternalSecretDataRemoteRef{
{
Key: remoteKey,
Extract: esv1alpha1.ExternalSecretExtract{
Key: remoteKey,
},
},
}
fakeProvider.WithGetSecretMap(map[string][]byte{

View file

@ -115,13 +115,13 @@ func (a *Akeyless) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretD
return nil, err
}
version := int32(0)
if ref.Version != "" {
i, err := strconv.ParseInt(ref.Version, 10, 32)
if ref.Extract.Version != "" {
i, err := strconv.ParseInt(ref.Extract.Version, 10, 32)
if err == nil {
version = int32(i)
}
}
value, err := a.Client.GetSecretByType(ref.Key, token, version)
value, err := a.Client.GetSecretByType(ref.Extract.Key, token, version)
if err != nil {
return nil, err
}

View file

@ -51,8 +51,10 @@ func makeValidAkeylessTestCase() *akeylessTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "test-secret",
Version: "1",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "test-secret",
Version: "1",
},
}
}

View file

@ -116,26 +116,26 @@ func (kms *KeyManagementService) GetSecret(ctx context.Context, ref esv1alpha1.E
return nil, fmt.Errorf(errUninitalizedAlibabaProvider)
}
kmsRequest := kmssdk.CreateGetSecretValueRequest()
kmsRequest.VersionId = ref.Version
kmsRequest.SecretName = ref.Key
kmsRequest.VersionId = ref.Extract.Version
kmsRequest.SecretName = ref.Extract.Key
kmsRequest.SetScheme("https")
secretOut, err := kms.Client.GetSecretValue(kmsRequest)
if err != nil {
return nil, util.SanitizeErr(err)
}
if ref.Property == "" {
if ref.Extract.Property == "" {
if secretOut.SecretData != "" {
return []byte(secretOut.SecretData), nil
}
return nil, fmt.Errorf("invalid secret received. no secret string nor binary for key: %s", ref.Key)
return nil, fmt.Errorf("invalid secret received. no secret string nor binary for key: %s", ref.Extract.Key)
}
var payload string
if secretOut.SecretData != "" {
payload = secretOut.SecretData
}
val := gjson.Get(payload, ref.Property)
val := gjson.Get(payload, ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(val.String()), nil
}
@ -156,7 +156,7 @@ func (kms *KeyManagementService) GetSecretMap(ctx context.Context, ref esv1alpha
kv := make(map[string]string)
err = json.Unmarshal(data, &kv)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Key, err)
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Extract.Key, err)
}
secretData := make(map[string][]byte)
for k, v := range kv {

View file

@ -62,7 +62,9 @@ func makeValidKMSTestCase() *keyManagementServiceTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: secretName,
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretName,
},
}
}
@ -127,7 +129,7 @@ func TestAlibabaKMSGetSecret(t *testing.T) {
// good case: custom version set
setCustomKey := func(kmstc *keyManagementServiceTestCase) {
kmstc.apiOutput.SecretName = "test-example-other"
kmstc.ref.Key = "test-example-other"
kmstc.ref.Extract.Key = "test-example-other"
kmstc.apiOutput.SecretData = secretValue
kmstc.expectedSecret = secretValue
}

View file

@ -50,23 +50,23 @@ func New(sess client.ConfigProvider) (*ParameterStore, error) {
// GetSecret returns a single secret from the provider.
func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
log.Info("fetching secret value", "key", ref.Key)
log.Info("fetching secret value", "key", ref.Extract.Key)
out, err := pm.client.GetParameter(&ssm.GetParameterInput{
Name: &ref.Key,
Name: &ref.Extract.Key,
WithDecryption: aws.Bool(true),
})
if err != nil {
return nil, util.SanitizeErr(err)
}
if ref.Property == "" {
if ref.Extract.Property == "" {
if out.Parameter.Value != nil {
return []byte(*out.Parameter.Value), nil
}
return nil, fmt.Errorf("invalid secret received. parameter value is nil for key: %s", ref.Key)
return nil, fmt.Errorf("invalid secret received. parameter value is nil for key: %s", ref.Extract.Key)
}
val := gjson.Get(*out.Parameter.Value, ref.Property)
val := gjson.Get(*out.Parameter.Value, ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(val.String()), nil
}
@ -80,7 +80,7 @@ func (pm *ParameterStore) GetAllSecrets(ctx context.Context, ref esv1alpha1.Exte
// GetSecretMap returns multiple k/v pairs from the provider.
func (pm *ParameterStore) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
log.Info("fetching secret map", "key", ref.Key)
log.Info("fetching secret map", "key", ref.Extract.Key)
data, err := pm.GetSecret(ctx, ref)
if err != nil {
return nil, err
@ -88,7 +88,7 @@ func (pm *ParameterStore) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
kv := make(map[string]string)
err = json.Unmarshal(data, &kv)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Key, err)
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Extract.Key, err)
}
secretData := make(map[string][]byte)
for k, v := range kv {

View file

@ -68,7 +68,9 @@ func makeValidAPIOutput() *ssm.GetParameterOutput {
func makeValidRemoteRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "/baz",
},
}
}
@ -94,20 +96,20 @@ func TestGetSecret(t *testing.T) {
setExtractProperty := func(pstc *parameterstoreTestCase) {
pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo": "bang"}`)
pstc.expectedSecret = "bang"
pstc.remoteRef.Property = "/shmoo"
pstc.remoteRef.Extract.Property = "/shmoo"
}
// bad case: missing property
setMissingProperty := func(pstc *parameterstoreTestCase) {
pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo": "bang"}`)
pstc.remoteRef.Property = "INVALPROP"
pstc.remoteRef.Extract.Property = "INVALPROP"
pstc.expectError = "key INVALPROP does not exist in secret"
}
// bad case: extract property failure due to invalid json
setPropertyFail := func(pstc *parameterstoreTestCase) {
pstc.apiOutput.Parameter.Value = aws.String(`------`)
pstc.remoteRef.Property = "INVALPROP"
pstc.remoteRef.Extract.Property = "INVALPROP"
pstc.expectError = "key INVALPROP does not exist in secret"
}

View file

@ -52,18 +52,18 @@ func New(sess client.ConfigProvider) (*SecretsManager, error) {
func (sm *SecretsManager) fetch(_ context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (*awssm.GetSecretValueOutput, error) {
ver := "AWSCURRENT"
if ref.Version != "" {
ver = ref.Version
if ref.Extract.Version != "" {
ver = ref.Extract.Version
}
log.Info("fetching secret value", "key", ref.Key, "version", ver)
log.Info("fetching secret value", "key", ref.Extract.Key, "version", ver)
cacheKey := fmt.Sprintf("%s#%s", ref.Key, ver)
cacheKey := fmt.Sprintf("%s#%s", ref.Extract.Key, ver)
if secretOut, found := sm.cache[cacheKey]; found {
log.Info("found secret in cache", "key", ref.Key, "version", ver)
log.Info("found secret in cache", "key", ref.Extract.Key, "version", ver)
return secretOut, nil
}
secretOut, err := sm.client.GetSecretValue(&awssm.GetSecretValueInput{
SecretId: &ref.Key,
SecretId: &ref.Extract.Key,
VersionStage: &ver,
})
if err != nil {
@ -80,14 +80,14 @@ func (sm *SecretsManager) GetSecret(ctx context.Context, ref esv1alpha1.External
if err != nil {
return nil, util.SanitizeErr(err)
}
if ref.Property == "" {
if ref.Extract.Property == "" {
if secretOut.SecretString != nil {
return []byte(*secretOut.SecretString), nil
}
if secretOut.SecretBinary != nil {
return secretOut.SecretBinary, nil
}
return nil, fmt.Errorf("invalid secret received. no secret string nor binary for key: %s", ref.Key)
return nil, fmt.Errorf("invalid secret received. no secret string nor binary for key: %s", ref.Extract.Key)
}
var payload string
if secretOut.SecretString != nil {
@ -97,16 +97,16 @@ func (sm *SecretsManager) GetSecret(ctx context.Context, ref esv1alpha1.External
payload = string(secretOut.SecretBinary)
}
val := gjson.Get(payload, ref.Property)
val := gjson.Get(payload, ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(val.String()), nil
}
// GetSecretMap returns multiple k/v pairs from the provider.
func (sm *SecretsManager) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
log.Info("fetching secret map", "key", ref.Key)
log.Info("fetching secret map", "key", ref.Extract.Key)
data, err := sm.GetSecret(ctx, ref)
if err != nil {
return nil, err
@ -114,7 +114,7 @@ func (sm *SecretsManager) GetSecretMap(ctx context.Context, ref esv1alpha1.Exter
kv := make(map[string]json.RawMessage)
err = json.Unmarshal(data, &kv)
if err != nil {
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Key, err)
return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Extract.Key, err)
}
secretData := make(map[string][]byte)
for k, v := range kv {

View file

@ -61,8 +61,10 @@ func makeValidSecretsManagerTestCase() *secretsManagerTestCase {
func makeValidRemoteRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Version: "AWSCURRENT",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "/baz",
Version: "AWSCURRENT",
},
}
}
@ -108,20 +110,20 @@ func TestSecretsManagerGetSecret(t *testing.T) {
// good case: extract property
// Testing that the property exists in the SecretString
setRemoteRefPropertyExistsInKey := func(smtc *secretsManagerTestCase) {
smtc.remoteRef.Property = "/shmoo"
smtc.remoteRef.Extract.Property = "/shmoo"
smtc.apiOutput.SecretString = aws.String(`{"/shmoo": "bang"}`)
smtc.expectedSecret = "bang"
}
// bad case: missing property
setRemoteRefMissingProperty := func(smtc *secretsManagerTestCase) {
smtc.remoteRef.Property = "INVALPROP"
smtc.remoteRef.Extract.Property = "INVALPROP"
smtc.expectError = "key INVALPROP does not exist in secret"
}
// bad case: extract property failure due to invalid json
setRemoteRefMissingPropertyInvalidJSON := func(smtc *secretsManagerTestCase) {
smtc.remoteRef.Property = "INVALPROP"
smtc.remoteRef.Extract.Property = "INVALPROP"
smtc.apiOutput.SecretString = aws.String(`------`)
smtc.expectError = "key INVALPROP does not exist in secret"
}
@ -144,14 +146,14 @@ func TestSecretsManagerGetSecret(t *testing.T) {
setNestedSecretValueJSONParsing := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = nil
smtc.apiOutput.SecretBinary = []byte(`{"foobar":{"baz":"nestedval"}}`)
smtc.remoteRef.Property = "foobar.baz"
smtc.remoteRef.Extract.Property = "foobar.baz"
smtc.expectedSecret = "nestedval"
}
// good case: custom version set
setCustomVersion := func(smtc *secretsManagerTestCase) {
smtc.apiInput.VersionStage = aws.String("1234")
smtc.remoteRef.Version = "1234"
smtc.remoteRef.Extract.Version = "1234"
smtc.apiOutput.SecretString = aws.String("FOOBA!")
smtc.expectedSecret = "FOOBA!"
}
@ -190,26 +192,26 @@ func TestCaching(t *testing.T) {
// over 1
firstCall := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = aws.String(`{"foo":"bar", "bar":"vodka"}`)
smtc.remoteRef.Property = "foo"
smtc.remoteRef.Extract.Property = "foo"
smtc.expectedSecret = "bar"
smtc.expectedCounter = aws.Int(1)
smtc.fakeClient = fakeClient
}
secondCall := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = aws.String(`{"foo":"bar", "bar":"vodka"}`)
smtc.remoteRef.Property = "bar"
smtc.remoteRef.Extract.Property = "bar"
smtc.expectedSecret = "vodka"
smtc.expectedCounter = aws.Int(1)
smtc.fakeClient = fakeClient
}
notCachedCall := func(smtc *secretsManagerTestCase) {
smtc.apiOutput.SecretString = aws.String(`{"sheldon":"bazinga", "bar":"foo"}`)
smtc.remoteRef.Property = "sheldon"
smtc.remoteRef.Extract.Property = "sheldon"
smtc.expectedSecret = "bazinga"
smtc.expectedCounter = aws.Int(2)
smtc.fakeClient = fakeClient
smtc.apiInput.SecretId = aws.String("xyz")
smtc.remoteRef.Key = "xyz" // it should reset the cache since the key is different
smtc.remoteRef.Extract.Key = "xyz" // it should reset the cache since the key is different
}
cachedCases := []*secretsManagerTestCase{

View file

@ -99,8 +99,8 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretData
return nil, fmt.Errorf("%s name cannot be empty", objectType)
}
if ref.Version != "" {
version = ref.Version
if ref.Extract.Version != "" {
version = ref.Extract.Version
}
switch objectType {
@ -111,12 +111,12 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretData
if err != nil {
return nil, err
}
if ref.Property == "" {
if ref.Extract.Property == "" {
return []byte(*secretResp.Value), nil
}
res := gjson.Get(*secretResp.Value, ref.Property)
res := gjson.Get(*secretResp.Value, ref.Extract.Property)
if !res.Exists() {
return nil, fmt.Errorf("property %s does not exist in key %s", ref.Property, ref.Key)
return nil, fmt.Errorf("property %s does not exist in key %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(res.String()), err
case "cert":
@ -179,8 +179,8 @@ func (a *Azure) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretD
func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
basicClient := a.baseClient
secretsMap := make(map[string][]byte)
checkTags := len(ref.Tags) > 0
checkName := len(ref.RegExp) > 0
checkTags := len(ref.Find.Tags) > 0
checkName := len(ref.Find.Name.RegExp) > 0
secretListIter, err := basicClient.GetSecretsComplete(context.Background(), a.vaultURL, nil)
@ -219,13 +219,13 @@ func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1alpha1.ExternalSecret
}
func okByName(ref esv1alpha1.ExternalSecretDataRemoteRef, secretName string) bool {
matches, _ := regexp.MatchString(ref.RegExp, secretName)
matches, _ := regexp.MatchString(ref.Find.Name.RegExp, secretName)
return matches
}
func okByTags(ref esv1alpha1.ExternalSecretDataRemoteRef, secret keyvault.SecretItem) bool {
tagsFound := true
for k, v := range ref.Tags {
for k, v := range ref.Find.Tags {
if val, ok := secret.Tags[k]; !ok || *val != v {
tagsFound = false
break
@ -333,7 +333,7 @@ func (a *Azure) Close(ctx context.Context) error {
func getObjType(ref esv1alpha1.ExternalSecretDataRemoteRef) (string, string) {
objectType := defaultObjType
secretName := ref.Key
secretName := ref.Extract.Key
nameSplitted := strings.Split(secretName, "/")
if len(nameSplitted) > 1 {

View file

@ -30,7 +30,7 @@ import (
v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
fake "github.com/external-secrets/external-secrets/pkg/provider/azure/keyvault/fake"
"github.com/external-secrets/external-secrets/pkg/provider/schema"
utils "github.com/external-secrets/external-secrets/pkg/utils"
"github.com/external-secrets/external-secrets/pkg/utils"
)
type secretManagerTestCase struct {
@ -187,7 +187,7 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
}
badNoNameSecret := func(smtc *secretManagerTestCase) {
smtc.ref.Key = ""
smtc.ref.Extract.Key = ""
smtc.expectedSecret = ""
smtc.secretName = "secret/"
smtc.expectError = fmt.Sprintf("%s name cannot be empty", "secret")
@ -198,8 +198,8 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &secretString,
}
smtc.ref.Version = "v1"
smtc.secretVersion = smtc.ref.Version
smtc.ref.Extract.Version = "v1"
smtc.secretVersion = smtc.ref.Extract.Version
}
setSecretWithProperty := func(smtc *secretManagerTestCase) {
@ -208,7 +208,7 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &jsonString,
}
smtc.ref.Property = "Name"
smtc.ref.Extract.Property = "Name"
}
badSecretWithProperty := func(smtc *secretManagerTestCase) {
@ -217,8 +217,8 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &jsonString,
}
smtc.ref.Property = "Age"
smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Property, smtc.ref.Key)
smtc.ref.Extract.Property = "Age"
smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Extract.Property, smtc.ref.Extract.Key)
smtc.apiErr = fmt.Errorf(smtc.expectError)
}
@ -229,7 +229,7 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.keyOutput = keyvault.KeyBundle{
Key: newKVJWK([]byte(jwkPubRSA)),
}
smtc.ref.Key = smtc.secretName
smtc.ref.Extract.Key = smtc.secretName
}
// // good case: key set
@ -239,7 +239,7 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.keyOutput = keyvault.KeyBundle{
Key: newKVJWK([]byte(jwkPubEC)),
}
smtc.ref.Key = smtc.secretName
smtc.ref.Extract.Key = smtc.secretName
}
// // good case: key set
@ -250,14 +250,14 @@ func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
smtc.certOutput = keyvault.CertificateBundle{
Cer: &byteArrString,
}
smtc.ref.Key = smtc.secretName
smtc.ref.Extract.Key = smtc.secretName
}
badSecretType := func(smtc *secretManagerTestCase) {
smtc.secretName = "name"
smtc.expectedSecret = ""
smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName)
smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
smtc.ref.Extract.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
}
successCases := []*secretManagerTestCase{
@ -312,7 +312,7 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &jsonString,
}
smtc.ref.Property = "Address"
smtc.ref.Extract.Property = "Address"
smtc.expectedData["Street"] = []byte("Myroad st.")
smtc.expectedData["CP"] = []byte("J4K4T4")
@ -324,8 +324,8 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &jsonString,
}
smtc.ref.Property = "Age"
smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Property, smtc.ref.Key)
smtc.ref.Extract.Property = "Age"
smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Extract.Property, smtc.ref.Extract.Key)
smtc.apiErr = fmt.Errorf(smtc.expectError)
}
@ -335,7 +335,7 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
smtc.keyOutput = keyvault.KeyBundle{
Key: newKVJWK([]byte(jwkPubRSA)),
}
smtc.ref.Key = smtc.secretName
smtc.ref.Extract.Key = smtc.secretName
smtc.expectError = "cannot get use dataFrom to get key secret"
}
@ -346,7 +346,7 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
smtc.certOutput = keyvault.CertificateBundle{
Cer: &byteArrString,
}
smtc.ref.Key = smtc.secretName
smtc.ref.Extract.Key = smtc.secretName
smtc.expectError = "cannot get use dataFrom to get certificate secret"
}
@ -354,7 +354,7 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
smtc.secretName = "name"
smtc.expectedSecret = ""
smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName)
smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
smtc.ref.Extract.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
}
successCases := []*secretManagerTestCase{
@ -382,6 +382,12 @@ func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
secretString := "changedvalue"
secretName := "example-1"
wrongName := "not-valid"
environment := "dev"
author := "seb"
regexp := "^example"
enabled := true
getNextPage := func(ctx context.Context, list keyvault.SecretListResult) (result keyvault.SecretListResult, err error) {
return keyvault.SecretListResult{
@ -391,10 +397,7 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
}
setOneSecretByName := func(smtc *secretManagerTestCase) {
smtc.ref.RegExp = "^example"
secretName := "example-1"
enabled := true
smtc.ref.Find.Name.RegExp = regexp
enabledAtt := keyvault.SecretAttributes{
Enabled: &enabled,
}
@ -422,11 +425,7 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
}
setTwoSecretsByName := func(smtc *secretManagerTestCase) {
smtc.ref.RegExp = "^example"
secretName := "example-1"
wrongName := "not-valid"
enabled := true
smtc.ref.Find.Name.RegExp = regexp
enabledAtt := keyvault.SecretAttributes{
Enabled: &enabled,
}
@ -460,11 +459,6 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
}
setOneSecretByTag := func(smtc *secretManagerTestCase) {
secretName := "example-1"
environment := "dev"
enabled := true
enabledAtt := keyvault.SecretAttributes{
Enabled: &enabled,
}
@ -488,16 +482,12 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &secretString,
}
smtc.ref.Tags = map[string]string{"environment": environment}
smtc.ref.Find.Tags = map[string]string{"environment": environment}
smtc.expectedData["example-1"] = []byte(secretString)
smtc.expectedData[secretName] = []byte(secretString)
}
setTwoSecretsByTag := func(smtc *secretManagerTestCase) {
secretName := "example-1"
environment := "dev"
author := "seb"
enabled := true
enabledAtt := keyvault.SecretAttributes{
Enabled: &enabled,
@ -522,9 +512,9 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
smtc.secretOutput = keyvault.SecretBundle{
Value: &secretString,
}
smtc.ref.Tags = map[string]string{"environment": environment, "author": author}
smtc.ref.Find.Tags = map[string]string{"environment": environment, "author": author}
smtc.expectedData["example-1"] = []byte(secretString)
smtc.expectedData[secretName] = []byte(secretString)
}
successCases := []*secretManagerTestCase{
@ -549,7 +539,9 @@ func TestAzureKeyVaultSecretManagerGetAllSecrets(t *testing.T) {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "test-secret",
Version: "default",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "test-secret",
Version: "default",
},
}
}

View file

@ -167,24 +167,24 @@ func (sm *ProviderGCP) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSec
return nil, fmt.Errorf(errUninitalizedGCPProvider)
}
version := ref.Version
version := ref.Extract.Version
if version == "" {
version = defaultVersion
}
req := &secretmanagerpb.AccessSecretVersionRequest{
Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", sm.projectID, ref.Key, version),
Name: fmt.Sprintf("projects/%s/secrets/%s/versions/%s", sm.projectID, ref.Extract.Key, version),
}
result, err := sm.SecretManagerClient.AccessSecretVersion(ctx, req)
if err != nil {
return nil, fmt.Errorf(errClientGetSecretAccess, err)
}
if ref.Property == "" {
if ref.Extract.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 nil, fmt.Errorf("invalid secret received. no secret string for key: %s", ref.Extract.Key)
}
var payload string
@ -192,9 +192,9 @@ func (sm *ProviderGCP) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSec
payload = string(result.Payload.Data)
}
val := gjson.Get(payload, ref.Property)
val := gjson.Get(payload, ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(val.String()), nil
}

View file

@ -58,8 +58,10 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Version: "default",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "/baz",
Version: "default",
},
}
}
@ -111,9 +113,11 @@ func TestSecretManagerGetSecret(t *testing.T) {
// good case: ref with
setCustomRef := func(smtc *secretManagerTestCase) {
smtc.ref = &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "/baz",
Version: "default",
Property: "name.first",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "/baz",
Version: "default",
Property: "name.first",
},
}
smtc.apiInput.Name = "projects/default/secrets//baz/versions/default"
smtc.apiOutput.Payload.Data = []byte(
@ -130,7 +134,7 @@ func TestSecretManagerGetSecret(t *testing.T) {
// good case: custom version set
setCustomVersion := func(smtc *secretManagerTestCase) {
smtc.ref.Version = "1234"
smtc.ref.Extract.Version = "1234"
smtc.apiInput.Name = "projects/default/secrets//baz/versions/1234"
smtc.apiOutput.Payload.Data = []byte("FOOBA!")
smtc.expectedSecret = "FOOBA!"

View file

@ -153,7 +153,7 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDat
return nil, fmt.Errorf(errUninitalizedGitlabProvider)
}
// Need to replace hyphens with underscores to work with Gitlab API
ref.Key = strings.ReplaceAll(ref.Key, "-", "_")
ref.Extract.Key = strings.ReplaceAll(ref.Extract.Key, "-", "_")
// Retrieves a gitlab variable in the form
// {
// "key": "TEST_VARIABLE_1",
@ -161,16 +161,16 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDat
// "value": "TEST_1",
// "protected": false,
// "masked": true
data, _, err := g.client.GetVariable(g.projectID, ref.Key, nil) // Optional 'filter' parameter could be added later
data, _, err := g.client.GetVariable(g.projectID, ref.Extract.Key, nil) // Optional 'filter' parameter could be added later
if err != nil {
return nil, err
}
if ref.Property == "" {
if ref.Extract.Property == "" {
if data.Value != "" {
return []byte(data.Value), nil
}
return nil, fmt.Errorf("invalid secret received. no secret string for key: %s", ref.Key)
return nil, fmt.Errorf("invalid secret received. no secret string for key: %s", ref.Extract.Key)
}
var payload string
@ -178,9 +178,9 @@ func (g *Gitlab) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDat
payload = data.Value
}
val := gjson.Get(payload, ref.Property)
val := gjson.Get(payload, ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
return []byte(val.String()), nil
}
@ -196,7 +196,7 @@ func (g *Gitlab) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecret
// Gets a secret as normal, expecting secret value to be a json object
data, err := g.GetSecret(ctx, ref)
if err != nil {
return nil, fmt.Errorf("error getting secret %s: %w", ref.Key, err)
return nil, fmt.Errorf("error getting secret %s: %w", ref.Extract.Key, err)
}
// Maps the json data to a string:string map

View file

@ -59,8 +59,10 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "test-secret",
Version: "default",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "test-secret",
Version: "default",
},
}
}

View file

@ -106,7 +106,7 @@ func (ibm *providerIBM) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSe
}
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretName := ref.Key
secretName := ref.Extract.Key
nameSplitted := strings.Split(secretName, "/")
if len(nameSplitted) > 1 {
@ -121,7 +121,7 @@ func (ibm *providerIBM) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSe
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
if ref.Property == "" {
if ref.Extract.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type username_password")
}
return getUsernamePasswordSecret(ibm, &secretName, ref)
@ -132,8 +132,8 @@ func (ibm *providerIBM) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSe
case sm.CreateSecretOptionsSecretTypeImportedCertConst:
if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type imported_cert")
if ref.Extract.Property == "" {
return nil, fmt.Errorf("remoteRef.Extract.property required for secret type imported_cert")
}
return getImportCertSecret(ibm, &secretName, ref)
@ -171,10 +171,10 @@ func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1alpha1.Ex
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
if val, ok := secretData[ref.Property]; ok {
if val, ok := secretData[ref.Extract.Property]; ok {
return []byte(val.(string)), nil
}
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
func getIamCredentialsSecret(ibm *providerIBM, secretName *string) ([]byte, error) {
@ -206,10 +206,10 @@ func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1alp
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData.(map[string]interface{})
if val, ok := secretData[ref.Property]; ok {
if val, ok := secretData[ref.Extract.Property]; ok {
return []byte(val.(string)), nil
}
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Extract.Property, ref.Extract.Key)
}
func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
@ -218,7 +218,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1alpha1.Externa
}
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretName := ref.Key
secretName := ref.Extract.Key
nameSplitted := strings.Split(secretName, "/")
if len(nameSplitted) > 1 {
@ -231,7 +231,7 @@ func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1alpha1.Externa
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &ref.Key,
ID: &ref.Extract.Key,
})
if err != nil {
return nil, err

View file

@ -63,8 +63,10 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "test-secret",
Version: "default",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "test-secret",
Version: "default",
},
}
}
@ -146,7 +148,7 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
Name: utilpointer.StringPtr("testyname"),
SecretData: secretData,
}}
smtc.ref.Key = "testyname"
smtc.ref.Extract.Key = "testyname"
smtc.apiInput.ID = utilpointer.StringPtr("testyname")
smtc.apiOutput.Resources = resources
smtc.expectedSecret = secretString
@ -164,7 +166,7 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretUserPass
smtc.ref.Extract.Key = secretUserPass
smtc.expectError = "remoteRef.property required for secret type username_password"
}
@ -179,8 +181,8 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretUserPass
smtc.ref.Property = "password"
smtc.ref.Extract.Key = secretUserPass
smtc.ref.Extract.Property = "password"
smtc.expectedSecret = secretPassword
}
@ -195,7 +197,7 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "iam_credentials/test-secret"
smtc.ref.Extract.Key = "iam_credentials/test-secret"
smtc.expectedSecret = secretAPIKey
}
@ -211,8 +213,8 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretCert
smtc.ref.Property = "certificate"
smtc.ref.Extract.Key = secretCert
smtc.ref.Extract.Property = "certificate"
smtc.expectedSecret = secretCertificate
}
@ -227,8 +229,8 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretCert
smtc.expectError = "remoteRef.property required for secret type imported_cert"
smtc.ref.Extract.Key = secretCert
smtc.expectError = "remoteRef.Extract.property required for secret type imported_cert"
}
successCases := []*secretManagerTestCase{
@ -311,7 +313,7 @@ func TestGetSecretMap(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "username_password/test-secret"
smtc.ref.Extract.Key = "username_password/test-secret"
smtc.expectedData["username"] = []byte(secretUsername)
smtc.expectedData["password"] = []byte(secretPassword)
}
@ -327,7 +329,7 @@ func TestGetSecretMap(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "iam_credentials/test-secret"
smtc.ref.Extract.Key = "iam_credentials/test-secret"
smtc.expectedData["apikey"] = []byte(secretAPIKey)
}
@ -347,7 +349,7 @@ func TestGetSecretMap(t *testing.T) {
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = "imported_cert/test-secret"
smtc.ref.Extract.Key = "imported_cert/test-secret"
smtc.expectedData["certificate"] = []byte(secretCertificate)
smtc.expectedData["private_key"] = []byte(secretPrivateKey)
smtc.expectedData["intermediate"] = []byte(secretIntermediate)

View file

@ -132,8 +132,8 @@ func (vms *VaultManagementService) GetSecret(ctx context.Context, ref esv1alpha1
sec, err := vms.Client.GetSecretBundleByName(ctx, secrets.GetSecretBundleByNameRequest{
VaultId: &vms.vault,
SecretName: &ref.Key,
Stage: secrets.GetSecretBundleByNameStageEnum(ref.Version),
SecretName: &ref.Extract.Key,
Stage: secrets.GetSecretBundleByNameStageEnum(ref.Extract.Version),
})
if err != nil {
return nil, util.SanitizeErr(err)
@ -149,14 +149,14 @@ func (vms *VaultManagementService) GetSecret(ctx context.Context, ref esv1alpha1
return nil, err
}
if ref.Property == "" {
if ref.Extract.Property == "" {
return payload, nil
}
val := gjson.Get(string(payload), ref.Property)
val := gjson.Get(string(payload), ref.Extract.Property)
if !val.Exists() {
return nil, fmt.Errorf(errMissingKey, ref.Key)
return nil, fmt.Errorf(errMissingKey, ref.Extract.Key)
}
return []byte(val.String()), nil

View file

@ -55,8 +55,10 @@ func makeValidVaultTestCase() *vaultTestCase {
func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
return &esv1alpha1.ExternalSecretDataRemoteRef{
Key: "test-secret",
Version: "default",
Extract: esv1alpha1.ExternalSecretExtract{
Key: "test-secret",
Version: "default",
},
}
}

View file

@ -148,19 +148,19 @@ func (c *connector) NewClient(ctx context.Context, store esv1alpha1.GenericStore
}
func (v *client) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
data, err := v.readSecret(ctx, ref.Key, ref.Version)
data, err := v.readSecret(ctx, ref.Extract.Key, ref.Extract.Version)
if err != nil {
return nil, err
}
value, exists := data[ref.Property]
value, exists := data[ref.Extract.Property]
if !exists {
return nil, fmt.Errorf(errSecretKeyFmt, ref.Property)
return nil, fmt.Errorf(errSecretKeyFmt, ref.Extract.Property)
}
return value, nil
}
func (v *client) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
return v.readSecret(ctx, ref.Key, ref.Version)
return v.readSecret(ctx, ref.Extract.Key, ref.Extract.Version)
}
// Implements store.Client.GetAllSecrets Interface.

View file

@ -181,9 +181,9 @@ func (w *WebHook) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecre
func (w *WebHook) getTemplateData(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef, secrets []esv1alpha1.WebhookSecret) (map[string]map[string]string, error) {
data := map[string]map[string]string{
"remoteRef": {
"key": url.QueryEscape(ref.Key),
"version": url.QueryEscape(ref.Version),
"property": url.QueryEscape(ref.Property),
"key": url.QueryEscape(ref.Extract.Key),
"version": url.QueryEscape(ref.Extract.Version),
"property": url.QueryEscape(ref.Extract.Property),
},
}
for _, secref := range secrets {

View file

@ -270,8 +270,10 @@ func runTestCase(tc testCase, t *testing.T) {
func testGetSecretMap(tc testCase, t *testing.T, client provider.SecretsClient) {
testRef := esv1alpha1.ExternalSecretDataRemoteRef{
Key: tc.Args.Key,
Version: tc.Args.Version,
Extract: esv1alpha1.ExternalSecretExtract{
Key: tc.Args.Key,
Version: tc.Args.Version,
},
}
secretmap, err := client.GetSecretMap(context.Background(), testRef)
errStr := ""
@ -295,8 +297,10 @@ func testGetSecretMap(tc testCase, t *testing.T, client provider.SecretsClient)
func testGetSecret(tc testCase, t *testing.T, client provider.SecretsClient) {
testRef := esv1alpha1.ExternalSecretDataRemoteRef{
Key: tc.Args.Key,
Version: tc.Args.Version,
Extract: esv1alpha1.ExternalSecretExtract{
Key: tc.Args.Key,
Version: tc.Args.Version,
},
}
secret, err := client.GetSecret(context.Background(), testRef)
errStr := ""

View file

@ -226,12 +226,12 @@ type lockboxSecretsClient struct {
// GetSecret returns a single secret from the provider.
func (c *lockboxSecretsClient) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
entries, err := c.lockboxClient.GetPayloadEntries(ctx, c.iamToken, ref.Key, ref.Version)
entries, err := c.lockboxClient.GetPayloadEntries(ctx, c.iamToken, ref.Extract.Key, ref.Extract.Version)
if err != nil {
return nil, fmt.Errorf("unable to request secret payload to get secret: %w", err)
}
if ref.Property == "" {
if ref.Extract.Property == "" {
keyToValue := make(map[string]interface{}, len(entries))
for _, entry := range entries {
value, err := getValueAsIs(entry)
@ -247,7 +247,7 @@ func (c *lockboxSecretsClient) GetSecret(ctx context.Context, ref esv1alpha1.Ext
return out, nil
}
entry, err := findEntryByKey(entries, ref.Property)
entry, err := findEntryByKey(entries, ref.Extract.Property)
if err != nil {
return nil, err
}
@ -263,7 +263,7 @@ func (c *lockboxSecretsClient) GetAllSecrets(ctx context.Context, ref esv1alpha1
// GetSecretMap returns multiple k/v pairs from the provider.
func (c *lockboxSecretsClient) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
entries, err := c.lockboxClient.GetPayloadEntries(ctx, c.iamToken, ref.Key, ref.Version)
entries, err := c.lockboxClient.GetPayloadEntries(ctx, c.iamToken, ref.Extract.Key, ref.Extract.Version)
if err != nil {
return nil, fmt.Errorf("unable to request secret payload to get secret map: %w", err)
}

View file

@ -131,7 +131,11 @@ func TestGetSecretForAllEntries(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID})
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
},
})
tassert.Nil(t, err)
tassert.Equal(
@ -169,7 +173,12 @@ func TestGetSecretForTextEntry(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Property: k1})
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Property: k1,
},
})
tassert.Nil(t, err)
tassert.Equal(t, v1, string(data))
@ -200,7 +209,12 @@ func TestGetSecretForBinaryEntry(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Property: k2})
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Property: k2,
},
})
tassert.Nil(t, err)
tassert.Equal(t, v2, data)
@ -229,7 +243,12 @@ func TestGetSecretByVersionID(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: oldVersionID})
data, err := secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: oldVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string]string{oldKey: oldVal}, unmarshalStringMap(t, data))
@ -239,11 +258,21 @@ func TestGetSecretByVersionID(t *testing.T) {
textEntry(newKey, newVal),
)
data, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: oldVersionID})
data, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: oldVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string]string{oldKey: oldVal}, unmarshalStringMap(t, data))
data, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: newVersionID})
data, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: newVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string]string{newKey: newVal}, unmarshalStringMap(t, data))
}
@ -271,7 +300,11 @@ func TestGetSecretUnauthorized(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID})
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
},
})
tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
}
@ -294,13 +327,22 @@ func TestGetSecretNotFound(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: "no-secret-with-this-id"})
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: "no-secret-with-this-id",
},
})
tassert.EqualError(t, err, errSecretPayloadNotFound)
secretID, _ := lockboxBackend.CreateSecret(authorizedKey,
textEntry("k1", "v1"),
)
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: "no-version-with-this-id"})
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: "no-version-with-this-id",
},
})
tassert.EqualError(t, err, "unable to request secret payload to get secret: version not found")
}
@ -339,17 +381,37 @@ func TestGetSecretWithTwoNamespaces(t *testing.T) {
secretsClient2, err := provider.NewClient(ctx, store2, k8sClient, namespace2)
tassert.Nil(t, err)
data, err := secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID1, Property: k1})
data, err := secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
Property: k1,
},
})
tassert.Equal(t, v1, string(data))
tassert.Nil(t, err)
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID2, Property: k2})
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID2,
Property: k2,
},
})
tassert.Nil(t, data)
tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID1, Property: k1})
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
Property: k1,
},
})
tassert.Nil(t, data)
tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID2, Property: k2})
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID2,
Property: k2,
},
})
tassert.Equal(t, v2, string(data))
tassert.Nil(t, err)
}
@ -400,17 +462,37 @@ func TestGetSecretWithTwoApiEndpoints(t *testing.T) {
var data []byte
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID1, Property: k1})
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
Property: k1,
},
})
tassert.Equal(t, v1, string(data))
tassert.Nil(t, err)
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID2, Property: k2})
data, err = secretsClient1.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID2,
Property: k2,
},
})
tassert.Nil(t, data)
tassert.EqualError(t, err, errSecretPayloadNotFound)
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID1, Property: k1})
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
Property: k1,
},
})
tassert.Nil(t, data)
tassert.EqualError(t, err, errSecretPayloadNotFound)
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID2, Property: k2})
data, err = secretsClient2.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
Property: k2,
},
})
tassert.Equal(t, v2, string(data))
tassert.Nil(t, err)
}
@ -442,19 +524,34 @@ func TestGetSecretWithIamTokenExpiration(t *testing.T) {
oldSecretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err = oldSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Property: k1})
data, err = oldSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Property: k1,
},
})
tassert.Equal(t, v1, string(data))
tassert.Nil(t, err)
lockboxBackend.AdvanceClock(2 * tokenExpirationTime)
data, err = oldSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Property: k1})
data, err = oldSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Property: k1,
},
})
tassert.Nil(t, data)
tassert.EqualError(t, err, "unable to request secret payload to get secret: iam token expired")
newSecretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err = newSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Property: k1})
data, err = newSecretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Property: k1,
},
})
tassert.Equal(t, v1, string(data))
tassert.Nil(t, err)
}
@ -499,7 +596,11 @@ func TestGetSecretWithIamTokenCleanup(t *testing.T) {
// Access secretID1 with authorizedKey1, IAM token for authorizedKey1 should be cached
secretsClient, err := provider.NewClient(ctx, store1, k8sClient, namespace)
tassert.Nil(t, err)
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID1})
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID1,
},
})
tassert.Nil(t, err)
tassert.True(t, provider.isIamTokenCached(authorizedKey1))
@ -510,7 +611,11 @@ func TestGetSecretWithIamTokenCleanup(t *testing.T) {
// Access secretID2 with authorizedKey2, IAM token for authorizedKey2 should be cached
secretsClient, err = provider.NewClient(ctx, store2, k8sClient, namespace)
tassert.Nil(t, err)
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID2})
_, err = secretsClient.GetSecret(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID2,
},
})
tassert.Nil(t, err)
tassert.True(t, provider.isIamTokenCached(authorizedKey1))
@ -562,7 +667,11 @@ func TestGetSecretMap(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID})
data, err := secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
},
})
tassert.Nil(t, err)
tassert.Equal(
@ -598,7 +707,12 @@ func TestGetSecretMapByVersionID(t *testing.T) {
})
secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
tassert.Nil(t, err)
data, err := secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: oldVersionID})
data, err := secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: oldVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string][]byte{oldKey: []byte(oldVal)}, data)
@ -608,11 +722,21 @@ func TestGetSecretMapByVersionID(t *testing.T) {
textEntry(newKey, newVal),
)
data, err = secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: oldVersionID})
data, err = secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: oldVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string][]byte{oldKey: []byte(oldVal)}, data)
data, err = secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{Key: secretID, Version: newVersionID})
data, err = secretsClient.GetSecretMap(ctx, esv1alpha1.ExternalSecretDataRemoteRef{
Extract: esv1alpha1.ExternalSecretExtract{
Key: secretID,
Version: newVersionID,
},
})
tassert.Nil(t, err)
tassert.Equal(t, map[string][]byte{newKey: []byte(newVal)}, data)
}