diff --git a/pkg/secrets/interfaces.go b/pkg/secrets/interfaces.go index 1b4107246..126b3cb6e 100644 --- a/pkg/secrets/interfaces.go +++ b/pkg/secrets/interfaces.go @@ -10,6 +10,8 @@ import ( type SecretStore interface { // GetSecret retrieves ref secret from various cloud secret manager. GetSecret(ctx context.Context, ref v1.ExternalSecretRef) ([]byte, error) + // SetSecret sets ref secret to various cloud secret manager. + SetSecret(ctx context.Context, ref v1.ExternalSecretRef, data []byte) error } // SecretStoreProvider is a factory type for secret store. diff --git a/pkg/secrets/providers/alicloud/secretsmanager/secretsmanager.go b/pkg/secrets/providers/alicloud/secretsmanager/secretsmanager.go index 090cac190..bb584eb50 100644 --- a/pkg/secrets/providers/alicloud/secretsmanager/secretsmanager.go +++ b/pkg/secrets/providers/alicloud/secretsmanager/secretsmanager.go @@ -6,7 +6,7 @@ import ( "os" "strings" - "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" + v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" "kusionstack.io/kusion/pkg/secrets" "github.com/aliyun/aliyun-secretsmanager-client-go/sdk" @@ -19,6 +19,7 @@ const ( errMissingProviderSpec = "store spec is missing provider" errMissingAlicloudProvider = "invalid provider spec. Missing Alicloud field in store provider spec" errFailedToCreateClient = "failed to create Alicloud Secrets Manager client: %w" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) var ( @@ -91,6 +92,11 @@ func (s *smSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretRef) return []byte(val.String()), nil } +// SetSecret stores ref secret value to Alicloud Secrets Manager. +func (s *smSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, secretValue []byte) error { + return fmt.Errorf(errMethodNotImplemented, "Alicloud Secrets Manager", "SetSecret") +} + func (s *smSecretStore) convertSecretToGjson(secretInfo *models.SecretInfo, refProperty string) gjson.Result { var payload string if secretInfo.SecretValue != "" { diff --git a/pkg/secrets/providers/aws/secretsmanager/secretsmanager.go b/pkg/secrets/providers/aws/secretsmanager/secretsmanager.go index ebff24c7b..5cb9ba3de 100644 --- a/pkg/secrets/providers/aws/secretsmanager/secretsmanager.go +++ b/pkg/secrets/providers/aws/secretsmanager/secretsmanager.go @@ -10,7 +10,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" "github.com/tidwall/gjson" - "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" + v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" "kusionstack.io/kusion/pkg/secrets" "kusionstack.io/kusion/pkg/secrets/providers/aws/auth" ) @@ -19,6 +19,7 @@ const ( errMissingProviderSpec = "store spec is missing provider" errMissingAWSProvider = "invalid provider spec. Missing AWS field in store provider spec" errFailedToCreateSession = "failed to create usable AWS session: %w" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) // DefaultSecretStoreProvider should implement the secrets.SecretStoreProvider interface @@ -80,6 +81,11 @@ func (s *smSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretRef) return []byte(val.String()), nil } +// SetSecret sets ref secret value to AWS Secrets Manager. +func (s *smSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, secretValue []byte) error { + return fmt.Errorf(errMethodNotImplemented, "AWS Secret Manager", "SetSecret") +} + // buildGetSecretValueInput constructs target GetSecretValueInput request with specific external secret ref. func (s *smSecretStore) buildGetSecretValueInput(ref v1.ExternalSecretRef) *secretsmanager.GetSecretValueInput { version := "AWSCURRENT" diff --git a/pkg/secrets/providers/azure/keyvault/keyvault.go b/pkg/secrets/providers/azure/keyvault/keyvault.go index 69fd414b0..8c8f19752 100644 --- a/pkg/secrets/providers/azure/keyvault/keyvault.go +++ b/pkg/secrets/providers/azure/keyvault/keyvault.go @@ -13,7 +13,7 @@ import ( "github.com/Azure/go-autorest/autorest/azure/auth" "github.com/tidwall/gjson" - "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" + v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" "kusionstack.io/kusion/pkg/secrets" ) @@ -27,6 +27,7 @@ const ( errMissingClientIDSecret = "cannot read clientID/clientSecret from environment variables" errPropertyNotExist = "property %s does not exist in key %s" errUnknownObjectType = "unknown Azure KeyVault object Type for %s" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) // DefaultSecretStoreProvider should implement the secrets.SecretStoreProvider interface @@ -155,6 +156,11 @@ func (k *kvSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretRef) return nil, fmt.Errorf(errUnknownObjectType, secretName) } +// SetSecret sets ref secret value to Azure KeyVault. +func (k *kvSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, secretValue []byte) error { + return fmt.Errorf(errMethodNotImplemented, "Azure KeyVault", "SetSecret") +} + // Retrieves a property value if specified and the secret value if not. func getProperty(secret, property, key string) ([]byte, error) { if property == "" { diff --git a/pkg/secrets/providers/fake/fake.go b/pkg/secrets/providers/fake/fake.go index 168745809..2bdfc6913 100644 --- a/pkg/secrets/providers/fake/fake.go +++ b/pkg/secrets/providers/fake/fake.go @@ -11,8 +11,9 @@ import ( ) const ( - errMissingProviderSpec = "secret store spec is missing provider" - errMissingFakeProvider = "invalid provider spec. Missing Fake field in secret store provider spec" + errMissingProviderSpec = "secret store spec is missing provider" + errMissingFakeProvider = "invalid provider spec. Missing Fake field in secret store provider spec" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) type SecretData struct { @@ -77,6 +78,11 @@ func (f *fakeSecretStore) GetSecret(_ context.Context, ref v1.ExternalSecretRef) return []byte(data.Value), nil } +// SetSecret sets ref secret value to backend data map. +func (f *fakeSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, secretValue []byte) error { + return fmt.Errorf(errMethodNotImplemented, "fake", "SetSecret") +} + func mapKey(key, version string) string { // Add the version suffix to preserve entries with the old versions as well. return fmt.Sprintf("%v%v", key, version) diff --git a/pkg/secrets/providers/hashivault/vault.go b/pkg/secrets/providers/hashivault/vault.go index cbdef6802..5432a129b 100644 --- a/pkg/secrets/providers/hashivault/vault.go +++ b/pkg/secrets/providers/hashivault/vault.go @@ -13,7 +13,7 @@ import ( vault "github.com/hashicorp/vault/api" "github.com/tidwall/gjson" - "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" + v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" "kusionstack.io/kusion/pkg/secrets" ) @@ -26,6 +26,7 @@ const ( errDataPropertyFormat = "unexpected data format %s for property field: %s" errSecretFormat = "cannot find property %s in secret data" errBuildVaultClient = "failed to new Vault client: %w" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) // DefaultSecretStoreProvider should implement the secrets.SecretStoreProvider interface @@ -120,6 +121,11 @@ func (v *vaultSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretR return []byte(val.String()), nil } +// SetSecret sets ref secret value to Vault server. +func (v *vaultSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, value []byte) error { + return fmt.Errorf(errMethodNotImplemented, "vault", "SetSecret") +} + func (v *vaultSecretStore) readSecret(ctx context.Context, path, version string) (map[string]interface{}, error) { // build correct path according to vault docs for v1 and v2 API secretPath := v.buildPath(path) diff --git a/pkg/secrets/providers/viettelcloud/secretsmanager/secretsmanager.go b/pkg/secrets/providers/viettelcloud/secretsmanager/secretsmanager.go index acb895577..ba43a4b89 100644 --- a/pkg/secrets/providers/viettelcloud/secretsmanager/secretsmanager.go +++ b/pkg/secrets/providers/viettelcloud/secretsmanager/secretsmanager.go @@ -22,6 +22,7 @@ const ( errMissingProviderSpec = "store spec is missing provider" errMissingViettelCloudProvider = "invalid provider spec. Missing ViettelCloud field in store provider spec" errFailedToCreateClient = "failed to create ViettelCloud Secrets Manager client: %w" + errMethodNotImplemented = "method not implemented. secret provider: %s, method: %s" ) var ( @@ -86,6 +87,7 @@ func (p *DefaultSecretStoreProvider) NewSecretStore(spec *v1.SecretStore) (secre }, nil } +// GetSecret retrieves a secret from the ViettelCloud secret store. func (s *smSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretRef) ([]byte, error) { secretResponse, err := s.client.SecretManagerSecretsRetrieveWithResponse(ctx, ref.Name, &vclient.SecretManagerSecretsRetrieveParams{ ProjectID: s.projectID, @@ -115,6 +117,11 @@ func (s *smSecretStore) GetSecret(ctx context.Context, ref v1.ExternalSecretRef) return []byte(val.String()), nil } +// SetSecret sets a secret to the ViettelCloud secret store. +func (s *smSecretStore) SetSecret(ctx context.Context, ref v1.ExternalSecretRef, secretValue []byte) error { + return fmt.Errorf(errMethodNotImplemented, "ViettelCloud", "SetSecret") +} + func (s *smSecretStore) convertSecretToGjson(secretInfo *vclient.SecretRetrieve, refProperty string) gjson.Result { var payload string if secretInfo.Secret != nil { diff --git a/pkg/secrets/providers_test.go b/pkg/secrets/providers_test.go index 3865c6de4..8bc766e04 100644 --- a/pkg/secrets/providers_test.go +++ b/pkg/secrets/providers_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" + v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1" ) // FakeSecretStore is the fake implementation of SecretStore. @@ -17,6 +17,11 @@ func (fss *FakeSecretStore) GetSecret(_ context.Context, _ v1.ExternalSecretRef) return []byte("NOOP"), nil } +// Fake implementation of SecretStore.SetSecret. +func (fss *FakeSecretStore) SetSecret(_ context.Context, _ v1.ExternalSecretRef, _ []byte) error { + return nil +} + // FakeSecretStoreProvider is the fake implementation of SecretStoreProvider. type FakeSecretStoreProvider struct{}