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/AzureAD/microsoft-authentication-library-for-go v1.0.0
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/sprig/v3 v3.2.3
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/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/secrets-manager-go-sdk v1.2.0 h1:bgFfBF+LjHLtUfV3hTLkfgE8EjFsJaeU2icA2Hg+M50=
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 h1:Lx4Bvim/MfoHEYR+n312bty5DirAJypBGGS9YZo3zCw=
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/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
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
import (
"context"
"fmt"
"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/cmpopts"
)
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) {
return mc.getSecret(getSecretOptions)
type IBMMockClientParams struct {
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 {
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
// use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp.
if !cmp.Equal(paramReq, input, cmpopts.IgnoreUnexported(sm.GetSecret{})) {
return nil, nil, fmt.Errorf("unexpected test argument")
if !cmp.Equal(paramReq, params.GetSecretOptions, cmpopts.IgnoreUnexported(sm.Secret{})) {
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"
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"
corev1 "k8s.io/api/core/v1"
types "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
@ -40,6 +39,14 @@ const (
STSEndpointEnv = "IBM_STS_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"
errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey"
errUninitalizedIBMProvider = "provider IBM is not initialized"
@ -47,14 +54,17 @@ const (
errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
errMissingSAK = "missing SecretAccessKey"
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
var _ esv1beta1.SecretsClient = &providerIBM{}
var _ esv1beta1.Provider = &providerIBM{}
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 {
@ -69,8 +79,6 @@ type client struct {
credentials []byte
}
var log = ctrl.Log.WithName("provider").WithName("ibm").WithName("secretsmanager")
func (c *client) setAuth(ctx context.Context) error {
credentialsSecret := &corev1.Secret{}
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)
}
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretType := sm.Secret_SecretType_Arbitrary
secretName := ref.Key
nameSplitted := strings.Split(secretName, "/")
@ -132,22 +140,21 @@ func (ibm *providerIBM) GetSecret(_ context.Context, ref esv1beta1.ExternalSecre
}
switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst:
case sm.Secret_SecretType_Arbitrary:
return getArbitrarySecret(ibm, &secretName)
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
case sm.Secret_SecretType_UsernamePassword:
if ref.Property == "" {
return nil, fmt.Errorf("remoteRef.property required for secret type username_password")
}
return getUsernamePasswordSecret(ibm, &secretName, ref)
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
case sm.Secret_SecretType_IamCredentials:
return getIamCredentialsSecret(ibm, &secretName)
case sm.CreateSecretOptionsSecretTypeImportedCertConst:
case sm.Secret_SecretType_ImportedCert:
if ref.Property == "" {
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)
case sm.CreateSecretOptionsSecretTypePublicCertConst:
case sm.Secret_SecretType_PublicCert:
if ref.Property == "" {
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)
case sm.CreateSecretOptionsSecretTypePrivateCertConst:
case sm.Secret_SecretType_PrivateCert:
if ref.Property == "" {
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)
case sm.CreateSecretOptionsSecretTypeKvConst:
case sm.Secret_SecretType_Kv:
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) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
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)
secretData := secret.SecretData
arbitrarySecretPayload := secretData["payload"].(string)
return []byte(arbitrarySecretPayload), nil
return []byte(*secret.Payload), nil
}
func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
secret, ok := response.(*sm.ImportedCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_ImportedCert)
}
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 getPublicCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
secret, ok := response.(*sm.PublicCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_PublicCert)
}
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) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
secret, ok := response.(*sm.PrivateCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_PrivateCert)
}
switch ref.Property {
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) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := *secret.APIKey
return []byte(secretData), nil
secret, ok := response.(*sm.IAMCredentialsSecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_IamCredentials)
}
return []byte(*secret.ApiKey), nil
}
func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
response, err := getSecretData(ibm, secretName)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
if val, ok := secretData[ref.Property]; ok {
return []byte(val.(string)), nil
secret, ok := response.(*sm.UsernamePasswordSecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_UsernamePassword)
}
switch ref.Property {
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.
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 {
return nil, err
}
log.Info("fetching secret", "secretName", secretName, "key", ref.Key)
secretData := secret.SecretData
payload, ok := secretData["payload"]
secret, ok := response.(*sm.KVSecret)
if !ok {
return nil, fmt.Errorf("no payload returned for secret %s", ref.Key)
return nil, fmt.Errorf(errExtractingSecret, *secretName, sm.Secret_SecretType_Kv)
}
payloadJSON := payload
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)
payloadJSONByte, err := json.Marshal(secret.Data)
if err != nil {
return nil, fmt.Errorf("marshaling payload from secret failed. %w", err)
}
payloadJSON := string(payloadJSONByte)
// no property requested, return the entire payload
if ref.Property == "" {
return []byte(payloadJSON.(string)), nil
return []byte(payloadJSON), nil
}
// returns the requested key
@ -340,7 +327,7 @@ func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSec
if idx > 0 {
refProperty = strings.ReplaceAll(refProperty, ".", "\\.")
val := gjson.Get(payloadJSON.(string), refProperty)
val := gjson.Get(payloadJSON, refProperty)
if val.Exists() {
return []byte(val.String()), nil
}
@ -348,7 +335,7 @@ func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSec
// b) "." is symbole for JSON path
// try to get value for this path
val := gjson.Get(payloadJSON.(string), ref.Property)
val := gjson.Get(payloadJSON, ref.Property)
if !val.Exists() {
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)
}
func getSecretByType(ibm *providerIBM, secretName *string, secretType string) (*sm.SecretResource, error) {
response, _, err := ibm.IBMClient.GetSecret(
func getSecretData(ibm *providerIBM, secretName *string) (sm.SecretIntf, error) {
ctx, cancel := context.WithTimeout(context.Background(), contextTimeout)
defer cancel()
response, _, err := ibm.IBMClient.GetSecretWithContext(
ctx,
&sm.GetSecretOptions{
SecretType: core.StringPtr(secretType),
ID: secretName,
ID: secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
}
secret := response.Resources[0].(*sm.SecretResource)
return secret, nil
return response, nil
}
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)
}
secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
secretType := sm.Secret_SecretType_Arbitrary
secretName := ref.Key
nameSplitted := strings.Split(secretName, "/")
@ -388,124 +374,73 @@ func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSe
secretName = nameSplitted[1]
}
secretMap := make(map[string][]byte)
response, err := getSecretData(ibm, &secretName)
if err != nil {
return nil, err
}
switch secretType {
case sm.GetSecretOptionsSecretTypeArbitraryConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
ID: &ref.Key,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
case sm.Secret_SecretType_Arbitrary:
secretData, ok := response.(*sm.ArbitrarySecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_Arbitrary)
}
secretMap[arbitraryConst] = []byte(*secretData.Payload)
return secretMap, nil
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
arbitrarySecretPayload := secretData["payload"].(string)
kv := make(map[string]interface{})
err = json.Unmarshal([]byte(arbitrarySecretPayload), &kv)
if err != nil {
return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
case sm.Secret_SecretType_UsernamePassword:
secretData, ok := response.(*sm.UsernamePasswordSecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_UsernamePassword)
}
secretMap := byteArrayMap(kv)
secretMap[usernameConst] = []byte(*secretData.Username)
secretMap[passwordConst] = []byte(*secretData.Password)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
case sm.Secret_SecretType_IamCredentials:
secretData, ok := response.(*sm.IAMCredentialsSecret)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_IamCredentials)
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
secretMap[apikeyConst] = []byte(*secretData.ApiKey)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
case sm.Secret_SecretType_ImportedCert:
secretData, ok := response.(*sm.ImportedCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_ImportedCert)
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := *secret.APIKey
secretMap := make(map[string][]byte)
secretMap["apikey"] = []byte(secretData)
secretMap[certificateConst] = []byte(*secretData.Certificate)
secretMap[intermediateConst] = []byte(*secretData.Intermediate)
secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypeImportedCertConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
case sm.Secret_SecretType_PublicCert:
secretData, ok := response.(*sm.PublicCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_PublicCert)
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
secretMap[certificateConst] = []byte(*secretData.Certificate)
secretMap[intermediateConst] = []byte(*secretData.Intermediate)
secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypePublicCertConst:
response, _, err := ibm.IBMClient.GetSecret(
&sm.GetSecretOptions{
SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst),
ID: &secretName,
})
metrics.ObserveAPICall(metrics.ProviderIBMSM, metrics.CallIBMSMGetSecret, err)
if err != nil {
return nil, err
case sm.Secret_SecretType_PrivateCert:
secretData, ok := response.(*sm.PrivateCertificate)
if !ok {
return nil, fmt.Errorf(errExtractingSecret, secretName, sm.Secret_SecretType_PrivateCert)
}
secret := response.Resources[0].(*sm.SecretResource)
secretData := secret.SecretData
secretMap := byteArrayMap(secretData)
secretMap[certificateConst] = []byte(*secretData.Certificate)
secretMap[privateKeyConst] = []byte(*secretData.PrivateKey)
return secretMap, nil
case sm.CreateSecretOptionsSecretTypePrivateCertConst:
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:
case sm.Secret_SecretType_Kv:
secret, err := getKVSecret(ibm, &secretName, ref)
if err != nil {
return nil, err
@ -513,7 +448,7 @@ func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSe
m := make(map[string]interface{})
err = json.Unmarshal(secret, &m)
if err != nil {
return nil, err
return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
}
secretMap := byteArrayMap(m)
@ -618,7 +553,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
}
var err error
var secretsManager *sm.SecretsManagerV1
var secretsManager *sm.SecretsManagerV2
containerAuthProfile := iStore.store.Auth.ContainerAuth.Profile
if containerAuthProfile != "" {
// container-based auth
@ -642,7 +577,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
if err != nil {
return nil, fmt.Errorf(errIBMClient, err)
}
secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
secretsManager, err = sm.NewSecretsManagerV2(&sm.SecretsManagerV2Options{
URL: *storeSpec.Provider.IBM.ServiceURL,
Authenticator: authenticator,
})
@ -655,7 +590,7 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
return nil, err
}
secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
secretsManager, err = sm.NewSecretsManagerV2(&sm.SecretsManagerV2Options{
URL: *storeSpec.Provider.IBM.ServiceURL,
Authenticator: &core.IamAuthenticator{
ApiKey: string(iStore.credentials),

View file

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