github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/backend/remote-state/s3/validate.go (about)

     1  package s3
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"github.com/aws/aws-sdk-go/aws/arn"
     8  	"github.com/terramate-io/tf/tfdiags"
     9  	"github.com/zclconf/go-cty/cty"
    10  )
    11  
    12  const (
    13  	multiRegionKeyIdPattern = `mrk-[a-f0-9]{32}`
    14  	uuidRegexPattern        = `[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[ab89][a-f0-9]{3}-[a-f0-9]{12}`
    15  )
    16  
    17  func validateKMSKey(path cty.Path, s string) (diags tfdiags.Diagnostics) {
    18  	if arn.IsARN(s) {
    19  		return validateKMSKeyARN(path, s)
    20  	}
    21  	return validateKMSKeyID(path, s)
    22  }
    23  
    24  func validateKMSKeyID(path cty.Path, s string) (diags tfdiags.Diagnostics) {
    25  	keyIdRegex := regexp.MustCompile(`^` + uuidRegexPattern + `|` + multiRegionKeyIdPattern + `$`)
    26  	if !keyIdRegex.MatchString(s) {
    27  		diags = diags.Append(tfdiags.AttributeValue(
    28  			tfdiags.Error,
    29  			"Invalid KMS Key ID",
    30  			fmt.Sprintf("Value must be a valid KMS Key ID, got %q", s),
    31  			path,
    32  		))
    33  		return diags
    34  	}
    35  
    36  	return diags
    37  }
    38  
    39  func validateKMSKeyARN(path cty.Path, s string) (diags tfdiags.Diagnostics) {
    40  	parsedARN, err := arn.Parse(s)
    41  	if err != nil {
    42  		diags = diags.Append(tfdiags.AttributeValue(
    43  			tfdiags.Error,
    44  			"Invalid KMS Key ARN",
    45  			fmt.Sprintf("Value must be a valid KMS Key ARN, got %q", s),
    46  			path,
    47  		))
    48  		return diags
    49  	}
    50  
    51  	if !isKeyARN(parsedARN) {
    52  		diags = diags.Append(tfdiags.AttributeValue(
    53  			tfdiags.Error,
    54  			"Invalid KMS Key ARN",
    55  			fmt.Sprintf("Value must be a valid KMS Key ARN, got %q", s),
    56  			path,
    57  		))
    58  		return diags
    59  	}
    60  
    61  	return diags
    62  }
    63  
    64  func isKeyARN(arn arn.ARN) bool {
    65  	return keyIdFromARNResource(arn.Resource) != ""
    66  }
    67  
    68  func keyIdFromARNResource(s string) string {
    69  	keyIdResourceRegex := regexp.MustCompile(`^key/(` + uuidRegexPattern + `|` + multiRegionKeyIdPattern + `)$`)
    70  	matches := keyIdResourceRegex.FindStringSubmatch(s)
    71  	if matches == nil || len(matches) != 2 {
    72  		return ""
    73  	}
    74  
    75  	return matches[1]
    76  }