Skip to content

Commit 6648df7

Browse files
philwittyRadek Simko
authored andcommitted
Added AWS KMS key & alias support
1 parent ec5643f commit 6648df7

4 files changed

Lines changed: 314 additions & 0 deletions

File tree

builtin/providers/aws/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"github.com/aws/aws-sdk-go/service/glacier"
4343
"github.com/aws/aws-sdk-go/service/iam"
4444
"github.com/aws/aws-sdk-go/service/kinesis"
45+
"github.com/aws/aws-sdk-go/service/kms"
4546
"github.com/aws/aws-sdk-go/service/lambda"
4647
"github.com/aws/aws-sdk-go/service/opsworks"
4748
"github.com/aws/aws-sdk-go/service/rds"
@@ -97,6 +98,7 @@ type AWSClient struct {
9798
rdsconn *rds.RDS
9899
iamconn *iam.IAM
99100
kinesisconn *kinesis.Kinesis
101+
kmsconn *kms.KMS
100102
firehoseconn *firehose.Firehose
101103
elasticacheconn *elasticache.ElastiCache
102104
elasticbeanstalkconn *elasticbeanstalk.ElasticBeanstalk
@@ -294,6 +296,8 @@ func (c *Config) Client() (interface{}, error) {
294296
log.Println("[INFO] Initializing Redshift SDK connection")
295297
client.redshiftconn = redshift.New(sess)
296298

299+
log.Println("[INFO] Initializing KMS connection")
300+
client.kmsconn = kms.New(sess)
297301
}
298302

299303
if len(errs) > 0 {

builtin/providers/aws/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ func Provider() terraform.ResourceProvider {
184184
"aws_key_pair": resourceAwsKeyPair(),
185185
"aws_kinesis_firehose_delivery_stream": resourceAwsKinesisFirehoseDeliveryStream(),
186186
"aws_kinesis_stream": resourceAwsKinesisStream(),
187+
"aws_kms_alias": resourceAwsKmsAlias(),
188+
"aws_kms_key": resourceAwsKmsKey(),
187189
"aws_lambda_function": resourceAwsLambdaFunction(),
188190
"aws_lambda_event_source_mapping": resourceAwsLambdaEventSourceMapping(),
189191
"aws_lambda_alias": resourceAwsLambdaAlias(),
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"regexp"
7+
8+
"github.com/hashicorp/terraform/helper/schema"
9+
10+
"github.com/aws/aws-sdk-go/aws"
11+
"github.com/aws/aws-sdk-go/service/kms"
12+
)
13+
14+
func resourceAwsKmsAlias() *schema.Resource {
15+
return &schema.Resource{
16+
Create: resourceAwsKmsAliasCreate,
17+
Read: resourceAwsKmsAliasRead,
18+
Update: resourceAwsKmsAliasUpdate,
19+
Delete: resourceAwsKmsAliasDelete,
20+
21+
Schema: map[string]*schema.Schema{
22+
"arn": &schema.Schema{
23+
Type: schema.TypeString,
24+
Computed: true,
25+
},
26+
"name": &schema.Schema{
27+
Type: schema.TypeString,
28+
Required: true,
29+
ForceNew: true,
30+
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
31+
value := v.(string)
32+
if !regexp.MustCompile(`^(alias\/)[a-zA-Z0-9:/_-]+$`).MatchString(value) {
33+
es = append(es, fmt.Errorf(
34+
"name must begin with 'alias/' and be comprised of only [a-zA-Z0-9:/_-]", k))
35+
}
36+
return
37+
},
38+
},
39+
"target_key_id": &schema.Schema{
40+
Type: schema.TypeString,
41+
Required: true,
42+
ForceNew: false,
43+
},
44+
},
45+
}
46+
}
47+
48+
func resourceAwsKmsAliasCreate(d *schema.ResourceData, meta interface{}) error {
49+
conn := meta.(*AWSClient).kmsconn
50+
name := d.Get("name").(string)
51+
targetKeyId := d.Get("target_key_id").(string)
52+
53+
log.Printf("[DEBUG] KMS alias create name: %s, target_key: %s", name, targetKeyId)
54+
55+
req := &kms.CreateAliasInput{
56+
AliasName: aws.String(name),
57+
TargetKeyId: aws.String(targetKeyId),
58+
}
59+
_, err := conn.CreateAlias(req)
60+
if err != nil {
61+
return err
62+
}
63+
d.SetId(name)
64+
return resourceAwsKmsAliasRead(d, meta)
65+
}
66+
67+
func resourceAwsKmsAliasRead(d *schema.ResourceData, meta interface{}) error {
68+
conn := meta.(*AWSClient).kmsconn
69+
name := d.Get("name").(string)
70+
71+
req := &kms.ListAliasesInput{}
72+
resp, err := conn.ListAliases(req)
73+
if err != nil {
74+
return err
75+
}
76+
for _,e := range resp.Aliases {
77+
if name == *e.AliasName {
78+
if err := d.Set("arn", e.AliasArn); err != nil {
79+
return err
80+
}
81+
if err := d.Set("target_key_id", e.TargetKeyId); err != nil {
82+
return err
83+
}
84+
return nil
85+
}
86+
}
87+
88+
log.Printf("[DEBUG] KMS alias read: alias not found")
89+
d.SetId("")
90+
return nil
91+
}
92+
93+
func resourceAwsKmsAliasUpdate(d *schema.ResourceData, meta interface{}) error {
94+
conn := meta.(*AWSClient).kmsconn
95+
96+
if d.HasChange("target_key_id") {
97+
if err := resourceAwsKmsAliasTargetUpdate(conn, d); err != nil {
98+
return err
99+
}
100+
}
101+
return nil
102+
}
103+
104+
func resourceAwsKmsAliasTargetUpdate(conn *kms.KMS, d *schema.ResourceData) error {
105+
name := d.Get("name").(string)
106+
targetKeyId := d.Get("target_key_id").(string)
107+
108+
log.Printf("[DEBUG] KMS alias: %s, update target: %s", name, targetKeyId)
109+
110+
req := &kms.UpdateAliasInput{
111+
AliasName: aws.String(name),
112+
TargetKeyId: aws.String(targetKeyId),
113+
}
114+
_, err := conn.UpdateAlias(req)
115+
116+
return err
117+
}
118+
119+
func resourceAwsKmsAliasDelete(d *schema.ResourceData, meta interface{}) error {
120+
conn := meta.(*AWSClient).kmsconn
121+
name := d.Get("name").(string)
122+
123+
req := &kms.DeleteAliasInput{
124+
AliasName: aws.String(name),
125+
}
126+
_, err := conn.DeleteAlias(req)
127+
128+
log.Printf("[DEBUG] KMS Alias: %s deleted.", name)
129+
d.SetId("")
130+
return err
131+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/hashicorp/terraform/helper/schema"
8+
9+
"github.com/aws/aws-sdk-go/aws"
10+
"github.com/aws/aws-sdk-go/service/kms"
11+
)
12+
13+
func resourceAwsKmsKey() *schema.Resource {
14+
return &schema.Resource{
15+
Create: resourceAwsKmsKeyCreate,
16+
Read: resourceAwsKmsKeyRead,
17+
Update: resourceAwsKmsKeyUpdate,
18+
Delete: resourceAwsKmsKeyDelete,
19+
20+
Schema: map[string]*schema.Schema{
21+
"arn": &schema.Schema{
22+
Type: schema.TypeString,
23+
Computed: true,
24+
},
25+
"key_id": &schema.Schema{
26+
Type: schema.TypeString,
27+
Computed: true,
28+
},
29+
"enabled": &schema.Schema{
30+
Type: schema.TypeBool,
31+
Computed: true,
32+
},
33+
"description": &schema.Schema{
34+
Type: schema.TypeString,
35+
Optional: true,
36+
Computed: true,
37+
ForceNew: false,
38+
},
39+
"key_usage": &schema.Schema{
40+
Type: schema.TypeString,
41+
Optional: true,
42+
Computed: true,
43+
ForceNew: true,
44+
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
45+
value := v.(string)
46+
if !(value == "ENCRYPT_DECRYPT" || value == "") {
47+
es = append(es, fmt.Errorf(
48+
"key_usage must be ENCRYPT_DECRYPT or not specified"))
49+
}
50+
return
51+
},
52+
},
53+
"policy": &schema.Schema{
54+
Type: schema.TypeString,
55+
Optional: true,
56+
Computed: true,
57+
ForceNew: false,
58+
},
59+
},
60+
}
61+
}
62+
63+
func resourceAwsKmsKeyCreate(d *schema.ResourceData, meta interface{}) error {
64+
conn := meta.(*AWSClient).kmsconn
65+
66+
// Allow aws to chose default values if we don't pass them
67+
var req kms.CreateKeyInput
68+
if v, exists := d.GetOk("description"); exists {
69+
req.Description = aws.String(v.(string))
70+
}
71+
if v, exists := d.GetOk("key_usage"); exists {
72+
req.KeyUsage = aws.String(v.(string))
73+
}
74+
if v, exists := d.GetOk("policy"); exists {
75+
req.Policy = aws.String(v.(string))
76+
}
77+
78+
resp, err := conn.CreateKey(&req)
79+
if err != nil {
80+
return err
81+
}
82+
return resourceAwsKmsKeyReadResult(d, resp.KeyMetadata)
83+
}
84+
85+
func resourceAwsKmsKeyRead(d *schema.ResourceData, meta interface{}) error {
86+
conn := meta.(*AWSClient).kmsconn
87+
keyId := d.Get("key_id").(string)
88+
89+
req := &kms.DescribeKeyInput{
90+
KeyId: aws.String(keyId),
91+
}
92+
resp, err := conn.DescribeKey(req)
93+
if err != nil {
94+
return err
95+
}
96+
return resourceAwsKmsKeyReadResult(d, resp.KeyMetadata)
97+
}
98+
99+
func resourceAwsKmsKeyReadResult(d *schema.ResourceData, metadata *kms.KeyMetadata) error {
100+
d.SetId(*metadata.KeyId)
101+
102+
if err := d.Set("arn", metadata.Arn); err != nil {
103+
return err
104+
}
105+
if err := d.Set("key_id", metadata.KeyId); err != nil {
106+
return err
107+
}
108+
if err := d.Set("enabled", metadata.Enabled); err != nil {
109+
return err
110+
}
111+
if err := d.Set("description", metadata.Description); err != nil {
112+
return err
113+
}
114+
if err := d.Set("key_usage", metadata.KeyUsage); err != nil {
115+
return err
116+
}
117+
return nil
118+
}
119+
120+
func resourceAwsKmsKeyUpdate(d *schema.ResourceData, meta interface{}) error {
121+
conn := meta.(*AWSClient).kmsconn
122+
123+
if d.HasChange("description") {
124+
if err := resourceAwsKmsKeyDescriptionUpdate(conn, d); err != nil {
125+
return err
126+
}
127+
}
128+
if d.HasChange("policy") {
129+
if err := resourceAwsKmsKeyPolicyUpdate(conn, d); err != nil {
130+
return err
131+
}
132+
}
133+
return resourceAwsKmsKeyRead(d, meta)
134+
}
135+
136+
func resourceAwsKmsKeyDescriptionUpdate(conn *kms.KMS, d *schema.ResourceData) error {
137+
description := d.Get("description").(string)
138+
keyId := d.Get("key_id").(string)
139+
140+
log.Printf("[DEBUG] KMS key: %s, update description: %s", keyId, description)
141+
142+
req := &kms.UpdateKeyDescriptionInput{
143+
Description: aws.String(description),
144+
KeyId: aws.String(keyId),
145+
}
146+
_, err := conn.UpdateKeyDescription(req)
147+
return err
148+
}
149+
150+
func resourceAwsKmsKeyPolicyUpdate(conn *kms.KMS, d *schema.ResourceData) error {
151+
policy := d.Get("policy").(string)
152+
keyId := d.Get("key_id").(string)
153+
154+
log.Printf("[DEBUG] KMS key: %s, update policy: %s", keyId, policy)
155+
156+
req := &kms.PutKeyPolicyInput{
157+
KeyId: aws.String(keyId),
158+
Policy: aws.String(policy),
159+
PolicyName: aws.String("default"),
160+
}
161+
_, err := conn.PutKeyPolicy(req)
162+
return err
163+
}
164+
165+
func resourceAwsKmsKeyDelete(d *schema.ResourceData, meta interface{}) error {
166+
conn := meta.(*AWSClient).kmsconn
167+
keyId := d.Get("key_id").(string)
168+
169+
req := &kms.DisableKeyInput{
170+
KeyId: aws.String(keyId),
171+
}
172+
_, err := conn.DisableKey(req)
173+
174+
log.Printf("[DEBUG] KMS Key: %s deactivated.", keyId)
175+
d.SetId("")
176+
return err
177+
}

0 commit comments

Comments
 (0)