Skip to content

Commit

Permalink
Merge pull request #17836 from hashicorp/asymmetric-kms-grant
Browse files Browse the repository at this point in the history
resource/aws_kms_grant: Support operations on asymmetric keys
  • Loading branch information
gdavison committed Mar 2, 2021
2 parents 9b1275f + c6d1219 commit b57b116
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 26 deletions.
3 changes: 3 additions & 0 deletions .changelog/17836.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_kms_grant: Adds support for operations on asymmetric keys
```
34 changes: 9 additions & 25 deletions aws/resource_aws_kms_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,8 @@ func resourceAwsKmsGrant() *schema.Resource {
Type: schema.TypeSet,
Set: schema.HashString,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
kms.GrantOperationCreateGrant,
kms.GrantOperationDecrypt,
kms.GrantOperationDescribeKey,
kms.GrantOperationEncrypt,
kms.GrantOperationGenerateDataKey,
kms.GrantOperationGenerateDataKeyWithoutPlaintext,
kms.GrantOperationReEncryptFrom,
kms.GrantOperationReEncryptTo,
kms.GrantOperationRetireGrant,
}, false),
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice(kms.GrantOperation_Values(), false),
},
Required: true,
ForceNew: true,
Expand Down Expand Up @@ -155,8 +145,6 @@ func resourceAwsKmsGrantCreate(d *schema.ResourceData, meta interface{}) error {
input.GrantTokens = expandStringSet(v.(*schema.Set))
}

log.Printf("[DEBUG]: Adding new KMS Grant: %s", input)

var out *kms.CreateGrantOutput

err := resource.Retry(3*time.Minute, func() *resource.RetryError {
Expand All @@ -171,10 +159,8 @@ func resourceAwsKmsGrantCreate(d *schema.ResourceData, meta interface{}) error {
isAWSErr(err, kms.ErrCodeInternalException, "") ||
isAWSErr(err, kms.ErrCodeInvalidArnException, "") {
return resource.RetryableError(
fmt.Errorf("Error adding new KMS Grant for key: %s, retrying %s",
*input.KeyId, err))
fmt.Errorf("error creating KMS Grant for Key (%s), retrying: %w", keyId, err))
}
log.Printf("[ERROR] An error occurred creating new AWS KMS Grant: %s", err)
return resource.NonRetryableError(err)
}
return nil
Expand All @@ -185,11 +171,10 @@ func resourceAwsKmsGrantCreate(d *schema.ResourceData, meta interface{}) error {
}

if err != nil {
return fmt.Errorf("Error creating KMS grant: %s", err)
return fmt.Errorf("error creating KMS Grant for Key (%s): %w", keyId, err)
}

log.Printf("[DEBUG] Created new KMS Grant: %s", *out.GrantId)
d.SetId(fmt.Sprintf("%s:%s", keyId, *out.GrantId))
d.SetId(fmt.Sprintf("%s:%s", keyId, aws.StringValue(out.GrantId)))
d.Set("grant_id", out.GrantId)
d.Set("grant_token", out.GrantToken)

Expand All @@ -204,20 +189,19 @@ func resourceAwsKmsGrantRead(d *schema.ResourceData, meta interface{}) error {
return err
}

log.Printf("[DEBUG] Looking for grant id: %s", grantId)
grant, err := findKmsGrantByIdWithRetry(conn, keyId, grantId)

if err != nil {
if isResourceNotFoundError(err) {
log.Printf("[WARN] %s KMS grant id not found for key id %s, removing from state file", grantId, keyId)
log.Printf("[WARN] KMS Grant (%s) not found for Key (%s), removing from state file", grantId, keyId)
d.SetId("")
return nil
}
return err
}

if grant == nil {
log.Printf("[WARN] %s KMS grant id not found for key id %s, removing from state file", grantId, keyId)
log.Printf("[WARN] KMS Grant (%s) not found for Key (%s), removing from state file", grantId, keyId)
d.SetId("")
return nil
}
Expand Down Expand Up @@ -245,7 +229,7 @@ func resourceAwsKmsGrantRead(d *schema.ResourceData, meta interface{}) error {
if err := d.Set("operations", aws.StringValueSlice(grant.Operations)); err != nil {
log.Printf("[DEBUG] Error setting operations for grant %s with error %s", grantId, err)
}
if *grant.Name != "" {
if aws.StringValue(grant.Name) != "" {
d.Set("name", grant.Name)
}
if grant.Constraints != nil {
Expand Down Expand Up @@ -402,7 +386,7 @@ func findKmsGrantById(conn *kms.KMS, keyId string, grantId string, marker *strin
}

if err != nil {
return nil, fmt.Errorf("error listing KMS Grants: %s", err)
return nil, fmt.Errorf("error listing KMS Grants: %w", err)
}

grant = getKmsGrantById(out.Grants, grantId)
Expand Down
62 changes: 62 additions & 0 deletions aws/resource_aws_kms_grant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,31 @@ func TestAccAWSKmsGrant_ARN(t *testing.T) {
})
}

func TestAccAWSKmsGrant_AsymmetricKey(t *testing.T) {
resourceName := "aws_kms_grant.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSKmsGrantDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSKmsGrant_AsymmetricKey(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSKmsGrantExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"grant_token", "retire_on_delete"},
},
},
})
}

func TestAccAWSKmsGrant_disappears(t *testing.T) {
resourceName := "aws_kms_grant.test"
rName := acctest.RandomWithPrefix("tf-acc-test")
Expand Down Expand Up @@ -327,3 +352,40 @@ resource "aws_kms_grant" "test" {
}
`, rName, operations)
}

func testAccAWSKmsGrant_AsymmetricKey(rName string) string {
return fmt.Sprintf(`
resource "aws_kms_grant" "test" {
name = "%[1]s"
key_id = aws_kms_key.test.key_id
grantee_principal = aws_iam_role.test.arn
operations = ["GetPublicKey", "Sign", "Verify"]
}
resource "aws_kms_key" "test" {
description = "Terraform acc test key %[1]s"
deletion_window_in_days = 7
key_usage = "SIGN_VERIFY"
customer_master_key_spec = "RSA_2048"
}
data "aws_iam_policy_document" "test" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "test" {
name = %[1]q
path = "/service-role/"
assume_role_policy = data.aws_iam_policy_document.test.json
}
`, rName)
}
2 changes: 1 addition & 1 deletion website/docs/r/kms_grant.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ The following arguments are supported:
* `name` - (Optional, Forces new resources) A friendly name for identifying the grant.
* `key_id` - (Required, Forces new resources) The unique identifier for the customer master key (CMK) that the grant applies to. Specify the key ID or the Amazon Resource Name (ARN) of the CMK. To specify a CMK in a different AWS account, you must use the key ARN.
* `grantee_principal` - (Required, Forces new resources) The principal that is given permission to perform the operations that the grant permits in ARN format. Note that due to eventual consistency issues around IAM principals, terraform's state may not always be refreshed to reflect what is true in AWS.
* `operations` - (Required, Forces new resources) A list of operations that the grant permits. The permitted values are: `Decrypt, Encrypt, GenerateDataKey, GenerateDataKeyWithoutPlaintext, ReEncryptFrom, ReEncryptTo, CreateGrant, RetireGrant, DescribeKey`
* `operations` - (Required, Forces new resources) A list of operations that the grant permits. The permitted values are: `Decrypt`, `Encrypt`, `GenerateDataKey`, `GenerateDataKeyWithoutPlaintext`, `ReEncryptFrom`, `ReEncryptTo`, `Sign`, `Verify`, `GetPublicKey`, `CreateGrant`, `RetireGrant`, `DescribeKey`, `GenerateDataKeyPair`, or `GenerateDataKeyPairWithoutPlaintext`.
* `retiring_principal` - (Optional, Forces new resources) The principal that is given permission to retire the grant by using RetireGrant operation in ARN format. Note that due to eventual consistency issues around IAM principals, terraform's state may not always be refreshed to reflect what is true in AWS.
* `constraints` - (Optional, Forces new resources) A structure that you can use to allow certain operations in the grant only when the desired encryption context is present. For more information about encryption context, see [Encryption Context](http://docs.aws.amazon.com/kms/latest/developerguide/encryption-context.html).
* `grant_creation_tokens` - (Optional, Forces new resources) A list of grant tokens to be used when creating the grant. See [Grant Tokens](http://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#grant_token) for more information about grant tokens.
Expand Down

0 comments on commit b57b116

Please sign in to comment.