Adds KMS Key validation

pull/33534/head
Graham Davison 3 years ago
parent 2fda09aab2
commit 454eed63e7

@ -279,6 +279,8 @@ func (b *Backend) PrepareConfig(obj cty.Value) (cty.Value, tfdiags.Diagnostics)
cty.Path{},
))
}
diags = diags.Append(validateKMSKey(cty.Path{cty.GetAttrStep{Name: "kms_key_id"}}, val.AsString()))
}
if val := obj.GetAttr("workspace_key_prefix"); !val.IsNull() {

@ -0,0 +1,26 @@
package s3
import (
"github.com/hashicorp/terraform/internal/tfdiags"
)
// diagnosticComparer is a Comparer function for use with cmp.Diff to compare two tfdiags.Diagnostic values
func diagnosticComparer(l, r tfdiags.Diagnostic) bool {
if l.Severity() != r.Severity() {
return false
}
if l.Description() != r.Description() {
return false
}
lp := tfdiags.GetAttribute(l)
rp := tfdiags.GetAttribute(r)
if len(lp) != len(rp) {
return false
}
if !lp.Equals(rp) {
return false
}
return true
}

@ -0,0 +1,80 @@
package s3
import (
"fmt"
"regexp"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/hashicorp/terraform/internal/tfdiags"
"github.com/zclconf/go-cty/cty"
)
const (
multiRegionKeyIdPattern = `mrk-[a-f0-9]{32}`
uuidRegexPattern = `[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[ab89][a-f0-9]{3}-[a-f0-9]{12}`
)
func validateKMSKey(path cty.Path, s string) (diags tfdiags.Diagnostics) {
if arn.IsARN(s) {
return validateKMSKeyARN(path, s)
}
return validateKMSKeyID(path, s)
}
func validateKMSKeyID(path cty.Path, s string) (diags tfdiags.Diagnostics) {
keyIdRegex := regexp.MustCompile(`^` + uuidRegexPattern + `|` + multiRegionKeyIdPattern + `$`)
if !keyIdRegex.MatchString(s) {
diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ID",
fmt.Sprintf("Value must be a valid KMS Key ID, got %q", s),
path,
))
return diags
}
return diags
}
func validateKMSKeyARN(path cty.Path, s string) (diags tfdiags.Diagnostics) {
if _, err := arn.Parse(s); err != nil {
diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
fmt.Sprintf("Value must be a valid KMS Key ARN, got %q", s),
path,
))
return diags
}
if !isKeyARN(s) {
diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
fmt.Sprintf("Value must be a valid KMS Key ARN, got %q", s),
path,
))
return diags
}
return diags
}
func isKeyARN(s string) bool {
parsedARN, err := arn.Parse(s)
if err != nil {
return false
}
return keyIdFromARNResource(parsedARN.Resource) != ""
}
func keyIdFromARNResource(s string) string {
keyIdResourceRegex := regexp.MustCompile(`^key/(` + uuidRegexPattern + `|` + multiRegionKeyIdPattern + `)$`)
matches := keyIdResourceRegex.FindStringSubmatch(s)
if matches == nil || len(matches) != 2 {
return ""
}
return matches[1]
}

@ -0,0 +1,154 @@
package s3
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform/internal/tfdiags"
"github.com/zclconf/go-cty/cty"
)
func TestValidateKMSKey(t *testing.T) {
t.Parallel()
path := cty.Path{cty.GetAttrStep{Name: "field"}}
testcases := map[string]struct {
in string
expected tfdiags.Diagnostics
}{
"kms key id": {
in: "57ff7a43-341d-46b6-aee3-a450c9de6dc8",
},
"kms key arn": {
in: "arn:aws:kms:us-west-2:111122223333:key/57ff7a43-341d-46b6-aee3-a450c9de6dc8",
},
"kms multi-region key id": {
in: "mrk-f827515944fb43f9b902a09d2c8b554f",
},
"kms multi-region key arn": {
in: "arn:aws:kms:us-west-2:111122223333:key/mrk-a835af0b39c94b86a21a8fc9535df681",
},
"kms key alias": {
in: "alias/arbitrary-key",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ID",
`Value must be a valid KMS Key ID, got "alias/arbitrary-key"`,
path,
),
},
},
"kms key alias arn": {
in: "arn:aws:kms:us-west-2:111122223333:alias/arbitrary-key",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
`Value must be a valid KMS Key ARN, got "arn:aws:kms:us-west-2:111122223333:alias/arbitrary-key"`,
path,
),
},
},
"invalid key": {
in: "$%wrongkey",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ID",
`Value must be a valid KMS Key ID, got "$%wrongkey"`,
path,
),
},
},
"non-kms arn": {
in: "arn:aws:lamda:foo:bar:key/xyz",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
`Value must be a valid KMS Key ARN, got "arn:aws:lamda:foo:bar:key/xyz"`,
path,
),
},
},
}
for name, testcase := range testcases {
testcase := testcase
t.Run(name, func(t *testing.T) {
t.Parallel()
diags := validateKMSKey(path, testcase.in)
if diff := cmp.Diff(diags, testcase.expected, cmp.Comparer(diagnosticComparer)); diff != "" {
t.Errorf("unexpected diagnostics difference: %s", diff)
}
})
}
}
func TestValidateKeyARN(t *testing.T) {
t.Parallel()
path := cty.Path{cty.GetAttrStep{Name: "field"}}
testcases := map[string]struct {
in string
expected tfdiags.Diagnostics
}{
"kms key id": {
in: "arn:aws:kms:us-west-2:123456789012:key/57ff7a43-341d-46b6-aee3-a450c9de6dc8",
},
"kms mrk key id": {
in: "arn:aws:kms:us-west-2:111122223333:key/mrk-a835af0b39c94b86a21a8fc9535df681",
},
"kms non-key id": {
in: "arn:aws:kms:us-west-2:123456789012:something/else",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
`Value must be a valid KMS Key ARN, got "arn:aws:kms:us-west-2:123456789012:something/else"`,
path,
),
},
},
"non-kms arn": {
in: "arn:aws:iam::123456789012:user/David",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
`Value must be a valid KMS Key ARN, got "arn:aws:iam::123456789012:user/David"`,
path,
),
},
},
"not an arn": {
in: "not an arn",
expected: tfdiags.Diagnostics{
tfdiags.AttributeValue(
tfdiags.Error,
"Invalid KMS Key ARN",
`Value must be a valid KMS Key ARN, got "not an arn"`,
path,
),
},
},
}
for name, testcase := range testcases {
testcase := testcase
t.Run(name, func(t *testing.T) {
t.Parallel()
diags := validateKMSKeyARN(path, testcase.in)
if diff := cmp.Diff(diags, testcase.expected, cmp.Comparer(diagnosticComparer)); diff != "" {
t.Errorf("unexpected diagnostics difference: %s", diff)
}
})
}
}
Loading…
Cancel
Save