2015-05-26 16:52:58 +02:00
|
|
|
package aws
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/sha1"
|
|
|
|
"encoding/hex"
|
|
|
|
"fmt"
|
2015-07-28 21:02:26 +02:00
|
|
|
"log"
|
2015-05-26 16:52:58 +02:00
|
|
|
"strings"
|
|
|
|
|
2015-06-03 20:36:57 +02:00
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
|
|
|
"github.com/aws/aws-sdk-go/service/iam"
|
2015-05-26 16:52:58 +02:00
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
|
|
|
func resourceAwsIAMServerCertificate() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceAwsIAMServerCertificateCreate,
|
|
|
|
Read: resourceAwsIAMServerCertificateRead,
|
|
|
|
Delete: resourceAwsIAMServerCertificateDelete,
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"certificate_body": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
StateFunc: normalizeCert,
|
|
|
|
},
|
|
|
|
|
|
|
|
"certificate_chain": &schema.Schema{
|
2015-06-24 07:31:24 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
ForceNew: true,
|
2015-06-21 07:40:09 +02:00
|
|
|
StateFunc: normalizeCert,
|
2015-05-26 16:52:58 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
"path": &schema.Schema{
|
2015-07-28 21:02:26 +02:00
|
|
|
Type: schema.TypeString,
|
2015-05-26 16:52:58 +02:00
|
|
|
Optional: true,
|
2015-07-28 21:02:26 +02:00
|
|
|
Default: "/",
|
2015-05-26 16:52:58 +02:00
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"private_key": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
StateFunc: normalizeCert,
|
|
|
|
},
|
|
|
|
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"arn": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsIAMServerCertificateCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).iamconn
|
|
|
|
|
|
|
|
createOpts := &iam.UploadServerCertificateInput{
|
|
|
|
CertificateBody: aws.String(d.Get("certificate_body").(string)),
|
|
|
|
PrivateKey: aws.String(d.Get("private_key").(string)),
|
|
|
|
ServerCertificateName: aws.String(d.Get("name").(string)),
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, ok := d.GetOk("certificate_chain"); ok {
|
|
|
|
createOpts.CertificateChain = aws.String(v.(string))
|
|
|
|
}
|
|
|
|
|
2015-07-28 21:02:26 +02:00
|
|
|
if v, ok := d.GetOk("path"); ok {
|
2015-05-26 16:52:58 +02:00
|
|
|
createOpts.Path = aws.String(v.(string))
|
|
|
|
}
|
|
|
|
|
2015-07-28 21:02:26 +02:00
|
|
|
log.Printf("[DEBUG] Creating IAM Server Certificate with opts: %s", createOpts)
|
2015-05-26 16:52:58 +02:00
|
|
|
resp, err := conn.UploadServerCertificate(createOpts)
|
|
|
|
if err != nil {
|
|
|
|
if awsErr, ok := err.(awserr.Error); ok {
|
|
|
|
return fmt.Errorf("[WARN] Error uploading server certificate, error: %s: %s", awsErr.Code(), awsErr.Message())
|
|
|
|
}
|
|
|
|
return fmt.Errorf("[WARN] Error uploading server certificate, error: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(*resp.ServerCertificateMetadata.ServerCertificateID)
|
|
|
|
|
|
|
|
return resourceAwsIAMServerCertificateRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsIAMServerCertificateRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).iamconn
|
|
|
|
resp, err := conn.GetServerCertificate(&iam.GetServerCertificateInput{
|
|
|
|
ServerCertificateName: aws.String(d.Get("name").(string)),
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if awsErr, ok := err.(awserr.Error); ok {
|
|
|
|
return fmt.Errorf("[WARN] Error reading IAM Server Certificate: %s: %s", awsErr.Code(), awsErr.Message())
|
|
|
|
}
|
|
|
|
return fmt.Errorf("[WARN] Error reading IAM Server Certificate: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// these values should always be present, and have a default if not set in
|
|
|
|
// configuration, and so safe to reference with nil checks
|
|
|
|
d.Set("certificate_body", normalizeCert(resp.ServerCertificate.CertificateBody))
|
2015-07-28 21:02:26 +02:00
|
|
|
|
|
|
|
c := normalizeCert(resp.ServerCertificate.CertificateChain)
|
|
|
|
if c != "" {
|
|
|
|
d.Set("certificate_chain", c)
|
|
|
|
}
|
|
|
|
|
2015-05-26 16:52:58 +02:00
|
|
|
d.Set("path", resp.ServerCertificate.ServerCertificateMetadata.Path)
|
|
|
|
d.Set("arn", resp.ServerCertificate.ServerCertificateMetadata.ARN)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceAwsIAMServerCertificateDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
conn := meta.(*AWSClient).iamconn
|
|
|
|
_, err := conn.DeleteServerCertificate(&iam.DeleteServerCertificateInput{
|
|
|
|
ServerCertificateName: aws.String(d.Get("name").(string)),
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if awsErr, ok := err.(awserr.Error); ok {
|
|
|
|
return fmt.Errorf("[WARN] Error deleting server certificate: %s: %s", awsErr.Code(), awsErr.Message())
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func normalizeCert(cert interface{}) string {
|
2015-07-28 21:02:26 +02:00
|
|
|
if cert == nil || cert == (*string)(nil) {
|
2015-05-26 16:52:58 +02:00
|
|
|
return ""
|
|
|
|
}
|
2015-07-28 21:02:26 +02:00
|
|
|
|
2015-05-26 16:52:58 +02:00
|
|
|
switch cert.(type) {
|
|
|
|
case string:
|
|
|
|
hash := sha1.Sum([]byte(strings.TrimSpace(cert.(string))))
|
|
|
|
return hex.EncodeToString(hash[:])
|
|
|
|
case *string:
|
|
|
|
hash := sha1.Sum([]byte(strings.TrimSpace(*cert.(*string))))
|
|
|
|
return hex.EncodeToString(hash[:])
|
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|