Skip to content

Commit

Permalink
resource/aws_cloudtrail: Add insight_selector configuration block (#1…
Browse files Browse the repository at this point in the history
…2390)

Output from acceptance testing:

```
--- PASS: TestAccAWSCloudTrail_serial (345.05s)
    --- PASS: TestAccAWSCloudTrail_serial/Trail (345.05s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/cloudwatch (56.41s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/enableLogging (37.83s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/isMultiRegion (39.66s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/logValidation (28.02s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/kmsKey (16.51s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/insightSelector (16.55s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/basic (26.48s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/includeGlobalServiceEvents (15.51s)
        --- SKIP: TestAccAWSCloudTrail_serial/Trail/isOrganization (1.04s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/tags (36.75s)
        --- PASS: TestAccAWSCloudTrail_serial/Trail/eventSelector (70.30s)
```
  • Loading branch information
DrFaust92 authored Sep 2, 2020
1 parent 255384a commit adb6b7a
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
89 changes: 89 additions & 0 deletions aws/resource_aws_cloudtrail.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,19 @@ func resourceAwsCloudTrail() *schema.Resource {
Computed: true,
},
"tags": tagsSchema(),
"insight_selector": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"insight_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(cloudtrail.InsightType_Values(), false),
},
},
},
},
},
}
}
Expand Down Expand Up @@ -219,6 +232,12 @@ func resourceAwsCloudTrailCreate(d *schema.ResourceData, meta interface{}) error
}
}

if _, ok := d.GetOk("insight_selector"); ok {
if err := cloudTrailSetInsightSelectors(conn, d); err != nil {
return err
}
}

return resourceAwsCloudTrailRead(d, meta)
}

Expand Down Expand Up @@ -300,6 +319,21 @@ func resourceAwsCloudTrailRead(d *schema.ResourceData, meta interface{}) error {
return err
}

// Get InsightSelectors
insightSelectors, err := conn.GetInsightSelectors(&cloudtrail.GetInsightSelectorsInput{
TrailName: aws.String(d.Id()),
})
if err != nil {
if !isAWSErr(err, cloudtrail.ErrCodeInsightNotEnabledException, "") {
return fmt.Errorf("error getting Cloud Trail (%s) Insight Selectors: %w", d.Id(), err)
}
}
if insightSelectors != nil {
if err := d.Set("insight_selector", flattenAwsCloudTrailInsightSelector(insightSelectors.InsightSelectors)); err != nil {
return err
}
}

return nil
}

Expand Down Expand Up @@ -387,6 +421,13 @@ func resourceAwsCloudTrailUpdate(d *schema.ResourceData, meta interface{}) error
}
}

if !d.IsNewResource() && d.HasChange("insight_selector") {
log.Printf("[DEBUG] Updating insight selector on CloudTrail: %s", input)
if err := cloudTrailSetInsightSelectors(conn, d); err != nil {
return err
}
}

log.Printf("[DEBUG] CloudTrail updated: %s", t)

return resourceAwsCloudTrailRead(d, meta)
Expand Down Expand Up @@ -548,3 +589,51 @@ func flattenAwsCloudTrailEventSelectorDataResource(configured []*cloudtrail.Data

return dataResources
}

func cloudTrailSetInsightSelectors(conn *cloudtrail.CloudTrail, d *schema.ResourceData) error {
input := &cloudtrail.PutInsightSelectorsInput{
TrailName: aws.String(d.Id()),
}

insightSelector := expandAwsCloudTrailInsightSelector(d.Get("insight_selector").([]interface{}))
input.InsightSelectors = insightSelector

if err := input.Validate(); err != nil {
return fmt.Errorf("Error validate CloudTrail (%s): %s", d.Id(), err)
}

_, err := conn.PutInsightSelectors(input)
if err != nil {
return fmt.Errorf("Error set insight selector on CloudTrail (%s): %s", d.Id(), err)
}

return nil
}

func expandAwsCloudTrailInsightSelector(configured []interface{}) []*cloudtrail.InsightSelector {
insightSelectors := make([]*cloudtrail.InsightSelector, 0, len(configured))

for _, raw := range configured {
data := raw.(map[string]interface{})

is := &cloudtrail.InsightSelector{
InsightType: aws.String(data["insight_type"].(string)),
}
insightSelectors = append(insightSelectors, is)
}

return insightSelectors
}

func flattenAwsCloudTrailInsightSelector(configured []*cloudtrail.InsightSelector) []map[string]interface{} {
insightSelectors := make([]map[string]interface{}, 0, len(configured))

for _, raw := range configured {
item := make(map[string]interface{})
item["insight_type"] = aws.StringValue(raw.InsightType)

insightSelectors = append(insightSelectors, item)
}

return insightSelectors
}
72 changes: 72 additions & 0 deletions aws/resource_aws_cloudtrail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func TestAccAWSCloudTrail_serial(t *testing.T) {
"kmsKey": testAccAWSCloudTrail_kmsKey,
"tags": testAccAWSCloudTrail_tags,
"eventSelector": testAccAWSCloudTrail_event_selector,
"insightSelector": testAccAWSCloudTrail_insight_selector,
},
}

Expand Down Expand Up @@ -545,6 +546,31 @@ func testAccAWSCloudTrail_event_selector(t *testing.T) {
})
}

func testAccAWSCloudTrail_insight_selector(t *testing.T) {
resourceName := "aws_cloudtrail.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_insightSelector(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "insight_selector.#", "1"),
resource.TestCheckResourceAttr(resourceName, "insight_selector.0.insight_type", "ApiCallRateInsight"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckCloudTrailExists(n string, trail *cloudtrail.Trail) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down Expand Up @@ -1552,3 +1578,49 @@ POLICY
}
`, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
}

func testAccAWSCloudTrailConfig_insightSelector(rName string) string {
return fmt.Sprintf(`
resource "aws_cloudtrail" "test" {
name = %[1]q
s3_bucket_name = aws_s3_bucket.test.id
insight_selector {
insight_type = "ApiCallRateInsight"
}
}
resource "aws_s3_bucket" "test" {
bucket = %[1]q
force_destroy = true
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::%[1]s"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::%[1]s/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}
`, rName)
}
7 changes: 7 additions & 0 deletions website/docs/r/cloudtrail.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ The following arguments are supported:
Defaults to `false`.
* `kms_key_id` - (Optional) Specifies the KMS key ARN to use to encrypt the logs delivered by CloudTrail.
* `event_selector` - (Optional) Specifies an event selector for enabling data event logging. Fields documented below. Please note the [CloudTrail limits](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/WhatIsCloudTrail-Limits.html) when configuring these.
* `insight_selector` - (Optional) Specifies an insight selector for identifying unusual operational activity. Fields documented below.
* `tags` - (Optional) A map of tags to assign to the trail

### Event Selector Arguments
Expand All @@ -187,6 +188,12 @@ For **data_resource** the following attributes are supported.
* `type` (Required) - The resource type in which you want to log data events. You can specify only the following value: "AWS::S3::Object", "AWS::Lambda::Function"
* `values` (Required) - A list of ARN for the specified S3 buckets and object prefixes..

### Insight Selector Arguments

For **insight_selector** the following attributes are supported.

* `insight_type` (Optional) - The type of insights to log on a trail. In this release, only `ApiCallRateInsight` is supported as an insight type.

## Attribute Reference

In addition to all arguments above, the following attributes are exported:
Expand Down

0 comments on commit adb6b7a

Please sign in to comment.