From b38f7f426a563131677e80a4f4cbc699ca08557b Mon Sep 17 00:00:00 2001 From: dnitsch Date: Mon, 23 Jan 2023 14:30:05 +0000 Subject: [PATCH] docs: additional info around new providers --- README.md | 25 ++++++++++++++------ docs/adding-provider.md | 47 ++++++++++++++++++++------------------ pkg/generator/generator.go | 2 +- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 519ee1a..3eae032 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,14 @@ Package used for retrieving application settings from various sources. Currently supported variable and secrets implementations: -- AWS SecretsManager -- AWS ParameterStore -- AzureKeyvault Secrets -- TODO: - - GCP - - Hashicorp +- [AWS SecretsManager](https://aws.amazon.com/secrets-manager/) +- [AWS ParameterStore](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) +- [AzureKeyvault Secrets](https://azure.microsoft.com/en-gb/products/key-vault/) + - see [Special consideration for AZKVSECRET](#special-consideration-for-azkvsecret) around how to structure the token in this case. +- [GCP Secrets](https://cloud.google.com/secret-manager) +- [Hashicorp Vault](https://developer.hashicorp.com/vault/docs/secrets/kv) + - using the V2 endpoint + - see The main driver is to use component level configuration objects, if stored in a `"namespaced"` manner e.g. in AWS ParamStore as `/nonprod/component-service-a/configVar`, however this is not a requirement and the param name can be whatever. Though whilst using some sort of a organised manner it will be more straight forward to allow other services to consume certain secrets/params based on resource/access policies. @@ -137,6 +139,15 @@ For Azure KeyVault the first part of the token needs to be the name of the vault > The preceeding slash to the vault name is optional - `AZKVSECRET#/test-vault/no-slash-token-1` and `AZKVSECRET#test-vault/no-slash-token-1` will both identify the vault of name `test-vault` +### Special consideration for HashicorpVault + +For HashicorpVault the first part of the token needs to be the name of the mountpath. In Dev Vaults this is `"secret"`, + e.g.: + +`VAULT://secret/demo/configmanager|test` + +The Hashicorp Vault functions in the same exact way as the other implementations. It will retrieve the JSON object and can be looked up within it by using a key separator. + ## Go API latest api [here](https://pkg.go.dev/github.com/dnitsch/configmanager) @@ -240,6 +251,6 @@ func credentialString(ctx context.Context, pwdToken, hostToken string) (string, ## Help - More implementations should be easily added with a specific implementation under the strategy interface - - e.g. GCP equivalent + - see [add additional providers](docs/adding-provider.md) - maybe run as cron in the background to perform a periodic sync in case values change? diff --git a/docs/adding-provider.md b/docs/adding-provider.md index 24d2380..34d02be 100644 --- a/docs/adding-provider.md +++ b/docs/adding-provider.md @@ -1,36 +1,39 @@ # adding provider -Add Token - -`VarPrefix = map[string]bool{SecretMgrPrefix: true, ParamStorePrefix: true, AzKeyVaultSecretsPrefix: true, GcpSecretMgrPrefix: true}` // <-- ADD here +Add Token Prefix ```go const ( - // tokenSeparator used for identifying the end of a prefix and beginning of token - // see notes about special consideration for AZKVSECRET tokens - tokenSeparator = "#" - // keySeparator used for accessing nested objects within the retrieved map - keySeparator = "|" // AWS SecretsManager prefix - SecretMgrPrefix = "AWSSECRETS" + SecretMgrPrefix ImplementationPrefix = "AWSSECRETS" // AWS Parameter Store prefix - ParamStorePrefix = "AWSPARAMSTR" + ParamStorePrefix ImplementationPrefix = "AWSPARAMSTR" // Azure Key Vault Secrets prefix - AzKeyVaultSecretsPrefix = "AZKVSECRET" - // GCP SecretsManager prefix - GcpSecretMgrPrefix = "GCPSECRETS" // <-- ADD here + AzKeyVaultSecretsPrefix ImplementationPrefix = "AZKVSECRET" + // Hashicorp Vault prefix + HashicorpVaultPrefix ImplementationPrefix = "VAULT" + // GcpSecrets + GcpSecretsPrefix ImplementationPrefix = "GCPSECRETS" ) ``` -inside - ```go -func (imp *GcpSecrets) getTokenValue(v *retrieveStrategy) (string, error) { +var ( + // default varPrefix used by the replacer function + // any token must beging with one of these else + // it will be skipped as not a replaceable token + VarPrefix = map[ImplementationPrefix]bool{SecretMgrPrefix: true, ParamStorePrefix: true, AzKeyVaultSecretsPrefix: true, GcpSecretsPrefix: true, HashicorpVaultPrefix: true} // <-- ADD here +) +``` - log.Infof("%s", "Concrete implementation GcpSecrets") - log.Infof("Getting Secret: %s", imp.token) +ensure your implementation satisfy the `genVarsStrategy` interface + +```go +type genVarsStrategy interface { + getTokenValue(rs *retrieveStrategy) (s string, e error) + setToken(s string) + setValue(s string) +} +``` - input := &gcpsecretspb.AccessSecretVersionRequest{ - Name: fmt.Sprintf("%s/versions/latest", v.stripPrefix(imp.token, GcpSecretsPrefix)), // <-- Ensure this is set correctly - } -``` \ No newline at end of file +Even if the native type is K/V return a marshalled version of the JSON as the rest of the flow will decide how to present it back to the final consumer. diff --git a/pkg/generator/generator.go b/pkg/generator/generator.go index 8e56fc0..0c63d27 100644 --- a/pkg/generator/generator.go +++ b/pkg/generator/generator.go @@ -39,7 +39,7 @@ var ( // default varPrefix used by the replacer function // any token must beging with one of these else // it will be skipped as not a replaceable token - VarPrefix = map[ImplementationPrefix]bool{SecretMgrPrefix: true, ParamStorePrefix: true, AzKeyVaultSecretsPrefix: true, HashicorpVaultPrefix: true} + VarPrefix = map[ImplementationPrefix]bool{SecretMgrPrefix: true, ParamStorePrefix: true, AzKeyVaultSecretsPrefix: true, GcpSecretsPrefix: true, HashicorpVaultPrefix: true} ) // Generatoriface describes the exported methods