Skip to content

Commit

Permalink
Merge pull request #25109 from kurtmc/feature/acmpca_policy
Browse files Browse the repository at this point in the history
r/aws_acmpca_policy - new resource
  • Loading branch information
ewbankkit authored Jun 2, 2022
2 parents 3fb9e82 + b2cf32f commit 7bc9573
Show file tree
Hide file tree
Showing 6 changed files with 372 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/25109.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_acmpca_policy
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,7 @@ func Provider() *schema.Provider {
"aws_acmpca_certificate": acmpca.ResourceCertificate(),
"aws_acmpca_certificate_authority": acmpca.ResourceCertificateAuthority(),
"aws_acmpca_certificate_authority_certificate": acmpca.ResourceCertificateAuthorityCertificate(),
"aws_acmpca_policy": acmpca.ResourcePolicy(),

"aws_prometheus_workspace": amp.ResourceWorkspace(),
"aws_prometheus_alert_manager_definition": amp.ResourceAlertManagerDefinition(),
Expand Down
26 changes: 26 additions & 0 deletions internal/service/acmpca/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/aws/aws-sdk-go/service/acmpca"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

// FindCertificateAuthorityByARN returns the certificate authority corresponding to the specified ARN.
Expand Down Expand Up @@ -53,3 +54,28 @@ func FindCertificateAuthorityCertificateByARN(conn *acmpca.ACMPCA, arn string) (

return output, nil
}

func FindPolicyByARN(conn *acmpca.ACMPCA, arn string) (string, error) {
input := &acmpca.GetPolicyInput{
ResourceArn: aws.String(arn),
}

output, err := conn.GetPolicy(input)

if tfawserr.ErrCodeEquals(err, acmpca.ErrCodeResourceNotFoundException) {
return "", &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return "", err
}

if output == nil || output.Policy == nil {
return "", tfresource.NewEmptyResultError(input)
}

return aws.StringValue(output.Policy), nil
}
117 changes: 117 additions & 0 deletions internal/service/acmpca/policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package acmpca

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/acmpca"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourcePolicy() *schema.Resource {
return &schema.Resource{
Create: resourcePolicyPut,
Read: resourcePolicyRead,
Update: resourcePolicyPut,
Delete: resourcePolicyDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"policy": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: verify.SuppressEquivalentPolicyDiffs,
StateFunc: func(v interface{}) string {
json, _ := structure.NormalizeJsonString(v)
return json
},
},
"resource_arn": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

func resourcePolicyPut(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ACMPCAConn

policy, err := structure.NormalizeJsonString(d.Get("policy").(string))

if err != nil {
return fmt.Errorf("policy (%s) is invalid JSON: %w", d.Get("policy").(string), err)
}

resourceARN := d.Get("resource_arn").(string)
input := &acmpca.PutPolicyInput{
Policy: aws.String(policy),
ResourceArn: aws.String(resourceARN),
}

log.Printf("[DEBUG] Putting ACM PCA Policy: %s", input)
_, err = conn.PutPolicy(input)

if err != nil {
return fmt.Errorf("putting ACM PCA Policy (%s): %w", resourceARN, err)
}

d.SetId(resourceARN)

return resourcePolicyRead(d, meta)
}

func resourcePolicyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ACMPCAConn

policy, err := FindPolicyByARN(conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] ACM PCA Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("reading ACM PCA Policy (%s): %w", d.Id(), err)
}

d.Set("policy", policy)
d.Set("resource_arn", d.Id())

return nil
}

func resourcePolicyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ACMPCAConn

log.Printf("[DEBUG] Deleting ACM PCA Policy: %s", d.Id())
_, err := conn.DeletePolicy(&acmpca.DeletePolicyInput{
ResourceArn: aws.String(d.Id()),
})

if tfawserr.ErrCodeEquals(err, acmpca.ErrCodeResourceNotFoundException) ||
tfawserr.ErrCodeEquals(err, acmpca.ErrCodeRequestAlreadyProcessedException) ||
tfawserr.ErrCodeEquals(err, acmpca.ErrCodeRequestInProgressException) ||
tfawserr.ErrMessageContains(err, acmpca.ErrCodeInvalidRequestException, "Self-signed policy can not be revoked") {
return nil
}

if err != nil {
return fmt.Errorf("deleting ACM PCA Policy (%s): %w", d.Id(), err)
}

return nil
}
149 changes: 149 additions & 0 deletions internal/service/acmpca/policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package acmpca_test

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/acmpca"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfacmpca "github.com/hashicorp/terraform-provider-aws/internal/service/acmpca"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func TestAccACMPCAPolicy_Basic(t *testing.T) {
resourceName := "aws_acmpca_policy.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, acmpca.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccPolicyConfig(),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckPolicyExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "policy"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckPolicyDestroy(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).ACMPCAConn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_acmpca_policy" {
continue
}

_, err := tfacmpca.FindPolicyByARN(conn, rs.Primary.ID)

if tfresource.NotFound(err) {
continue
}

if err != nil {
return err
}

return fmt.Errorf("ACM PCA Policy %s still exists", rs.Primary.ID)
}

return nil
}

func testAccCheckPolicyExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ACM PCA Policy ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).ACMPCAConn

_, err := tfacmpca.FindPolicyByARN(conn, rs.Primary.ID)

if err != nil {
return err
}

return nil
}
}

func testAccPolicyConfig() string {
return `
data "aws_caller_identity" "current" {}
data "aws_partition" "current" {}
resource "aws_acmpca_certificate_authority" "test" {
certificate_authority_configuration {
key_algorithm = "RSA_4096"
signing_algorithm = "SHA512WITHRSA"
subject {
common_name = "example.com"
}
}
permanent_deletion_time_in_days = 7
}
resource "aws_acmpca_policy" "test" {
resource_arn = aws_acmpca_certificate_authority.test.arn
policy = <<EOF
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"1",
"Effect":"Allow",
"Principal":{
"AWS":"${data.aws_caller_identity.current.account_id}"
},
"Action":[
"acm-pca:DescribeCertificateAuthority",
"acm-pca:GetCertificate",
"acm-pca:GetCertificateAuthorityCertificate",
"acm-pca:ListPermissions",
"acm-pca:ListTags"
],
"Resource":"${aws_acmpca_certificate_authority.test.arn}"
},
{
"Sid":"1",
"Effect":"Allow",
"Principal":{
"AWS":"${data.aws_caller_identity.current.account_id}"
},
"Action":[
"acm-pca:IssueCertificate"
],
"Resource":"${aws_acmpca_certificate_authority.test.arn}",
"Condition":{
"StringEquals":{
"acm-pca:TemplateArn":"arn:${data.aws_partition.current.partition}:acm-pca:::template/EndEntityCertificate/V1"
}
}
}
]
}
EOF
}
`
}
76 changes: 76 additions & 0 deletions website/docs/r/acmpca_policy.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
subcategory: "ACM PCA (Certificate Manager Private Certificate Authority)"
layout: "aws"
page_title: "AWS: aws_acmpca_policy"
description: |-
Attaches a resource based policy to an AWS Certificate Manager Private Certificate Authority (ACM PCA)
---

# Resource: aws_acmpca_policy

Attaches a resource based policy to a private CA.

## Example Usage

### Basic

```terraform
resource "aws_acmpca_policy" "example" {
resource_arn = aws_acmpca_certificate_authority.example.arn
policy = <<EOF
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"1",
"Effect":"Allow",
"Principal":{
"AWS":"${data.aws_caller_identity.current.account_id}"
},
"Action":[
"acm-pca:DescribeCertificateAuthority",
"acm-pca:GetCertificate",
"acm-pca:GetCertificateAuthorityCertificate",
"acm-pca:ListPermissions",
"acm-pca:ListTags"
],
"Resource":"${aws_acmpca_certificate_authority.example.arn}"
},
{
"Sid":"1",
"Effect":"Allow",
"Principal":{
"AWS":"${data.aws_caller_identity.current.account_id}"
},
"Action":[
"acm-pca:IssueCertificate"
],
"Resource":"${aws_acmpca_certificate_authority.example.arn}",
"Condition":{
"StringEquals":{
"acm-pca:TemplateArn":"arn:aws:acm-pca:::template/EndEntityCertificate/V1"
}
}
}
]
}
EOF
}
```

## Argument Reference

The following arguments are supported:

* `resource_arn` - (Required) Amazon Resource Name (ARN) of the private CA to associate with the policy.
* `policy` - (Required) JSON-formatted IAM policy to attach to the specified private CA resource.

## Attributes Reference

No additional attributes are exported.

## Import

`aws_acmpca_policy` can be imported using the `resource_arn` value.

$ terraform import aws_acmpca_policy.example arn:aws:acm-pca:us-east-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012

0 comments on commit 7bc9573

Please sign in to comment.