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_configuration_recorder recording_mode (Periodic recording) #35527

Merged
merged 14 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/35527.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_config_configuration_recorder: Add `recording_mode` configuration block
```
63 changes: 62 additions & 1 deletion internal/service/configservice/configuration_recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,48 @@ func ResourceConfigurationRecorder() *schema.Resource {
},
},
},
"recording_mode": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"recording_frequency": {
Type: schema.TypeString,
Optional: true,
Default: configservice.RecordingFrequencyContinuous,
ValidateFunc: validation.StringInSlice(configservice.RecordingFrequency_Values(), false),
},
"recording_mode_override": {
Type: schema.TypeList,
Optional: true,
// Even though the name is plural, the API only allows one override:
// ValidationException: 1 validation error detected: Value '[com.amazonaws.starling.dove.RecordingModeOverride@aa179030, com.amazonaws.starling.dove.RecordingModeOverride@4b13c61c]' at 'configurationRecorder.recordingMode.recordingModeOverrides' failed to satisfy constraint: Member must have length less than or equal to 1
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"description": {
Type: schema.TypeString,
Optional: true,
},
"recording_frequency": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice(configservice.RecordingFrequency_Values(), false),
},
"resource_types": {
Type: schema.TypeSet,
Required: true,
MinItems: 1,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
},
},
"role_arn": {
Type: schema.TypeString,
Required: true,
Expand All @@ -124,8 +166,11 @@ func resourceConfigurationRecorderPut(ctx context.Context, d *schema.ResourceDat
input.ConfigurationRecorder.RecordingGroup = expandRecordingGroup(v.([]interface{})[0].(map[string]interface{}))
}

_, err := conn.PutConfigurationRecorderWithContext(ctx, input)
if v, ok := d.GetOk("recording_mode"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.ConfigurationRecorder.RecordingMode = expandRecordingMode(v.([]interface{})[0].(map[string]interface{}))
}

_, err := conn.PutConfigurationRecorderWithContext(ctx, input)
if err != nil {
return sdkdiag.AppendErrorf(diags, "putting ConfigService Configuration Recorder (%s): %s", name, err)
}
Expand Down Expand Up @@ -162,6 +207,12 @@ func resourceConfigurationRecorderRead(ctx context.Context, d *schema.ResourceDa
}
}

if recorder.RecordingMode != nil {
if err := d.Set("recording_mode", flattenRecordingMode(recorder.RecordingMode)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting recording_mode: %s", err)
}
}

return diags
}

Expand Down Expand Up @@ -261,6 +312,16 @@ func resourceConfigCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v
}
}
}

/*
if g, ok := diff.GetOk("recording_mode"); ok {
mode := g.([]interface{})[0].(map[string]interface{})

if f, ok := mode["recording_frequency"]; ok {
if f.(string) != configservice.RecordingFrequencyOneHour && f.(string) != configservice.RecordingFrequencyThreeHours && f.(string) != configservice.RecordingFrequencySixHours && f.(string) != configservice.RecordingFrequencyTwelveHours && f.(string) != configservice.RecordingFrequencyTwentyFourHours {
}
}
*/
}
return nil
}
16 changes: 15 additions & 1 deletion internal/service/configservice/configuration_recorder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ func testAccConfigurationRecorder_allParams(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "recording_group.0.all_supported", "false"),
resource.TestCheckResourceAttr(resourceName, "recording_group.0.include_global_resource_types", "false"),
resource.TestCheckResourceAttr(resourceName, "recording_group.0.resource_types.#", "2"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.#", "1"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.0.recording_frequency", "DAILY"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.0.recording_mode_override.#", "1"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.0.recording_mode_override.0.recording_frequency", "CONTINUOUS"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.0.recording_mode_override.0.resource_types.#", "1"),
resource.TestCheckResourceAttr(resourceName, "recording_mode.0.recording_mode_override.0.resource_types.0", "AWS::EC2::Instance"),
acctest.CheckResourceAttrGlobalARN(resourceName, "role_arn", "iam", fmt.Sprintf("role/%s", rName)),
),
},
Expand Down Expand Up @@ -141,7 +147,6 @@ func testAccCheckConfigurationRecorderExists(ctx context.Context, n string, v *c
conn := acctest.Provider.Meta().(*conns.AWSClient).ConfigServiceConn(ctx)

output, err := tfconfig.FindConfigurationRecorderByName(ctx, conn, rs.Primary.ID)

if err != nil {
return err
}
Expand Down Expand Up @@ -252,6 +257,15 @@ resource "aws_config_configuration_recorder" "test" {
include_global_resource_types = false
resource_types = ["AWS::EC2::Instance", "AWS::CloudTrail::Trail"]
}

recording_mode {
recording_frequency = "DAILY"

recording_mode_override {
resource_types = ["AWS::EC2::Instance"]
recording_frequency = "CONTINUOUS"
}
}
}

resource "aws_iam_role" "test" {
Expand Down
75 changes: 75 additions & 0 deletions internal/service/configservice/flex.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,47 @@ func expandRecordingGroupRecordingStrategy(configured []interface{}) *configserv
return &recordingStrategy
}

func expandRecordingMode(mode map[string]interface{}) *configservice.RecordingMode {
recordingMode := configservice.RecordingMode{}

if v, ok := mode["recording_frequency"].(string); ok {
recordingMode.RecordingFrequency = aws.String(v)
}

if v, ok := mode["recording_mode_override"]; ok {
recordingMode.RecordingModeOverrides = expandRecordingModeRecordingModeOverrides(v.([]interface{}))
}

return &recordingMode
}

func expandRecordingModeRecordingModeOverrides(configured []interface{}) []*configservice.RecordingModeOverride {
var out []*configservice.RecordingModeOverride
for _, val := range configured {
m, ok := val.(map[string]interface{})
if !ok {
continue
}

e := &configservice.RecordingModeOverride{}

if v, ok := m["description"].(string); ok && v != "" {
e.Description = aws.String(v)
}

if v, ok := m["resource_types"]; ok {
e.ResourceTypes = flex.ExpandStringSet(v.(*schema.Set))
}

if v, ok := m["recording_frequency"].(string); ok && v != "" {
e.RecordingFrequency = aws.String(v)
}

out = append(out, e)
}
return out
}

func expandRulesEvaluationModes(in []interface{}) []*configservice.EvaluationModeConfiguration {
if len(in) == 0 {
return nil
Expand Down Expand Up @@ -260,6 +301,39 @@ func flattenRecordingGroup(g *configservice.RecordingGroup) []map[string]interfa

return []map[string]interface{}{m}
}

func flattenRecordingMode(g *configservice.RecordingMode) []map[string]interface{} {
m := make(map[string]interface{}, 1)

if g.RecordingFrequency != nil {
m["recording_frequency"] = aws.StringValue(g.RecordingFrequency)
}

if g.RecordingModeOverrides != nil && len(g.RecordingModeOverrides) > 0 {
m["recording_mode_override"] = flattenRecordingModeRecordingModeOverrides(g.RecordingModeOverrides)
}

return []map[string]interface{}{m}
}

func flattenRecordingModeRecordingModeOverrides(in []*configservice.RecordingModeOverride) []interface{} {
var out []interface{}
for _, v := range in {
m := map[string]interface{}{
"description": aws.StringValue(v.Description),
"recording_frequency": aws.StringValue(v.RecordingFrequency),
}

if v.ResourceTypes != nil {
m["resource_types"] = flex.FlattenStringSet(v.ResourceTypes)
}

out = append(out, m)
}

return out
}

func flattenExclusionByResourceTypes(exclusionByResourceTypes *configservice.ExclusionByResourceTypes) []interface{} {
if exclusionByResourceTypes == nil {
return nil
Expand Down Expand Up @@ -300,6 +374,7 @@ func flattenRecordingGroupRecordingStrategy(recordingStrategy *configservice.Rec

return []interface{}{m}
}

func flattenRuleScope(scope *configservice.Scope) []interface{} {
var items []interface{}

Expand Down
39 changes: 38 additions & 1 deletion website/docs/r/config_configuration_recorder.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,39 @@ resource "aws_config_configuration_recorder" "foo" {
}
```

### Periodic Recording

```terraform
resource "aws_config_configuration_recorder" "foo" {
name = "example"
role_arn = aws_iam_role.r.arn

recording_group {
all_supported = false
include_global_resource_types = false
resource_types = ["AWS::EC2::Instance", "AWS::EC2::NetworkInterface"]
}

recording_mode {
recording_frequency = "CONTINUOUS"

recording_mode_override {
description = "Only record EC2 network interfaces daily"
resource_types = ["AWS::EC2::NetworkInterface"]
recording_frequency = "DAILY"
}
}
}
```

## Argument Reference

This resource supports the following arguments:

* `name` - (Optional) The name of the recorder. Defaults to `default`. Changing it recreates the resource.
* `role_arn` - (Required) Amazon Resource Name (ARN) of the IAM role. Used to make read or write requests to the delivery channel and to describe the AWS resources associated with the account. See [AWS Docs](http://docs.aws.amazon.com/config/latest/developerguide/iamrole-permissions.html) for more details.
* `recording_group` - (Optional) Recording group - see below.
* `recording_mode` - (Optional) Recording mode - see below.

### recording_group Configuration Block

Expand All @@ -84,7 +110,18 @@ This resource supports the following arguments:

#### recording_strategy Configuration Block

* ` use_only` - (Optional) The recording strategy for the configuration recorder.See [relevant part of AWS Docs](https://docs.aws.amazon.com/config/latest/APIReference/API_RecordingStrategy.html)
* ` use_only` - (Optional) The recording strategy for the configuration recorder. See [relevant part of AWS Docs](https://docs.aws.amazon.com/config/latest/APIReference/API_RecordingStrategy.html)

### recording_mode Configuration Block

* `recording_frequency` - (Required) Default reecording frequency. `CONTINUOUS` or `DAILY`.
* `recording_mode_override` - (Optional) Recording mode overrides. Detailed below.

#### recording_mode_override Configuration Block

* `description` - (Optional) A description you provide of the override.
* `resource_types` - (Required) A list that specifies the types of AWS resources for which the override applies to. See [restrictions in the AWS Docs](https://docs.aws.amazon.com/config/latest/APIReference/API_RecordingModeOverride.html)
* `recording_frequency` - (Required) The recording frequency for the resources in the override block. `CONTINUOUS` or `DAILY`.

## Attribute Reference

Expand Down
Loading