Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport of backend/s3: prevent keys containing double slashes into v1.6 #33877

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
1 change: 1 addition & 0 deletions internal/backend/remote-state/s3/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ func (b *Backend) PrepareConfig(obj cty.Value) (cty.Value, tfdiags.Diagnostics)
Validators: []stringValidator{
validateStringNotEmpty,
validateStringS3Path,
validateStringDoesNotContain("//"),
},
}
keyValidators.ValidateAttr(val, attrPath, &diags)
Expand Down
14 changes: 14 additions & 0 deletions internal/backend/remote-state/s3/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,20 @@ func TestBackendConfig_PrepareConfigValidation(t *testing.T) {
),
},
},
"key with double slash": {
config: cty.ObjectVal(map[string]cty.Value{
"bucket": cty.StringVal("test"),
"key": cty.StringVal("test/with/double//slash"),
"region": cty.StringVal("us-west-2"),
}),
expectedDiags: tfdiags.Diagnostics{
attributeErrDiag(
"Invalid Value",
`Value must not contain "//"`,
cty.GetAttrPath("key"),
),
},
},

"null region": {
config: cty.ObjectVal(map[string]cty.Value{
Expand Down
12 changes: 12 additions & 0 deletions internal/backend/remote-state/s3/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ func validateStringMatches(re *regexp.Regexp, description string) stringValidato
}
}

func validateStringDoesNotContain(s string) stringValidator {
return func(val string, path cty.Path, diags *tfdiags.Diagnostics) {
if strings.Contains(val, s) {
*diags = diags.Append(attributeErrDiag(
"Invalid Value",
fmt.Sprintf(`Value must not contain "%s"`, s),
path,
))
}
}
}

func validateStringInSlice(sl []string) stringValidator {
return func(val string, path cty.Path, diags *tfdiags.Diagnostics) {
match := false
Expand Down
43 changes: 43 additions & 0 deletions internal/backend/remote-state/s3/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,3 +751,46 @@ func TestValidateStringURL(t *testing.T) {
}

}

func Test_validateStringDoesNotContain(t *testing.T) {
t.Parallel()

path := cty.GetAttrPath("field")

testcases := map[string]struct {
val string
s string
expected tfdiags.Diagnostics
}{
"valid": {
val: "foo",
s: "bar",
},

"invalid": {
val: "foobarbaz",
s: "bar",
expected: tfdiags.Diagnostics{
attributeErrDiag(
"Invalid Value",
`Value must not contain "bar"`,
path,
),
},
},
}

for name, testcase := range testcases {
testcase := testcase
t.Run(name, func(t *testing.T) {
t.Parallel()

var diags tfdiags.Diagnostics
validateStringDoesNotContain(testcase.s)(testcase.val, path, &diags)

if diff := cmp.Diff(diags, testcase.expected, cmp.Comparer(diagnosticComparer)); diff != "" {
t.Errorf("unexpected diagnostics difference: %s", diff)
}
})
}
}
Loading