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

update ibm secrets manager provider version to v2 (#2254)

* update ibm secrets manager version to v2

Signed-off-by: tanishg6@gmail.com <tanishg6@gmail.com>

* update go.mod to point to v2.0.0

Signed-off-by: tanishg6@gmail.com <tanishg6@gmail.com>

---------

Signed-off-by: tanishg6@gmail.com <tanishg6@gmail.com>
Signed-off-by: Shanti G <81566195+Shanti-G@users.noreply.github.com>
This commit is contained in:
Shanti G 2023-05-14 12:48:56 +05:30 committed by GitHub
parent ddfe51d715
commit 405c12c314
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 482 additions and 525 deletions

2
go.mod
View file

@ -11,7 +11,7 @@ require (
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/Azure/go-autorest/autorest/azure/auth v0.5.12
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0
github.com/IBM/go-sdk-core/v5 v5.13.1 github.com/IBM/go-sdk-core/v5 v5.13.1
github.com/IBM/secrets-manager-go-sdk v1.2.0 github.com/IBM/secrets-manager-go-sdk/v2 v2.0.0
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 github.com/Masterminds/sprig/v3 v3.2.3
github.com/PaesslerAG/jsonpath v0.1.1 github.com/PaesslerAG/jsonpath v0.1.1

4
go.sum
View file

@ -91,8 +91,8 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/IBM/go-sdk-core/v5 v5.13.1 h1:zD6p3t1whAlRJo/VBmE69c8RcH9LCHL1n0/sO1MWlpw= github.com/IBM/go-sdk-core/v5 v5.13.1 h1:zD6p3t1whAlRJo/VBmE69c8RcH9LCHL1n0/sO1MWlpw=
github.com/IBM/go-sdk-core/v5 v5.13.1/go.mod h1:pVkN7IGmsSdmR1ZCU4E/cLcCclqRKMYgg7ya+O2Mk6g= github.com/IBM/go-sdk-core/v5 v5.13.1/go.mod h1:pVkN7IGmsSdmR1ZCU4E/cLcCclqRKMYgg7ya+O2Mk6g=
github.com/IBM/secrets-manager-go-sdk v1.2.0 h1:bgFfBF+LjHLtUfV3hTLkfgE8EjFsJaeU2icA2Hg+M50= github.com/IBM/secrets-manager-go-sdk/v2 v2.0.0 h1:Lx4Bvim/MfoHEYR+n312bty5DirAJypBGGS9YZo3zCw=
github.com/IBM/secrets-manager-go-sdk v1.2.0/go.mod h1:qv+tQg8Z3Vb11DQYxDjEGeROHDtTLQxUWuOIrIdWg6E= github.com/IBM/secrets-manager-go-sdk/v2 v2.0.0/go.mod h1:jagqWmjZ0zUEqh5jdGB42ApSQS40fu2LWw6pdg8JJko=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=

View file

@ -14,31 +14,38 @@ limitations under the License.
package fake package fake
import ( import (
"context"
"fmt" "fmt"
"github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/go-sdk-core/v5/core"
sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1" sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
) )
type IBMMockClient struct { type IBMMockClient struct {
getSecret func(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) getSecretWithContext func(ctx context.Context, getSecretOptions *sm.GetSecretOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
} }
func (mc *IBMMockClient) GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) { type IBMMockClientParams struct {
return mc.getSecret(getSecretOptions) GetSecretOptions *sm.GetSecretOptions
GetSecretOutput sm.SecretIntf
GetSecretErr error
} }
func (mc *IBMMockClient) WithValue(input *sm.GetSecretOptions, output *sm.GetSecret, err error) { func (mc *IBMMockClient) GetSecretWithContext(ctx context.Context, getSecretOptions *sm.GetSecretOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error) {
return mc.getSecretWithContext(ctx, getSecretOptions)
}
func (mc *IBMMockClient) WithValue(params IBMMockClientParams) {
if mc != nil { if mc != nil {
mc.getSecret = func(paramReq *sm.GetSecretOptions) (*sm.GetSecret, *core.DetailedResponse, error) { mc.getSecretWithContext = func(ctx context.Context, paramReq *sm.GetSecretOptions) (sm.SecretIntf, *core.DetailedResponse, error) {
// type secretmanagerpb.AccessSecretVersionRequest contains unexported fields // type secretmanagerpb.AccessSecretVersionRequest contains unexported fields
// use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp. // use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp.
if !cmp.Equal(paramReq, input, cmpopts.IgnoreUnexported(sm.GetSecret{})) { if !cmp.Equal(paramReq, params.GetSecretOptions, cmpopts.IgnoreUnexported(sm.Secret{})) {
return nil, nil, fmt.Errorf("unexpected test argument") return nil, nil, fmt.Errorf("unexpected test argument for GetSecret: %s, %s", *paramReq.ID, *params.GetSecretOptions.ID)
} }
return output, nil, err return params.GetSecretOutput, nil, params.GetSecretErr
} }
} }
} }

View file

@ -23,11 +23,10 @@ import (
"time" "time"
core "github.com/IBM/go-sdk-core/v5/core" core "github.com/IBM/go-sdk-core/v5/core"
sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1" sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
gjson "github.com/tidwall/gjson" gjson "github.com/tidwall/gjson"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
types "k8s.io/apimachinery/pkg/types" types "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
kclient "sigs.k8s.io/controller-runtime/pkg/client" kclient "sigs.k8s.io/controller-runtime/pkg/client"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1" esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
@ -40,6 +39,14 @@ const (
STSEndpointEnv = "IBM_STS_ENDPOINT" STSEndpointEnv = "IBM_STS_ENDPOINT"
SSMEndpointEnv = "IBM_SSM_ENDPOINT" SSMEndpointEnv = "IBM_SSM_ENDPOINT"
certificateConst = "certificate"
intermediateConst = "intermediate"
privateKeyConst = "private_key"
usernameConst = "username"
passwordConst = "password"
apikeyConst = "apikey"
arbitraryConst = "arbitrary"
errIBMClient = "cannot setup new ibm client: %w" errIBMClient = "cannot setup new ibm client: %w"
errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey" errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey"
errUninitalizedIBMProvider = "provider IBM is not initialized" errUninitalizedIBMProvider = "provider IBM is not initialized"
@ -47,14 +54,17 @@ const (
errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w" errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
errMissingSAK = "missing SecretAccessKey" errMissingSAK = "missing SecretAccessKey"
errJSONSecretUnmarshal = "unable to unmarshal secret: %w" errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
errExtractingSecret = "unable to extract the fetched secret %s of type %s"
) )
var contextTimeout = time.Minute * 2
// https://github.com/external-secrets/external-secrets/issues/644 // https://github.com/external-secrets/external-secrets/issues/644
var _ esv1beta1.SecretsClient = &providerIBM{} var _ esv1beta1.SecretsClient = &providerIBM{}
var _ esv1beta1.Provider = &providerIBM{} var _ esv1beta1.Provider = &providerIBM{}
type SecretManagerClient interface { type SecretManagerClient interface {
GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error) GetSecretWithContext(ctx context.Context, getSecretOptions *sm.GetSecretOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
} }
type providerIBM struct { type providerIBM struct {
@ -69,8 +79,6 @@ type client struct {
credentials []byte credentials []byte
} }
var log = ctrl.Log.WithName("provider").WithName("ibm").WithName("secretsmanager")
func (c *client) setAuth(ctx context.Context) error { func (c *client) setAuth(ctx context.Context) error {
credentialsSecret := &corev1.Secret{} credentialsSecret := &corev1.Secret{}
credentialsSecretName := c.store.Auth.SecretRef.SecretAPIKey.Name credentialsSecretName := c.store.Auth.SecretRef.SecretAPIKey.Name
@ -122,7 +130,7 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
return nil, fmt.Errorf(errUninitalizedIBMProvider) return nil, fmt.Errorf(errUninitalizedIBMProvider)
} }
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst secretType := sm.Secret_SecretType_Arbitrary
secretName := ref.Key secretName := ref.Key
nameSplitted := strings.Split(secretName, "/") nameSplitted := strings.Split(secretName, "/")
@ -132,22 +140,21 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
} }
switch secretType { switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst: case sm.Secret_SecretType_Arbitrary:
return getArbitrarySecret(ibm, &secretName) return getArbitrarySecret(ibm, &secretName)
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst: case sm.Secret_SecretType_UsernamePassword:
if ref.Property == "" { if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type username_password") return nil, fmt.Errorf("remoteRef.property required for secret type username_password")
} }
return getUsernamePasswordSecret(ibm, &secretName, ref) return getUsernamePasswordSecret(ibm, &secretName, ref)
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst: case sm.Secret_SecretType_IamCredentials:
return getIamCredentialsSecret(ibm, &secretName) return getIamCredentialsSecret(ibm, &secretName)
case sm.CreateSecretOptionsSecretTypeImportedCertConst: case sm.Secret_SecretType_ImportedCert:
if ref.Property == "" { if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type imported_cert") return nil, fmt.Errorf("remoteRef.property required for secret type imported_cert")
@ -155,7 +162,7 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
return getImportCertSecret(ibm, &secretName, ref) return getImportCertSecret(ibm, &secretName, ref)
case sm.CreateSecretOptionsSecretTypePublicCertConst: case sm.Secret_SecretType_PublicCert:
if ref.Property == "" { if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type public_cert") return nil, fmt.Errorf("remoteRef.property required for secret type public_cert")
@ -163,7 +170,7 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
return getPublicCertSecret(ibm, &secretName, ref) return getPublicCertSecret(ibm, &secretName, ref)
case sm.CreateSecretOptionsSecretTypePrivateCertConst: case sm.Secret_SecretType_PrivateCert:
if ref.Property == "" { if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type private_cert") return nil, fmt.Errorf("remoteRef.property required for secret type private_cert")
@ -171,7 +178,7 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
return getPrivateCertSecret(ibm, &secretName, ref) return getPrivateCertSecret(ibm, &secretName, ref)
case sm.CreateSecretOptionsSecretTypeKvConst: case sm.Secret_SecretType_Kv:
return getKVSecret(ibm, &secretName, ref) return getKVSecret(ibm, &secretName, ref)
@ -181,150 +188,130 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
} }
func getArbitrarySecret(ibm *providerIBM, secretName *string) ([]byte, error) { func getArbitrarySecret(ibm *providerIBM, secretName *string) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.ArbitrarySecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_Arbitrary)
}
secret := response.Resources[0].(*sm.SecretResource) return []byte(*secret.Payload), nil
secretData := secret.SecretData
arbitrarySecretPayload := secretData["payload"].(string)
return []byte(arbitrarySecretPayload), nil
} }
func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.ImportedCertificate)
secret := response.Resources[0].(*sm.SecretResource) if !ok {
secretData := secret.SecretData return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_ImportedCert)
}
if val, ok := secretData[ref.Property]; ok { switch ref.Property {
return []byte(val.(string)), nil case certificateConst:
return []byte(*secret.Certificate), nil
case intermediateConst:
return []byte(*secret.Intermediate), nil
case privateKeyConst:
return []byte(*secret.PrivateKey), nil
default:
return nil, fmt.Errorf("unknown property type %s", ref.Property)
} }
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
} }
func getPublicCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { func getPublicCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.PublicCertificate)
secret := response.Resources[0].(*sm.SecretResource) if !ok {
secretData := secret.SecretData return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_PublicCert)
}
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil switch ref.Property {
case certificateConst:
return []byte(*secret.Certificate), nil
case intermediateConst:
return []byte(*secret.Intermediate), nil
case privateKeyConst:
return []byte(*secret.PrivateKey), nil
default:
return nil, fmt.Errorf("unknown property type %s", ref.Property)
} }
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
} }
func getPrivateCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { func getPrivateCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.PrivateCertificate)
secret := response.Resources[0].(*sm.SecretResource) if !ok {
secretData := secret.SecretData return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_PrivateCert)
}
if val, ok := secretData[ref.Property]; ok { switch ref.Property {
return []byte(val.(string)), nil case certificateConst:
return []byte(*secret.Certificate), nil
case privateKeyConst:
return []byte(*secret.PrivateKey), nil
default:
return nil, fmt.Errorf("unknown property type %s", ref.Property)
} }
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
} }
func getIamCredentialsSecret(ibm *providerIBM, secretName *string) ([]byte, error) { func getIamCredentialsSecret(ibm *providerIBM, secretName *string) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.IAMCredentialsSecret)
secret := response.Resources[0].(*sm.SecretResource) if !ok {
secretData := *secret.APIKey return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_IamCredentials)
}
return []byte(secretData), nil return []byte(*secret.ApiKey), nil
} }
func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret( response, err := getSecretData(ibm, secretName)
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.UsernamePasswordSecret)
secret := response.Resources[0].(*sm.SecretResource) if !ok {
secretData := secret.SecretData return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_UsernamePassword)
}
if val, ok := secretData[ref.Property]; ok { switch ref.Property {
return []byte(val.(string)), nil case "username":
return []byte(*secret.Username), nil
case "password":
return []byte(*secret.Password), nil
default:
return nil, fmt.Errorf("unknown property type %s", ref.Property)
} }
return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
} }
// Returns a secret of type kv and supports json path. // Returns a secret of type kv and supports json path.
func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) { func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
secret, err := getSecretByType(ibm, secretName, sm.CreateSecretOptionsSecretTypeKvConst) response, err := getSecretData(ibm, secretName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
secret, ok := response.(*sm.KVSecret)
log.Info("fetching secret", "secretName", secretName, "key", ref.Key)
secretData := secret.SecretData
payload, ok := secretData["payload"]
if !ok { if !ok {
return nil, fmt.Errorf("no payload returned for secret %s", ref.Key) return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_Kv)
} }
payloadJSONByte, err := json.Marshal(secret.Data)
payloadJSON := payload if err != nil {
return nil, fmt.Errorf("marshaling payload from secret failed. %w", err)
payloadJSONMap, ok := payloadJSON.(map[string]interface{})
if ok {
var payloadJSONByte []byte
payloadJSONByte, err = json.Marshal(payloadJSONMap)
if err != nil {
return nil, fmt.Errorf("marshaling payload from secret failed. %w", err)
}
payloadJSON = string(payloadJSONByte)
} }
payloadJSON := string(payloadJSONByte)
// no property requested, return the entire payload // no property requested, return the entire payload
if ref.Property == "" { if ref.Property == "" {
return []byte(payloadJSON.(string)), nil return []byte(payloadJSON), nil
} }
// returns the requested key // returns the requested key
@ -340,7 +327,7 @@ func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSec
if idx > 0 { if idx > 0 {
refProperty = strings.ReplaceAll(refProperty, ".", "\\.") refProperty = strings.ReplaceAll(refProperty, ".", "\\.")
val := gjson.Get(payloadJSON.(string), refProperty) val := gjson.Get(payloadJSON, refProperty)
if val.Exists() { if val.Exists() {
return []byte(val.String()), nil return []byte(val.String()), nil
} }
@ -348,7 +335,7 @@ func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSec
// b) "." is symbole for JSON path // b) "." is symbole for JSON path
// try to get value for this path // try to get value for this path
val := gjson.Get(payloadJSON.(string), ref.Property) val := gjson.Get(payloadJSON, ref.Property)
if !val.Exists() { 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.Property, ref.Key)
} }
@ -358,20 +345,19 @@ func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSec
return nil, fmt.Errorf("no property provided for secret %s", ref.Key) return nil, fmt.Errorf("no property provided for secret %s", ref.Key)
} }
func getSecretByType(ibm *providerIBM, secretName *string, secretType string) (*sm.SecretResource, error) { func getSecretData(ibm *providerIBM, secretName *string) (sm.SecretIntf, error) {
response, _, err := ibm.IBMClient.GetSecret( ctx, cancel := context.WithTimeout(context.Background(), contextTimeout)
defer cancel()
response, _, err := ibm.IBMClient.GetSecretWithContext(
ctx,
&sm.GetSecretOptions{ &sm.GetSecretOptions{
SecretType: core.StringPtr(secretType), ID: secretName,
ID: secretName,
}) })
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err) metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return response, nil
secret := response.Resources[0].(*sm.SecretResource)
return secret, nil
} }
func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) { func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
@ -379,7 +365,7 @@ func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSe
return nil, fmt.Errorf(errUninitalizedIBMProvider) return nil, fmt.Errorf(errUninitalizedIBMProvider)
} }
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst secretType := sm.Secret_SecretType_Arbitrary
secretName := ref.Key secretName := ref.Key
nameSplitted := strings.Split(secretName, "/") nameSplitted := strings.Split(secretName, "/")
@ -388,124 +374,73 @@ func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSe
secretName = nameSplitted[1] secretName = nameSplitted[1]
} }
secretMap := make(map[string][]byte)
response, err := getSecretData(ibm, &secretName)
if err != nil {
return nil, err
}
switch secretType { switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst: case sm.Secret_SecretType_Arbitrary:
response, _, err := ibm.IBMClient.GetSecret( secretData, ok := response.(*sm.ArbitrarySecret)
&sm.GetSecretOptions{ if !ok {
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst), return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_Arbitrary)
ID: &ref.Key,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
} }
secretMap[arbitraryConst] = []byte(*secretData.Payload)
return secretMap, nil
secret := response.Resources[0].(*sm.SecretResource) case sm.Secret_SecretType_UsernamePassword:
secretData := secret.SecretData secretData, ok := response.(*sm.UsernamePasswordSecret)
arbitrarySecretPayload := secretData["payload"].(string) if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_UsernamePassword)
kv := make(map[string]interface{})
err = json.Unmarshal([]byte(arbitrarySecretPayload), &kv)
if err != nil {
return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
} }
secretMap[usernameConst] = []byte(*secretData.Username)
secretMap := byteArrayMap(kv) secretMap[passwordConst] = []byte(*secretData.Password)
return secretMap, nil return secretMap, nil
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst: case sm.Secret_SecretType_IamCredentials:
response, _, err := ibm.IBMClient.GetSecret( secretData, ok := response.(*sm.IAMCredentialsSecret)
&sm.GetSecretOptions{ if !ok {
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_IamCredentials)
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
} }
secretMap[apikeyConst] = []byte(*secretData.ApiKey)
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
return secretMap, nil return secretMap, nil
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst: case sm.Secret_SecretType_ImportedCert:
response, _, err := ibm.IBMClient.GetSecret( secretData, ok := response.(*sm.ImportedCertificate)
&sm.GetSecretOptions{ if !ok {
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst), return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_ImportedCert)
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
} }
secretMap[certificateConst] = []byte(*secretData.Certificate)
secret := response.Resources[0].(*sm.SecretResource) secretMap[intermediateConst] = []byte(*secretData.Intermediate)
secretData := *secret.APIKey secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
secretMap := make(map[string][]byte)
secretMap["apikey"] = []byte(secretData)
return secretMap, nil return secretMap, nil
case sm.CreateSecretOptionsSecretTypeImportedCertConst: case sm.Secret_SecretType_PublicCert:
response, _, err := ibm.IBMClient.GetSecret( secretData, ok := response.(*sm.PublicCertificate)
&sm.GetSecretOptions{ if !ok {
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst), return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_PublicCert)
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
} }
secretMap[certificateConst] = []byte(*secretData.Certificate)
secret := response.Resources[0].(*sm.SecretResource) secretMap[intermediateConst] = []byte(*secretData.Intermediate)
secretData := secret.SecretData secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
secretMap := byteArrayMap(secretData)
return secretMap, nil return secretMap, nil
case sm.CreateSecretOptionsSecretTypePublicCertConst: case sm.Secret_SecretType_PrivateCert:
response, _, err := ibm.IBMClient.GetSecret( secretData, ok := response.(*sm.PrivateCertificate)
&sm.GetSecretOptions{ if !ok {
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst), return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_PrivateCert)
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
} }
secretMap[certificateConst] = []byte(*secretData.Certificate)
secret := response.Resources[0].(*sm.SecretResource) secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
return secretMap, nil return secretMap, nil
case sm.CreateSecretOptionsSecretTypePrivateCertConst: case sm.Secret_SecretType_Kv:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst),
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeKvConst:
secret, err := getKVSecret(ibm, &secretName, ref) secret, err := getKVSecret(ibm, &secretName, ref)
if err != nil { if err != nil {
return nil, err return nil, err
@ -513,7 +448,7 @@ func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSe
m := make(map[string]interface{}) m := make(map[string]interface{})
err = json.Unmarshal(secret, &m) err = json.Unmarshal(secret, &m)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
} }
secretMap := byteArrayMap(m) secretMap := byteArrayMap(m)
@ -618,7 +553,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
} }
var err error var err error
var secretsManager *sm.SecretsManagerV1 var secretsManager *sm.SecretsManagerV2
containerAuthProfile := iStore.store.Auth.ContainerAuth.Profile containerAuthProfile := iStore.store.Auth.ContainerAuth.Profile
if containerAuthProfile != "" { if containerAuthProfile != "" {
// container-based auth // container-based auth
@ -642,7 +577,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
if err != nil { if err != nil {
return nil, fmt.Errorf(errIBMClient, err) return nil, fmt.Errorf(errIBMClient, err)
} }
secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{ secretsManager, err = sm.NewSecretsManagerV2(&sm.SecretsManagerV2Options{
URL: *storeSpec.Provider.IBM.ServiceURL, URL: *storeSpec.Provider.IBM.ServiceURL,
Authenticator: authenticator, Authenticator: authenticator,
}) })
@ -655,7 +590,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
return nil, err return nil, err
} }
secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{ secretsManager, err = sm.NewSecretsManagerV2(&sm.SecretsManagerV2Options{
URL: *storeSpec.Provider.IBM.ServiceURL, URL: *storeSpec.Provider.IBM.ServiceURL,
Authenticator: &core.IamAuthenticator{ Authenticator: &core.IamAuthenticator{
ApiKey: string(iStore.credentials), ApiKey: string(iStore.credentials),

View file

@ -15,13 +15,14 @@ package ibm
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"github.com/IBM/go-sdk-core/v5/core" "github.com/IBM/go-sdk-core/v5/core"
sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1" sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilpointer "k8s.io/utils/pointer" utilpointer "k8s.io/utils/pointer"
@ -35,12 +36,14 @@ import (
const ( const (
errExpectedErr = "wanted error got nil" errExpectedErr = "wanted error got nil"
secretKey = "test-secret" secretKey = "test-secret"
secretUUID = "d5deb37a-7883-4fe2-a5e7-3c15420adc76"
) )
type secretManagerTestCase struct { type secretManagerTestCase struct {
name string
mockClient *fakesm.IBMMockClient mockClient *fakesm.IBMMockClient
apiInput *sm.GetSecretOptions apiInput *sm.GetSecretOptions
apiOutput *sm.GetSecret apiOutput sm.SecretIntf
ref *esv1beta1.ExternalSecretDataRemoteRef ref *esv1beta1.ExternalSecretDataRemoteRef
serviceURL *string serviceURL *string
apiErr error apiErr error
@ -62,37 +65,36 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
expectedSecret: "", expectedSecret: "",
expectedData: map[string][]byte{}, expectedData: map[string][]byte{},
} }
smtc.mockClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr) mcParams := fakesm.IBMMockClientParams{
GetSecretOptions: smtc.apiInput,
GetSecretOutput: smtc.apiOutput,
GetSecretErr: smtc.apiErr,
}
smtc.mockClient.WithValue(mcParams)
return &smtc return &smtc
} }
func makeValidRef() *esv1beta1.ExternalSecretDataRemoteRef { func makeValidRef() *esv1beta1.ExternalSecretDataRemoteRef {
return &esv1beta1.ExternalSecretDataRemoteRef{ return &esv1beta1.ExternalSecretDataRemoteRef{
Key: secretKey, Key: secretUUID,
Version: "default", Version: "default",
} }
} }
func makeValidAPIInput() *sm.GetSecretOptions { func makeValidAPIInput() *sm.GetSecretOptions {
return &sm.GetSecretOptions{ return &sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst), ID: utilpointer.String(secretUUID),
ID: utilpointer.String(secretKey),
} }
} }
func makeValidAPIOutput() *sm.GetSecret { func makeValidAPIOutput() sm.SecretIntf {
secretData := make(map[string]interface{}) secret := &sm.Secret{
secretData["payload"] = "" SecretType: utilpointer.String(sm.Secret_SecretType_Arbitrary),
Name: utilpointer.String("testyname"),
return &sm.GetSecret{ ID: utilpointer.String(secretUUID),
Resources: []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.String("testytype"),
Name: utilpointer.String("testyname"),
SecretData: secretData,
},
},
} }
var i sm.SecretIntf = secret
return i
} }
func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase { func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
@ -100,7 +102,12 @@ func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTest
for _, fn := range tweaks { for _, fn := range tweaks {
fn(smtc) fn(smtc)
} }
smtc.mockClient.WithValue(smtc.apiInput, smtc.apiOutput, smtc.apiErr) mcParams := fakesm.IBMMockClientParams{
GetSecretOptions: smtc.apiInput,
GetSecretOutput: smtc.apiOutput,
GetSecretErr: smtc.apiErr,
}
smtc.mockClient.WithValue(mcParams)
return smtc return smtc
} }
@ -168,71 +175,71 @@ func TestValidateStore(t *testing.T) {
// test the sm<->gcp interface // test the sm<->gcp interface
// make sure correct values are passed and errors are handled accordingly. // make sure correct values are passed and errors are handled accordingly.
func TestIBMSecretManagerGetSecret(t *testing.T) { func TestIBMSecretManagerGetSecret(t *testing.T) {
secretData := make(map[string]interface{})
secretString := "changedvalue" secretString := "changedvalue"
secretUsername := "userName"
secretPassword := "P@ssw0rd" secretPassword := "P@ssw0rd"
secretAPIKey := "01234567890" secretAPIKey := "01234567890"
secretCertificate := "certificate_value" secretCertificate := "certificate_value"
secretData["payload"] = secretString
secretData["password"] = secretPassword
secretData["certificate"] = secretCertificate
// good case: default version is set // good case: default version is set
// key is passed in, output is sent back // key is passed in, output is sent back
setSecretString := func(smtc *secretManagerTestCase) { setSecretString := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.ArbitrarySecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Arbitrary),
SecretType: utilpointer.String("testytype"), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretData, Payload: &secretString,
}} }
smtc.name = "good case: default version is set"
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.expectedSecret = secretString smtc.expectedSecret = secretString
} }
// good case: custom version set // good case: custom version set
setCustomKey := func(smtc *secretManagerTestCase) { setCustomKey := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.ArbitrarySecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Arbitrary),
SecretType: utilpointer.String("testytype"), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretData, Payload: &secretString,
}} }
smtc.ref.Key = "testyname" smtc.name = "good case: custom version set"
smtc.apiInput.ID = utilpointer.String("testyname") smtc.ref.Key = "arbitrary/" + secretUUID
smtc.apiOutput.Resources = resources smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.expectedSecret = secretString smtc.expectedSecret = secretString
} }
// bad case: username_password type without property // bad case: username_password type without property
secretUserPass := "username_password/test-secret" secretUserPass := "username_password/" + secretUUID
badSecretUserPass := func(smtc *secretManagerTestCase) { badSecretUserPass := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.UsernamePasswordSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_UsernamePassword),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretData, Username: &secretUsername,
}} Password: &secretPassword,
}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst) smtc.name = "bad case: username_password type without property"
smtc.apiOutput.Resources = resources smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.ref.Key = secretUserPass smtc.ref.Key = secretUserPass
smtc.expectError = "remoteRef.property required for secret type username_password" smtc.expectError = "remoteRef.property required for secret type username_password"
} }
// good case: username_password type with property // good case: username_password type with property
setSecretUserPass := func(smtc *secretManagerTestCase) { setSecretUserPass := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.UsernamePasswordSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_UsernamePassword),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretData, Username: &secretUsername,
}} Password: &secretPassword,
}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst) smtc.name = "good case: username_password type with property"
smtc.apiOutput.Resources = resources smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.ref.Key = secretUserPass smtc.ref.Key = secretUserPass
smtc.ref.Property = "password" smtc.ref.Property = "password"
smtc.expectedSecret = secretPassword smtc.expectedSecret = secretPassword
@ -240,31 +247,25 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
// good case: iam_credenatials type // good case: iam_credenatials type
setSecretIam := func(smtc *secretManagerTestCase) { setSecretIam := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.IAMCredentialsSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_IamCredentials),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeIamCredentialsConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
APIKey: utilpointer.String(secretAPIKey), ApiKey: utilpointer.String(secretAPIKey),
}} }
smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst) smtc.name = "good case: iam_credenatials type"
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = "iam_credentials/test-secret" smtc.ref.Key = "iam_credentials/" + secretUUID
smtc.expectedSecret = secretAPIKey smtc.expectedSecret = secretAPIKey
} }
funcSetCertSecretTest := func(certType string, good bool) func(*secretManagerTestCase) { funcSetCertSecretTest := func(secret sm.SecretIntf, name, certType string, good bool) func(*secretManagerTestCase) {
return func(smtc *secretManagerTestCase) { return func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ smtc.name = name
&sm.SecretResource{ smtc.apiInput.ID = utilpointer.String(secretUUID)
SecretType: utilpointer.String(certType), smtc.apiOutput = secret
Name: utilpointer.String("testyname"), smtc.ref.Key = certType + "/" + secretUUID
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(certType)
smtc.apiOutput.Resources = resources
smtc.ref.Key = certType + "/" + secretKey
if good { if good {
smtc.ref.Property = "certificate" smtc.ref.Property = "certificate"
smtc.expectedSecret = secretCertificate smtc.expectedSecret = secretCertificate
@ -275,61 +276,82 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
} }
// good case: imported_cert type with property // good case: imported_cert type with property
setSecretCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypeImportedCertConst, true) importedCert := &sm.ImportedCertificate{
SecretType: utilpointer.String(sm.Secret_SecretType_ImportedCert),
Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
Certificate: utilpointer.String(secretCertificate),
Intermediate: utilpointer.String("intermediate"),
PrivateKey: utilpointer.String("private_key"),
}
setSecretCert := funcSetCertSecretTest(importedCert, "good case: imported_cert type with property", sm.Secret_SecretType_ImportedCert, true)
// bad case: imported_cert type without property // bad case: imported_cert type without property
badSecretCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypeImportedCertConst, false) badSecretCert := funcSetCertSecretTest(importedCert, "bad case: imported_cert type without property", sm.Secret_SecretType_ImportedCert, false)
// good case: public_cert type with property // good case: public_cert type with property
setSecretPublicCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypePublicCertConst, true) publicCert := &sm.PublicCertificate{
SecretType: utilpointer.String(sm.Secret_SecretType_PublicCert),
Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
Certificate: utilpointer.String(secretCertificate),
Intermediate: utilpointer.String("intermediate"),
PrivateKey: utilpointer.String("private_key"),
}
setSecretPublicCert := funcSetCertSecretTest(publicCert, "good case: public_cert type with property", sm.Secret_SecretType_PublicCert, true)
// bad case: public_cert type without property // bad case: public_cert type without property
badSecretPublicCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypePublicCertConst, false) badSecretPublicCert := funcSetCertSecretTest(publicCert, "bad case: public_cert type without property", sm.Secret_SecretType_PublicCert, false)
// good case: private_cert type with property // good case: private_cert type with property
setSecretPrivateCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypePrivateCertConst, true) privateCert := &sm.PrivateCertificate{
SecretType: utilpointer.String(sm.Secret_SecretType_PublicCert),
Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
Certificate: utilpointer.String(secretCertificate),
PrivateKey: utilpointer.String("private_key"),
}
setSecretPrivateCert := funcSetCertSecretTest(privateCert, "good case: private_cert type with property", sm.Secret_SecretType_PrivateCert, true)
// bad case: private_cert type without property // bad case: private_cert type without property
badSecretPrivateCert := funcSetCertSecretTest(sm.CreateSecretOptionsSecretTypePrivateCertConst, false) badSecretPrivateCert := funcSetCertSecretTest(privateCert, "bad case: private_cert type without property", sm.Secret_SecretType_PrivateCert, false)
secretDataKV := make(map[string]interface{}) secretDataKV := make(map[string]interface{})
secretKVPayload := make(map[string]interface{}) secretDataKV["key1"] = "val1"
secretKVPayload["key1"] = "val1"
secretDataKV["payload"] = secretKVPayload
secretDataKVComplex := make(map[string]interface{}) secretDataKVComplex := make(map[string]interface{})
secretKVComplex := `{"key1":"val1","key2":"val2","key3":"val3","keyC":{"keyC1":"valC1", "keyC2":"valC2"}, "special.log": "file-content"}` secretKVComplex := `{"key1":"val1","key2":"val2","key3":"val3","keyC":{"keyC1":"valC1","keyC2":"valC2"},"special.log":"file-content"}`
json.Unmarshal([]byte(secretKVComplex), &secretDataKVComplex)
secretDataKVComplex["payload"] = secretKVComplex secretKV := "kv/" + secretUUID
secretKV := "kv/test-secret"
// bad case: kv type with key which is not in payload // bad case: kv type with key which is not in payload
badSecretKV := func(smtc *secretManagerTestCase) { badSecretKV := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKV, Data: secretDataKV,
}} }
smtc.name = "bad case: kv type with key which is not in payload"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.ref.Property = "other-key" smtc.ref.Property = "other-key"
smtc.expectError = "key other-key does not exist in secret kv/test-secret" smtc.expectError = "key other-key does not exist in secret kv/" + secretUUID
} }
// good case: kv type with property // good case: kv type with property
setSecretKV := func(smtc *secretManagerTestCase) { setSecretKV := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKV, Data: secretDataKV,
}} }
smtc.name = "good case: kv type with property"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.ref.Property = "key1" smtc.ref.Property = "key1"
smtc.expectedSecret = "val1" smtc.expectedSecret = "val1"
@ -337,15 +359,15 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
// good case: kv type with property, returns specific value // good case: kv type with property, returns specific value
setSecretKVWithKey := func(smtc *secretManagerTestCase) { setSecretKVWithKey := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKVComplex, Data: secretDataKVComplex,
}} }
smtc.name = "good case: kv type with property, returns specific value"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.ref.Property = "key2" smtc.ref.Property = "key2"
smtc.expectedSecret = "val2" smtc.expectedSecret = "val2"
@ -353,15 +375,15 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
// good case: kv type with property and path, returns specific value // good case: kv type with property and path, returns specific value
setSecretKVWithKeyPath := func(smtc *secretManagerTestCase) { setSecretKVWithKeyPath := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKVComplex, Data: secretDataKVComplex,
}} }
smtc.name = "good case: kv type with property and path, returns specific value"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.ref.Property = "keyC.keyC2" smtc.ref.Property = "keyC.keyC2"
smtc.expectedSecret = "valC2" smtc.expectedSecret = "valC2"
@ -369,15 +391,15 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
// good case: kv type with property and dot, returns specific value // good case: kv type with property and dot, returns specific value
setSecretKVWithKeyDot := func(smtc *secretManagerTestCase) { setSecretKVWithKeyDot := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKVComplex, Data: secretDataKVComplex,
}} }
smtc.name = "good case: kv type with property and dot, returns specific value"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.ref.Property = "special.log" smtc.ref.Property = "special.log"
smtc.expectedSecret = "file-content" smtc.expectedSecret = "file-content"
@ -385,21 +407,20 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
// good case: kv type without property, returns all // good case: kv type without property, returns all
setSecretKVWithOutKey := func(smtc *secretManagerTestCase) { setSecretKVWithOutKey := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.KVSecret{
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), Name: utilpointer.String("testyname"),
Name: utilpointer.String("testyname"), ID: utilpointer.String(secretUUID),
SecretData: secretDataKVComplex, Data: secretDataKVComplex,
}} }
smtc.name = "good case: kv type without property, returns all"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKV smtc.ref.Key = secretKV
smtc.expectedSecret = secretKVComplex smtc.expectedSecret = secretKVComplex
} }
successCases := []*secretManagerTestCase{ successCases := []*secretManagerTestCase{
makeValidSecretManagerTestCase(),
makeValidSecretManagerTestCaseCustom(setSecretString), makeValidSecretManagerTestCaseCustom(setSecretString),
makeValidSecretManagerTestCaseCustom(setCustomKey), makeValidSecretManagerTestCaseCustom(setCustomKey),
makeValidSecretManagerTestCaseCustom(setAPIErr), makeValidSecretManagerTestCaseCustom(setAPIErr),
@ -408,13 +429,13 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
makeValidSecretManagerTestCaseCustom(setSecretUserPass), makeValidSecretManagerTestCaseCustom(setSecretUserPass),
makeValidSecretManagerTestCaseCustom(setSecretIam), makeValidSecretManagerTestCaseCustom(setSecretIam),
makeValidSecretManagerTestCaseCustom(setSecretCert), makeValidSecretManagerTestCaseCustom(setSecretCert),
makeValidSecretManagerTestCaseCustom(badSecretCert),
makeValidSecretManagerTestCaseCustom(setSecretKV), makeValidSecretManagerTestCaseCustom(setSecretKV),
makeValidSecretManagerTestCaseCustom(setSecretKVWithKey), makeValidSecretManagerTestCaseCustom(setSecretKVWithKey),
makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyPath), makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyPath),
makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyDot), makeValidSecretManagerTestCaseCustom(setSecretKVWithKeyDot),
makeValidSecretManagerTestCaseCustom(setSecretKVWithOutKey), makeValidSecretManagerTestCaseCustom(setSecretKVWithOutKey),
makeValidSecretManagerTestCaseCustom(badSecretKV), makeValidSecretManagerTestCaseCustom(badSecretKV),
makeValidSecretManagerTestCaseCustom(badSecretCert),
makeValidSecretManagerTestCaseCustom(setSecretPublicCert), makeValidSecretManagerTestCaseCustom(setSecretPublicCert),
makeValidSecretManagerTestCaseCustom(badSecretPublicCert), makeValidSecretManagerTestCaseCustom(badSecretPublicCert),
makeValidSecretManagerTestCaseCustom(setSecretPrivateCert), makeValidSecretManagerTestCaseCustom(setSecretPrivateCert),
@ -423,19 +444,20 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
sm := providerIBM{} sm := providerIBM{}
for k, v := range successCases { for k, v := range successCases {
sm.IBMClient = v.mockClient t.Run(v.name, func(t *testing.T) {
out, err := sm.GetSecret(context.Background(), *v.ref) sm.IBMClient = v.mockClient
if !ErrorContains(err, v.expectError) { out, err := sm.GetSecret(context.Background(), *v.ref)
t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError) if !ErrorContains(err, v.expectError) {
} t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
if string(out) != v.expectedSecret { }
t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out)) if string(out) != v.expectedSecret {
} t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out))
}
})
} }
} }
func TestGetSecretMap(t *testing.T) { func TestGetSecretMap(t *testing.T) {
secretKeyName := "kv/test-secret"
secretUsername := "user1" secretUsername := "user1"
secretPassword := "P@ssw0rd" secretPassword := "P@ssw0rd"
secretAPIKey := "01234567890" secretAPIKey := "01234567890"
@ -454,89 +476,60 @@ func TestGetSecretMap(t *testing.T) {
}, },
} }
// good case: default version & deserialization // good case: arbitrary
setDeserialization := func(smtc *secretManagerTestCase) { setArbitrary := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) payload := `{"foo":"bar"}`
secretData["payload"] = `{"foo":"bar"}` secret := &sm.ArbitrarySecret{
Name: utilpointer.String("testyname"),
resources := []sm.SecretResourceIntf{ ID: utilpointer.String(secretUUID),
&sm.SecretResource{ SecretType: utilpointer.String(sm.Secret_SecretType_Arbitrary),
SecretType: utilpointer.String("testytype"), Payload: &payload,
Name: utilpointer.String("testyname"), }
SecretData: secretData, smtc.name = "good case: arbitrary"
}} smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.apiOutput.Resources = resources smtc.ref.Key = secretUUID
smtc.expectedData["foo"] = []byte("bar") smtc.expectedData["arbitrary"] = []byte(payload)
}
// bad case: invalid json
setInvalidJSON := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{})
secretData["payload"] = `-----------------`
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.String("testytype"),
Name: utilpointer.String("testyname"),
SecretData: secretData,
}}
smtc.apiOutput.Resources = resources
smtc.expectError = "unable to unmarshal secret: invalid character '-' in numeric literal"
} }
// good case: username_password // good case: username_password
setSecretUserPass := func(smtc *secretManagerTestCase) { setSecretUserPass := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) secret := &sm.UsernamePasswordSecret{
secretData["username"] = secretUsername Name: utilpointer.String("testyname"),
secretData["password"] = secretPassword ID: utilpointer.String(secretUUID),
resources := []sm.SecretResourceIntf{ SecretType: utilpointer.String(sm.Secret_SecretType_UsernamePassword),
&sm.SecretResource{ Username: &secretUsername,
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst), Password: &secretPassword,
Name: utilpointer.String("testyname"), }
SecretData: secretData, smtc.name = "good case: username_password"
}} smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst) smtc.ref.Key = "username_password/" + secretUUID
smtc.apiOutput.Resources = resources
smtc.ref.Key = "username_password/test-secret"
smtc.expectedData["username"] = []byte(secretUsername) smtc.expectedData["username"] = []byte(secretUsername)
smtc.expectedData["password"] = []byte(secretPassword) smtc.expectedData["password"] = []byte(secretPassword)
} }
// good case: iam_credentials // good case: iam_credentials
setSecretIam := func(smtc *secretManagerTestCase) { setSecretIam := func(smtc *secretManagerTestCase) {
resources := []sm.SecretResourceIntf{ secret := &sm.IAMCredentialsSecret{
&sm.SecretResource{ Name: utilpointer.String("testyname"),
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeIamCredentialsConst), ID: utilpointer.String(secretUUID),
Name: utilpointer.String("testyname"), SecretType: utilpointer.String(sm.Secret_SecretType_IamCredentials),
APIKey: utilpointer.String(secretAPIKey), ApiKey: utilpointer.String(secretAPIKey),
}} }
smtc.name = "good case: iam_credentials"
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst) smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = "iam_credentials/test-secret" smtc.ref.Key = "iam_credentials/" + secretUUID
smtc.expectedData["apikey"] = []byte(secretAPIKey) smtc.expectedData["apikey"] = []byte(secretAPIKey)
} }
funcCertTest := func(certType string) func(*secretManagerTestCase) { funcCertTest := func(secret sm.SecretIntf, name, certType string) func(*secretManagerTestCase) {
return func(smtc *secretManagerTestCase) { return func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) smtc.name = name
secretData["certificate"] = secretCertificate smtc.apiInput.ID = utilpointer.String(secretUUID)
secretData["private_key"] = secretPrivateKey smtc.apiOutput = secret
secretData["intermediate"] = secretIntermediate smtc.ref.Key = certType + "/" + secretUUID
resources := []sm.SecretResourceIntf{
&sm.SecretResource{
SecretType: utilpointer.String(certType),
Name: utilpointer.String("testyname"),
SecretData: secretData,
}}
smtc.apiInput.SecretType = core.StringPtr(certType)
smtc.apiOutput.Resources = resources
smtc.ref.Key = certType + "/test-secret"
smtc.expectedData["certificate"] = []byte(secretCertificate) smtc.expectedData["certificate"] = []byte(secretCertificate)
smtc.expectedData["private_key"] = []byte(secretPrivateKey) smtc.expectedData["private_key"] = []byte(secretPrivateKey)
smtc.expectedData["intermediate"] = []byte(secretIntermediate) smtc.expectedData["intermediate"] = []byte(secretIntermediate)
@ -544,27 +537,57 @@ func TestGetSecretMap(t *testing.T) {
} }
// good case: imported_cert // good case: imported_cert
setSecretCert := funcCertTest(sm.CreateSecretOptionsSecretTypeImportedCertConst) importedCert := &sm.ImportedCertificate{
// good case: public_cert SecretType: utilpointer.String(sm.Secret_SecretType_ImportedCert),
setSecretPublicCert := funcCertTest(sm.CreateSecretOptionsSecretTypePublicCertConst) Name: utilpointer.String("testyname"),
// good case: public_cert ID: utilpointer.String(secretUUID),
setSecretPrivateCert := funcCertTest(sm.CreateSecretOptionsSecretTypePrivateCertConst) Certificate: utilpointer.String(secretCertificate),
Intermediate: utilpointer.String(secretIntermediate),
PrivateKey: utilpointer.String(secretPrivateKey),
}
setSecretCert := funcCertTest(importedCert, "good case: imported_cert", sm.Secret_SecretType_ImportedCert)
// good case: public_cert
publicCert := &sm.PublicCertificate{
SecretType: utilpointer.String(sm.Secret_SecretType_PublicCert),
Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
Certificate: utilpointer.String(secretCertificate),
Intermediate: utilpointer.String(secretIntermediate),
PrivateKey: utilpointer.String(secretPrivateKey),
}
setSecretPublicCert := funcCertTest(publicCert, "good case: public_cert", sm.Secret_SecretType_PublicCert)
// good case: private_cert
setSecretPrivateCert := func(smtc *secretManagerTestCase) {
secret := &sm.PrivateCertificate{
Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
SecretType: utilpointer.String(sm.Secret_SecretType_PrivateCert),
Certificate: &secretCertificate,
PrivateKey: &secretPrivateKey,
}
smtc.name = "good case: private_cert"
smtc.apiInput.ID = utilpointer.String(secretUUID)
smtc.apiOutput = secret
smtc.ref.Key = "private_cert/" + secretUUID
smtc.expectedData["certificate"] = []byte(secretCertificate)
smtc.expectedData["private_key"] = []byte(secretPrivateKey)
}
secretKeyKV := "kv/" + secretUUID
// good case: kv, no property, return entire payload as key:value pairs // good case: kv, no property, return entire payload as key:value pairs
setSecretKV := func(smtc *secretManagerTestCase) { setSecretKV := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) secret := &sm.KVSecret{
secretData["payload"] = secretComplex Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
resources := []sm.SecretResourceIntf{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
&sm.SecretResource{ Data: secretComplex,
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), }
Name: utilpointer.String("testyname"), smtc.name = "good case: kv, no property, return entire payload as key:value pairs"
SecretData: secretData, smtc.apiInput.ID = core.StringPtr(secretUUID)
}} smtc.apiOutput = secret
smtc.ref.Key = secretKeyKV
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst)
smtc.apiOutput.Resources = resources
smtc.ref.Key = secretKeyName
smtc.expectedData["key1"] = []byte("val1") smtc.expectedData["key1"] = []byte("val1")
smtc.expectedData["key2"] = []byte("val2") smtc.expectedData["key2"] = []byte("val2")
smtc.expectedData["keyC"] = []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`) smtc.expectedData["keyC"] = []byte(`{"keyC1":{"keyA":"valA","keyB":"valB"}}`)
@ -572,65 +595,55 @@ func TestGetSecretMap(t *testing.T) {
// good case: kv, with property // good case: kv, with property
setSecretKVWithProperty := func(smtc *secretManagerTestCase) { setSecretKVWithProperty := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) secret := &sm.KVSecret{
secretData["payload"] = secretComplex Name: utilpointer.String("d5deb37a-7883-4fe2-a5e7-3c15420adc76"),
ID: utilpointer.String(secretUUID),
resources := []sm.SecretResourceIntf{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
&sm.SecretResource{ Data: secretComplex,
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), }
Name: utilpointer.String("testyname"), smtc.name = "good case: kv, with property"
SecretData: secretData, smtc.apiInput.ID = core.StringPtr(secretUUID)
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst)
smtc.ref.Property = "keyC" smtc.ref.Property = "keyC"
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKeyName smtc.ref.Key = secretKeyKV
smtc.expectedData["keyC1"] = []byte(`{"keyA":"valA","keyB":"valB"}`) smtc.expectedData["keyC1"] = []byte(`{"keyA":"valA","keyB":"valB"}`)
} }
// good case: kv, with property and path // good case: kv, with property and path
setSecretKVWithPathAndProperty := func(smtc *secretManagerTestCase) { setSecretKVWithPathAndProperty := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) secret := &sm.KVSecret{
secretData["payload"] = secretComplex Name: utilpointer.String(secretUUID),
ID: utilpointer.String(secretUUID),
resources := []sm.SecretResourceIntf{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
&sm.SecretResource{ Data: secretComplex,
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), }
Name: utilpointer.String("testyname"), smtc.name = "good case: kv, with property and path"
SecretData: secretData, smtc.apiInput.ID = core.StringPtr(secretUUID)
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst)
smtc.ref.Property = "keyC.keyC1" smtc.ref.Property = "keyC.keyC1"
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKeyName smtc.ref.Key = secretKeyKV
smtc.expectedData["keyA"] = []byte("valA") smtc.expectedData["keyA"] = []byte("valA")
smtc.expectedData["keyB"] = []byte("valB") smtc.expectedData["keyB"] = []byte("valB")
} }
// bad case: kv, with property and path // bad case: kv, with property and path
badSecretKVWithUnknownProperty := func(smtc *secretManagerTestCase) { badSecretKVWithUnknownProperty := func(smtc *secretManagerTestCase) {
secretData := make(map[string]interface{}) secret := &sm.KVSecret{
secretData["payload"] = secretComplex Name: utilpointer.String("testyname"),
ID: utilpointer.String(secretUUID),
resources := []sm.SecretResourceIntf{ SecretType: utilpointer.String(sm.Secret_SecretType_Kv),
&sm.SecretResource{ Data: secretComplex,
SecretType: utilpointer.String(sm.CreateSecretOptionsSecretTypeKvConst), }
Name: utilpointer.String("testyname"), smtc.name = "bad case: kv, with property and path"
SecretData: secretData, smtc.apiInput.ID = core.StringPtr(secretUUID)
}}
smtc.apiInput.SecretType = core.StringPtr(sm.CreateSecretOptionsSecretTypeKvConst)
smtc.ref.Property = "unknown.property" smtc.ref.Property = "unknown.property"
smtc.apiOutput.Resources = resources smtc.apiOutput = secret
smtc.ref.Key = secretKeyName smtc.ref.Key = secretKeyKV
smtc.expectError = "key unknown.property does not exist in secret kv/test-secret" smtc.expectError = "key unknown.property does not exist in secret " + secretKeyKV
} }
successCases := []*secretManagerTestCase{ successCases := []*secretManagerTestCase{
makeValidSecretManagerTestCaseCustom(setDeserialization), makeValidSecretManagerTestCaseCustom(setArbitrary),
makeValidSecretManagerTestCaseCustom(setInvalidJSON),
makeValidSecretManagerTestCaseCustom(setNilMockClient), makeValidSecretManagerTestCaseCustom(setNilMockClient),
makeValidSecretManagerTestCaseCustom(setAPIErr), makeValidSecretManagerTestCaseCustom(setAPIErr),
makeValidSecretManagerTestCaseCustom(setSecretUserPass), makeValidSecretManagerTestCaseCustom(setSecretUserPass),
@ -646,14 +659,16 @@ func TestGetSecretMap(t *testing.T) {
sm := providerIBM{} sm := providerIBM{}
for k, v := range successCases { for k, v := range successCases {
sm.IBMClient = v.mockClient t.Run(v.name, func(t *testing.T) {
out, err := sm.GetSecretMap(context.Background(), *v.ref) sm.IBMClient = v.mockClient
if !ErrorContains(err, v.expectError) { out, err := sm.GetSecretMap(context.Background(), *v.ref)
t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError) if !ErrorContains(err, v.expectError) {
} t.Errorf(" unexpected error: %s, expected: '%s'", err.Error(), v.expectError)
if err == nil && !reflect.DeepEqual(out, v.expectedData) { }
t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedData, out) if err == nil && !reflect.DeepEqual(out, v.expectedData) {
} t.Errorf("[%d] unexpected secret data: expected %+v, got %v", k, v.expectedData, out)
}
})
} }
} }