1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-15 17:51:01 +00:00

Add support for referencing secrets manager secrets by their VersionId

This commit is contained in:
Matt Demers 2022-05-11 16:16:34 -04:00
parent c532bac0be
commit b004894b77
3 changed files with 78 additions and 7 deletions

View file

@ -57,4 +57,54 @@ This is an example on how you would look up nested keys in the above json object
{% include 'aws-sm-external-secret.yaml' %}
```
### Secret Versions
SecretsManager creates a new version of a secret every time it is updated. The secret version can be reference in two ways, the `VersionStage` and the `VersionId`. The `VersionId` is a unique uuid which is generated every time the secret changes. This id is immutable and will always refer to the same secret data. The `VersionStage` is an alias to a `VersionId`, and can refer to different secret data as the secret is updated. By default, SecretsManager will add the version stages `AWSCURRENT` and `AWSPREVIOUS` to every secret, but other stages can be created via the [update-secret-version-stage](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/update-secret-version-stage.html) api.
The `version` field on the `remoteRef` of the ExternalSecret will normally consider the version to be a `VersionStage`, but if the field is prefixed with `uuid/`, then the version will be considered a `VersionId`.
So in this example, the operator will request the secret with `VersionStage` as `AWSPREVIOUS`:
``` yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: 1h
secretStoreRef:
name: secretstore-sample
kind: SecretStore
target:
name: secret-to-be-created
creationPolicy: Owner
data:
- secretKey: secret-key-to-be-managed
remoteRef:
key: "example/secret"
version: "AWSPREVIOUS"
```
While in this example, the operator will request the secret with `VersionId` as `abcd-1234`
``` yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: example
spec:
refreshInterval: 1h
secretStoreRef:
name: secretstore-sample
kind: SecretStore
target:
name: secret-to-be-created
creationPolicy: Owner
data:
- secretKey: secret-key-to-be-managed
remoteRef:
key: "example/secret"
version: "uuid/abcd-1234"
```
--8<-- "snippets/provider-aws-access.md"

View file

@ -77,10 +77,21 @@ func (sm *SecretsManager) fetch(_ context.Context, ref esv1beta1.ExternalSecretD
log.Info("found secret in cache", "key", ref.Key, "version", ver)
return secretOut, nil
}
secretOut, err := sm.client.GetSecretValue(&awssm.GetSecretValueInput{
SecretId: &ref.Key,
VersionStage: &ver,
})
var getSecretValueInput *awssm.GetSecretValueInput
if strings.HasPrefix(ver, "uuid/") {
versionID := strings.TrimPrefix(ver, "uuid/")
getSecretValueInput = &awssm.GetSecretValueInput{
SecretId: &ref.Key,
VersionId: &versionID,
}
} else {
getSecretValueInput = &awssm.GetSecretValueInput{
SecretId: &ref.Key,
VersionStage: &ver,
}
}
secretOut, err := sm.client.GetSecretValue(getSecretValueInput)
var nf *awssm.ResourceNotFoundException
if errors.As(err, &nf) {
return nil, esv1beta1.NoSecretErr

View file

@ -155,14 +155,23 @@ func TestSecretsManagerGetSecret(t *testing.T) {
smtc.expectedSecret = "nestedval"
}
// good case: custom version set
setCustomVersion := func(smtc *secretsManagerTestCase) {
// good case: custom version stage set
setCustomVersionStage := func(smtc *secretsManagerTestCase) {
smtc.apiInput.VersionStage = aws.String("1234")
smtc.remoteRef.Version = "1234"
smtc.apiOutput.SecretString = aws.String("FOOBA!")
smtc.expectedSecret = "FOOBA!"
}
// good case: custom version id set
setCustomVersionID := func(smtc *secretsManagerTestCase) {
smtc.apiInput.VersionStage = nil
smtc.apiInput.VersionId = aws.String("1234-5678")
smtc.remoteRef.Version = "uuid/1234-5678"
smtc.apiOutput.SecretString = aws.String("myvalue")
smtc.expectedSecret = "myvalue"
}
successCases := []*secretsManagerTestCase{
makeValidSecretsManagerTestCase(),
makeValidSecretsManagerTestCaseCustom(setSecretString),
@ -173,7 +182,8 @@ func TestSecretsManagerGetSecret(t *testing.T) {
makeValidSecretsManagerTestCaseCustom(setSecretBinaryAndSecretStringToNil),
makeValidSecretsManagerTestCaseCustom(setNestedSecretValueJSONParsing),
makeValidSecretsManagerTestCaseCustom(setSecretValueWithDot),
makeValidSecretsManagerTestCaseCustom(setCustomVersion),
makeValidSecretsManagerTestCaseCustom(setCustomVersionStage),
makeValidSecretsManagerTestCaseCustom(setCustomVersionID),
makeValidSecretsManagerTestCaseCustom(setAPIErr),
}