-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3928 from TimeIncOSS/aws-kms
provider/aws: Add support for KMS
- Loading branch information
Showing
13 changed files
with
3,837 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"regexp" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/kms" | ||
) | ||
|
||
func resourceAwsKmsAlias() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsKmsAliasCreate, | ||
Read: resourceAwsKmsAliasRead, | ||
Update: resourceAwsKmsAliasUpdate, | ||
Delete: resourceAwsKmsAliasDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"arn": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { | ||
value := v.(string) | ||
if !regexp.MustCompile(`^(alias\/)[a-zA-Z0-9:/_-]+$`).MatchString(value) { | ||
es = append(es, fmt.Errorf( | ||
"%q must begin with 'alias/' and be comprised of only [a-zA-Z0-9:/_-]", k)) | ||
} | ||
return | ||
}, | ||
}, | ||
"target_key_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsKmsAliasCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).kmsconn | ||
name := d.Get("name").(string) | ||
targetKeyId := d.Get("target_key_id").(string) | ||
|
||
log.Printf("[DEBUG] KMS alias create name: %s, target_key: %s", name, targetKeyId) | ||
|
||
req := &kms.CreateAliasInput{ | ||
AliasName: aws.String(name), | ||
TargetKeyId: aws.String(targetKeyId), | ||
} | ||
_, err := conn.CreateAlias(req) | ||
if err != nil { | ||
return err | ||
} | ||
d.SetId(name) | ||
return resourceAwsKmsAliasRead(d, meta) | ||
} | ||
|
||
func resourceAwsKmsAliasRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).kmsconn | ||
name := d.Get("name").(string) | ||
|
||
alias, err := findKmsAliasByName(conn, name, nil) | ||
if err != nil { | ||
return err | ||
} | ||
if alias == nil { | ||
log.Printf("[DEBUG] Removing KMS Alias %q as it's already gone", name) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
log.Printf("[DEBUG] Found KMS Alias: %s", alias) | ||
|
||
d.Set("arn", alias.AliasArn) | ||
d.Set("target_key_id", alias.TargetKeyId) | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsKmsAliasUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).kmsconn | ||
|
||
if d.HasChange("target_key_id") { | ||
err := resourceAwsKmsAliasTargetUpdate(conn, d) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func resourceAwsKmsAliasTargetUpdate(conn *kms.KMS, d *schema.ResourceData) error { | ||
name := d.Get("name").(string) | ||
targetKeyId := d.Get("target_key_id").(string) | ||
|
||
log.Printf("[DEBUG] KMS alias: %s, update target: %s", name, targetKeyId) | ||
|
||
req := &kms.UpdateAliasInput{ | ||
AliasName: aws.String(name), | ||
TargetKeyId: aws.String(targetKeyId), | ||
} | ||
_, err := conn.UpdateAlias(req) | ||
|
||
return err | ||
} | ||
|
||
func resourceAwsKmsAliasDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).kmsconn | ||
name := d.Get("name").(string) | ||
|
||
req := &kms.DeleteAliasInput{ | ||
AliasName: aws.String(name), | ||
} | ||
_, err := conn.DeleteAlias(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Printf("[DEBUG] KMS Alias: %s deleted.", name) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
// API by default limits results to 50 aliases | ||
// This is how we make sure we won't miss any alias | ||
// See http://docs.aws.amazon.com/kms/latest/APIReference/API_ListAliases.html | ||
func findKmsAliasByName(conn *kms.KMS, name string, marker *string) (*kms.AliasListEntry, error) { | ||
req := kms.ListAliasesInput{ | ||
Limit: aws.Int64(int64(100)), | ||
} | ||
if marker != nil { | ||
req.Marker = marker | ||
} | ||
|
||
log.Printf("[DEBUG] Listing KMS aliases: %s", req) | ||
resp, err := conn.ListAliases(&req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, entry := range resp.Aliases { | ||
if *entry.AliasName == name { | ||
return entry, nil | ||
} | ||
} | ||
if *resp.Truncated { | ||
log.Printf("[DEBUG] KMS alias list is truncated, listing more via %s", *resp.NextMarker) | ||
return findKmsAliasByName(conn, name, resp.NextMarker) | ||
} | ||
|
||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSKmsAlias_basic(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSKmsAliasDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccAWSKmsSingleAlias, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSKmsAliasExists("aws_kms_alias.single"), | ||
), | ||
}, | ||
resource.TestStep{ | ||
Config: testAccAWSKmsSingleAlias_modified, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSKmsAliasExists("aws_kms_alias.single"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccAWSKmsAlias_multiple(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSKmsAliasDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccAWSKmsMultipleAliases, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSKmsAliasExists("aws_kms_alias.one"), | ||
testAccCheckAWSKmsAliasExists("aws_kms_alias.two"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSKmsAliasDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).kmsconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_kms_alias" { | ||
continue | ||
} | ||
|
||
entry, err := findKmsAliasByName(conn, rs.Primary.ID, nil) | ||
if err != nil { | ||
return err | ||
} | ||
if entry != nil { | ||
return fmt.Errorf("KMS alias still exists:\n%#v", entry) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccCheckAWSKmsAliasExists(name string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
_, ok := s.RootModule().Resources[name] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", name) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
var kmsAliasTimestamp = time.Now().Format(time.RFC1123) | ||
var testAccAWSKmsSingleAlias = fmt.Sprintf(` | ||
resource "aws_kms_key" "one" { | ||
description = "Terraform acc test One %s" | ||
deletion_window_in_days = 7 | ||
} | ||
resource "aws_kms_key" "two" { | ||
description = "Terraform acc test Two %s" | ||
deletion_window_in_days = 7 | ||
} | ||
resource "aws_kms_alias" "single" { | ||
name = "alias/tf-acc-key-alias" | ||
target_key_id = "${aws_kms_key.one.key_id}" | ||
}`, kmsAliasTimestamp, kmsAliasTimestamp) | ||
|
||
var testAccAWSKmsSingleAlias_modified = fmt.Sprintf(` | ||
resource "aws_kms_key" "one" { | ||
description = "Terraform acc test One %s" | ||
deletion_window_in_days = 7 | ||
} | ||
resource "aws_kms_key" "two" { | ||
description = "Terraform acc test Two %s" | ||
deletion_window_in_days = 7 | ||
} | ||
resource "aws_kms_alias" "single" { | ||
name = "alias/tf-acc-key-alias" | ||
target_key_id = "${aws_kms_key.two.key_id}" | ||
}`, kmsAliasTimestamp, kmsAliasTimestamp) | ||
|
||
var testAccAWSKmsMultipleAliases = fmt.Sprintf(` | ||
resource "aws_kms_key" "single" { | ||
description = "Terraform acc test One %s" | ||
deletion_window_in_days = 7 | ||
} | ||
resource "aws_kms_alias" "one" { | ||
name = "alias/tf-acc-key-alias-one" | ||
target_key_id = "${aws_kms_key.single.key_id}" | ||
} | ||
resource "aws_kms_alias" "two" { | ||
name = "alias/tf-acc-key-alias-two" | ||
target_key_id = "${aws_kms_key.single.key_id}" | ||
}`, kmsAliasTimestamp) |
Oops, something went wrong.