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

Aws Config Remediation #13884

Merged
merged 25 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8df05f1
feature(config): manage AWS Config Remediation Configuration
Jul 15, 2019
7bb7d31
feat(tests): write unit tests
Jul 16, 2019
06a307b
feedback(pr): 1st lot
andy-b-84 Aug 27, 2019
d3d3b17
feedback(pr): 2nd lot
andy-b-84 Aug 27, 2019
604c6a9
feedback(pr): 3rd lot
andy-b-84 Aug 27, 2019
5cb06a2
update to recent version
cgetzen Jun 22, 2020
b9d6c0c
documentation
cgetzen Jun 22, 2020
834e417
Update aws/resource_aws_config_remediation_configuration.go
cgetzen Aug 30, 2020
327b183
Update aws/resource_aws_config_remediation_configuration.go
cgetzen Aug 30, 2020
4ae7afa
Update aws/resource_aws_config_remediation_configuration.go
cgetzen Aug 30, 2020
943e342
Update aws/resource_aws_config_remediation_configuration_test.go
cgetzen Aug 30, 2020
44b08d0
Update aws/resource_aws_config_remediation_configuration_test.go
cgetzen Aug 30, 2020
3390d4c
remove website changes
charliegetzen-okta Aug 30, 2020
8bf3715
Merge branch 'master' of github-personal.com:terraform-providers/terr…
charliegetzen-okta Aug 30, 2020
6d8b7e6
documentation formatting
charliegetzen-okta Aug 30, 2020
5afda14
only pass repeated parameter once
charliegetzen-okta Aug 30, 2020
7073583
Add test for out-of-band deletion
charliegetzen-okta Sep 7, 2020
57a4373
Add test for recreation
cgetzen Sep 7, 2020
93f95b2
Add test for updates
cgetzen Sep 8, 2020
5b2973c
All acceptance tests pass
cgetzen Sep 15, 2020
57fe47e
linting terraform
cgetzen Sep 15, 2020
ae16b2c
linting go
cgetzen Sep 15, 2020
f6e73d2
linting go (2)
cgetzen Sep 15, 2020
2739db6
Update aws/resource_aws_config_remediation_configuration.go
gdavison Sep 16, 2020
7399705
Adds package name and fixes formatting
gdavison Sep 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
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 @@ -462,6 +462,7 @@ func Provider() *schema.Provider {
"aws_config_delivery_channel": resourceAwsConfigDeliveryChannel(),
"aws_config_organization_custom_rule": resourceAwsConfigOrganizationCustomRule(),
"aws_config_organization_managed_rule": resourceAwsConfigOrganizationManagedRule(),
"aws_config_remediation_configuration": resourceAwsConfigRemediationConfiguration(),
"aws_cognito_identity_pool": resourceAwsCognitoIdentityPool(),
"aws_cognito_identity_pool_roles_attachment": resourceAwsCognitoIdentityPoolRolesAttachment(),
"aws_cognito_identity_provider": resourceAwsCognitoIdentityProvider(),
Expand Down
240 changes: 240 additions & 0 deletions aws/resource_aws_config_remediation_configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package aws

import (
"fmt"
"log"
"time"

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

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/configservice"
)

func resourceAwsConfigRemediationConfiguration() *schema.Resource {
return &schema.Resource{
Create: resourceAwsConfigRemediationConfigurationPut,
Read: resourceAwsConfigRemediationConfigurationRead,
Update: resourceAwsConfigRemediationConfigurationPut,
Delete: resourceAwsConfigRemediationConfigurationDelete,

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

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"config_rule_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 64),
},
"resource_type": {
Type: schema.TypeString,
Optional: true,
},
"target_id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(1, 256),
},
"target_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(configservice.RemediationTargetType_Values(), false),
},
"target_version": {
Type: schema.TypeString,
Optional: true,
},
"parameter": {
Type: schema.TypeSet,
MaxItems: 25,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"resource_value": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 256),
},
"static_value": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
},
}
}

func expandConfigRemediationConfigurationParameters(configured *schema.Set) (map[string]*configservice.RemediationParameterValue, error) {
results := make(map[string]*configservice.RemediationParameterValue)

for _, item := range configured.List() {
detail := item.(map[string]interface{})
rpv := configservice.RemediationParameterValue{}
resourceName, ok := detail["name"].(string)
if ok {
results[resourceName] = &rpv
} else {
return nil, fmt.Errorf("Could not extract name from parameter.")
}
if resourceValue, ok := detail["resource_value"].(string); ok && len(resourceValue) > 0 {
rpv.ResourceValue = &configservice.ResourceValue{
Value: &resourceValue,
}
} else if staticValue, ok := detail["static_value"].(string); ok && len(staticValue) > 0 {
rpv.StaticValue = &configservice.StaticValue{
Values: []*string{&staticValue},
}
} else {
return nil, fmt.Errorf("Parameter '%s' needs one of resource_value or static_value", resourceName)
}
}

return results, nil
}

func flattenRemediationConfigurationParameters(parameters map[string]*configservice.RemediationParameterValue) []interface{} {
var items []interface{}

for key, value := range parameters {
item := make(map[string]interface{})
item["name"] = key
if value.ResourceValue != nil {
item["resource_value"] = *value.ResourceValue.Value
}
if value.StaticValue != nil && len(value.StaticValue.Values) > 0 {
item["static_value"] = *value.StaticValue.Values[0]
}

items = append(items, item)
}

return items
}

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

name := d.Get("config_rule_name").(string)
remediationConfigurationInput := configservice.RemediationConfiguration{
ConfigRuleName: aws.String(name),
}

if v, ok := d.GetOk("parameter"); ok {
params, err := expandConfigRemediationConfigurationParameters(v.(*schema.Set))
if err != nil {
return err
}
remediationConfigurationInput.Parameters = params
}
if v, ok := d.GetOk("resource_type"); ok {
remediationConfigurationInput.ResourceType = aws.String(v.(string))
}
if v, ok := d.GetOk("target_id"); ok {
remediationConfigurationInput.TargetId = aws.String(v.(string))
}
if v, ok := d.GetOk("target_type"); ok {
remediationConfigurationInput.TargetType = aws.String(v.(string))
}
if v, ok := d.GetOk("target_version"); ok {
remediationConfigurationInput.TargetVersion = aws.String(v.(string))
}

input := configservice.PutRemediationConfigurationsInput{
RemediationConfigurations: []*configservice.RemediationConfiguration{&remediationConfigurationInput},
}
log.Printf("[DEBUG] Creating AWSConfig remediation configuration: %s", input)
_, err := conn.PutRemediationConfigurations(&input)
if err != nil {
return fmt.Errorf("Failed to create AWSConfig remediation configuration: %w", err)
}

d.SetId(name)

log.Printf("[DEBUG] AWSConfig config remediation configuration for rule %q created", name)

return resourceAwsConfigRemediationConfigurationRead(d, meta)
}

func resourceAwsConfigRemediationConfigurationRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).configconn
out, err := conn.DescribeRemediationConfigurations(&configservice.DescribeRemediationConfigurationsInput{
ConfigRuleNames: []*string{aws.String(d.Id())},
})
if err != nil {
if isAWSErr(err, configservice.ErrCodeNoSuchConfigRuleException, "") {
log.Printf("[WARN] Config Rule %q is gone (NoSuchConfigRuleException)", d.Id())
d.SetId("")
return nil
}
return err
}

numberOfRemediationConfigurations := len(out.RemediationConfigurations)
if numberOfRemediationConfigurations < 1 {
log.Printf("[WARN] No Remediation Configuration for Config Rule %q (no remediation configuration found)", d.Id())
d.SetId("")
return nil
}

log.Printf("[DEBUG] AWS Config remediation configurations received: %s", out)

remediationConfiguration := out.RemediationConfigurations[0]
d.Set("arn", remediationConfiguration.Arn)
d.Set("config_rule_name", remediationConfiguration.ConfigRuleName)
d.Set("resource_type", remediationConfiguration.ResourceType)
d.Set("target_id", remediationConfiguration.TargetId)
d.Set("target_type", remediationConfiguration.TargetType)
d.Set("target_version", remediationConfiguration.TargetVersion)
d.Set("parameter", flattenRemediationConfigurationParameters(remediationConfiguration.Parameters))
d.SetId(*remediationConfiguration.ConfigRuleName)

return nil
}

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

name := d.Get("config_rule_name").(string)

deleteRemediationConfigurationInput := configservice.DeleteRemediationConfigurationInput{
ConfigRuleName: aws.String(name),
}

if v, ok := d.GetOk("resource_type"); ok {
deleteRemediationConfigurationInput.ResourceType = aws.String(v.(string))
}

log.Printf("[DEBUG] Deleting AWS Config remediation configurations for rule %q", name)
err := resource.Retry(2*time.Minute, func() *resource.RetryError {
_, err := conn.DeleteRemediationConfiguration(&deleteRemediationConfigurationInput)
if err != nil {
if isAWSErr(err, configservice.ErrCodeResourceInUseException, "") {
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
if err != nil {
return fmt.Errorf("Deleting Remediation Configurations failed: %s", err)
}

log.Printf("[DEBUG] AWS Config remediation configurations for rule %q deleted", name)

return nil
}