Skip to content

Commit

Permalink
Merge branch 'add_securityhub_custom_action_resource' of ssh://github…
Browse files Browse the repository at this point in the history
….com/hhamalai/terraform-provider-aws into hhamalai-add_securityhub_custom_action_resource
  • Loading branch information
bflad committed Aug 25, 2020
2 parents b8e69a1 + 3be7aec commit d1b104a
Show file tree
Hide file tree
Showing 5 changed files with 321 additions and 0 deletions.
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ func Provider() *schema.Provider {
"aws_securityhub_member": resourceAwsSecurityHubMember(),
"aws_securityhub_product_subscription": resourceAwsSecurityHubProductSubscription(),
"aws_securityhub_standards_subscription": resourceAwsSecurityHubStandardsSubscription(),
"aws_securityhub_action_target": ResourceAwsSecurityHubActionTarget(),
"aws_servicecatalog_portfolio": resourceAwsServiceCatalogPortfolio(),
"aws_service_discovery_http_namespace": resourceAwsServiceDiscoveryHttpNamespace(),
"aws_service_discovery_private_dns_namespace": resourceAwsServiceDiscoveryPrivateDnsNamespace(),
Expand Down
166 changes: 166 additions & 0 deletions aws/resource_aws_securityhub_action_target.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package aws

import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/securityhub"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"log"
"regexp"
"strings"
)

func ResourceAwsSecurityHubActionTarget() *schema.Resource {
return &schema.Resource{
Create: resourceAwsSecurityHubActionTargetCreate,
Read: resourceAwsSecurityHubActionTargetRead,
Update: resourceAwsSecurityHubActionTargetUpdate,
Delete: resourceAwsSecurityHubActionTargetDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"identifier": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 20),
validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9]+$`), "must contain only alphanumeric characters"),
),
},
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 20),
),
},
"description": {
Type: schema.TypeString,
Required: true,
},
"action_target_arn": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceAwsSecurityHubActionTargetCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).securityhubconn
description := d.Get("description").(string)
name := d.Get("name").(string)
identifier := d.Get("identifier").(string)

log.Printf("[DEBUG] Creating Security Hub custom action target %s", identifier)

resp, err := conn.CreateActionTarget(&securityhub.CreateActionTargetInput{
Description: aws.String(description),
Id: aws.String(identifier),
Name: aws.String(name),
})

if err != nil {
return fmt.Errorf("Error creating Security Hub custom action target %s: %s", identifier, err)
}

d.SetId(*resp.ActionTargetArn)

return resourceAwsSecurityHubActionTargetRead(d, meta)
}

func resourceAwsSecurityHubActionTargetParseIdentifier(identifier string) (string, error) {
parts := strings.Split(identifier, "/")

if len(parts) != 3 {
return "", fmt.Errorf("Expected Security Hub Custom action ARN, received: %s", identifier)
}

return parts[2], nil
}

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

log.Printf("[DEBUG] Reading Security Hub custom action targets to find %s", d.Id())

actionTargetIdentifier, err := resourceAwsSecurityHubActionTargetParseIdentifier(d.Id())

if err != nil {
return err
}

actionTarget, err := resourceAwsSecurityHubActionTargetCheckExists(conn, d.Id())

if err != nil {
return fmt.Errorf("Error reading Security Hub custom action targets to find %s: %s", d.Id(), err)
}

if actionTarget == nil {
log.Printf("[WARN] Security Hub custom action target (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("identifier", actionTargetIdentifier)
d.Set("description", actionTarget.Description)
d.Set("action_target_arn", actionTarget.ActionTargetArn)
d.Set("name", actionTarget.Name)

return nil
}

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

input := &securityhub.UpdateActionTargetInput{
ActionTargetArn: aws.String(d.Id()),
Description: aws.String(d.Get("description").(string)),
Name: aws.String(d.Get("name").(string)),
}
if _, err := conn.UpdateActionTarget(input); err != nil {
return fmt.Errorf("error updating Security Hub Action Target (%s): %w", d.Id(), err)
}
return nil
}

func resourceAwsSecurityHubActionTargetCheckExists(conn *securityhub.SecurityHub, actionTargetArn string) (*securityhub.ActionTarget, error) {
input := &securityhub.DescribeActionTargetsInput{
ActionTargetArns: aws.StringSlice([]string{actionTargetArn}),
}
var found *securityhub.ActionTarget = nil
err := conn.DescribeActionTargetsPages(input, func(page *securityhub.DescribeActionTargetsOutput, lastPage bool) bool {
for _, actionTarget := range page.ActionTargets {
if aws.StringValue(actionTarget.ActionTargetArn) == actionTargetArn {
found = actionTarget
return false
}
}
return !lastPage
})

if err != nil {
return nil, err
}

return found, nil
}

func resourceAwsSecurityHubActionTargetDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).securityhubconn
log.Printf("[DEBUG] Deleting Security Hub custom action target %s", d.Id())

_, err := conn.DeleteActionTarget(&securityhub.DeleteActionTargetInput{
ActionTargetArn: aws.String(d.Get("action_target_arn").(string)),
})

if err != nil {
return fmt.Errorf("Error deleting Security Hub custom action target %s: %s", d.Id(), err)
}

return nil
}
103 changes: 103 additions & 0 deletions aws/resource_aws_securityhub_action_target_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func testAccAwsSecurityHubActionTarget_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSecurityHubAccountDestroy,
Steps: []resource.TestStep{
{
Config: testAccAwsSecurityHubActionTargetConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityHubAccountExists("aws_securityhub_account.example"),
testAccCheckAwsSecurityHubActionTargetExists("aws_securityhub_action_target.example"),
),
},
{
ResourceName: "aws_securityhub_action_target.example",
ImportState: true,
ImportStateVerify: true,
},
{
// Check Destroy - but only target the specific resource (otherwise Security Hub
// will be disabled and the destroy check will fail)
Config: testAccAwsSecurityHubActionTargetConfig_empty,
Check: testAccCheckAwsSecurityHubActionTargetDestroy,
},
},
})
}

func testAccCheckAwsSecurityHubActionTargetExists(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 Security Hub custom action ARN is set")
}

conn := testAccProvider.Meta().(*AWSClient).securityhubconn

action, err := resourceAwsSecurityHubActionTargetCheckExists(conn, rs.Primary.ID)

if err != nil {
return err
}

if action == nil {
return fmt.Errorf("Security Hub custom action %s not found", rs.Primary.ID)
}

return nil
}
}

func testAccCheckAwsSecurityHubActionTargetDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).securityhubconn

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

action, err := resourceAwsSecurityHubActionTargetCheckExists(conn, rs.Primary.ID)

if err != nil {
return err
}

if action == nil {
return fmt.Errorf("Security Hub custom action %s still exists", rs.Primary.ID)
}
}

return nil
}

const testAccAwsSecurityHubActionTargetConfig_empty = `
resource "aws_securityhub_account" "example" {}
`

const testAccAwsSecurityHubActionTargetConfig = `
resource "aws_securityhub_account" "example" {}
data "aws_region" "current" {}
resource "aws_securityhub_action_target" "example" {
depends_on = ["aws_securityhub_account.example"]
name = "Test action"
identifier = "testaction"
description = "This is a test custom action"
}
`
3 changes: 3 additions & 0 deletions aws/resource_aws_securityhub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ func TestAccAWSSecurityHub_serial(t *testing.T) {
"basic": testAccAWSSecurityHubMember_basic,
"invite": testAccAWSSecurityHubMember_invite,
},
"CustomAction": {
"basic": testAccAwsSecurityHubActionTarget_basic,
},
"ProductSubscription": {
"basic": testAccAWSSecurityHubProductSubscription_basic,
},
Expand Down
48 changes: 48 additions & 0 deletions website/docs/r/securityhub_action_target.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
subcategory: "Security Hub"
layout: "aws"
page_title: "AWS: aws_securityhub_action_target"
description: |-
Creates Security Hub custom action.
---

# Resource: aws_securityhub_action_target

Creates Security Hub custom action.

## Example Usage

```hcl
resource "aws_securityhub_account" "example" {}
data "aws_region" "current" {}
resource "aws_securityhub_action_target" "example" {
depends_on = ["aws_securityhub_account.example"]
name = "Send notification to chat"
identifier = "SendToChat"
description = "This is custom action sends selected findings to chat"
}
```

## Argument Reference

The following arguments are supported:

* `name` - (Required) The description for the custom action target.
* `identifier` - (Required) The ID for the custom action target.
* `description` - (Required) The name of the custom action target.

## Attributes Reference

The following attributes are exported in addition to the arguments listed above:

* `action_target_arn` - The action target ARN of the Security Hub custom action.

## Import

Security Hub custom action can be imported using the action target ARN e.g.

```sh
$ terraform import aws_securityhub_action_target.example arn:aws:securityhub:eu-west-1:312940875350:action/custom/a
```

0 comments on commit d1b104a

Please sign in to comment.