Skip to content

Commit 8314623

Browse files
committed
feat(access-analyzer): support configurations for unused access and internal access
1 parent 8cbd08d commit 8314623

File tree

6 files changed

+168
-42
lines changed

6 files changed

+168
-42
lines changed

modules/access-analyzer/README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@ This module creates following resources.
1010

1111
| Name | Version |
1212
|------|---------|
13-
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.6 |
14-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.34 |
13+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.12 |
14+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.12 |
1515

1616
## Providers
1717

1818
| Name | Version |
1919
|------|---------|
20-
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.46.0 |
20+
| <a name="provider_aws"></a> [aws](#provider\_aws) | 6.13.0 |
2121

2222
## Modules
2323

2424
| Name | Source | Version |
2525
|------|--------|---------|
26-
| <a name="module_resource_group"></a> [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.10.0 |
26+
| <a name="module_resource_group"></a> [resource\_group](#module\_resource\_group) | tedilabs/misc/aws//modules/resource-group | ~> 0.12.0 |
2727

2828
## Resources
2929

@@ -37,15 +37,15 @@ This module creates following resources.
3737
| Name | Description | Type | Default | Required |
3838
|------|-------------|------|---------|:--------:|
3939
| <a name="input_name"></a> [name](#input\_name) | (Required) The name of the Analyzer. | `string` | n/a | yes |
40-
| <a name="input_archive_rules"></a> [archive\_rules](#input\_archive\_rules) | (Optional) A list of archive rules for the AccessAnalyzer Analyzer. Each item of `archive_rules` block as defined below.<br> (Required) `name` - The name of archive rule.<br> (Required) `filters` - A list of filter criterias for the archive rule. Each item of `filters` block as defined below.<br> (Required) `criteria` - The filter criteria.<br> (Optional) `contains` - Contains comparator.<br> (Optional) `exists` - Exists comparator (Boolean).<br> (Optional) `eq` - Equal comparator.<br> (Optional) `neq` - Not Equal comparator. | `any` | `[]` | no |
40+
| <a name="input_archive_rules"></a> [archive\_rules](#input\_archive\_rules) | (Optional) A list of archive rules for the AccessAnalyzer Analyzer. Each item of `archive_rules` block as defined below.<br/> (Required) `name` - The name of archive rule.<br/> (Required) `filters` - A list of filter criterias for the archive rule. Each item of `filters` block as defined below.<br/> (Required) `criteria` - The filter criteria.<br/> (Optional) `contains` - Contains comparator.<br/> (Optional) `exists` - Exists comparator (Boolean).<br/> (Optional) `eq` - Equal comparator.<br/> (Optional) `neq` - Not Equal comparator. | <pre>list(object({<br/> name = string<br/> filters = list(object({<br/> criteria = string<br/> contains = optional(list(string))<br/> exists = optional(bool)<br/> eq = optional(list(string))<br/> neq = optional(list(string))<br/> }))<br/> }))</pre> | `[]` | no |
41+
| <a name="input_internal_access_analysis"></a> [internal\_access\_analysis](#input\_internal\_access\_analysis) | (Optional) A configurations for the `INTERNAL_ACCESS` type Analyzer. `internal_access_analysis` as defined below.<br/> (Optional) `rules` - A list of rules for internal access analyzer. Each item of `rules` block as defined below.<br/> (Required) `inclusion` - An inclusion rule to filter findings. `inclusion` as defined below.<br/> (Optional) `accounts` - A set of account IDs to include in the analysis. Account IDs can only be applied to the analysis rule criteria for organization-level analyzers.<br/> (Optional) `resource_arns` - A set of resource ARNs to include in the analysis. The analyzer will only generate findings for resources that match these ARNs.<br/> (Optional) `resource_types` - A set of resource types to include in the analysis. The analyzer will only generate findings for resources of these types | <pre>object({<br/> rules = optional(list(object({<br/> inclusion = object({<br/> accounts = optional(set(string), [])<br/> resource_arns = optional(set(string), [])<br/> resource_types = optional(set(string), [])<br/> })<br/> })), [])<br/> })</pre> | `{}` | no |
4142
| <a name="input_module_tags_enabled"></a> [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no |
42-
| <a name="input_resource_group_description"></a> [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no |
43-
| <a name="input_resource_group_enabled"></a> [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no |
44-
| <a name="input_resource_group_name"></a> [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no |
43+
| <a name="input_region"></a> [region](#input\_region) | (Optional) The region in which to create the module resources. If not provided, the module resources will be created in the provider's configured region. | `string` | `null` | no |
44+
| <a name="input_resource_group"></a> [resource\_group](#input\_resource\_group) | (Optional) A configurations of Resource Group for this module. `resource_group` as defined below.<br/> (Optional) `enabled` - Whether to create Resource Group to find and group AWS resources which are created by this module. Defaults to `true`.<br/> (Optional) `name` - The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. If not provided, a name will be generated using the module name and instance name.<br/> (Optional) `description` - The description of Resource Group. Defaults to `Managed by Terraform.`. | <pre>object({<br/> enabled = optional(bool, true)<br/> name = optional(string, "")<br/> description = optional(string, "Managed by Terraform.")<br/> })</pre> | `{}` | no |
4545
| <a name="input_scope"></a> [scope](#input\_scope) | (Optional) A scope of Analyzer. Valid values are `ACCOUNT` or `ORGANIZATION`. Defaults to `ACCOUNT`. | `string` | `"ACCOUNT"` | no |
4646
| <a name="input_tags"></a> [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no |
47-
| <a name="input_type"></a> [type](#input\_type) | (Optional) A finding type of Analyzer. Valid values are `EXTERNAL_ACCESS` or `UNUSED_ACCESS`. Defaults to `EXTERNAL_ACCESS`. | `string` | `"EXTERNAL_ACCESS"` | no |
48-
| <a name="input_unused_access_tracking_period"></a> [unused\_access\_tracking\_period](#input\_unused\_access\_tracking\_period) | (Optional) A number of days for the tracking the period. Findings will be generated for access that hasn't been used in more than the specified number of days. Defaults to `90`. | `number` | `90` | no |
47+
| <a name="input_type"></a> [type](#input\_type) | (Optional) A finding type of Analyzer. Valid values are `EXTERNAL_ACCESS`, `INTERNAL_ACCESS` or `UNUSED_ACCESS`. Defaults to `EXTERNAL_ACCESS`. | `string` | `"EXTERNAL_ACCESS"` | no |
48+
| <a name="input_unused_access_analysis"></a> [unused\_access\_analysis](#input\_unused\_access\_analysis) | (Optional) A configurations for the `UNUSED_ACCESS` type Analyzer. `unused_access_analysis` as defined below.<br/> (Optional) `tracking_period` - A number of days for the tracking the period. Findings will be generated for access that hasn't been used in more than the specified number of days. Defaults to `90`.<br/> (Optional) `rules` - A list of rules for unused access analyzer. Each item of `rules` block as defined below.<br/> (Required) `exclusion` - An exclusion rule to filter findings. `exclusion` as defined below.<br/> (Optional) `accounts` - A set of account IDs to exclude from the analysis. Account IDs can only be applied to the analysis rule criteria for organization-level analyzers.<br/> (Optional) `resource_tags` - A list of tag key and value pairs to exclude from the analysis. | <pre>object({<br/> tracking_period = optional(number, 90)<br/> rules = optional(list(object({<br/> exclusion = object({<br/> accounts = optional(set(string), [])<br/> resource_tags = optional(list(map(string)), [])<br/> })<br/> })), [])<br/> })</pre> | `{}` | no |
4949

5050
## Outputs
5151

@@ -54,8 +54,11 @@ This module creates following resources.
5454
| <a name="output_archive_rules"></a> [archive\_rules](#output\_archive\_rules) | A list of archive rules for the Analyzer. |
5555
| <a name="output_arn"></a> [arn](#output\_arn) | The Amazon Resource Name (ARN) of this Analyzer. |
5656
| <a name="output_id"></a> [id](#output\_id) | The ID of this Analyzer. |
57+
| <a name="output_internal_access_analysis"></a> [internal\_access\_analysis](#output\_internal\_access\_analysis) | The configurations for the `INTERNAL_ACCESS` type Analyzer. |
5758
| <a name="output_name"></a> [name](#output\_name) | The name of the Analyzer. |
59+
| <a name="output_region"></a> [region](#output\_region) | The AWS region this module resources resides in. |
60+
| <a name="output_resource_group"></a> [resource\_group](#output\_resource\_group) | The resource group created to manage resources in this module. |
5861
| <a name="output_scope"></a> [scope](#output\_scope) | The scope of Analyzer. |
5962
| <a name="output_type"></a> [type](#output\_type) | The finding type of Analyzer. |
60-
| <a name="output_unused_access_tracking_period"></a> [unused\_access\_tracking\_period](#output\_unused\_access\_tracking\_period) | The scope of Analyzer. |
63+
| <a name="output_unused_access_analysis"></a> [unused\_access\_analysis](#output\_unused\_access\_analysis) | The configurations for the `UNUSED_ACCESS` type Analyzer. |
6164
<!-- END_TF_DOCS -->

modules/access-analyzer/main.tf

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,74 @@ locals {
2020
###################################################
2121

2222
resource "aws_accessanalyzer_analyzer" "this" {
23+
region = var.region
24+
2325
analyzer_name = var.name
24-
type = (var.type == "EXTERNAL_ACCESS"
25-
? var.scope
26-
: (var.type == "UNUSED_ACCESS"
27-
? "${var.scope}_UNUSED_ACCESS"
28-
: null
29-
)
30-
)
26+
type = "${var.scope}${var.type == "EXTERNAL_ACCESS" ? "" : "_${var.type}"}"
3127

3228
dynamic "configuration" {
33-
for_each = var.type == "UNUSED_ACCESS" ? ["go"] : []
29+
for_each = contains(["INTERNAL_ACCESS", "UNUSED_ACCESS"], var.type) ? ["go"] : []
3430

3531
content {
32+
dynamic "internal_access" {
33+
for_each = var.type == "INTERNAL_ACCESS" ? ["go"] : []
34+
35+
content {
36+
dynamic "analysis_rule" {
37+
for_each = length(var.internal_access_analysis.rules) > 0 ? ["go"] : []
38+
iterator = rule
39+
40+
content {
41+
dynamic "inclusion" {
42+
for_each = var.internal_access_analysis.rules[*].inclusion
43+
44+
content {
45+
account_ids = (length(inclusion.value.accounts) > 0
46+
? inclusion.value.accounts
47+
: null
48+
)
49+
resource_arns = (length(inclusion.value.resource_arns) > 0
50+
? inclusion.value.resource_arns
51+
: null
52+
)
53+
resource_types = (length(inclusion.value.resource_types) > 0
54+
? inclusion.value.resource_types
55+
: null
56+
)
57+
}
58+
}
59+
}
60+
}
61+
}
62+
}
63+
3664
dynamic "unused_access" {
3765
for_each = var.type == "UNUSED_ACCESS" ? ["go"] : []
3866

3967
content {
40-
unused_access_age = var.unused_access_tracking_period
68+
unused_access_age = var.unused_access_analysis.tracking_period
69+
70+
dynamic "analysis_rule" {
71+
for_each = length(var.unused_access_analysis.rules) > 0 ? ["go"] : []
72+
iterator = rule
73+
74+
content {
75+
dynamic "exclusion" {
76+
for_each = var.unused_access_analysis.rules[*].exclusion
77+
78+
content {
79+
account_ids = (length(exclusion.value.accounts) > 0
80+
? exclusion.value.accounts
81+
: null
82+
)
83+
resource_tags = (length(exclusion.value.resource_tags) > 0
84+
? exclusion.value.resource_tags
85+
: null
86+
)
87+
}
88+
}
89+
}
90+
}
4191
}
4292
}
4393
}
@@ -58,6 +108,8 @@ resource "aws_accessanalyzer_archive_rule" "this" {
58108
rule.name => rule
59109
}
60110

111+
region = var.region
112+
61113
analyzer_name = aws_accessanalyzer_analyzer.this.analyzer_name
62114
rule_name = each.key
63115

modules/access-analyzer/outputs.tf

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
output "region" {
2+
description = "The AWS region this module resources resides in."
3+
value = aws_accessanalyzer_analyzer.this.region
4+
}
5+
16
output "name" {
27
description = "The name of the Analyzer."
38
value = aws_accessanalyzer_analyzer.this.analyzer_name
@@ -23,10 +28,23 @@ output "scope" {
2328
value = var.scope
2429
}
2530

26-
output "unused_access_tracking_period" {
27-
description = "The scope of Analyzer."
31+
output "internal_access_analysis" {
32+
description = "The configurations for the `INTERNAL_ACCESS` type Analyzer."
33+
value = (var.type == "INTERNAL_ACCESS"
34+
? {
35+
rules = var.internal_access_analysis.rules
36+
}
37+
: null
38+
)
39+
}
40+
41+
output "unused_access_analysis" {
42+
description = "The configurations for the `UNUSED_ACCESS` type Analyzer."
2843
value = (var.type == "UNUSED_ACCESS"
29-
? one(aws_accessanalyzer_analyzer.this.configuration[0].unused_access[*].unused_access_age)
44+
? {
45+
tracking_period = one(aws_accessanalyzer_analyzer.this.configuration[0].unused_access[*].unused_access_age)
46+
rules = var.unused_access_analysis.rules
47+
}
3048
: null
3149
)
3250
}

modules/access-analyzer/resource-group.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ module "resource_group" {
1616

1717
count = (var.resource_group.enabled && var.module_tags_enabled) ? 1 : 0
1818

19+
region = var.region
20+
1921
name = local.resource_group_name
2022
description = var.resource_group.description
2123

modules/access-analyzer/variables.tf

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1+
variable "region" {
2+
description = "(Optional) The region in which to create the module resources. If not provided, the module resources will be created in the provider's configured region."
3+
type = string
4+
default = null
5+
nullable = true
6+
}
7+
18
variable "name" {
29
description = "(Required) The name of the Analyzer."
310
type = string
11+
nullable = false
412
}
513

614
variable "type" {
7-
description = "(Optional) A finding type of Analyzer. Valid values are `EXTERNAL_ACCESS` or `UNUSED_ACCESS`. Defaults to `EXTERNAL_ACCESS`."
15+
description = "(Optional) A finding type of Analyzer. Valid values are `EXTERNAL_ACCESS`, `INTERNAL_ACCESS` or `UNUSED_ACCESS`. Defaults to `EXTERNAL_ACCESS`."
816
type = string
917
default = "EXTERNAL_ACCESS"
1018
nullable = false
1119

1220
validation {
13-
condition = contains(["EXTERNAL_ACCESS", "UNUSED_ACCESS"], var.type)
14-
error_message = "The `type` should be one of `EXTERNAL_ACCESS`, `UNUSED_ACCESS`."
21+
condition = contains(["EXTERNAL_ACCESS", "INTERNAL_ACCESS", "UNUSED_ACCESS"], var.type)
22+
error_message = "The `type` should be one of `EXTERNAL_ACCESS`, `INTERNAL_ACCESS`, `UNUSED_ACCESS`."
1523
}
1624
}
1725

@@ -27,18 +35,55 @@ variable "scope" {
2735
}
2836
}
2937

30-
variable "unused_access_tracking_period" {
31-
description = "(Optional) A number of days for the tracking the period. Findings will be generated for access that hasn't been used in more than the specified number of days. Defaults to `90`."
32-
type = number
33-
default = 90
34-
nullable = false
38+
variable "internal_access_analysis" {
39+
description = <<EOF
40+
(Optional) A configurations for the `INTERNAL_ACCESS` type Analyzer. `internal_access_analysis` as defined below.
41+
(Optional) `rules` - A list of rules for internal access analyzer. Each item of `rules` block as defined below.
42+
(Required) `inclusion` - An inclusion rule to filter findings. `inclusion` as defined below.
43+
(Optional) `accounts` - A set of account IDs to include in the analysis. Account IDs can only be applied to the analysis rule criteria for organization-level analyzers.
44+
(Optional) `resource_arns` - A set of resource ARNs to include in the analysis. The analyzer will only generate findings for resources that match these ARNs.
45+
(Optional) `resource_types` - A set of resource types to include in the analysis. The analyzer will only generate findings for resources of these types
46+
EOF
47+
type = object({
48+
rules = optional(list(object({
49+
inclusion = object({
50+
accounts = optional(set(string), [])
51+
resource_arns = optional(set(string), [])
52+
resource_types = optional(set(string), [])
53+
})
54+
})), [])
55+
})
56+
default = {}
57+
nullable = false
58+
}
59+
60+
variable "unused_access_analysis" {
61+
description = <<EOF
62+
(Optional) A configurations for the `UNUSED_ACCESS` type Analyzer. `unused_access_analysis` as defined below.
63+
(Optional) `tracking_period` - A number of days for the tracking the period. Findings will be generated for access that hasn't been used in more than the specified number of days. Defaults to `90`.
64+
(Optional) `rules` - A list of rules for unused access analyzer. Each item of `rules` block as defined below.
65+
(Required) `exclusion` - An exclusion rule to filter findings. `exclusion` as defined below.
66+
(Optional) `accounts` - A set of account IDs to exclude from the analysis. Account IDs can only be applied to the analysis rule criteria for organization-level analyzers.
67+
(Optional) `resource_tags` - A list of tag key and value pairs to exclude from the analysis.
68+
EOF
69+
type = object({
70+
tracking_period = optional(number, 90)
71+
rules = optional(list(object({
72+
exclusion = object({
73+
accounts = optional(set(string), [])
74+
resource_tags = optional(list(map(string)), [])
75+
})
76+
})), [])
77+
})
78+
default = {}
79+
nullable = false
3580

3681
validation {
3782
condition = alltrue([
38-
var.unused_access_tracking_period >= 1,
39-
var.unused_access_tracking_period <= 180
83+
var.unused_access_analysis.tracking_period >= 1,
84+
var.unused_access_analysis.tracking_period <= 180
4085
])
41-
error_message = "Valid value for `unused_access_tracking_period` is between 1 and 180."
86+
error_message = "Valid value for `tracking_period` is between 1 and 180."
4287
}
4388
}
4489

@@ -53,9 +98,18 @@ variable "archive_rules" {
5398
(Optional) `eq` - Equal comparator.
5499
(Optional) `neq` - Not Equal comparator.
55100
EOF
56-
type = any
57-
default = []
58-
nullable = false
101+
type = list(object({
102+
name = string
103+
filters = list(object({
104+
criteria = string
105+
contains = optional(list(string))
106+
exists = optional(bool)
107+
eq = optional(list(string))
108+
neq = optional(list(string))
109+
}))
110+
}))
111+
default = []
112+
nullable = false
59113

60114
validation {
61115
condition = alltrue([
@@ -85,9 +139,6 @@ variable "module_tags_enabled" {
85139
# Resource Group
86140
###################################################
87141

88-
89-
90-
91142
variable "resource_group" {
92143
description = <<EOF
93144
(Optional) A configurations of Resource Group for this module. `resource_group` as defined below.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
terraform {
2-
required_version = ">= 1.6"
2+
required_version = ">= 1.12"
33

44
required_providers {
55
aws = {
66
source = "hashicorp/aws"
7-
version = ">= 5.34"
7+
version = ">= 6.12"
88
}
99
}
1010
}

0 commit comments

Comments
 (0)