fix: secret name generation when secretId is not part of the secret name

This commit is contained in:
test
2023-12-04 14:37:41 +01:00
committed by decentral1se
parent 02b726db02
commit 99e3ed416f
7 changed files with 89 additions and 62 deletions

View File

@ -21,11 +21,24 @@ import (
"github.com/sirupsen/logrus"
)
// SecretValue represents a parsed `SECRET_FOO=v1 # length=bar` env var config
// secret definition.
type SecretValue struct {
// Secret represents a secret.
type Secret struct {
// Version comes from the secret version environment variable.
// For example:
// SECRET_FOO=v1
Version string
Length int
// Length comes from the length modifier at the secret version environment
// variable. For Example:
// SECRET_FOO=v1 # length=12
Length int
// RemoteName is the name of the secret on the server. For example:
// name: ${STACK_NAME}_test_pass_two_${SECRET_TEST_PASS_TWO_VERSION}
// With the following:
// STACK_NAME=test_example_com
// SECRET_TEST_PASS_TWO_VERSION=v2
// Will have this remote name:
// test_example_com_test_pass_two_v2
RemoteName string
}
// GeneratePasswords generates passwords.
@ -67,11 +80,13 @@ func GeneratePassphrases(count uint) ([]string, error) {
// and some times you don't (as the caller). We need to be able to handle the
// "app new" case where we pass in the .env.sample and the "secret generate"
// case where the app is created.
func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName string) (map[string]SecretValue, error) {
func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName string) (map[string]Secret, error) {
appEnv, appModifiers, err := config.ReadEnvWithModifiers(appEnvPath)
if err != nil {
return nil, err
}
// Set the STACK_NAME to be able to generate the remote name correctly.
appEnv["STACK_NAME"] = stackName
opts := stack.Deploy{Composefiles: composeFiles}
config, err := loader.LoadComposefile(opts, appEnv)
@ -96,7 +111,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName stri
return nil, nil
}
secretValues := map[string]SecretValue{}
secretValues := map[string]Secret{}
for secretId, secretConfig := range config.Secrets {
if string(secretConfig.Name[len(secretConfig.Name)-1]) == "_" {
return nil, fmt.Errorf("missing version for secret? (%s)", secretId)
@ -109,7 +124,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName stri
lastIdx := strings.LastIndex(secretConfig.Name, "_")
secretVersion := secretConfig.Name[lastIdx+1:]
value := SecretValue{Version: secretVersion}
value := Secret{Version: secretVersion, RemoteName: secretConfig.Name}
// Check if the length modifier is set for this secret.
for envName, modifierValues := range appModifiers {
@ -138,7 +153,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, recipeName stri
}
// GenerateSecrets generates secrets locally and sends them to a remote server for storage.
func GenerateSecrets(cl *dockerClient.Client, secrets map[string]SecretValue, appName, server string) (map[string]string, error) {
func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server string) (map[string]string, error) {
secretsGenerated := map[string]string{}
var mutex sync.Mutex
var wg sync.WaitGroup
@ -146,11 +161,10 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]SecretValue, ap
for n, v := range secrets {
wg.Add(1)
go func(secretName string, secret SecretValue) {
go func(secretName string, secret Secret) {
defer wg.Done()
secretRemoteName := fmt.Sprintf("%s_%s_%s", appName, secretName, secret.Version)
logrus.Debugf("attempting to generate and store %s on %s", secretRemoteName, server)
logrus.Debugf("attempting to generate and store %s on %s", secret.RemoteName, server)
if secret.Length > 0 {
passwords, err := GeneratePasswords(1, uint(secret.Length))
@ -159,9 +173,9 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]SecretValue, ap
return
}
if err := client.StoreSecret(cl, secretRemoteName, passwords[0], server); err != nil {
if err := client.StoreSecret(cl, secret.RemoteName, passwords[0], server); err != nil {
if strings.Contains(err.Error(), "AlreadyExists") {
logrus.Warnf("%s already exists, moving on...", secretRemoteName)
logrus.Warnf("%s already exists, moving on...", secret.RemoteName)
ch <- nil
} else {
ch <- err
@ -179,9 +193,9 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]SecretValue, ap
return
}
if err := client.StoreSecret(cl, secretRemoteName, passphrases[0], server); err != nil {
if err := client.StoreSecret(cl, secret.RemoteName, passphrases[0], server); err != nil {
if strings.Contains(err.Error(), "AlreadyExists") {
logrus.Warnf("%s already exists, moving on...", secretRemoteName)
logrus.Warnf("%s already exists, moving on...", secret.RemoteName)
ch <- nil
} else {
ch <- err
@ -230,7 +244,7 @@ func PollSecretsStatus(cl *dockerClient.Client, app config.App) (secretStatuses,
return secStats, err
}
secretsConfig, err := ReadSecretsConfig(app.Path, composeFiles, app.Recipe)
secretsConfig, err := ReadSecretsConfig(app.Path, composeFiles, app.StackName())
if err != nil {
return secStats, err
}