├── .gitignore ├── .header.md ├── .pre-commit-config.yaml ├── .terraform-docs.yaml ├── .tfsec.yaml ├── .tfsec ├── launch_configuration_imdsv2_tfchecks.json ├── launch_template_imdsv2_tfchecks.json ├── no_launch_config_tfchecks.json ├── sg_no_embedded_egress_rules_tfchecks.json └── sg_no_embedded_ingress_rules_tfchecks.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE.txt ├── README.md ├── docs ├── Architectures-SecurityHub_Org.png └── Architectures-SecurityHub_Standalone.png ├── main.tf ├── modules ├── organizations_admin │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── organizations_member │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── outputs.tf ├── tests ├── organizations │ ├── complete │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ ├── delegated_admin │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf │ └── member_only │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── variables.tf │ │ └── versions.tf └── standalone │ ├── complete │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf │ └── quickstart │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── variables.tf └── versions.tf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | .build 4 | *.vscode 5 | 6 | # mkdocs documentation 7 | /site 8 | 9 | # Local .terraform directories 10 | **/.terraform/* 11 | 12 | # Terraform lockfile 13 | .terraform.lock.hcl 14 | 15 | # .tfstate files 16 | *.tfstate 17 | *.tfstate.* 18 | *.tfplan 19 | 20 | # Crash log files 21 | crash.log 22 | 23 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as 24 | # password, private keys, and other secrets. These should not be part of version 25 | # control as they are data points which are potentially sensitive and subject 26 | # to change depending on the environment. 27 | *.tfvars 28 | 29 | # Ignore override files as they are usually used to override resources locally and so 30 | # are not checked in 31 | override.tf 32 | override.tf.json 33 | *_override.tf 34 | *_override.tf.json 35 | 36 | # Ignore CLI configuration files 37 | .terraformrc 38 | terraform.rc 39 | 40 | # TFSec files 41 | .tfsec 42 | 43 | # local env 44 | *.envrc 45 | *kube-config.yaml 46 | -------------------------------------------------------------------------------- /.header.md: -------------------------------------------------------------------------------- 1 | # Terraform Module for AWS Security Hub 2 | 3 | Terraform module that creates AWS Security Hub resources. 4 | 5 | - [Terraform Module for AWS Security Hub](#terraform-module-for-aws-security-hub) 6 | - [Usage](#usage) 7 | - [Standalone](#standalone) 8 | - [Organizations](#organizations) 9 | - [Overview Diagrams](#overview-diagrams) 10 | - [Standalone](#standalone-1) 11 | - [Organizations](#organizations-1) 12 | - [Terraform Module](#terraform-module) 13 | 14 | 15 | ## Usage 16 | 17 | ### Standalone 18 | 19 | ```hcl 20 | module "security_hub" { 21 | source = "../../../" 22 | 23 | enable_default_standards = false 24 | control_finding_generator = "STANDARD_CONTROL" 25 | auto_enable_controls = true 26 | 27 | product_config = [{ 28 | enable = true 29 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 30 | }] 31 | 32 | standards_config = { 33 | aws_foundational_security_best_practices = { 34 | enable = true 35 | status = "ENABLED" 36 | } 37 | cis_aws_foundations_benchmark_v120 = { 38 | enable = false 39 | } 40 | cis_aws_foundations_benchmark_v140 = { 41 | enable = true 42 | status = "ENABLED" 43 | } 44 | nist_sp_800_53_rev5 = { 45 | enable = false 46 | } 47 | pci_dss = { 48 | enable = false 49 | } 50 | } 51 | 52 | action_target = [{ 53 | name = "Send to Amazon SNS" 54 | identifier = "SendToSNS" 55 | description = "This is a custom action to send findings to SNS Topic" 56 | }] 57 | 58 | } 59 | 60 | resource "aws_securityhub_standards_control" "ensure_iam_password_policy_prevents_password_reuse" { 61 | standards_control_arn = "arn:aws:securityhub:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:control/cis-aws-foundations-benchmark/v/1.4.0/1.10" 62 | control_status = "DISABLED" 63 | disabled_reason = "Password policies are managed by external resource" 64 | 65 | depends_on = [module.security_hub] 66 | } 67 | 68 | resource "aws_securityhub_insight" "this" { 69 | filters { 70 | created_at { 71 | date_range { 72 | unit = "DAYS" 73 | value = 7 74 | } 75 | } 76 | network_source_ipv4 { 77 | cidr = "10.0.0.0/16" 78 | } 79 | criticality { 80 | gte = "80" 81 | } 82 | resource_tags { 83 | comparison = "EQUALS" 84 | key = "Environment" 85 | value = "Development" 86 | } 87 | } 88 | 89 | group_by_attribute = "AwsAccountId" 90 | 91 | name = "insight" 92 | 93 | depends_on = [module.standalone_security_hub] 94 | } 95 | ``` 96 | 97 | ### Organizations 98 | 99 | ```hcl 100 | module "delegated_admin" { 101 | source = "aws-ia/terraform-aws-security-hub/aws//modules/organizations_admin/" 102 | 103 | admin_account_id = data.aws_caller_identity.current.account_id 104 | auto_enable_standards = "DEFAULT" 105 | 106 | depends_on = [module.security_hub] 107 | } 108 | 109 | module "member_account" { 110 | source = "aws-ia/terraform-aws-security-hub/aws//modules/organizations_member/" 111 | 112 | providers = { 113 | aws = aws 114 | aws.member = aws.member 115 | } 116 | 117 | member_config = [{ 118 | account_id = "281190191734" 119 | email = "required@example.com" 120 | invite = false 121 | }] 122 | 123 | depends_on = [module.security_hub] 124 | } 125 | 126 | module "security_hub" { 127 | source = "aws-ia/terraform-aws-security-hub" 128 | 129 | enable_default_standards = false 130 | control_finding_generator = "STANDARD_CONTROL" 131 | auto_enable_controls = true 132 | 133 | product_config = [{ 134 | enable = true 135 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 136 | }] 137 | 138 | standards_config = { 139 | aws_foundational_security_best_practices = { 140 | enable = true 141 | status = "ENABLED" 142 | } 143 | cis_aws_foundations_benchmark_v120 = { 144 | enable = false 145 | } 146 | cis_aws_foundations_benchmark_v140 = { 147 | enable = true 148 | status = "ENABLED" 149 | } 150 | nist_sp_800_53_rev5 = { 151 | enable = false 152 | } 153 | pci_dss = { 154 | enable = false 155 | } 156 | } 157 | 158 | action_target = [{ 159 | name = "Send to Amazon SNS" 160 | identifier = "SendToSNS" 161 | description = "This is a custom action to send findings to SNS Topic" 162 | }] 163 | } 164 | 165 | resource "aws_securityhub_insight" "this" { 166 | filters { 167 | aws_account_id { 168 | comparison = "EQUALS" 169 | value = "123456789012" 170 | } 171 | aws_account_id { 172 | comparison = "EQUALS" 173 | value = "098765432109" 174 | } 175 | created_at { 176 | date_range { 177 | unit = "DAYS" 178 | value = 7 179 | } 180 | } 181 | network_source_ipv4 { 182 | cidr = "10.0.0.0/16" 183 | } 184 | criticality { 185 | gte = "80" 186 | } 187 | resource_tags { 188 | comparison = "EQUALS" 189 | key = "Environment" 190 | value = "Development" 191 | } 192 | } 193 | 194 | group_by_attribute = "AwsAccountId" 195 | 196 | name = "insight-per-account-id" 197 | 198 | depends_on = [module.security_hub] 199 | } 200 | ``` 201 | 202 | ## Overview Diagrams 203 | 204 | ### Standalone 205 | 206 | ![standalone-diagram](./docs/Architectures-SecurityHub_Standalone.png) 207 | 208 | ### Organizations 209 | 210 | ![organizations-diagram](./docs/Architectures-SecurityHub_Org.png) 211 | 212 | ## Terraform Module 213 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.4.0 4 | hooks: 5 | - id: trailing-whitespace 6 | args: ['--markdown-linebreak-ext=md'] 7 | - id: end-of-file-fixer 8 | - id: check-merge-conflict 9 | - id: detect-private-key 10 | - id: detect-aws-credentials 11 | args: ['--allow-missing-credentials'] 12 | - repo: https://github.com/antonbabenko/pre-commit-terraform 13 | rev: v1.81.0 14 | hooks: 15 | - id: terraform_fmt 16 | - id: terraform_docs 17 | args: 18 | - '--args=--lockfile=false' 19 | - id: terraform_tflint 20 | args: 21 | - '--args=--only=terraform_deprecated_interpolation' 22 | - '--args=--only=terraform_deprecated_index' 23 | - '--args=--only=terraform_unused_declarations' 24 | - '--args=--only=terraform_comment_syntax' 25 | - '--args=--only=terraform_documented_outputs' 26 | - '--args=--only=terraform_documented_variables' 27 | - '--args=--only=terraform_typed_variables' 28 | - '--args=--only=terraform_module_pinned_source' 29 | - '--args=--only=terraform_naming_convention' 30 | - '--args=--only=terraform_required_version' 31 | - '--args=--only=terraform_required_providers' 32 | - '--args=--only=terraform_standard_module_structure' 33 | - '--args=--only=terraform_workspace_remote' 34 | - id: terraform_validate 35 | exclude: docs 36 | exclude: modules/organizations_member 37 | - id: terraform_tfsec 38 | args: 39 | - --args=--config-file=__GIT_WORKING_DIR__/.tfsec.yaml 40 | - --args=--concise-output 41 | - id: terraform_checkov 42 | -------------------------------------------------------------------------------- /.terraform-docs.yaml: -------------------------------------------------------------------------------- 1 | formatter: markdown 2 | header-from: .header.md 3 | settings: 4 | anchor: true 5 | color: true 6 | default: true 7 | escape: true 8 | html: true 9 | indent: 3 10 | required: true 11 | sensitive: true 12 | type: true 13 | lockfile: false 14 | footer: true 15 | 16 | sort: 17 | enabled: true 18 | by: required 19 | 20 | output: 21 | file: README.md 22 | mode: replace 23 | template: |- 24 | {{ .Content }} 25 | {{- printf "\n" -}} 26 | -------------------------------------------------------------------------------- /.tfsec.yaml: -------------------------------------------------------------------------------- 1 | exclude: 2 | -------------------------------------------------------------------------------- /.tfsec/launch_configuration_imdsv2_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS002", 5 | "description": "Check to IMDSv2 is required on EC2 instances created by this Launch Template", 6 | "impact": "Instance metadata service can be interacted with freely", 7 | "resolution": "Enable HTTP token requirement for IMDS", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_configuration" 13 | ], 14 | "severity": "CRITICAL", 15 | "matchSpec": { 16 | "action": "isPresent", 17 | "name": "metadata_options", 18 | "subMatch": { 19 | "action": "and", 20 | "predicateMatchSpec": [ 21 | { 22 | "action": "equals", 23 | "name": "http_tokens", 24 | "value": "required" 25 | 26 | } 27 | ] 28 | } 29 | }, 30 | 31 | "errorMessage": "is missing `metadata_options` block - it is required with `http_tokens` set to `required` to make Instance Metadata Service more secure.", 32 | "relatedLinks": [ 33 | "https://tfsec.dev/docs/aws/ec2/enforce-http-token-imds#aws/ec2", 34 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_configuration#metadata-options", 35 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.tfsec/launch_template_imdsv2_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS001", 5 | "description": "Check to IMDSv2 is required on EC2 instances created by this Launch Template", 6 | "impact": "Instance metadata service can be interacted with freely", 7 | "resolution": "Enable HTTP token requirement for IMDS", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_template" 13 | ], 14 | "severity": "CRITICAL", 15 | "matchSpec": { 16 | "action": "isPresent", 17 | "name": "metadata_options", 18 | "subMatch": { 19 | "action": "and", 20 | "predicateMatchSpec": [ 21 | { 22 | "action": "equals", 23 | "name": "http_tokens", 24 | "value": "required" 25 | 26 | } 27 | ] 28 | } 29 | }, 30 | 31 | "errorMessage": "is missing `metadata_options` block - it is required with `http_tokens` set to `required` to make Instance Metadata Service more secure.", 32 | "relatedLinks": [ 33 | "https://tfsec.dev/docs/aws/ec2/enforce-http-token-imds#aws/ec2", 34 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#metadata-options", 35 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.tfsec/no_launch_config_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS003", 5 | "description": "Use `aws_launch_template` over `aws_launch_configuration", 6 | "impact": "Launch configurations are not capable of versions", 7 | "resolution": "Convert resource type and attributes to `aws_launch_template`", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_launch_configuration" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "image_id" 18 | }, 19 | 20 | "errorMessage": "should be changed to `aws_launch_template` since the functionality is the same but templates can be versioned.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template", 23 | "https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.tfsec/sg_no_embedded_egress_rules_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS005", 5 | "description": "Security group rules should be defined with `aws_security_group_rule` instead of embedded.", 6 | "impact": "Embedded security group rules can cause issues during configuration updates.", 7 | "resolution": "Move `egress` rules to `aws_security_group_rule` and attach to `aws_security_group`.", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_security_group" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "egress" 18 | }, 19 | 20 | "errorMessage": "`egress` rules should be moved to `aws_security_group_rule` and attached to `aws_security_group` instead of embedded.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule", 23 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /.tfsec/sg_no_embedded_ingress_rules_tfchecks.json: -------------------------------------------------------------------------------- 1 | { 2 | "checks": [ 3 | { 4 | "code": "CUS004", 5 | "description": "Security group rules should be defined with `aws_security_group_rule` instead of embedded.", 6 | "impact": "Embedded security group rules can cause issues during configuration updates.", 7 | "resolution": "Move `ingress` rules to `aws_security_group_rule` and attach to `aws_security_group`.", 8 | "requiredTypes": [ 9 | "resource" 10 | ], 11 | "requiredLabels": [ 12 | "aws_security_group" 13 | ], 14 | "severity": "MEDIUM", 15 | "matchSpec": { 16 | "action": "notPresent", 17 | "name": "ingress" 18 | }, 19 | 20 | "errorMessage": "`ingress` rules should be moved to `aws_security_group_rule` and attached to `aws_security_group` instead of embedded.", 21 | "relatedLinks": [ 22 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule", 23 | "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group" 24 | ] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | ## Reporting Bugs/Feature Requests 10 | 11 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 12 | 13 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 14 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 15 | 16 | - A reproducible test case or series of steps 17 | - The version of our code being used 18 | - Any modifications you've made relevant to the bug 19 | - Anything unusual about your environment or deployment 20 | 21 | ## Contributing via Pull Requests 22 | 23 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 24 | 25 | 1. You are working against the latest source on the _main_ branch. 26 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 27 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 28 | 29 | To send us a pull request, please: 30 | 31 | 1. Fork the repository. 32 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 33 | 3. Ensure local tests pass. 34 | 4. Commit to your fork using clear commit messages. 35 | 5. Send us a pull request, answering any default questions in the pull request interface. 36 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 37 | 38 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 39 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 40 | 41 | ## Finding contributions to work on 42 | 43 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 44 | 45 | ## Code of Conduct 46 | 47 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 48 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 49 | opensource-codeofconduct@amazon.com with any additional questions or comments. 50 | 51 | ## Security issue notifications 52 | 53 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 54 | 55 | ## Licensing 56 | 57 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2023 Amazon Web Services, Inc 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at 4 | 5 | http://aws.amazon.com/apache2.0/ 6 | 7 | or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Module for AWS Security Hub 2 | 3 | Terraform module that creates AWS Security Hub resources. 4 | 5 | - [Terraform Module for AWS Security Hub](#terraform-module-for-aws-security-hub) 6 | - [Usage](#usage) 7 | - [Standalone](#standalone) 8 | - [Organizations](#organizations) 9 | - [Overview Diagrams](#overview-diagrams) 10 | - [Standalone](#standalone-1) 11 | - [Organizations](#organizations-1) 12 | - [Terraform Module](#terraform-module) 13 | 14 | ## Usage 15 | 16 | ### Standalone 17 | 18 | ```hcl 19 | module "security_hub" { 20 | source = "../../../" 21 | 22 | enable_default_standards = false 23 | control_finding_generator = "STANDARD_CONTROL" 24 | auto_enable_controls = true 25 | 26 | product_config = [{ 27 | enable = true 28 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 29 | }] 30 | 31 | standards_config = { 32 | aws_foundational_security_best_practices = { 33 | enable = true 34 | status = "ENABLED" 35 | } 36 | cis_aws_foundations_benchmark_v120 = { 37 | enable = false 38 | } 39 | cis_aws_foundations_benchmark_v140 = { 40 | enable = true 41 | status = "ENABLED" 42 | } 43 | nist_sp_800_53_rev5 = { 44 | enable = false 45 | } 46 | pci_dss = { 47 | enable = false 48 | } 49 | } 50 | 51 | action_target = [{ 52 | name = "Send to Amazon SNS" 53 | identifier = "SendToSNS" 54 | description = "This is a custom action to send findings to SNS Topic" 55 | }] 56 | 57 | } 58 | 59 | resource "aws_securityhub_standards_control" "ensure_iam_password_policy_prevents_password_reuse" { 60 | standards_control_arn = "arn:aws:securityhub:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:control/cis-aws-foundations-benchmark/v/1.4.0/1.10" 61 | control_status = "DISABLED" 62 | disabled_reason = "Password policies are managed by external resource" 63 | 64 | depends_on = [module.security_hub] 65 | } 66 | 67 | resource "aws_securityhub_insight" "this" { 68 | filters { 69 | created_at { 70 | date_range { 71 | unit = "DAYS" 72 | value = 7 73 | } 74 | } 75 | network_source_ipv4 { 76 | cidr = "10.0.0.0/16" 77 | } 78 | criticality { 79 | gte = "80" 80 | } 81 | resource_tags { 82 | comparison = "EQUALS" 83 | key = "Environment" 84 | value = "Development" 85 | } 86 | } 87 | 88 | group_by_attribute = "AwsAccountId" 89 | 90 | name = "insight" 91 | 92 | depends_on = [module.standalone_security_hub] 93 | } 94 | ``` 95 | 96 | ### Organizations 97 | 98 | ```hcl 99 | module "delegated_admin" { 100 | source = "aws-ia/terraform-aws-security-hub/aws//modules/organizations_admin/" 101 | 102 | admin_account_id = data.aws_caller_identity.current.account_id 103 | auto_enable_standards = "DEFAULT" 104 | 105 | depends_on = [module.security_hub] 106 | } 107 | 108 | module "member_account" { 109 | source = "aws-ia/terraform-aws-security-hub/aws//modules/organizations_member/" 110 | 111 | providers = { 112 | aws = aws 113 | aws.member = aws.member 114 | } 115 | 116 | member_config = [{ 117 | account_id = "281190191734" 118 | email = "required@example.com" 119 | invite = false 120 | }] 121 | 122 | depends_on = [module.security_hub] 123 | } 124 | 125 | module "security_hub" { 126 | source = "aws-ia/terraform-aws-security-hub" 127 | 128 | enable_default_standards = false 129 | control_finding_generator = "STANDARD_CONTROL" 130 | auto_enable_controls = true 131 | 132 | product_config = [{ 133 | enable = true 134 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 135 | }] 136 | 137 | standards_config = { 138 | aws_foundational_security_best_practices = { 139 | enable = true 140 | status = "ENABLED" 141 | } 142 | cis_aws_foundations_benchmark_v120 = { 143 | enable = false 144 | } 145 | cis_aws_foundations_benchmark_v140 = { 146 | enable = true 147 | status = "ENABLED" 148 | } 149 | nist_sp_800_53_rev5 = { 150 | enable = false 151 | } 152 | pci_dss = { 153 | enable = false 154 | } 155 | } 156 | 157 | action_target = [{ 158 | name = "Send to Amazon SNS" 159 | identifier = "SendToSNS" 160 | description = "This is a custom action to send findings to SNS Topic" 161 | }] 162 | } 163 | 164 | resource "aws_securityhub_insight" "this" { 165 | filters { 166 | aws_account_id { 167 | comparison = "EQUALS" 168 | value = "123456789012" 169 | } 170 | aws_account_id { 171 | comparison = "EQUALS" 172 | value = "098765432109" 173 | } 174 | created_at { 175 | date_range { 176 | unit = "DAYS" 177 | value = 7 178 | } 179 | } 180 | network_source_ipv4 { 181 | cidr = "10.0.0.0/16" 182 | } 183 | criticality { 184 | gte = "80" 185 | } 186 | resource_tags { 187 | comparison = "EQUALS" 188 | key = "Environment" 189 | value = "Development" 190 | } 191 | } 192 | 193 | group_by_attribute = "AwsAccountId" 194 | 195 | name = "insight-per-account-id" 196 | 197 | depends_on = [module.security_hub] 198 | } 199 | ``` 200 | 201 | ## Overview Diagrams 202 | 203 | ### Standalone 204 | 205 | ![standalone-diagram](./docs/Architectures-SecurityHub\_Standalone.png) 206 | 207 | ### Organizations 208 | 209 | ![organizations-diagram](./docs/Architectures-SecurityHub\_Org.png) 210 | 211 | ## Terraform Module 212 | 213 | ### Requirements 214 | 215 | | Name | Version | 216 | |------|---------| 217 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 218 | | [aws](#requirement\_aws) | >= 4.47 | 219 | | [time](#requirement\_time) | >= 0.9 | 220 | 221 | ### Providers 222 | 223 | | Name | Version | 224 | |------|---------| 225 | | [aws](#provider\_aws) | >= 4.47 | 226 | | [time](#provider\_time) | >= 0.9 | 227 | 228 | ### Modules 229 | 230 | No modules. 231 | 232 | ### Resources 233 | 234 | | Name | Type | 235 | |------|------| 236 | | [aws_securityhub_account.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_account) | resource | 237 | | [aws_securityhub_action_target.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_action_target) | resource | 238 | | [aws_securityhub_finding_aggregator.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_finding_aggregator) | resource | 239 | | [aws_securityhub_product_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_product_subscription) | resource | 240 | | [aws_securityhub_standards_subscription.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_standards_subscription) | resource | 241 | | [time_sleep.wait_securityhub_enable](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | 242 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 243 | 244 | ### Inputs 245 | 246 | | Name | Description | Type | Default | Required | 247 | |------|-------------|------|---------|:--------:| 248 | | [action\_target](#input\_action\_target) | Creates Security Hub custom action.
`name` - The description for the custom action target.
`identifier` - The ID for the custom action target.
`description` - The name of the custom action target. |
list(object({
name = string
identifier = string
description = string
}))
| `[]` | no | 249 | | [auto\_enable\_controls](#input\_auto\_enable\_controls) | Whether to automatically enable new controls when they are added to standards that are enabled. By default, this is set to true, and new controls are enabled automatically. To not automatically enable new controls, set this to false. | `bool` | `true` | no | 250 | | [control\_finding\_generator](#input\_control\_finding\_generator) | Updates whether the calling account has consolidated control findings turned on. If the value for this field is set to SECURITY\_CONTROL, Security Hub generates a single finding for a control check even when the check applies to multiple enabled standards. If the value for this field is set to STANDARD\_CONTROL, Security Hub generates separate findings for a control check when the check applies to multiple enabled standards. For accounts that are part of an organization, this value can only be updated in the administrator account. | `string` | `"STANDARD_CONTROL"` | no | 251 | | [enable\_default\_standards](#input\_enable\_default\_standards) | Whether to enable the security standards that Security Hub has designated as automatically enabled including: AWS Foundational Security Best Practices v1.0.0 and CIS AWS Foundations Benchmark v1.2.0. Defaults to `true`. | `bool` | `true` | no | 252 | | [linking\_mode](#input\_linking\_mode) | Indicates whether to aggregate findings from all of the available Regions or from a specified list. The options are ALL\_REGIONS, ALL\_REGIONS\_EXCEPT\_SPECIFIED or SPECIFIED\_REGIONS. When ALL\_REGIONS or ALL\_REGIONS\_EXCEPT\_SPECIFIED are used, Security Hub will automatically aggregate findings from new Regions as Security Hub supports them and you opt into them. | `string` | `"ALL_REGIONS"` | no | 253 | | [product\_config](#input\_product\_config) | The ARN of the product that generates findings that you want to import into Security Hub. |
list(object({
enable = bool
arn = string
}))
| `null` | no | 254 | | [specified\_regions](#input\_specified\_regions) | List of regions to include or exclude (required if linking\_mode is set to ALL\_REGIONS\_EXCEPT\_SPECIFIED or SPECIFIED\_REGIONS) | `list(string)` | `null` | no | 255 | | [standards\_config](#input\_standards\_config) | `aws_foundational_security_best_practices` - AWS Foundational Security Best Practices
`cis_aws_foundations_benchmark_v120` - CIS AWS Foundations Benchmark v1.2.0
`cis_aws_foundations_benchmark_v140` - CIS AWS Foundations Benchmark v1.4.0
`nist_sp_800_53_rev5` - NIST SP 800-53 Rev. 5
`pci_dss` - PCI DSS |
object({
aws_foundational_security_best_practices = object({
enable = bool
status = optional(string)
disabled_reason = optional(string)
})
cis_aws_foundations_benchmark_v120 = object({
enable = bool
status = optional(string)
disabled_reason = optional(string)
})
cis_aws_foundations_benchmark_v140 = object({
enable = bool
status = optional(string)
disabled_reason = optional(string)
})
nist_sp_800_53_rev5 = object({
enable = bool
status = optional(string)
disabled_reason = optional(string)
})
pci_dss = object({
enable = bool
status = optional(string)
disabled_reason = optional(string)
})
})
|
{
"aws_foundational_security_best_practices": {
"enable": true,
"status": "ENABLED"
},
"cis_aws_foundations_benchmark_v120": {
"enable": true,
"status": "ENABLED"
},
"cis_aws_foundations_benchmark_v140": {
"enable": false
},
"nist_sp_800_53_rev5": {
"enable": false
},
"pci_dss": {
"enable": false
}
}
| no | 256 | 257 | ### Outputs 258 | 259 | | Name | Description | 260 | |------|-------------| 261 | | [action\_target](#output\_action\_target) | Security Hub custome action targets. | 262 | | [finding\_aggregator](#output\_finding\_aggregator) | Security Hub finding aggregator configuration. | 263 | | [product\_subscription](#output\_product\_subscription) | Security Hub products subscriptions. | 264 | | [securityhub\_account](#output\_securityhub\_account) | Security Hub AWS account configuration. | 265 | | [standards\_subscription](#output\_standards\_subscription) | Security Hub compliance standards subscriptions. | 266 | -------------------------------------------------------------------------------- /docs/Architectures-SecurityHub_Org.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/docs/Architectures-SecurityHub_Org.png -------------------------------------------------------------------------------- /docs/Architectures-SecurityHub_Standalone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/docs/Architectures-SecurityHub_Standalone.png -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | data "aws_region" "current" {} 2 | 3 | locals { 4 | standards_subscription = { 5 | aws_foundational_security_best_practices = var.standards_config != null ? merge(var.standards_config.aws_foundational_security_best_practices, 6 | { 7 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::standards/aws-foundational-security-best-practices/v/1.0.0" 8 | }) : null 9 | cis_aws_foundations_benchmark_v120 = var.standards_config != null ? merge(var.standards_config.cis_aws_foundations_benchmark_v120, 10 | { 11 | arn = "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0" 12 | }) : null 13 | cis_aws_foundations_benchmark_v140 = var.standards_config != null ? merge(var.standards_config.cis_aws_foundations_benchmark_v140, 14 | { 15 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::standards/cis-aws-foundations-benchmark/v/1.4.0" 16 | }) : null 17 | nist_sp_800_53_rev5 = var.standards_config != null ? merge(var.standards_config.nist_sp_800_53_rev5, 18 | { 19 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::standards/nist-800-53/v/5.0.0" 20 | }) : null 21 | pci_dss = var.standards_config != null ? merge(var.standards_config.pci_dss, 22 | { 23 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::standards/pci-dss/v/3.2.1" 24 | }) : null 25 | } 26 | } 27 | 28 | ################################################## 29 | # Security Hub 30 | ################################################## 31 | resource "aws_securityhub_account" "this" { 32 | enable_default_standards = var.enable_default_standards 33 | control_finding_generator = var.control_finding_generator 34 | auto_enable_controls = var.auto_enable_controls 35 | } 36 | 37 | resource "time_sleep" "wait_securityhub_enable" { 38 | 39 | create_duration = "10s" 40 | 41 | depends_on = [aws_securityhub_account.this] 42 | } 43 | 44 | resource "aws_securityhub_finding_aggregator" "this" { 45 | linking_mode = var.linking_mode 46 | specified_regions = var.specified_regions 47 | 48 | depends_on = [time_sleep.wait_securityhub_enable] 49 | } 50 | 51 | ################################################## 52 | # Security Hub Subscriptions 53 | ################################################## 54 | resource "aws_securityhub_product_subscription" "this" { 55 | for_each = var.product_config != null ? { for product in var.product_config : product.arn => product } : {} 56 | product_arn = each.value.arn 57 | 58 | depends_on = [time_sleep.wait_securityhub_enable] 59 | } 60 | 61 | resource "aws_securityhub_standards_subscription" "this" { 62 | for_each = var.standards_config != null ? { for standards in local.standards_subscription : standards.arn => standards if standards.enable } : {} 63 | 64 | standards_arn = each.value.arn 65 | 66 | depends_on = [time_sleep.wait_securityhub_enable] 67 | } 68 | 69 | ################################################## 70 | # Security Hub Action Targets 71 | ################################################## 72 | resource "aws_securityhub_action_target" "this" { 73 | for_each = var.action_target != null ? { for target in var.action_target : target.identifier => target } : {} 74 | 75 | name = each.value.name 76 | identifier = each.value.identifier 77 | description = each.value.description 78 | 79 | depends_on = [time_sleep.wait_securityhub_enable] 80 | } 81 | -------------------------------------------------------------------------------- /modules/organizations_admin/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | 5.5.0 | 13 | 14 | ## Modules 15 | 16 | No modules. 17 | 18 | ## Resources 19 | 20 | | Name | Type | 21 | |------|------| 22 | | [aws_securityhub_organization_admin_account.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_organization_admin_account) | resource | 23 | | [aws_securityhub_organization_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_organization_configuration) | resource | 24 | 25 | ## Inputs 26 | 27 | | Name | Description | Type | Default | Required | 28 | |------|-------------|------|---------|:--------:| 29 | | [admin\_account\_id](#input\_admin\_account\_id) | AWS Organizations Admin Account Id. Defaults to `null` | `string` | `null` | no | 30 | | [auto\_enable\_standards](#input\_auto\_enable\_standards) | Automatically enable Security Hub default standards for new member accounts in the organization. To opt-out of enabling default standards, set to `NONE`. Defaults to `DEFAULT`. | `string` | `"DEFAULT"` | no | 31 | 32 | ## Outputs 33 | 34 | | Name | Description | 35 | |------|-------------| 36 | | [securityhub\_delegated\_admin\_account](#output\_securityhub\_delegated\_admin\_account) | AWS Security Hub Delegated Admin account. | 37 | | [securityhub\_organization\_configuration](#output\_securityhub\_organization\_configuration) | AWS Security Hub Organizations configuration. | 38 | -------------------------------------------------------------------------------- /modules/organizations_admin/main.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Delegated Admin 3 | ################################################## 4 | resource "aws_securityhub_organization_admin_account" "this" { 5 | count = var.admin_account_id == null ? 0 : 1 6 | admin_account_id = var.admin_account_id 7 | } 8 | 9 | resource "aws_securityhub_organization_configuration" "this" { 10 | auto_enable = true 11 | auto_enable_standards = var.auto_enable_standards 12 | 13 | depends_on = [aws_securityhub_organization_admin_account.this] 14 | } 15 | -------------------------------------------------------------------------------- /modules/organizations_admin/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Delegated Admin 3 | ################################################## 4 | output "securityhub_delegated_admin_account" { 5 | description = "AWS Security Hub Delegated Admin account." 6 | value = aws_securityhub_organization_admin_account.this 7 | } 8 | 9 | output "securityhub_organization_configuration" { 10 | description = "AWS Security Hub Organizations configuration." 11 | value = aws_securityhub_organization_configuration.this 12 | } 13 | -------------------------------------------------------------------------------- /modules/organizations_admin/variables.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Delegated Admin 3 | ################################################## 4 | variable "admin_account_id" { 5 | description = "AWS Organizations Admin Account Id. Defaults to `null`" 6 | type = string 7 | default = null 8 | } 9 | 10 | variable "auto_enable_standards" { 11 | description = "Automatically enable Security Hub default standards for new member accounts in the organization. To opt-out of enabling default standards, set to `NONE`. Defaults to `DEFAULT`." 12 | type = string 13 | default = "DEFAULT" 14 | } 15 | -------------------------------------------------------------------------------- /modules/organizations_admin/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /modules/organizations_member/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | >= 4.47 | 13 | | [aws.member](#provider\_aws.member) | >= 4.47 | 14 | 15 | ## Modules 16 | 17 | No modules. 18 | 19 | ## Resources 20 | 21 | | Name | Type | 22 | |------|------| 23 | | [aws_securityhub_account.member](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_account) | resource | 24 | | [aws_securityhub_invite_accepter.member](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_invite_accepter) | resource | 25 | | [aws_securityhub_member.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_member) | resource | 26 | 27 | ## Inputs 28 | 29 | | Name | Description | Type | Default | Required | 30 | |------|-------------|------|---------|:--------:| 31 | | [member\_config](#input\_member\_config) | Specifies the member account configuration:
`account_id` - The 13 digit ID number of the member account. Example: `123456789012`.
`email` - Email address to send the invite for member account. Defaults to `null`.
`invite` - Whether to invite the account to SecurityHub as a member. Defaults to `false`. To detect if an invitation needs to be (re-)sent, the Terraform state value is true based on a `member_status` of `Disabled` \| `Enabled` \| `Invited` \| EmailVerificationInProgress. |
list(object({
account_id = number
email = string
invite = bool
}))
| `null` | no | 32 | 33 | ## Outputs 34 | 35 | | Name | Description | 36 | |------|-------------| 37 | | [securityhub\_member](#output\_securityhub\_member) | AWS Security Hub member configuration. | 38 | | [securityhub\_member\_account](#output\_securityhub\_member\_account) | AWS Security Hub member account configuration. | 39 | | [securityhub\_member\_invite](#output\_securityhub\_member\_invite) | AWS Security Hub organizations invite. | 40 | -------------------------------------------------------------------------------- /modules/organizations_member/main.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Account Member 3 | ################################################## 4 | resource "aws_securityhub_member" "this" { 5 | for_each = var.member_config != null ? { for member in var.member_config : member.account_id => member } : {} 6 | 7 | account_id = each.value.account_id 8 | email = each.value.email 9 | invite = each.value.invite 10 | } 11 | 12 | resource "aws_securityhub_account" "member" { 13 | for_each = var.member_config != null ? { for member in var.member_config : member.account_id => member } : {} 14 | provider = aws.member 15 | } 16 | 17 | ################################################## 18 | # Security Hub Invite 19 | ################################################## 20 | resource "aws_securityhub_invite_accepter" "member" { 21 | for_each = var.member_config != null ? { for member in var.member_config : member.account_id => member if member.invite } : {} 22 | provider = aws.member 23 | 24 | master_id = aws_securityhub_member.this[each.key].master_id 25 | 26 | depends_on = [aws_securityhub_account.member] 27 | } 28 | -------------------------------------------------------------------------------- /modules/organizations_member/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Account Member 3 | ################################################## 4 | output "securityhub_member" { 5 | description = "AWS Security Hub member configuration." 6 | value = aws_securityhub_member.this 7 | } 8 | 9 | output "securityhub_member_account" { 10 | description = "AWS Security Hub member account configuration." 11 | value = aws_securityhub_account.member 12 | } 13 | 14 | ################################################## 15 | # Security Hub Organizations Invite 16 | ################################################## 17 | output "securityhub_member_invite" { 18 | description = "AWS Security Hub organizations invite." 19 | value = aws_securityhub_invite_accepter.member 20 | } 21 | -------------------------------------------------------------------------------- /modules/organizations_member/variables.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub Account Member 3 | ################################################## 4 | variable "member_config" { 5 | description = < [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | 5.5.0 | 13 | 14 | ## Modules 15 | 16 | | Name | Source | Version | 17 | |------|--------|---------| 18 | | [delegated\_admin](#module\_delegated\_admin) | ../../../modules/organizations_admin/ | n/a | 19 | | [member\_account](#module\_member\_account) | ../../../modules/organizations_member/ | n/a | 20 | | [organizations\_security\_hub](#module\_organizations\_security\_hub) | ../../../ | n/a | 21 | 22 | ## Resources 23 | 24 | | Name | Type | 25 | |------|------| 26 | | [aws_securityhub_insight.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight) | resource | 27 | | [aws_securityhub_standards_control.ensure_iam_password_policy_prevents_password_reuse](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_standards_control) | resource | 28 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 29 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 30 | 31 | ## Inputs 32 | 33 | No inputs. 34 | 35 | ## Outputs 36 | 37 | | Name | Description | 38 | |------|-------------| 39 | | [delegated\_admin](#output\_delegated\_admin) | AWS Security Hub Delegated admin. | 40 | | [member](#output\_member) | Organizations account member AWS Security Hub. | 41 | | [organizations\_security\_hub](#output\_organizations\_security\_hub) | Organizations AWS Security Hub Configuration. | 42 | -------------------------------------------------------------------------------- /tests/organizations/complete/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | shared_config_files = ["~/.aws/config"] 3 | shared_credentials_files = ["~/.aws/credentials"] 4 | profile = "member" 5 | alias = "member" 6 | } 7 | 8 | data "aws_caller_identity" "current" {} 9 | 10 | data "aws_region" "current" {} 11 | 12 | module "delegated_admin" { 13 | source = "aws-ia/security-hub/aws//modules/organizations_admin" 14 | version = "0.0.1" 15 | 16 | admin_account_id = data.aws_caller_identity.current.account_id 17 | auto_enable_standards = "DEFAULT" 18 | 19 | depends_on = [module.organizations_security_hub] 20 | } 21 | 22 | module "member_account" { 23 | source = "aws-ia/security-hub/aws//modules/organizations_member" 24 | version = "0.0.1" 25 | 26 | providers = { 27 | aws = aws 28 | aws.member = aws.member 29 | } 30 | 31 | member_config = [{ 32 | account_id = "0123456789012" 33 | email = "required@example.com" 34 | invite = false 35 | }] 36 | 37 | depends_on = [module.delegated_admin] 38 | } 39 | 40 | module "organizations_security_hub" { 41 | source = "aws-ia/security-hub/aws" 42 | version = "0.0.1" 43 | 44 | enable_default_standards = false 45 | control_finding_generator = "STANDARD_CONTROL" 46 | auto_enable_controls = true 47 | 48 | product_config = [{ 49 | enable = true 50 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 51 | }] 52 | 53 | standards_config = { 54 | aws_foundational_security_best_practices = { 55 | enable = true 56 | status = "ENABLED" 57 | } 58 | cis_aws_foundations_benchmark_v120 = { 59 | enable = false 60 | } 61 | cis_aws_foundations_benchmark_v140 = { 62 | enable = true 63 | status = "ENABLED" 64 | } 65 | nist_sp_800_53_rev5 = { 66 | enable = false 67 | } 68 | pci_dss = { 69 | enable = false 70 | } 71 | } 72 | 73 | action_target = [{ 74 | name = "Send to Amazon SNS" 75 | identifier = "SendToSNS" 76 | description = "This is a custom action to send findings to SNS Topic" 77 | }] 78 | } 79 | 80 | # Security Hub Standards Control Example 81 | # Sample control findings https://docs.aws.amazon.com/securityhub/latest/userguide/sample-control-findings.html 82 | 83 | resource "aws_securityhub_standards_control" "ensure_iam_password_policy_prevents_password_reuse" { 84 | standards_control_arn = "arn:aws:securityhub:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:control/cis-aws-foundations-benchmark/v/1.4.0/1.10" 85 | control_status = "DISABLED" 86 | disabled_reason = "Password policies are managed by external resource" 87 | 88 | depends_on = [module.organizations_security_hub] 89 | } 90 | 91 | # Security Hub Insights Examples 92 | # Full list of filters https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight#filters 93 | 94 | resource "aws_securityhub_insight" "this" { 95 | filters { 96 | aws_account_id { 97 | comparison = "EQUALS" 98 | value = "123456789012" 99 | } 100 | aws_account_id { 101 | comparison = "EQUALS" 102 | value = "098765432109" 103 | } 104 | created_at { 105 | date_range { 106 | unit = "DAYS" 107 | value = 7 108 | } 109 | } 110 | network_source_ipv4 { 111 | cidr = "10.0.0.0/16" 112 | } 113 | criticality { 114 | gte = "80" 115 | } 116 | resource_tags { 117 | comparison = "EQUALS" 118 | key = "Environment" 119 | value = "Development" 120 | } 121 | } 122 | 123 | group_by_attribute = "AwsAccountId" 124 | 125 | name = "insight-per-account-id" 126 | 127 | depends_on = [module.organizations_security_hub] 128 | } 129 | -------------------------------------------------------------------------------- /tests/organizations/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | output "delegated_admin" { 2 | description = "AWS Security Hub Delegated admin." 3 | value = module.delegated_admin 4 | } 5 | 6 | output "organizations_security_hub" { 7 | description = "Organizations AWS Security Hub Configuration." 8 | value = module.organizations_security_hub 9 | } 10 | 11 | output "member" { 12 | description = "Organizations account member AWS Security Hub." 13 | value = module.member_account 14 | } 15 | -------------------------------------------------------------------------------- /tests/organizations/complete/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/tests/organizations/complete/variables.tf -------------------------------------------------------------------------------- /tests/organizations/complete/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | configuration_aliases = [ 9 | aws.member, 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/organizations/delegated_admin/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | 5.6.2 | 13 | 14 | ## Modules 15 | 16 | | Name | Source | Version | 17 | |------|--------|---------| 18 | | [delegated\_admin](#module\_delegated\_admin) | ../../../modules/organizations_admin/ | n/a | 19 | | [organizations\_security\_hub](#module\_organizations\_security\_hub) | ../../../ | n/a | 20 | 21 | ## Resources 22 | 23 | | Name | Type | 24 | |------|------| 25 | | [aws_securityhub_insight.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight) | resource | 26 | | [aws_securityhub_standards_control.ensure_iam_password_policy_prevents_password_reuse](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_standards_control) | resource | 27 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 28 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 29 | 30 | ## Inputs 31 | 32 | No inputs. 33 | 34 | ## Outputs 35 | 36 | | Name | Description | 37 | |------|-------------| 38 | | [delegated\_admin](#output\_delegated\_admin) | AWS Security Hub delegated admin | 39 | -------------------------------------------------------------------------------- /tests/organizations/delegated_admin/main.tf: -------------------------------------------------------------------------------- 1 | data "aws_caller_identity" "current" {} 2 | 3 | data "aws_region" "current" {} 4 | 5 | module "delegated_admin" { 6 | source = "aws-ia/security-hub/aws//modules/organizations_admin" 7 | version = "0.0.1" 8 | 9 | admin_account_id = data.aws_caller_identity.current.account_id 10 | auto_enable_standards = "DEFAULT" 11 | } 12 | 13 | module "organizations_security_hub" { 14 | source = "aws-ia/security-hub/aws" 15 | version = "0.0.1" 16 | 17 | enable_default_standards = false 18 | control_finding_generator = "STANDARD_CONTROL" 19 | auto_enable_controls = true 20 | 21 | product_config = [{ 22 | enable = true 23 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 24 | }] 25 | 26 | standards_config = { 27 | aws_foundational_security_best_practices = { 28 | enable = true 29 | status = "ENABLED" 30 | } 31 | cis_aws_foundations_benchmark_v120 = { 32 | enable = false 33 | } 34 | cis_aws_foundations_benchmark_v140 = { 35 | enable = true 36 | status = "ENABLED" 37 | } 38 | nist_sp_800_53_rev5 = { 39 | enable = false 40 | } 41 | pci_dss = { 42 | enable = false 43 | } 44 | } 45 | 46 | action_target = [{ 47 | name = "Send to Amazon SNS" 48 | identifier = "SendToSNS" 49 | description = "This is a custom action to send findings to SNS Topic" 50 | }] 51 | } 52 | 53 | # Security Hub Standards Control Example 54 | # Sample control findings https://docs.aws.amazon.com/securityhub/latest/userguide/sample-control-findings.html 55 | 56 | resource "aws_securityhub_standards_control" "ensure_iam_password_policy_prevents_password_reuse" { 57 | standards_control_arn = "arn:aws:securityhub:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:control/cis-aws-foundations-benchmark/v/1.4.0/1.10" 58 | control_status = "DISABLED" 59 | disabled_reason = "Password policies are managed by external resource" 60 | 61 | depends_on = [module.organizations_security_hub] 62 | } 63 | 64 | # Security Hub Insights Examples 65 | # Full list of filters https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight#filters 66 | 67 | resource "aws_securityhub_insight" "this" { 68 | filters { 69 | aws_account_id { 70 | comparison = "EQUALS" 71 | value = "123456789012" 72 | } 73 | aws_account_id { 74 | comparison = "EQUALS" 75 | value = "098765432109" 76 | } 77 | created_at { 78 | date_range { 79 | unit = "DAYS" 80 | value = 7 81 | } 82 | } 83 | network_source_ipv4 { 84 | cidr = "10.0.0.0/16" 85 | } 86 | criticality { 87 | gte = "80" 88 | } 89 | resource_tags { 90 | comparison = "EQUALS" 91 | key = "Environment" 92 | value = "Development" 93 | } 94 | } 95 | 96 | group_by_attribute = "AwsAccountId" 97 | 98 | name = "insight-per-account-id" 99 | 100 | depends_on = [module.organizations_security_hub] 101 | } 102 | -------------------------------------------------------------------------------- /tests/organizations/delegated_admin/outputs.tf: -------------------------------------------------------------------------------- 1 | output "delegated_admin" { 2 | description = "AWS Security Hub delegated admin" 3 | value = module.delegated_admin 4 | } 5 | -------------------------------------------------------------------------------- /tests/organizations/delegated_admin/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/tests/organizations/delegated_admin/variables.tf -------------------------------------------------------------------------------- /tests/organizations/delegated_admin/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | configuration_aliases = [ 9 | aws.member, 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/organizations/member_only/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | 5.6.2 | 13 | 14 | ## Modules 15 | 16 | | Name | Source | Version | 17 | |------|--------|---------| 18 | | [member\_account](#module\_member\_account) | ../../../modules/organizations_member/ | n/a | 19 | 20 | ## Resources 21 | 22 | | Name | Type | 23 | |------|------| 24 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 25 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 26 | 27 | ## Inputs 28 | 29 | No inputs. 30 | 31 | ## Outputs 32 | 33 | | Name | Description | 34 | |------|-------------| 35 | | [member](#output\_member) | Organizations account member AWS Security Hub. | 36 | -------------------------------------------------------------------------------- /tests/organizations/member_only/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | shared_config_files = ["~/.aws/config"] 3 | shared_credentials_files = ["~/.aws/credentials"] 4 | profile = "member" 5 | alias = "member" 6 | } 7 | 8 | module "member_account" { 9 | source = "aws-ia/security-hub/aws//modules/organizations_member" 10 | version = "0.0.1" 11 | 12 | providers = { 13 | aws = aws 14 | aws.member = aws.member 15 | } 16 | 17 | member_config = [{ 18 | account_id = "123456789012" 19 | email = "required@example.com" 20 | invite = false 21 | }] 22 | } 23 | -------------------------------------------------------------------------------- /tests/organizations/member_only/outputs.tf: -------------------------------------------------------------------------------- 1 | output "member" { 2 | description = "Organizations account member AWS Security Hub." 3 | value = module.member_account 4 | } 5 | -------------------------------------------------------------------------------- /tests/organizations/member_only/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/tests/organizations/member_only/variables.tf -------------------------------------------------------------------------------- /tests/organizations/member_only/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | configuration_aliases = [ 9 | aws.member, 10 | ] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/standalone/complete/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | | Name | Version | 11 | |------|---------| 12 | | [aws](#provider\_aws) | 4.67.0 | 13 | 14 | ## Modules 15 | 16 | | Name | Source | Version | 17 | |------|--------|---------| 18 | | [standalone\_security\_hub](#module\_standalone\_security\_hub) | ../../../ | n/a | 19 | 20 | ## Resources 21 | 22 | | Name | Type | 23 | |------|------| 24 | | [aws_securityhub_insight.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight) | resource | 25 | | [aws_securityhub_standards_control.ensure_iam_password_policy_prevents_password_reuse](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_standards_control) | resource | 26 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 27 | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | 28 | 29 | ## Inputs 30 | 31 | No inputs. 32 | 33 | ## Outputs 34 | 35 | | Name | Description | 36 | |------|-------------| 37 | | [insights](#output\_insights) | AWS Security Hub Custom Insights | 38 | | [security\_hub](#output\_security\_hub) | AWS Security Hub Standalone deploymeent | 39 | | [standards\_control](#output\_standards\_control) | AWS Security Hub Standards Control Customization | 40 | -------------------------------------------------------------------------------- /tests/standalone/complete/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" {} 2 | 3 | data "aws_caller_identity" "current" {} 4 | 5 | data "aws_region" "current" {} 6 | 7 | module "standalone_security_hub" { 8 | source = "aws-ia/security-hub/aws" 9 | version = "0.0.1" 10 | 11 | enable_default_standards = false 12 | control_finding_generator = "STANDARD_CONTROL" 13 | auto_enable_controls = true 14 | 15 | product_config = [{ 16 | enable = true 17 | arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty" 18 | }] 19 | 20 | standards_config = { 21 | aws_foundational_security_best_practices = { 22 | enable = true 23 | status = "ENABLED" 24 | } 25 | cis_aws_foundations_benchmark_v120 = { 26 | enable = false 27 | } 28 | cis_aws_foundations_benchmark_v140 = { 29 | enable = true 30 | status = "ENABLED" 31 | } 32 | nist_sp_800_53_rev5 = { 33 | enable = false 34 | } 35 | pci_dss = { 36 | enable = false 37 | } 38 | } 39 | 40 | action_target = [{ 41 | name = "Send to Amazon SNS" 42 | identifier = "SendToSNS" 43 | description = "This is a custom action to send findings to SNS Topic" 44 | }] 45 | 46 | } 47 | 48 | # Security Hub Standards Control Example 49 | # Sample control findings https://docs.aws.amazon.com/securityhub/latest/userguide/sample-control-findings.html 50 | 51 | resource "aws_securityhub_standards_control" "ensure_iam_password_policy_prevents_password_reuse" { 52 | standards_control_arn = "arn:aws:securityhub:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:control/cis-aws-foundations-benchmark/v/1.4.0/1.10" 53 | control_status = "DISABLED" 54 | disabled_reason = "Password policies are managed by external resource" 55 | 56 | depends_on = [module.standalone_security_hub] 57 | } 58 | 59 | # Security Hub Insights Examples 60 | # Full list of filters https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/securityhub_insight#filters 61 | 62 | resource "aws_securityhub_insight" "this" { 63 | filters { 64 | created_at { 65 | date_range { 66 | unit = "DAYS" 67 | value = 7 68 | } 69 | } 70 | network_source_ipv4 { 71 | cidr = "10.0.0.0/16" 72 | } 73 | criticality { 74 | gte = "80" 75 | } 76 | resource_tags { 77 | comparison = "EQUALS" 78 | key = "Environment" 79 | value = "Development" 80 | } 81 | } 82 | 83 | group_by_attribute = "AwsAccountId" 84 | 85 | name = "insight" 86 | 87 | depends_on = [module.standalone_security_hub] 88 | } 89 | -------------------------------------------------------------------------------- /tests/standalone/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | output "security_hub" { 2 | description = "AWS Security Hub Standalone deploymeent" 3 | value = module.standalone_security_hub 4 | } 5 | 6 | output "standards_control" { 7 | description = "AWS Security Hub Standards Control Customization" 8 | value = aws_securityhub_standards_control.ensure_iam_password_policy_prevents_password_reuse 9 | } 10 | 11 | output "insights" { 12 | description = "AWS Security Hub Custom Insights" 13 | value = aws_securityhub_insight.this 14 | } 15 | -------------------------------------------------------------------------------- /tests/standalone/complete/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/tests/standalone/complete/variables.tf -------------------------------------------------------------------------------- /tests/standalone/complete/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/standalone/quickstart/README.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | 3 | | Name | Version | 4 | |------|---------| 5 | | [terraform](#requirement\_terraform) | >= 1.0.0 | 6 | | [aws](#requirement\_aws) | >= 4.47 | 7 | 8 | ## Providers 9 | 10 | No providers. 11 | 12 | ## Modules 13 | 14 | | Name | Source | Version | 15 | |------|--------|---------| 16 | | [standalone\_security\_hub](#module\_standalone\_security\_hub) | ../../../ | n/a | 17 | 18 | ## Resources 19 | 20 | No resources. 21 | 22 | ## Inputs 23 | 24 | No inputs. 25 | 26 | ## Outputs 27 | 28 | | Name | Description | 29 | |------|-------------| 30 | | [security\_hub](#output\_security\_hub) | AWS Security Hub Standalone deploymeent | 31 | -------------------------------------------------------------------------------- /tests/standalone/quickstart/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" {} 2 | 3 | module "standalone_security_hub" { 4 | source = "aws-ia/security-hub/aws" 5 | version = "0.0.1" 6 | 7 | enable_default_standards = true 8 | control_finding_generator = "STANDARD_CONTROL" 9 | auto_enable_controls = true 10 | } 11 | -------------------------------------------------------------------------------- /tests/standalone/quickstart/outputs.tf: -------------------------------------------------------------------------------- 1 | output "security_hub" { 2 | description = "AWS Security Hub Standalone deploymeent" 3 | value = module.standalone_security_hub 4 | } 5 | -------------------------------------------------------------------------------- /tests/standalone/quickstart/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-ia/terraform-aws-security-hub/1e0cb72ff4a3ac888d7b2ce05563616a41064b03/tests/standalone/quickstart/variables.tf -------------------------------------------------------------------------------- /tests/standalone/quickstart/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 4.47" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Security Hub 3 | ################################################## 4 | variable "enable_default_standards" { 5 | description = "Whether to enable the security standards that Security Hub has designated as automatically enabled including: AWS Foundational Security Best Practices v1.0.0 and CIS AWS Foundations Benchmark v1.2.0. Defaults to `true`." 6 | type = bool 7 | default = true 8 | } 9 | 10 | variable "control_finding_generator" { 11 | description = "Updates whether the calling account has consolidated control findings turned on. If the value for this field is set to SECURITY_CONTROL, Security Hub generates a single finding for a control check even when the check applies to multiple enabled standards. If the value for this field is set to STANDARD_CONTROL, Security Hub generates separate findings for a control check when the check applies to multiple enabled standards. For accounts that are part of an organization, this value can only be updated in the administrator account." 12 | type = string 13 | default = "STANDARD_CONTROL" 14 | } 15 | 16 | variable "linking_mode" { 17 | description = "Indicates whether to aggregate findings from all of the available Regions or from a specified list. The options are ALL_REGIONS, ALL_REGIONS_EXCEPT_SPECIFIED or SPECIFIED_REGIONS. When ALL_REGIONS or ALL_REGIONS_EXCEPT_SPECIFIED are used, Security Hub will automatically aggregate findings from new Regions as Security Hub supports them and you opt into them." 18 | type = string 19 | default = "ALL_REGIONS" 20 | } 21 | 22 | variable "auto_enable_controls" { 23 | description = "Whether to automatically enable new controls when they are added to standards that are enabled. By default, this is set to true, and new controls are enabled automatically. To not automatically enable new controls, set this to false." 24 | type = bool 25 | default = true 26 | } 27 | 28 | variable "specified_regions" { 29 | description = "List of regions to include or exclude (required if linking_mode is set to ALL_REGIONS_EXCEPT_SPECIFIED or SPECIFIED_REGIONS)" 30 | type = list(string) 31 | default = null 32 | } 33 | 34 | ################################################## 35 | # Security Hub Subscriptions 36 | ################################################## 37 | variable "standards_config" { 38 | description = <