From b2a9e77834dee3bd43435b59ab15439081f76ee3 Mon Sep 17 00:00:00 2001 From: Rohith Jayawardene Date: Sat, 21 Sep 2024 16:26:50 +0100 Subject: [PATCH] feat: adding the ability to enforce tags via the iam boundary for machine roles, and deploying a similar policy for sso users (#48) * feat: adding the ability to enforce tags via the iam boundary for machine roles, and deploying a similar policy for sso users * docs: updating the docs to reflect the changes * fix: removing the .orig file and adding the gitignore * fix: the parameters in the template were incorrect * chore: updating the documentation to reflect the changes --- .gitignore | 1 + Makefile | 33 ++++++++--- README.md | 20 +++++-- assets/cloudformation/default-boundary.yml | 47 ++++++++++----- assets/cloudformation/permissive-boundary.yml | 29 ++++++++-- assets/cloudformation/tagging-boundary.yml | 46 +++++++++++++++ boundaries.tf | 40 ++++++++++++- examples/basic/README.md | 2 +- locals.tf | 7 +++ variables.tf | 57 +++++++++++++++++++ 10 files changed, 246 insertions(+), 36 deletions(-) create mode 100644 assets/cloudformation/tagging-boundary.yml diff --git a/.gitignore b/.gitignore index 1efb2f0..a05d725 100755 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ terraform.rc # Other .DS_Store todo.md +*.orig # Ignore securityhub-findings-forwarder lambda deployment package builds diff --git a/Makefile b/Makefile index 002bd7a..3ebfc54 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,4 @@ # -# Copyright (C) 2024 Appvia Ltd -# # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 @@ -14,23 +12,22 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -AUTHOR_EMAIL=info@appvia.io - -.PHONY: all security lint format documentation documentation-examples validate-all validate validate-examples init examples +.PHONY: all security lint format documentation documentation-examples validate-all validate validate-examples init examples tests default: all all: $(MAKE) init $(MAKE) validate + $(MAKE) tests $(MAKE) lint $(MAKE) security $(MAKE) format $(MAKE) documentation examples: - @echo "--> Generating documentation" $(MAKE) validate-examples + $(MAKE) tests $(MAKE) lint-examples $(MAKE) lint $(MAKE) security @@ -55,6 +52,19 @@ documentation-examples: find examples -type d -mindepth 1 -maxdepth 1 -exec terraform-docs markdown table --output-file README.md --output-mode inject {} \; ; \ fi +upgrade-terraform-providers: + @printf "%s Upgrading Terraform providers for %-24s" "-->" "." + @terraform init -upgrade >/dev/null && echo "[OK]" || echo "[FAILED]" + @$(MAKE) upgrade-terraform-example-providers + +upgrade-terraform-example-providers: + @if [ -d examples ]; then \ + find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ + printf "%s Upgrading Terraform providers for %-24s" "-->" "$$dir"; \ + terraform -chdir=$$dir init -upgrade >/dev/null && echo "[OK]" || echo "[FAILED]"; \ + done; \ + fi + init: @echo "--> Running terraform init" @terraform init -backend=false @@ -70,7 +80,7 @@ security-modules: @if [ -d modules ]; then \ find modules -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ echo "--> Validating $$dir"; \ - trivy config $$dir; \ + trivy config --format table --exit-code 1 --severity CRITICAL,HIGH --ignorefile .trivyignore $$dir; \ done; \ fi @@ -79,10 +89,14 @@ security-examples: @if [ -d examples ]; then \ find examples -type d -mindepth 1 -maxdepth 1 | while read -r dir; do \ echo "--> Validating $$dir"; \ - trivy config $$dir; \ + trivy config --format table --exit-code 1 --severity CRITICAL,HIGH --ignorefile .trivyignore $$dir; \ done; \ fi +tests: + @echo "--> Running Terraform Tests" + @terraform test + validate: @echo "--> Running terraform validate" @terraform init -backend=false @@ -110,6 +124,9 @@ validate-examples: done; \ fi +validate-commits: + @echo "--> Running commitlint against the " + lint: @echo "--> Running tflint" @tflint --init diff --git a/README.md b/README.md index 9ef6738..2fb668f 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,12 @@ identity_center_start_url = "" identity_center_role = "" ``` +## Tagging Enforcement + +The tagging enforcement feature updates the default IAM boundaries deployed by this module to include additional policy blocking the creation of resources without the required tags; defined in the `var.enforcable_tags` variable. The restrictions will be applied to all actions found in the `var.enforcable_tagging_actions`. These are the same IAM boundaries which are intended to be used by machine roles (i.e. CI/CD). + +Switching on the feature will also deploy a stackset across the entire organization implementing the tagging policy deny logic. This should be referenced by roles within the account. + ## Update Documentation The `terraform-docs` utility is used to generate this README. Follow the below steps to update: @@ -111,6 +117,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [network\_transit\_gateway\_admin](#module\_network\_transit\_gateway\_admin) | appvia/oidc/aws//modules/role | 1.3.2 | | [permissive\_boundary](#module\_permissive\_boundary) | appvia/boundary-stack/aws | 0.1.7 | | [securityhub\_notifications](#module\_securityhub\_notifications) | appvia/notifications/aws | 1.0.4 | +| [tagging\_boundary](#module\_tagging\_boundary) | appvia/boundary-stack/aws | 0.1.7 | ## Resources @@ -155,7 +162,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [accounts\_id\_to\_name](#input\_accounts\_id\_to\_name) | A mapping of account id and account name - used by notification lamdba to map an account ID to a human readable name | `map(string)` | `{}` | no | -| [aws\_accounts](#input\_aws\_accounts) | Map of AWS account names to their account IDs |
object({
network_account_id = optional(string, "")
remoteaccess_account_id = optional(string, "")
})
| n/a | yes | +| [aws\_accounts](#input\_aws\_accounts) | Map of AWS account names to their account IDs |
object({
network_account_id = optional(string, "")
remoteaccess_account_id = optional(string, "")
})
| n/a | yes | | [aws\_support\_role\_name](#input\_aws\_support\_role\_name) | Name of the AWS Support role | `string` | `"AWSSupportAccessRole"` | no | | [breakglass\_users](#input\_breakglass\_users) | The number of breakglass users to create | `number` | `2` | no | | [cloudaccess\_terraform\_state\_ro\_policy\_name](#input\_cloudaccess\_terraform\_state\_ro\_policy\_name) | Name of the IAM policy to attach to the CloudAccess Terraform state role | `string` | `"lza-cloudaccess-tfstate-ro"` | no | @@ -167,10 +174,15 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [enable\_breakglass](#input\_enable\_breakglass) | Indicates if we should enable breakglass users and group | `bool` | `false` | no | | [enable\_cis\_alarms](#input\_enable\_cis\_alarms) | Indicates if we should enable CIS alerts | `bool` | `true` | no | | [enable\_securityhub\_alarms](#input\_enable\_securityhub\_alarms) | Indicates if we should enable SecurityHub alarms | `bool` | `true` | no | +| [enable\_tag\_enforcement](#input\_enable\_tag\_enforcement) | Indicates if we should enable tagging enforcement | `bool` | `false` | no | +| [enforcable\_tagging\_actions](#input\_enforcable\_tagging\_actions) | List of enforceable tagging actions | `list(string)` |
[
"ec2:CreateInternetGateway",
"ec2:CreateVolume",
"ec2:CreateVpcPeeringConnection",
"ec2:RunInstances",
"ecs:CreateCluster",
"ecs:CreateService",
"ecs:CreateTaskSet",
"eks:CreateCluster",
"elasticfilesystem:CreateAccessPoint",
"elasticfilesystem:CreateFileSystem",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateRule",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:CreateTrustStore",
"network-firewall:CreateFirewall",
"network-firewall:CreateFirewallPolicy",
"network-firewall:CreateRuleGroup",
"ram:CreatePermission",
"ram:CreateResourceShare",
"redshift:CreateCluster",
"redshift:CreateClusterParameterGroup",
"redshift:CreateClusterSecurityGroup",
"redshift:CreateClusterSubnetGroup",
"route53:CreateHostedZone",
"secretsmanager:CreateSecret"
]
| no | +| [enforcable\_tagging\_policy\_name](#input\_enforcable\_tagging\_policy\_name) | Name of the IAM policy to use as a permissions boundary for enforceable tags | `string` | `"lza-enforceable-tags-boundary"` | no | +| [enforcable\_tagging\_resources](#input\_enforcable\_tagging\_resources) | List of enforceable tagging resources | `list(string)` |
[
"*"
]
| no | +| [enforcable\_tags](#input\_enforcable\_tags) | List of enforceable tags | `list(string)` | `[]` | no | | [identity\_center\_start\_url](#input\_identity\_center\_start\_url) | The start URL of your Identity Center instance | `string` | `null` | no | -| [notifications](#input\_notifications) | Configuration for the notifications |
object({
email = optional(object({
addresses = list(string)
}), null)
slack = optional(object({
webhook_url = string
}), null)
teams = optional(object({
webhook_url = string
}), null)
})
|
{
"email": {
"addresses": []
},
"slack": null,
"teams": null
}
| no | +| [notifications](#input\_notifications) | Configuration for the notifications |
object({
email = optional(object({
addresses = list(string)
}), null)
slack = optional(object({
webhook_url = string
}), null)
teams = optional(object({
webhook_url = string
}), null)
})
|
{
"email": {
"addresses": []
},
"slack": null,
"teams": null
}
| no | | [permissive\_permissions\_boundary\_name](#input\_permissive\_permissions\_boundary\_name) | Name of the permissive IAM policy to use as a permissions boundary | `string` | `"lza-permissive-boundary"` | no | -| [repositories](#input\_repositories) | List of repository locations for the pipelines |
object({
accelerator = optional(object({
url = string
role_name = optional(string, "lza-accelerator")
}), null)
connectivity = optional(object({
url = string
role_name = optional(string, "lza-connectivity")
}), null)
cost_management = optional(object({
url = string
role_name = optional(string, "lza-cost-management")
}), null)
firewall = optional(object({
url = string
role_name = optional(string, "lza-firewall")
}), null)
identity = optional(object({
url = string
role_name = optional(string, "lza-identity")
}), null)
})
| `{}` | no | +| [repositories](#input\_repositories) | List of repository locations for the pipelines |
object({
accelerator = optional(object({
url = string
role_name = optional(string, "lza-accelerator")
}), null)
connectivity = optional(object({
url = string
role_name = optional(string, "lza-connectivity")
}), null)
cost_management = optional(object({
url = string
role_name = optional(string, "lza-cost-management")
}), null)
firewall = optional(object({
url = string
role_name = optional(string, "lza-firewall")
}), null)
identity = optional(object({
url = string
role_name = optional(string, "lza-identity")
}), null)
})
| `{}` | no | | [scm\_name](#input\_scm\_name) | Name of the source control management system (github or gitlab) | `string` | `"github"` | no | | [security\_hub\_identity\_center\_role](#input\_security\_hub\_identity\_center\_role) | The name of the role to use when redirecting through Identity Center for security hub events | `string` | `null` | no | | [securityhub\_event\_bridge\_rule\_name](#input\_securityhub\_event\_bridge\_rule\_name) | Display name of the EventBridge rule for Security Hub findings | `string` | `"lza-securityhub-alerts"` | no | @@ -178,7 +190,7 @@ The `terraform-docs` utility is used to generate this README. Follow the below s | [securityhub\_lambda\_log\_group\_kms\_alias](#input\_securityhub\_lambda\_log\_group\_kms\_alias) | Name of the KMS alias for the CloudWatch log group | `string` | `"alias/accelerator/kms/cloudwatch/key"` | no | | [securityhub\_lambda\_role\_name](#input\_securityhub\_lambda\_role\_name) | Name of the IAM role for the Security Hub Lambda function | `string` | `"lza-securityhub-lambda-role"` | no | | [securityhub\_lambda\_runtime](#input\_securityhub\_lambda\_runtime) | Runtime for the Security Hub Lambda function | `string` | `"python3.12"` | no | -| [securityhub\_severity\_filter](#input\_securityhub\_severity\_filter) | Indicates if we should enable SecurityHub | `list(string)` |
[
"CRITICAL",
"HIGH"
]
| no | +| [securityhub\_severity\_filter](#input\_securityhub\_severity\_filter) | Indicates if we should enable SecurityHub | `list(string)` |
[
"CRITICAL",
"HIGH"
]
| no | | [securityhub\_sns\_topic\_name](#input\_securityhub\_sns\_topic\_name) | Name of the SNS topic to send Security Hub findings to | `string` | `"lza-securityhub-alerts"` | no | | [tags](#input\_tags) | Tags to apply to all resources | `map(string)` | n/a | yes | diff --git a/assets/cloudformation/default-boundary.yml b/assets/cloudformation/default-boundary.yml index ec05b52..aea1225 100644 --- a/assets/cloudformation/default-boundary.yml +++ b/assets/cloudformation/default-boundary.yml @@ -43,40 +43,40 @@ Resources: - iam:DeletePolicyVersion - iam:SetDefaultPolicyVersion Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${BoundaryName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" - Sid: DenyRemovalOfPermBoundaryFromAnyUserOrRole Effect: Deny Action: - iam:DeleteRolePermissionsBoundary - iam:DeleteUserPermissionsBoundary Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:user/*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:user/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:role/*" Condition: StringEquals: - "iam:PermissionsBoundary": !Sub "arn:aws:iam::${AWS::AccountId}:policy/${BoundaryName}" + "iam:PermissionsBoundary": !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" - Sid: DenyAccessIfRequiredPermBoundaryIsNotBeingApplied Effect: Deny Action: - iam:PutRolePermissionsBoundary - iam:PutUserPermissionsBoundary Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:user/*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:user/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:role/*" Condition: StringNotEquals: - "iam:PermissionsBoundary": !Sub "arn:aws:iam::${AWS::AccountId}:policy/${BoundaryName}" + "iam:PermissionsBoundary": !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" - Sid: DenyUserAndRoleCreationWithOutPermBoundary Effect: Deny Action: - iam:CreateRole - iam:CreateUser Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:user/*" - - !Sub "arn:aws:iam::${AWS::AccountId}:role/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:user/*" + - !Sub "arn:aws:iam::$${AWS::AccountId}:role/*" Condition: StringNotEquals: - "iam:PermissionsBoundary": !Sub "arn:aws:iam::${AWS::AccountId}:policy/${BoundaryName}" + "iam:PermissionsBoundary": !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" - Sid: NoCIPolicyEdit Effect: Deny Action: @@ -86,8 +86,8 @@ Resources: - iam:DeletePolicyVersion - iam:SetDefaultPolicyVersion Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${TerraformStateRWPolicyName}" - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${TerraformStateROPolicyName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${TerraformStateRWPolicyName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${TerraformStateROPolicyName}" - Sid: DenyCreateOrDestroyIAMUsers Effect: Deny Action: @@ -103,16 +103,33 @@ Resources: Action: - dynamoDB:DeleteTable Resource: - - !Sub "arn:aws:dynamodb::${AWS::AccountId}:table/${AWS::AccountId}-${AWS::Region}-tflock" + - !Sub "arn:aws:dynamodb::$${AWS::AccountId}:table/$${AWS::AccountId}-$${AWS::Region}-tflock" - Sid: ProtectS3RemoteState Effect: Deny Action: - s3:DeleteBucket Resource: - - !Sub "arn:aws:s3:::${AWS::AccountId}-${AWS::Region}-tfstate" + - !Sub "arn:aws:s3:::$${AWS::AccountId}-$${AWS::Region}-tfstate" - Sid: DenyCloudWatchAlarms Effect: Deny Action: - cloudwatch:* Resource: - - !Sub "arn:aws:cloudwatch::${AWS::AccountId}:alarm:*" + - !Sub "arn:aws:cloudwatch::$${AWS::AccountId}:alarm:*" + %{ if enable_tagging_enforcement ~} + - Sid: EnforceTaggingPolicy + Effect: Deny + Action: + %{ for action in actions ~} + - "${action}" + %{ endfor ~} + Resource: [ + %{ for resource in resources ~} + - "${resource}" + %{ endfor ~} + Condition: + Null: + %{ for tag in tags ~} + "aws:RequestTag/${tag}": "true" + %{ endfor ~} + %{ endif ~} diff --git a/assets/cloudformation/permissive-boundary.yml b/assets/cloudformation/permissive-boundary.yml index a66e03b..d98aca8 100644 --- a/assets/cloudformation/permissive-boundary.yml +++ b/assets/cloudformation/permissive-boundary.yml @@ -42,7 +42,7 @@ Resources: - iam:DeletePolicyVersion - iam:SetDefaultPolicyVersion Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${BoundaryName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" - Sid: NoCIPolicyEdit Effect: Deny Action: @@ -52,8 +52,8 @@ Resources: - iam:DeletePolicyVersion - iam:SetDefaultPolicyVersion Resource: - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${TerraformStateRWPolicyName}" - - !Sub "arn:aws:iam::${AWS::AccountId}:policy/${TerraformStateROPolicyName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${TerraformStateRWPolicyName}" + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${TerraformStateROPolicyName}" - Sid: DenyCreateOrDestroyIAMUsers Effect: Deny Action: @@ -69,16 +69,33 @@ Resources: Action: - dynamoDB:DeleteTable Resource: - - !Sub "arn:aws:dynamodb::${AWS::AccountId}:table/${AWS::AccountId}-${AWS::Region}-tflock" + - !Sub "arn:aws:dynamodb::$${AWS::AccountId}:table/$${AWS::AccountId}-$${AWS::Region}-tflock" - Sid: ProtectS3RemoteState Effect: Deny Action: - s3:DeleteBucket Resource: - - !Sub "arn:aws:s3:::${AWS::AccountId}-${AWS::Region}-tfstate" + - !Sub "arn:aws:s3:::$${AWS::AccountId}-$${AWS::Region}-tfstate" - Sid: DenyCloudWatchAlarms Effect: Deny Action: - cloudwatch:* Resource: - - !Sub "arn:aws:cloudwatch::${AWS::AccountId}:alarm:*" + - !Sub "arn:aws:cloudwatch::$${AWS::AccountId}:alarm:*" + %{ if enable_tagging_enforcement ~} + - Sid: EnforceTaggingPolicy + Effect: Deny + Action: + %{ for action in actions ~} + - "${action}" + %{ endfor ~} + Resource: [ + %{ for resource in resources ~} + - "${resource}" + %{ endfor ~} + Condition: + Null: + %{ for tag in tags ~} + "aws:RequestTag/${tag}": "true" + %{ endfor ~} + %{ endif ~} diff --git a/assets/cloudformation/tagging-boundary.yml b/assets/cloudformation/tagging-boundary.yml new file mode 100644 index 0000000..bb61273 --- /dev/null +++ b/assets/cloudformation/tagging-boundary.yml @@ -0,0 +1,46 @@ +--- +AWSTemplateFormatVersion: "2010-09-09" +Description: Provisions the IAM boundary used to enforce tagging policies + +Parameters: + BoundaryName: + Type: String + Description: The name of the Permissive Permissions Boundary + Default: lza-tagging-boundary + +Resources: + Boundary: + Type: AWS::IAM::ManagedPolicy + Properties: + ManagedPolicyName: !Ref BoundaryName + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowAdminAccess + Effect: Allow + Action: "*" + Resource: "*" + - Sid: DenyPermBoundaryIAMPolicyAlteration + Effect: Deny + Action: + - iam:CreatePolicyVersion + - iam:DeletePolicy + - iam:DeletePolicyVersion + - iam:SetDefaultPolicyVersion + Resource: + - !Sub "arn:aws:iam::$${AWS::AccountId}:policy/$${BoundaryName}" + - Sid: EnforceTaggingPolicy + Effect: Deny + Action: + %{ for action in actions ~} + - "${action}" + %{ endfor ~} + Resource: [ + %{ for resource in resources ~} + - "${resource}" + %{ endfor ~} + Condition: + Null: + %{ for tag in tags ~} + "aws:RequestTag/${tag}": "true" + %{ endfor ~} diff --git a/boundaries.tf b/boundaries.tf index 5f9377a..fa2d2fe 100644 --- a/boundaries.tf +++ b/boundaries.tf @@ -27,7 +27,13 @@ module "default_boundary" { parameters = local.boundary_default_stack_parameters region = local.region tags = var.tags - template = file("${path.module}/assets/cloudformation/default-boundary.yml") + + template = templatefile("${path.module}/assets/cloudformation/default-boundary.yml", { + actions = var.enforcable_tagging_actions + enable_tagging_enforcement = var.enable_tag_enforcement + resources = var.enforcable_tagging_resources + tags = var.enforcable_tags + }) providers = { aws = aws.management @@ -45,7 +51,37 @@ module "permissive_boundary" { parameters = local.boundary_permissive_stack_parameters region = local.region tags = var.tags - template = file("${path.module}/assets/cloudformation/permissive-boundary.yml") + + template = templatefile("${path.module}/assets/cloudformation/permissive-boundary.yml", { + actions = var.enforcable_tagging_actions + enable_tagging_enforcement = var.enable_tag_enforcement + resources = var.enforcable_tagging_resources + tags = var.enforcable_tags + }) + + providers = { + aws = aws.management + } +} + +# tfsec:ignore:aws-iam-no-policy-wildcards +module "tagging_boundary" { + count = var.enable_tag_enforcement ? 1 : 0 + source = "appvia/boundary-stack/aws" + version = "0.1.7" + + description = "Used to deploy the tagging boundary policy, used by human roles" + enable_management_account = true + name = local.boundary_tagging_stack_name + parameters = local.boundary_tagging_stack_parameters + region = local.region + tags = var.tags + + template = templatefile("${path.module}/assets/cloudformation/tagging-boundary.yml", { + actions = var.enforcable_tagging_actions + resources = var.enforcable_tagging_resources + tags = var.enforcable_tags + }) providers = { aws = aws.management diff --git a/examples/basic/README.md b/examples/basic/README.md index 7271f77..e4e0e03 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -24,7 +24,7 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [aws\_accounts](#input\_aws\_accounts) | Map of AWS account names to their account IDs | `map(string)` |
{
"management": "123456789012",
"network": "123456789012"
}
| no | +| [aws\_accounts](#input\_aws\_accounts) | Map of AWS account names to their account IDs | `map(string)` |
{
"management": "123456789012",
"network": "123456789012"
}
| no | | [region](#input\_region) | AWS Region to deploy resources in | `string` | `"us-west-2"` | no | | [tags](#input\_tags) | Tags to apply to all resources | `map(string)` | `{}` | no | diff --git a/locals.tf b/locals.tf index 5217c2f..380f4b3 100644 --- a/locals.tf +++ b/locals.tf @@ -43,6 +43,13 @@ locals { } + # Is the stack name of the tagging enforcement iam boundary + boundary_tagging_stack_name = "LZA-IAM-TaggingBoundary" + # The parameters for the tagging enforcement boundary_tagging_stack_name + boundary_tagging_stack_parameters = { + "BoundaryName" = var.enforcable_tagging_policy_name + } + ## The name of the identity stack identity_stack_name = "LZA-Identity-Permissions" ## The capabilities required for the identity stack diff --git a/variables.tf b/variables.tf index 087873d..082c4e8 100644 --- a/variables.tf +++ b/variables.tf @@ -36,6 +36,63 @@ variable "enable_securityhub_alarms" { default = true } +variable "enable_tag_enforcement" { + description = "Indicates if we should enable tagging enforcement" + type = bool + default = false +} + +variable "enforcable_tags" { + description = "List of enforceable tags" + type = list(string) + default = [] +} + +variable "enforcable_tagging_policy_name" { + description = "Name of the IAM policy to use as a permissions boundary for enforceable tags" + type = string + default = "lza-enforceable-tags-boundary" +} + +variable "enforcable_tagging_resources" { + description = "List of enforceable tagging resources" + type = list(string) + default = ["*"] +} + +variable "enforcable_tagging_actions" { + description = "List of enforceable tagging actions" + type = list(string) + default = [ + "ec2:CreateInternetGateway", + "ec2:CreateVolume", + "ec2:CreateVpcPeeringConnection", + "ec2:RunInstances", + "ecs:CreateCluster", + "ecs:CreateService", + "ecs:CreateTaskSet", + "eks:CreateCluster", + "elasticfilesystem:CreateAccessPoint", + "elasticfilesystem:CreateFileSystem", + "elasticloadbalancing:CreateListener", + "elasticloadbalancing:CreateLoadBalancer", + "elasticloadbalancing:CreateRule", + "elasticloadbalancing:CreateTargetGroup", + "elasticloadbalancing:CreateTrustStore", + "network-firewall:CreateFirewall", + "network-firewall:CreateFirewallPolicy", + "network-firewall:CreateRuleGroup", + "ram:CreatePermission", + "ram:CreateResourceShare", + "redshift:CreateCluster", + "redshift:CreateClusterParameterGroup", + "redshift:CreateClusterSecurityGroup", + "redshift:CreateClusterSubnetGroup", + "route53:CreateHostedZone", + "secretsmanager:CreateSecret", + ] +} + variable "securityhub_sns_topic_name" { description = "Name of the SNS topic to send Security Hub findings to" type = string