Merge pull request #35666 from bschaatsbergen/b/fix-secret-suffix

Add additional validation to `secret_suffix` in Kubernetes backend
pull/35818/head
Bruno Schaatsbergen 2 years ago committed by GitHub
commit 7d579e8729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -9,6 +9,8 @@ import (
"log"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/mitchellh/go-homedir"
"github.com/zclconf/go-cty/cty"
@ -54,7 +56,7 @@ func New() backend.Backend {
"secret_suffix": {
Type: cty.String,
Required: true,
Description: "Suffix used when creating the secret. The secret will be named in the format: `tfstate-{workspace}-{secret_suffix}`.",
Description: "Suffix used when creating the secret. The secret will be named in the format: `tfstate-{workspace}-{secret_suffix}`. Note that the backend may append its own numeric index to the secret name when chunking large state files into multiple secrets. In this case, there will be multiple secrets named in the format: `tfstate-{workspace}-{secret_suffix}-{index}`.",
},
"labels": {
Type: cty.Map(cty.String),
@ -322,7 +324,17 @@ func (b *Backend) Configure(configVal cty.Value) tfdiags.Diagnostics {
ns := data.String("namespace")
b.namespace = ns
b.nameSuffix = data.String("secret_suffix")
if hasNumericSuffix(b.nameSuffix, "-") {
// If the last segment is a number, it's considered invalid.
// The backend automatically appends its own numeric suffix when chunking large state files into multiple secrets.
// Allowing a user-defined numeric suffix could cause conflicts with this mechanism.
return backendbase.ErrorAsDiagnostics(
fmt.Errorf("secret_suffix must not end with '-<number>', got %q", b.nameSuffix),
)
}
b.config = cfg
return nil
@ -464,3 +476,16 @@ func decodeListOfString(v cty.Value) []string {
}
return ret
}
func hasNumericSuffix(value, substr string) bool {
// Find the last occurrence of '-' and get the part after it
if idx := strings.LastIndex(value, substr); idx != -1 {
lastPart := value[idx+1:]
// Try to convert the last part to an integer.
if _, err := strconv.Atoi(lastPart); err == nil {
return true
}
}
// Return false if no '-' is found or if the last part isn't numeric
return false
}

@ -197,3 +197,24 @@ func cleanupK8sResources(t *testing.T) {
t.Fatal(errs)
}
}
func Test_hasNumericSuffix(t *testing.T) {
tests := []struct {
input string
expected bool
}{
{"my-secret-123", true},
{"my-secret-abcd", false},
{"nodashhere", false},
{"another-secret-45abc", false},
{"some-thing-1", true},
{"some-thing-1-23", true},
}
for _, tt := range tests {
isNumeric := hasNumericSuffix(tt.input, "-")
if isNumeric != tt.expected {
t.Errorf("expected %v, got %v for input %s", tt.expected, isNumeric, tt.input)
}
}
}

@ -102,6 +102,8 @@ func (c *RemoteClient) getSecrets() ([]unstructured.Unstructured, error) {
for _, item := range res.Items {
name := item.GetName()
nameParts := strings.Split(name, "-")
// Because large Terraform state files are split into multiple secrets,
// we parse the index from the secret name.
index, err := strconv.Atoi(nameParts[len(nameParts)-1])
if err != nil {
index = 0

@ -48,7 +48,7 @@ data "terraform_remote_state" "foo" {
The following configuration options are supported:
* `secret_suffix` - (Required) Suffix used when creating secrets. Secrets will be named in the format: `tfstate-{workspace}-{secret_suffix}`.
* `secret_suffix` - (Required) Suffix used when creating the secret. The secret will be named in the format: `tfstate-{workspace}-{secret_suffix}`. Note that the backend may append its own numeric index to the secret name when chunking large state files into multiple secrets. In this case, there will be multiple secrets named in the format: `tfstate-{workspace}-{secret_suffix}-{index}`.
* `labels` - (Optional) Map of additional labels to be applied to the secret and lease.
* `namespace` - (Optional) Namespace to store the secret and lease in. Can be sourced from `KUBE_NAMESPACE`.
* `in_cluster_config` - (Optional) Used to authenticate to the cluster from inside a pod. Can be sourced from `KUBE_IN_CLUSTER_CONFIG`.

Loading…
Cancel
Save