Skip to content

Commit

Permalink
Merge pull request #17418 from hashicorp/b_fms_distribution
Browse files Browse the repository at this point in the history
Allow use of resource_type and resource_type_list
  • Loading branch information
bill-rich authored Feb 12, 2021
2 parents fc1c883 + 893ba66 commit 22a3875
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 40 deletions.
3 changes: 3 additions & 0 deletions .changelog/17418.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_fms_policy: Allow use of `resource_type` or `resource_type_list` attributes
```
83 changes: 44 additions & 39 deletions aws/resource_aws_fms_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,22 @@ func resourceAwsFmsPolicy() *schema.Resource {
},

"resource_type_list": {
Type: schema.TypeSet,
Required: true,
Type: schema.TypeSet,
Optional: true,
Computed: true,
Set: schema.HashString,
ConflictsWith: []string{"resource_type"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{"AWS::ApiGateway::Stage", "AWS::ElasticLoadBalancingV2::LoadBalancer", "AWS::CloudFront::Distribution", "AWS::EC2::NetworkInterface", "AWS::EC2::Instance", "AWS::EC2::SecurityGroup"}, false),
},
Set: schema.HashString,
},

"resource_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ConflictsWith: []string{"resource_type_list"},
},

"policy_update_token": {
Expand Down Expand Up @@ -138,31 +147,7 @@ func resourceAwsFmsPolicy() *schema.Resource {
func resourceAwsFmsPolicyCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).fmsconn

fmsPolicy := &fms.Policy{
PolicyName: aws.String(d.Get("name").(string)),
RemediationEnabled: aws.Bool(d.Get("remediation_enabled").(bool)),
ResourceType: aws.String("ResourceTypeList"),
ResourceTypeList: expandStringSet(d.Get("resource_type_list").(*schema.Set)),
ExcludeResourceTags: aws.Bool(d.Get("exclude_resource_tags").(bool)),
}

securityServicePolicy := d.Get("security_service_policy_data").([]interface{})[0].(map[string]interface{})
fmsPolicy.SecurityServicePolicyData = &fms.SecurityServicePolicyData{
ManagedServiceData: aws.String(securityServicePolicy["managed_service_data"].(string)),
Type: aws.String(securityServicePolicy["type"].(string)),
}

if rTags, tagsOk := d.GetOk("resource_tags"); tagsOk {
fmsPolicy.ResourceTags = constructResourceTags(rTags)
}

if v, ok := d.GetOk("include_map"); ok {
fmsPolicy.IncludeMap = expandFMSPolicyMap(v.([]interface{}))
}

if v, ok := d.GetOk("exclude_map"); ok {
fmsPolicy.ExcludeMap = expandFMSPolicyMap(v.([]interface{}))
}
fmsPolicy := resourceAwsFmsPolicyExpandPolicy(d)

params := &fms.PutPolicyInput{
Policy: fmsPolicy,
Expand Down Expand Up @@ -201,49 +186,61 @@ func resourceAwsFmsPolicyRead(d *schema.ResourceData, meta interface{}) error {
return err
}

return resourceAwsFmsPolicyFlattenPolicy(d, resp)
}

func resourceAwsFmsPolicyFlattenPolicy(d *schema.ResourceData, resp *fms.GetPolicyOutput) error {
d.Set("arn", aws.StringValue(resp.PolicyArn))

d.Set("name", aws.StringValue(resp.Policy.PolicyName))
d.Set("exclude_resource_tags", aws.BoolValue(resp.Policy.ExcludeResourceTags))
if err = d.Set("exclude_map", flattenFMSPolicyMap(resp.Policy.ExcludeMap)); err != nil {
if err := d.Set("exclude_map", flattenFMSPolicyMap(resp.Policy.ExcludeMap)); err != nil {
return err
}
if err = d.Set("include_map", flattenFMSPolicyMap(resp.Policy.IncludeMap)); err != nil {
if err := d.Set("include_map", flattenFMSPolicyMap(resp.Policy.IncludeMap)); err != nil {
return err
}
d.Set("remediation_enabled", aws.BoolValue(resp.Policy.RemediationEnabled))
if err = d.Set("resource_type_list", resp.Policy.ResourceTypeList); err != nil {
if err := d.Set("resource_type_list", resp.Policy.ResourceTypeList); err != nil {
return err
}
d.Set("resource_type", aws.StringValue(resp.Policy.ResourceType))
d.Set("policy_update_token", aws.StringValue(resp.Policy.PolicyUpdateToken))
if err = d.Set("resource_tags", flattenFMSResourceTags(resp.Policy.ResourceTags)); err != nil {
if err := d.Set("resource_tags", flattenFMSResourceTags(resp.Policy.ResourceTags)); err != nil {
return err
}

securityServicePolicy := []map[string]string{{
"type": *resp.Policy.SecurityServicePolicyData.Type,
"managed_service_data": *resp.Policy.SecurityServicePolicyData.ManagedServiceData,
}}
if err = d.Set("security_service_policy_data", securityServicePolicy); err != nil {
if err := d.Set("security_service_policy_data", securityServicePolicy); err != nil {
return err
}

return nil
}

func resourceAwsFmsPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).fmsconn
func resourceAwsFmsPolicyExpandPolicy(d *schema.ResourceData) *fms.Policy {
resourceType := aws.String("ResourceTypeList")
resourceTypeList := expandStringSet(d.Get("resource_type_list").(*schema.Set))
if t, ok := d.GetOk("resource_type"); ok {
resourceType = aws.String(t.(string))
}

fmsPolicy := &fms.Policy{
PolicyName: aws.String(d.Get("name").(string)),
PolicyId: aws.String(d.Id()),
PolicyUpdateToken: aws.String(d.Get("policy_update_token").(string)),
RemediationEnabled: aws.Bool(d.Get("remediation_enabled").(bool)),
ResourceType: aws.String("ResourceTypeList"),
ResourceTypeList: expandStringSet(d.Get("resource_type_list").(*schema.Set)),
ResourceType: resourceType,
ResourceTypeList: resourceTypeList,
ExcludeResourceTags: aws.Bool(d.Get("exclude_resource_tags").(bool)),
}

if d.Id() != "" {
fmsPolicy.PolicyId = aws.String(d.Id())
fmsPolicy.PolicyUpdateToken = aws.String(d.Get("policy_update_token").(string))
}

fmsPolicy.ExcludeMap = expandFMSPolicyMap(d.Get("exclude_map").([]interface{}))

fmsPolicy.IncludeMap = expandFMSPolicyMap(d.Get("include_map").([]interface{}))
Expand All @@ -256,6 +253,14 @@ func resourceAwsFmsPolicyUpdate(d *schema.ResourceData, meta interface{}) error
Type: aws.String(securityServicePolicy["type"].(string)),
}

return fmsPolicy
}

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

fmsPolicy := resourceAwsFmsPolicyExpandPolicy(d)

params := &fms.PutPolicyInput{Policy: fmsPolicy}
_, err := conn.PutPolicy(params)

Expand Down
54 changes: 54 additions & 0 deletions aws/resource_aws_fms_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,34 @@ func TestAccAWSFmsPolicy_basic(t *testing.T) {
})
}

func TestAccAWSFmsPolicy_cloudfrontDistribution(t *testing.T) {
fmsPolicyName := fmt.Sprintf("tf-fms-%s", acctest.RandString(5))
wafRuleGroupName := fmt.Sprintf("tf-waf-rg-%s", acctest.RandString(5))

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsFmsPolicyDestroy,
Steps: []resource.TestStep{
{
Config: testAccFmsPolicyConfig_cloudfrontDistribution(fmsPolicyName, wafRuleGroupName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsFmsPolicyExists("aws_fms_policy.test"),
testAccMatchResourceAttrRegionalARN("aws_fms_policy.test", "arn", "fms", regexp.MustCompile(`policy/`)),
resource.TestCheckResourceAttr("aws_fms_policy.test", "name", fmsPolicyName),
resource.TestCheckResourceAttr("aws_fms_policy.test", "security_service_policy_data.#", "1"),
),
},
{
ResourceName: "aws_fms_policy.test",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"policy_update_token", "delete_all_policy_resources"},
},
},
})
}

func TestAccAWSFmsPolicy_includeMap(t *testing.T) {
fmsPolicyName := fmt.Sprintf("tf-fms-%s", acctest.RandString(5))
wafRuleGroupName := fmt.Sprintf("tf-waf-rg-%s", acctest.RandString(5))
Expand Down Expand Up @@ -194,6 +222,32 @@ resource "aws_wafregional_rule_group" "test" {
`, name, group)
}

func testAccFmsPolicyConfig_cloudfrontDistribution(name string, group string) string {
return composeConfig(
testAccWebACLLoggingConfigurationDependenciesConfig(name),
testAccWebACLLoggingConfigurationKinesisDependencyConfig(name),
fmt.Sprintf(`
resource "aws_fms_policy" "test" {
exclude_resource_tags = false
name = "%[1]s"
remediation_enabled = false
resource_type = "AWS::CloudFront::Distribution"
security_service_policy_data {
type = "WAFV2"
managed_service_data = "{\"type\":\"WAFV2\",\"preProcessRuleGroups\":[{\"ruleGroupArn\":null,\"overrideAction\":{\"type\":\"NONE\"},\"managedRuleGroupIdentifier\":{\"version\":null,\"vendorName\":\"AWS\",\"managedRuleGroupName\":\"AWSManagedRulesAmazonIpReputationList\"},\"ruleGroupType\":\"ManagedRuleGroup\",\"excludeRules\":[]}],\"postProcessRuleGroups\":[],\"defaultAction\":{\"type\":\"ALLOW\"},\"overrideCustomerWebACLAssociation\":false,\"loggingConfiguration\":{\"logDestinationConfigs\":[\"${aws_kinesis_firehose_delivery_stream.test.arn}\"],\"redactedFields\":[{\"redactedFieldType\":\"SingleHeader\",\"redactedFieldValue\":\"Cookies\"}]}}"
}
}
resource "aws_wafregional_rule_group" "test" {
metric_name = "MyTest"
name = "%[2]s"
}
`, name, group),
)
}

func testAccFmsPolicyConfig_updated(name string, group string) string {
return fmt.Sprintf(`
resource "aws_fms_policy" "test" {
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/fms_policy.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ The following arguments are supported:
* `include_map` - (Optional) A map of lists, with a single key named 'account' with a list of AWS Account IDs to include for this policy.
* `remediation_enabled` - (Required) A boolean value, indicates if the policy should automatically applied to resources that already exist in the account.
* `resource_tags` - (Optional) A map of resource tags, that if present will filter protections on resources based on the exclude_resource_tags.
* `resource_type_list` - (Required, Forces new resource) A list of resource types to protect, valid values are: `AWS::ElasticLoadBalancingV2::LoadBalancer`, `AWS::ApiGateway::Stage`, `AWS::CloudFront::Distribution`.
* `resource_type` - (Optional) A resource type to protect, valid values are: `AWS::ElasticLoadBalancingV2::LoadBalancer`, `AWS::ApiGateway::Stage`, `AWS::CloudFront::Distribution`, `AWS::EC2::Instance`, `AWS::EC2::NetworkInterface`, `AWS::EC2::SecurityGroup`. Conflicts with `resource_type_list`.
* `resource_type_list` - (Optional) A list of resource types to protect, valid values are: `AWS::ElasticLoadBalancingV2::LoadBalancer`, `AWS::ApiGateway::Stage`, `AWS::CloudFront::Distribution`, `AWS::EC2::Instance`, `AWS::EC2::NetworkInterface`, `AWS::EC2::SecurityGroup`. Conflicts with `resource_type`.
* `security_service_policy_data` - (Required) The objects to include in Security Service Policy Data. Documented below.

## `exclude_map` Configuration Block
Expand Down

0 comments on commit 22a3875

Please sign in to comment.