Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add aws_iot_certificate resource #1225

Merged
merged 3 commits into from
Jul 24, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
147 changes: 147 additions & 0 deletions aws/resource_aws_iot_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
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,
},
"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 {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra line after function header

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

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("arn", out.CertificateDescription.CertificateArn)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is active also returned from the DescribeCertificate API call? If so, we need to set that here as well, to be able to catch any diffs between infra+state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


return nil
}

func resourceAwsIotCertificateUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iotconn

if d.HasChange("csr") {
// First create certificate with new 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 nil
}

// If everything worked, make the old one inactive
_, err = conn.UpdateCertificate(&iot.UpdateCertificateInput{
CertificateId: aws.String(d.Id()),
NewStatus: aws.String("INACTIVE"),
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this correctly, if a user updates the csr, Terraform will create a new certificate resource, and leak the existing one? Should we delete the original certificate here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is really no way to update the csr in API. Would it be more straightforward to delete the old one or just not allow changing it in the first place?


if err != nil {
log.Printf("[ERROR] %s", err)
return err
}

d.SetId(*out.CertificateId)

} else {

if d.HasChange("active") {
status := "INACTIVE"
if d.Get("active").(bool) {
status = "ACTIVE"
}

_, 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
}
71 changes: 71 additions & 0 deletions aws/resource_aws_iot_certificate_test.go
Original file line number Diff line number Diff line change
@@ -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
}
`
16 changes: 16 additions & 0 deletions aws/test-fixtures/iot-csr.pem
Original file line number Diff line number Diff line change
@@ -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-----
4 changes: 4 additions & 0 deletions website/aws.erb
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,10 @@
<a href="#">IoT Resources</a>
<ul class="nav nav-visible">

<li<%= sidebar_current("docs-aws-resource-iot-certificate") %>>
<a href="/docs/providers/aws/r/iot_certificate.html">aws_iot_certificate</a>
</li>

<li<%= sidebar_current("docs-aws-resource-iot-policy") %>>
<a href="/docs/providers/aws/r/iot_policy.html">aws_iot_policy</a>
</li>
Expand Down
32 changes: 32 additions & 0 deletions website/docs/r/iot_certificate.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
layout: "aws"
page_title: "AWS: aws_iot_certificate"
sidebar_current: "docs-aws-resource-iot-certificate"
description: |-
Creates and manages an AWS IoT certificate.
---

# aws\_iot\_certificate

Creates and manages an AWS IoT certificate.

## Example Usage

```hcl
resource "aws_iot_certificate" "cert" {
csr = "${file("/my/csr.pem")}"
active = true
}
```

## Argument Reference

* `active` - (Required) Boolean flag to indicate if the certificate should be active
* `csr` - (Required) The certificate signing request. Review the
[IoT API Reference Guide] (http://docs.aws.amazon.com/iot/latest/apireference/API_CreateCertificateFromCsr.html)
for more information on creating a certificate from a certificate signing request (CSR).


## Attributes Reference

* `arn` - The ARN of the created AWS IoT certificate