Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions packages/api/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,15 +593,16 @@ type GetRawSecretsV3Request struct {

type GetRawSecretsV3Response struct {
Secrets []struct {
ID string `json:"_id"`
Version int `json:"version"`
Workspace string `json:"workspace"`
Type string `json:"type"`
Environment string `json:"environment"`
SecretKey string `json:"secretKey"`
SecretValue string `json:"secretValue"`
SecretComment string `json:"secretComment"`
SecretPath string `json:"secretPath"`
ID string `json:"_id"`
Version int `json:"version"`
Workspace string `json:"workspace"`
Type string `json:"type"`
Environment string `json:"environment"`
SecretKey string `json:"secretKey"`
SecretValue string `json:"secretValue"`
SecretComment string `json:"secretComment"`
SecretPath string `json:"secretPath"`
SkipMultilineEncoding bool `json:"skipMultilineEncoding"`
} `json:"secrets"`
Imports []ImportedRawSecretV3 `json:"imports"`
ETag string
Expand All @@ -617,15 +618,16 @@ type GetRawSecretV3ByNameRequest struct {

type GetRawSecretV3ByNameResponse struct {
Secret struct {
ID string `json:"_id"`
Version int `json:"version"`
Workspace string `json:"workspace"`
Type string `json:"type"`
Environment string `json:"environment"`
SecretKey string `json:"secretKey"`
SecretValue string `json:"secretValue"`
SecretComment string `json:"secretComment"`
SecretPath string `json:"secretPath"`
ID string `json:"_id"`
Version int `json:"version"`
Workspace string `json:"workspace"`
Type string `json:"type"`
Environment string `json:"environment"`
SecretKey string `json:"secretKey"`
SecretValue string `json:"secretValue"`
SecretComment string `json:"secretComment"`
SecretPath string `json:"secretPath"`
SkipMultilineEncoding bool `json:"skipMultilineEncoding"`
} `json:"secret"`
ETag string
}
Expand Down
16 changes: 12 additions & 4 deletions packages/cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func formatAsCSV(envs []models.SingleEnvironmentVariable) string {
writer := csv.NewWriter(csvString)
writer.Write([]string{"Key", "Value"})
for _, env := range envs {
writer.Write([]string{env.Key, env.Value})
writer.Write([]string{env.Key, escapeNewLinesIfRequired(env)})
}
writer.Flush()
return csvString.String()
Expand All @@ -200,7 +200,7 @@ func formatAsCSV(envs []models.SingleEnvironmentVariable) string {
func formatAsDotEnv(envs []models.SingleEnvironmentVariable) string {
var dotenv string
for _, env := range envs {
dotenv += fmt.Sprintf("%s='%s'\n", env.Key, env.Value)
dotenv += fmt.Sprintf("%s='%s'\n", env.Key, escapeNewLinesIfRequired(env))
}
return dotenv
}
Expand All @@ -209,15 +209,15 @@ func formatAsDotEnv(envs []models.SingleEnvironmentVariable) string {
func formatAsDotEnvExport(envs []models.SingleEnvironmentVariable) string {
var dotenv string
for _, env := range envs {
dotenv += fmt.Sprintf("export %s='%s'\n", env.Key, env.Value)
dotenv += fmt.Sprintf("export %s='%s'\n", env.Key, escapeNewLinesIfRequired(env))
}
return dotenv
}

func formatAsYaml(envs []models.SingleEnvironmentVariable) (string, error) {
m := make(map[string]string)
for _, env := range envs {
m[env.Key] = env.Value
m[env.Key] = escapeNewLinesIfRequired(env)
}

yamlBytes, err := yaml.Marshal(m)
Expand All @@ -238,3 +238,11 @@ func formatAsJson(envs []models.SingleEnvironmentVariable) string {
}
return string(json)
}

func escapeNewLinesIfRequired(env models.SingleEnvironmentVariable) string {
if env.IsMultilineEncodingEnabled() && strings.ContainsRune(env.Value, '\n') {
return strings.ReplaceAll(env.Value, "\n", "\\n")
}

return env.Value
}
11 changes: 11 additions & 0 deletions packages/models/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ type SingleEnvironmentVariable struct {
} `json:"tags"`
Comment string `json:"comment"`
Etag string `json:"Etag"`

// Deprecated: SkipMultilineEncoding is deprecated. Use IsMultilineEncodingEnabled() instead.
SkipMultilineEncoding bool `json:"skipMultilineEncoding"`
}

// TLDR; Why you shouldn't depend on "SkipMultilineEncoding" and instead use this method
// "SkipMultilineEncoding" generally means that the value should not be encoded as a multiline string
// But due to historic reasons this property actually does the opposite - it encodes the value as a multiline string
func (s SingleEnvironmentVariable) IsMultilineEncodingEnabled() bool {
// Encode the value only if "skipMultilineEncoding" doesn't exist or is true
return s.SkipMultilineEncoding
}

type PlaintextSecretResult struct {
Expand Down
19 changes: 10 additions & 9 deletions packages/util/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string, environment str
plainTextSecrets := []models.SingleEnvironmentVariable{}

for _, secret := range rawSecrets.Secrets {
plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, Type: secret.Type, WorkspaceId: secret.Workspace})
plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, Type: secret.Type, WorkspaceId: secret.Workspace, SkipMultilineEncoding: secret.SkipMultilineEncoding})
}

if includeImports {
Expand Down Expand Up @@ -111,7 +111,7 @@ func GetPlainTextSecretsV3(accessToken string, workspaceId string, environmentNa
plainTextSecrets := []models.SingleEnvironmentVariable{}

for _, secret := range rawSecrets.Secrets {
plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, Type: secret.Type, WorkspaceId: secret.Workspace, SecretPath: secret.SecretPath})
plainTextSecrets = append(plainTextSecrets, models.SingleEnvironmentVariable{Key: secret.SecretKey, Value: secret.SecretValue, Type: secret.Type, WorkspaceId: secret.Workspace, SecretPath: secret.SecretPath, SkipMultilineEncoding: secret.SkipMultilineEncoding})
}

if includeImports {
Expand Down Expand Up @@ -150,13 +150,14 @@ func GetSinglePlainTextSecretByNameV3(accessToken string, workspaceId string, en
}

formattedSecrets := models.SingleEnvironmentVariable{
Key: rawSecret.Secret.SecretKey,
WorkspaceId: rawSecret.Secret.Workspace,
Value: rawSecret.Secret.SecretValue,
Type: rawSecret.Secret.Type,
ID: rawSecret.Secret.ID,
Comment: rawSecret.Secret.SecretComment,
SecretPath: rawSecret.Secret.SecretPath,
Key: rawSecret.Secret.SecretKey,
WorkspaceId: rawSecret.Secret.Workspace,
Value: rawSecret.Secret.SecretValue,
Type: rawSecret.Secret.Type,
ID: rawSecret.Secret.ID,
Comment: rawSecret.Secret.SecretComment,
SecretPath: rawSecret.Secret.SecretPath,
SkipMultilineEncoding: rawSecret.Secret.SkipMultilineEncoding,
}

return formattedSecrets, rawSecret.ETag, nil
Expand Down
Loading