diff --git a/cli/app/new.go b/cli/app/new.go index 1a430dd3..cdc713ab 100644 --- a/cli/app/new.go +++ b/cli/app/new.go @@ -183,6 +183,12 @@ type AppSecrets map[string]string // createSecrets creates all secrets for a new app. func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secret, sanitisedAppName string) (AppSecrets, error) { + // NOTE(d1): trim to match app.StackName() implementation + if len(sanitisedAppName) > config.MAX_SANITISED_APP_NAME_LENGTH { + logrus.Debugf("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH]) + sanitisedAppName = sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH] + } + secrets, err := secret.GenerateSecrets(cl, secretsConfig, internal.NewAppServer) if err != nil { return nil, err diff --git a/pkg/config/app.go b/pkg/config/app.go index 38b9ddc6..601d0636 100644 --- a/pkg/config/app.go +++ b/pkg/config/app.go @@ -69,9 +69,9 @@ func (a App) StackName() string { func StackName(appName string) string { stackName := SanitiseAppName(appName) - if len(stackName) > 45 { - logrus.Debugf("trimming %s to %s to avoid runtime limits", stackName, stackName[:45]) - stackName = stackName[:45] + if len(stackName) > MAX_SANITISED_APP_NAME_LENGTH { + logrus.Debugf("trimming %s to %s to avoid runtime limits", stackName, stackName[:MAX_SANITISED_APP_NAME_LENGTH]) + stackName = stackName[:MAX_SANITISED_APP_NAME_LENGTH] } return stackName diff --git a/pkg/config/env.go b/pkg/config/env.go index adedc6f4..45bd9757 100644 --- a/pkg/config/env.go +++ b/pkg/config/env.go @@ -36,6 +36,9 @@ var REPOS_BASE_URL = "https://git.coopcloud.tech/coop-cloud" var CATALOGUE_JSON_REPO_NAME = "recipes-catalogue-json" var SSH_URL_TEMPLATE = "ssh://git@git.coopcloud.tech:2222/coop-cloud/%s.git" +const MAX_SANITISED_APP_NAME_LENGTH = 45 +const MAX_DOCKER_SECRET_LENGTH = 64 + var BackupbotLabel = "coop-cloud.backupbot.enabled" // envVarModifiers is a list of env var modifier strings. These are added to diff --git a/pkg/lint/recipe.go b/pkg/lint/recipe.go index cae797f3..72e3b526 100644 --- a/pkg/lint/recipe.go +++ b/pkg/lint/recipe.go @@ -115,6 +115,13 @@ var LintRules = map[string][]LintRule{ HowToResolve: "upload your recipe to git.coopcloud.tech/coop-cloud/...", Function: LintHasRecipeRepo, }, + { + Ref: "R014", + Level: "warn", + Description: "Long secret names", + HowToResolve: "Reduce the length of secret names to 12 characters.", + Function: LintSecretLengths, + }, }, "error": { { @@ -401,6 +408,16 @@ func LintHasRecipeRepo(recipe recipe.Recipe) (bool, error) { return true, nil } +func LintSecretLengths(recipe recipe.Recipe) (bool, error) { + for name := range recipe.Config.Secrets { + if len(name) > 12 { + return false, fmt.Errorf("secret %s is longer than 12 characters", name) + } + } + + return true, nil +} + func LintValidTags(recipe recipe.Recipe) (bool, error) { recipeDir := path.Join(config.RECIPES_DIR, recipe.Name) diff --git a/pkg/secret/secret.go b/pkg/secret/secret.go index 282a0fab..f574a033 100644 --- a/pkg/secret/secret.go +++ b/pkg/secret/secret.go @@ -89,7 +89,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin appEnv["STACK_NAME"] = stackName opts := stack.Deploy{Composefiles: composeFiles} - config, err := loader.LoadComposefile(opts, appEnv) + composeConfig, err := loader.LoadComposefile(opts, appEnv) if err != nil { return nil, err } @@ -100,7 +100,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin } var enabledSecrets []string - for _, service := range config.Services { + for _, service := range composeConfig.Services { for _, secret := range service.Secrets { enabledSecrets = append(enabledSecrets, secret.Source) } @@ -112,7 +112,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin } secretValues := map[string]Secret{} - for secretId, secretConfig := range config.Secrets { + for secretId, secretConfig := range composeConfig.Secrets { if string(secretConfig.Name[len(secretConfig.Name)-1]) == "_" { return nil, fmt.Errorf("missing version for secret? (%s)", secretId) } @@ -126,6 +126,10 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin secretVersion := secretConfig.Name[lastIdx+1:] value := Secret{Version: secretVersion, RemoteName: secretConfig.Name} + if len(value.RemoteName) > config.MAX_DOCKER_SECRET_LENGTH { + return nil, fmt.Errorf("secret %s is > %d chars when combined with %s", secretId, config.MAX_DOCKER_SECRET_LENGTH, stackName) + } + // Check if the length modifier is set for this secret. for envName, modifierValues := range appModifiers { // configWithoutEnv contains the raw name as defined in the compose.yaml diff --git a/pkg/secret/secret_test.go b/pkg/secret/secret_test.go index fc10c098..f2830d2e 100644 --- a/pkg/secret/secret_test.go +++ b/pkg/secret/secret_test.go @@ -28,3 +28,14 @@ func TestReadSecretsConfig(t *testing.T) { assert.Equal(t, "v2", secretsFromConfig["test_pass_three"].Version) assert.Equal(t, 0, secretsFromConfig["test_pass_three"].Length) } + +func TestReadSecretsConfigWithLongDomain(t *testing.T) { + composeFiles := []string{"./testdir/compose.yaml"} + _, err := ReadSecretsConfig("./testdir/.env.sample", composeFiles, "should_break_on_forty_eight_char_stack_nameeeeee") + if err == nil { + t.Fatal("Expected to fail") + } + + // Check error + assert.Equal(t, "secret test_pass_one is > 64 chars when combined with should_break_on_forty_eight_char_stack_nameeeeee", err.Error()) +}