diff --git a/aws/provider.go b/aws/provider.go index fe99eeada268..8522665f0909 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -356,6 +356,7 @@ func Provider() terraform.ResourceProvider { "aws_inspector_resource_group": resourceAWSInspectorResourceGroup(), "aws_instance": resourceAwsInstance(), "aws_internet_gateway": resourceAwsInternetGateway(), + "aws_iot_certificate": resourceAwsIotCertificate(), "aws_iot_policy": resourceAwsIotPolicy(), "aws_key_pair": resourceAwsKeyPair(), "aws_kinesis_firehose_delivery_stream": resourceAwsKinesisFirehoseDeliveryStream(), diff --git a/aws/resource_aws_iot_certificate.go b/aws/resource_aws_iot_certificate.go new file mode 100644 index 000000000000..afa8699042d9 --- /dev/null +++ b/aws/resource_aws_iot_certificate.go @@ -0,0 +1,119 @@ +package aws + +import ( + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iot" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsIotCertificate() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsIotCertificateCreate, + Read: resourceAwsIotCertificateRead, + Update: resourceAwsIotCertificateUpdate, + Delete: resourceAwsIotCertificateDelete, + Schema: map[string]*schema.Schema{ + "csr": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "active": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + }, + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceAwsIotCertificateCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + log.Printf("[DEBUG] Creating certificate from csr") + out, err := conn.CreateCertificateFromCsr(&iot.CreateCertificateFromCsrInput{ + CertificateSigningRequest: aws.String(d.Get("csr").(string)), + SetAsActive: aws.Bool(d.Get("active").(bool)), + }) + + if err != nil { + log.Printf("[ERROR] %s", err) + return err + } + log.Printf("[DEBUG] Created certificate from csr") + + d.SetId(*out.CertificateId) + + return resourceAwsIotCertificateRead(d, meta) +} + +func resourceAwsIotCertificateRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + out, err := conn.DescribeCertificate(&iot.DescribeCertificateInput{ + CertificateId: aws.String(d.Id()), + }) + + if err != nil { + log.Printf("[ERROR] %s", err) + return err + } + + d.Set("active", aws.Bool(*out.CertificateDescription.Status == iot.CertificateStatusActive)) + d.Set("arn", out.CertificateDescription.CertificateArn) + + return nil +} + +func resourceAwsIotCertificateUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + if d.HasChange("active") { + status := iot.CertificateStatusInactive + if d.Get("active").(bool) { + status = iot.CertificateStatusActive + } + + _, err := conn.UpdateCertificate(&iot.UpdateCertificateInput{ + CertificateId: aws.String(d.Id()), + NewStatus: aws.String(status), + }) + + if err != nil { + log.Printf("[ERROR] %s", err) + return err + } + } + + return resourceAwsIotCertificateRead(d, meta) +} + +func resourceAwsIotCertificateDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iotconn + + _, err := conn.UpdateCertificate(&iot.UpdateCertificateInput{ + CertificateId: aws.String(d.Id()), + NewStatus: aws.String("INACTIVE"), + }) + + if err != nil { + log.Printf("[ERROR], %s", err) + return err + } + + _, err = conn.DeleteCertificate(&iot.DeleteCertificateInput{ + CertificateId: aws.String(d.Id()), + }) + + if err != nil { + log.Printf("[ERROR] %s", err) + return err + } + + return nil +} diff --git a/aws/resource_aws_iot_certificate_test.go b/aws/resource_aws_iot_certificate_test.go new file mode 100644 index 000000000000..6f82df03ebe4 --- /dev/null +++ b/aws/resource_aws_iot_certificate_test.go @@ -0,0 +1,71 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iot" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSIoTCertificate_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSIoTCertificateDestroy_basic, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSIoTCertificate_basic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("aws_iot_certificate.foo_cert", "arn"), + resource.TestCheckResourceAttrSet("aws_iot_certificate.foo_cert", "csr"), + resource.TestCheckResourceAttr("aws_iot_certificate.foo_cert", "active", "true"), + ), + }, + }, + }) +} + +func testAccCheckAWSIoTCertificateDestroy_basic(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).iotconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_iot_certificate" { + continue + } + + // Try to find the Cert + DescribeCertOpts := &iot.DescribeCertificateInput{ + CertificateId: aws.String(rs.Primary.ID), + } + + resp, err := conn.DescribeCertificate(DescribeCertOpts) + + if err == nil { + if resp.CertificateDescription != nil { + return fmt.Errorf("Device Certificate still exists") + } + } + + // Verify the error is what we want + if err != nil { + iotErr, ok := err.(awserr.Error) + if !ok || iotErr.Code() != "ResourceNotFoundException" { + return err + } + } + + } + + return nil +} + +var testAccAWSIoTCertificate_basic = ` +resource "aws_iot_certificate" "foo_cert" { + csr = "${file("test-fixtures/iot-csr.pem")}" + active = true +} +` diff --git a/aws/test-fixtures/iot-csr.pem b/aws/test-fixtures/iot-csr.pem new file mode 100644 index 000000000000..7d5c743f557b --- /dev/null +++ b/aws/test-fixtures/iot-csr.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx +ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMSUg2mO7mYnhvYUB55K0/ay9WLLgPjOHnbduyCv +N+udkJaZc+A65ux9LvVo33VHDTlV2Ms9H/42on902WtuS3BNuxdXfD068CpN2lb6 +bSAeuKc6Fdu4BIP2bFYKCyejqBoOmTEhYA8bOM1Wu/pRsq1PkAmcGkvw3mlRx45E +B2LRicWcg3YEleEBGyLYohyeMu0pnlsc7zsu5T4bwrjetdbDPVbzgu0Mf/evU9hJ +G/IisXNxQhzPh/DTQsKZSNddZ4bmkAQrRN1nmNXD6QoxBiVyjjgKGrPnX+hz4ugm +aaN9CsOO/cad1E3C0KiI0BQCjxRb80wOpI4utz4pEcY97sUCAwEAAaAAMA0GCSqG +SIb3DQEBBQUAA4IBAQC64L4JHvwxdxmnXT9Lv12p5CGx99d7VOXQXy29b1yH9cJ+ +FaQ2TH377uOdorSCS4bK7eje9/HLsCNgqftR0EruwSNnukF695BWN8e/AJSZe0vA +3J/llZ6G7MWuOIhCswsOxqNnM1htu3o6ujXVrgBMeMgQy2tfylWfI7SGR6UmtLYF +ZrPaqXdkpt47ROJNCm2Oht1B0J3QEOmbIp/2XMxrfknzwH6se/CjuliiXVPYxrtO +5hbZcRqjhugb8FWtaLirqh3Q3+1UIJ+CW0ZczsblP7DNdqqt8YQZpWVIqR64mSXV +Ajq/cupsJST9fey8chcNSTt4nKxOGs3OgXu1ftgy +-----END CERTIFICATE REQUEST----- diff --git a/website/aws.erb b/website/aws.erb index a7becca732ff..56f8d0a72c78 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -882,6 +882,10 @@ IoT Resources