├── Architecture.jpg ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── aws-security-hub-boostrap-and-operationalization ├── Architecture.jpg ├── README.md ├── cis_3-x.tf ├── cis_baseline_infrastructure.tf ├── cloudwatch-to-firehose.zip ├── config.tf ├── data.tf ├── elasticsearch_siem_extension.tf ├── provider.tf ├── prowler-integration │ └── README.md ├── security_hub_siem.tf ├── security_services.tf └── variables.tf ├── buildspec.yaml ├── provider.tf ├── variables.tf ├── waf-conditions.tf └── waf-rules.tf /Architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-security-services-with-terraform/d4c043f6e93f256fedbbaa5becfd247ad992061b/Architecture.jpg -------------------------------------------------------------------------------- /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 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 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. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | 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. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | 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. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## How to use CI/CD to deploy and configure AWS security services with Terraform 2 | 3 | This is sample code for the accompanying AWS Security Blog post How to use CI/CD to deploy and configure AWS security services with Terraform. A CodeBuild buildspec.yml and terraform config files to deploy a Global Web ACL & sample rules are provided. Other Terraform config files will be provided to give additional examples, however, the IAM policy provided through the blog will not cover most additional resources and you will need to make modifications. Readme's for each additional solution will live in their sub-folder. 4 | 5 | ### Solutions Architecture 6 | ![Architecture](https://github.com/aws-samples/aws-security-services-with-terraform/blob/master/Architecture.jpg) 7 | 1. Push your artifacts, Terraform configuration files and a build specification to a CodePipeline source 8 | 2. CodePipeline automatically invokes CodeBuild and downloads the source files 9 | 3. CodeBuild installs and executes Terraform according to our build specification 10 | 4. Terraform stores our state files in S3 and a record of the deployment in DynamoDB 11 | 5. Our WAF Web ACL is deployed and ready for use by our application teams 12 | 13 | ## License 14 | 15 | This library is licensed under the MIT-0 License. See the LICENSE file. -------------------------------------------------------------------------------- /aws-security-hub-boostrap-and-operationalization/Architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-security-services-with-terraform/d4c043f6e93f256fedbbaa5becfd247ad992061b/aws-security-hub-boostrap-and-operationalization/Architecture.jpg -------------------------------------------------------------------------------- /aws-security-hub-boostrap-and-operationalization/README.md: -------------------------------------------------------------------------------- 1 | ## AWS Security Hub - Bootstrap and Operationalization 2 | ![Architecture](https://github.com/aws-samples/aws-security-services-with-terraform/blob/master/aws-security-hub-boostrap-and-operationalization/Architecture.jpg) 3 | 4 | * ***NOTE*** These config files have been tested with Terraform v.0.11.14 and AWS Provider v2.46 5 | 6 | The Terraform configuration files within this folder are designed to help customers bootstrap and operationalize Security Hub by enabling downstream services (Config, GuardDuty, Inspector), creating resources that are compliant with AWS CIS Foundations Benchmark controls and extending Security Hub via CloudWatch and Kinesis by consuming all findings into Elasticsearch Service and using Kibana as a Security Information & Event Management (SIEM) tool. All Terraform config files are created seperately to offer modularity (though all variables are within `variables.tf`) if you already have certain resources deployed, or you wanted to craft your own Terraform config files. You can reuse your same `provider.tf` file from the WAF Blog for this solution as well to retain your state in your remote backend. 7 | 8 | ## Required IAM Permissions 9 | You will need to modify the CodeBuild role created for the WAF Blog to allow it to create all of these resources, which include the below. You need to give Terraform full create/update/read/delete permissions to be able to apply, update, describe and delete your State. 10 | - CloudWatch Events 11 | - CloudWatch Logs 12 | - CloudTrail 13 | - Config 14 | - Cognito 15 | - EC2 16 | - Elasticsearch Service 17 | - GuardDuty 18 | - IAM 19 | - Inspector 20 | - Kinesis Data Streams 21 | - Kinesis Data Firehose 22 | - KMS 23 | - Lambda 24 | - S3 25 | - SNS 26 | - VPC 27 | 28 | ## Terraform Configuration File Inventory 29 | ### variables.tf 30 | A majority of the variables in this config file are already filled out with `default` values. Comments are added to denote which variables belong to which config file. 31 | 32 | ### config.tf 33 | This config file will create all resources needed to create and enable an AWS Config recorder, if you already have one the state applied with this config file will fail. 34 | 35 | **NOTE** You may still need to go through the Config console and hit save for Config to be enabled. 36 | 37 | ### security_services.tf 38 | This config file will enable a GuardDuty detector, Security Hub (and the AWS CIS Foundations Benchmark), an IAM Access Analyzer detector and create an Inspector template and target group that will target all EC2 instances with all assessment templates. 39 | 40 | **NOTE** Ensure you replace the value for `aws_inspector_assessment_template.Inspector_Assessment_Template.rules_package_arns` with the proper Variable depending on your region, assessment templates are provided via a Terraform variable `list`, ensure you specify the correct one. If there are regions missing refer to [Amazon Inspector ARNS for Rules Packages](https://docs.aws.amazon.com/inspector/latest/userguide/inspector_rules-arns.html) for more information on creating your own. 41 | 42 | ### cis_baseline_infrastructure.tf 43 | This config file will create a multi-region CloudTrail trail along with a S3 bucket, CloudWatch Logs group, IAM Password Policy and Server Access Logging S3 Bucket that are all in compliance with CIS 1.x and 2.x controls. Additionally a VPC with private and public subnets, VPC flow logging and an empty default SG (compliant with CIS 4.3) and all IAM roles and policies needed will be created. This will help you be in compliance with CIS and can serve as a baseline for a new environment being created. The amount of AZs that will be created is dependnet on a variable named `Network_Resource_Count`, ensure you do not specify a value higher than the amount of AZs in your Region (i.e. 6 in us-east-1, 3 in us-east-2, etc.) 44 | 45 | ### cis_3-x.tf 46 | This config file will create a SNS topic and all needed metric filters and alarms needed to be in compliance with CIS 3.x controls. This depends on the CloudWatch group that was created in `cis_baseline_infrastructure.tf`, if you decide to not use that file you will need to specify your own CloudWatch Log Group that CloudTrail publishes to. 47 | 48 | **NOTE** Due to the way Terraform provisions resources, Email SNS subscriptions are not allowed to be created. **You must manually subscribe and accept an email subscription to the SNS topic for the Security Hub 3.x controls to be compliant.** 49 | 50 | ### security_hub_siem.tf 51 | This config file will create an ElasticSearch Service domain, Cognito resources (for use for signing into Kibana) and a delivery pipeline that includes a CloudWatch Event Rule, Kinesis Data Stream and Kinesis Data Firehose Delivery Stream to send all findings from Security Hub to Elasticsearch Service for exploration and analysis in Kibana. All necessary IAM roles and event patterns are created in this configuration file, you will need to modify the Firehose resource if you would rather send logs to S3 or to Splunk. 52 | 53 | ### elasticsearch_siem_extension.tf 54 | This config file creates infrastructure that will send VPC Flow Logs and CloudTrail logs from CloudWatch to the Elasticsearch Service domain created by `security_hub_siem.tf`. This pipeline uses CloudWatch Log subscriptions, Lambda functions, Kinesis Data Firehose Delivery Streams and IAM roles / policies to accomplish the task. 55 | 56 | **NOTE** See the below section for information on using Scripted fields for converting the CloudWatch Log Epochtime to a timestamp. 57 | 58 | ## Epochtime to Timestamp via Kibana Script fields 59 | In Kibana, select the indicies for your CloudTrail and VPC Flow logs and select the Script Fields tab and choose **Add scripted field** and configure the following: 60 | **Language**: painless 61 | **Type**: date 62 | **Format**: Date 63 | **Moment.js format pattern**: MMMM Do YYYY, HH:mm:ss.SSS 64 | **Script**: `doc['logEvents.timestamp'].value` 65 | 66 | Save the field and you should be able to sort by this new field moving forward. 67 | 68 | ## Troubleshooting 69 | #### Elasticsearch Service timeout 70 | Depending on the amount of nodes, Masters and the instance type Terraform may time out due to how long the Domain takes to deploy. Wait for it to be `Active` in the AWS Management Console and then re-apply state after it has completed to avoid race conditions or orphaned resources. 71 | 72 | #### Master node support for Elasticsearch Service 73 | Master's were removed (`commit f3f5d259ef53aaee3de0175cb37a2d88d55bfdf2`) from the template due to potential timeouts depending on Region and count of masters. To add them back in, replace the `cluster_config` with the following values. Please note, you will need to also add the reference variables to `variables.tf`: 74 | ```hcl 75 | cluster_config { 76 | dedicated_master_enabled = true 77 | zone_awareness_enabled = true 78 | instance_type = "${var.ElasticSearch_Domain_Instance_Type}" 79 | instance_count = "${var.ElasticSearch_Domain_Instance_Count}" 80 | dedicated_master_type = "${var.ElasticSearch_Master_Instance_Type}" 81 | dedicated_master_count = "${var.ElasticSearch_Master_Instance_Count}" 82 | } 83 | ``` 84 | 85 | #### Terraform v.0.12.x Support 86 | These Config files are written to v0.11.14, as was supported by the original WAF Terraform CI/CD blog, these will not work for v0.12.x without modifications. 87 | 88 | #### Error creating : ValidationException: 89 | Terraform has been observed throwing validation errors when creating a large amount of resources (this solution is over 100 resources), if you are running in CI/CD release the change again to deploy the missing state. If you are running from your local computer call `terraform apply` again. 90 | 91 | #### aws_inspector_assessment_template.Inspector_Assessment_Template: NoSuchEntityException 92 | Ensure you are using the Assessment Template variable that matches the region you are deploying to. 93 | 94 | #### Security Hub has compliance controls with "unknown" results 95 | Due to the way the graph for this whole solution works, Security Hub & the CIS AWS Foundations Benchmark compliance standard may be enabled before a majority of the resources. Some are periodic (3.x rules, namely) and will become Passed after you have subscribed to the SNS topic. If the problem persists after 24 hours, disable and re-enable the standard. 96 | 97 | ## License 98 | 99 | This library is licensed under the MIT-0 License. See the LICENSE file. -------------------------------------------------------------------------------- /aws-security-hub-boostrap-and-operationalization/cis_3-x.tf: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 5 | # software and associated documentation files (the "Software"), to deal in the Software 6 | # without restriction, including without limitation the rights to use, copy, modify, 7 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 11 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 12 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 13 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 14 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 15 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | 17 | # SNS topic to receive CIS 3.x alerts 18 | # You will need to subscribe via email manually as this is unsupported by terraform 19 | resource "aws_sns_topic" "CIS_Alerts_SNS_Topic" { 20 | name_prefix = "${var.CIS_SNS_Prefix}" 21 | } 22 | ## These next resources are the CloudWatch Log Metric Filter & associated Alarms to be in compliance with CIS Benchmarks 23 | resource "aws_cloudwatch_log_metric_filter" "CIS_Unauthorized_API_Calls_Metric_Filter" { 24 | name = "CIS-UnauthorizedAPICalls" 25 | pattern = "{ ($.errorCode = \"*UnauthorizedOperation\") || ($.errorCode = \"AccessDenied*\") }" 26 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 27 | 28 | metric_transformation { 29 | name = "CIS-UnauthorizedAPICalls" 30 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 31 | value = "1" 32 | } 33 | } 34 | resource "aws_cloudwatch_metric_alarm" "CIS_Unauthorized_API_Calls_CW_Alarm" { 35 | alarm_name = "CIS-3.1-UnauthorizedAPICalls" 36 | comparison_operator = "GreaterThanOrEqualToThreshold" 37 | evaluation_periods = "1" 38 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Unauthorized_API_Calls_Metric_Filter.id}" 39 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 40 | period = "300" 41 | statistic = "Sum" 42 | threshold = "1" 43 | alarm_description = "Monitoring unauthorized API calls will help reveal application errors and may reduce time to detect malicious activity." 44 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 45 | insufficient_data_actions = [] 46 | } 47 | resource "aws_cloudwatch_log_metric_filter" "CIS_No_MFA_Console_Signin_Metric_Filter" { 48 | name = "CIS-ConsoleSigninWithoutMFA" 49 | pattern = "{ ($.eventName = \"ConsoleLogin\") && ($.additionalEventData.MFAUsed != \"Yes\") }" 50 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 51 | 52 | metric_transformation { 53 | name = "CIS-ConsoleSigninWithoutMFA" 54 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 55 | value = "1" 56 | } 57 | } 58 | 59 | resource "aws_cloudwatch_metric_alarm" "CIS_No_MFA_Console_Signin_CW_Alarm" { 60 | alarm_name = "CIS-3.2-ConsoleSigninWithoutMFA" 61 | comparison_operator = "GreaterThanOrEqualToThreshold" 62 | evaluation_periods = "1" 63 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_No_MFA_Console_Signin_Metric_Filter.id}" 64 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 65 | period = "300" 66 | statistic = "Sum" 67 | threshold = "1" 68 | alarm_description = "Monitoring for single-factor console logins will increase visibility into accounts that are not protected by MFA." 69 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 70 | insufficient_data_actions = [] 71 | } 72 | 73 | resource "aws_cloudwatch_log_metric_filter" "CIS_Root_Account_Use_Metric_Filter" { 74 | name = "CIS-RootAccountUsage" 75 | pattern = "{ $.userIdentity.type = \"Root\" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != \"AwsServiceEvent\" }" 76 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 77 | 78 | metric_transformation { 79 | name = "CIS-RootAccountUsage" 80 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 81 | value = "1" 82 | } 83 | } 84 | 85 | resource "aws_cloudwatch_metric_alarm" "CIS_Root_Account_Use_CW_Alarm" { 86 | alarm_name = "CIS-3.3-RootAccountUsage" 87 | comparison_operator = "GreaterThanOrEqualToThreshold" 88 | evaluation_periods = "1" 89 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Root_Account_Use_Metric_Filter.id}" 90 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 91 | period = "300" 92 | statistic = "Sum" 93 | threshold = "1" 94 | alarm_description = "Monitoring for root account logins will provide visibility into the use of a fully privileged account and an opportunity to reduce the use of it." 95 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 96 | insufficient_data_actions = [] 97 | } 98 | resource "aws_cloudwatch_log_metric_filter" "CIS_IAM_Policy_Change_Metric_Filter" { 99 | name = "CIS-IAMPolicyChanges" 100 | pattern = "{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}" 101 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 102 | 103 | metric_transformation { 104 | name = "CIS-IAMPolicyChanges" 105 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 106 | value = "1" 107 | } 108 | } 109 | resource "aws_cloudwatch_metric_alarm" "CIS_IAM_Policy_Change_CW_Alarm" { 110 | alarm_name = "CIS-3.4-IAMPolicyChanges" 111 | comparison_operator = "GreaterThanOrEqualToThreshold" 112 | evaluation_periods = "1" 113 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_IAM_Policy_Change_Metric_Filter.id}" 114 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 115 | period = "300" 116 | statistic = "Sum" 117 | threshold = "1" 118 | alarm_description = "Monitoring changes to IAM policies will help ensure authentication and authorization controls remain intact." 119 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 120 | insufficient_data_actions = [] 121 | } 122 | resource "aws_cloudwatch_log_metric_filter" "CIS_CloudTrail_Config_Change_Metric_Filter" { 123 | name = "CIS-CloudTrailChanges" 124 | pattern = "{ ($.eventName = CreateTrail) || ($.eventName = UpdateTrail) || ($.eventName = DeleteTrail) || ($.eventName = StartLogging) || ($.eventName = StopLogging) }" 125 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 126 | 127 | metric_transformation { 128 | name = "CIS-CloudTrailChanges" 129 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 130 | value = "1" 131 | } 132 | } 133 | resource "aws_cloudwatch_metric_alarm" "CIS_CloudTrail_Config_Change_CW_Alarm" { 134 | alarm_name = "CIS-3.5-CloudTrailChanges" 135 | comparison_operator = "GreaterThanOrEqualToThreshold" 136 | evaluation_periods = "1" 137 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_CloudTrail_Config_Change_Metric_Filter.id}" 138 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 139 | period = "300" 140 | statistic = "Sum" 141 | threshold = "1" 142 | alarm_description = "Monitoring changes to CloudTrail's configuration will help ensure sustained visibility to activities performed in the AWS account." 143 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 144 | insufficient_data_actions = [] 145 | } 146 | resource "aws_cloudwatch_log_metric_filter" "CIS_Console_AuthN_Failure_Metric_Filter" { 147 | name = "CIS-ConsoleAuthenticationFailure" 148 | pattern = "{ ($.eventName = ConsoleLogin) && ($.errorMessage = \"Failed authentication\") }" 149 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 150 | 151 | metric_transformation { 152 | name = "CIS-ConsoleAuthenticationFailure" 153 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 154 | value = "1" 155 | } 156 | } 157 | resource "aws_cloudwatch_metric_alarm" "CIS_Console_AuthN_Failure_CW_Alarm" { 158 | alarm_name = "CIS-3.6-ConsoleAuthenticationFailure" 159 | comparison_operator = "GreaterThanOrEqualToThreshold" 160 | evaluation_periods = "1" 161 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Console_AuthN_Failure_Metric_Filter.id}" 162 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 163 | period = "300" 164 | statistic = "Sum" 165 | threshold = "1" 166 | alarm_description = "Monitoring failed console logins may decrease lead time to detect an attempt to brute force a credential, which may provide an indicator, such as source IP, that can be used in other event correlation." 167 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 168 | insufficient_data_actions = [] 169 | } 170 | resource "aws_cloudwatch_log_metric_filter" "CIS_Disable_Or_Delete_CMK_Metric_Filter" { 171 | name = "CIS-DisableOrDeleteCMK" 172 | pattern = "{ ($.eventSource = kms.amazonaws.com) && (($.eventName = DisableKey) || ($.eventName = ScheduleKeyDeletion)) }" 173 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 174 | 175 | metric_transformation { 176 | name = "CIS-DisableOrDeleteCMK" 177 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 178 | value = "1" 179 | } 180 | } 181 | resource "aws_cloudwatch_metric_alarm" "CIS_Disable_Or_Delete_CMK_CW_Alarm" { 182 | alarm_name = "CIS-3.7-DisableOrDeleteCMK" 183 | comparison_operator = "GreaterThanOrEqualToThreshold" 184 | evaluation_periods = "1" 185 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Disable_Or_Delete_CMK_Metric_Filter.id}" 186 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 187 | period = "300" 188 | statistic = "Sum" 189 | threshold = "1" 190 | alarm_description = "Monitoring failed console logins may decrease lead time to detect an attempt to brute force a credential, which may provide an indicator, such as source IP, that can be used in other event correlation." 191 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 192 | insufficient_data_actions = [] 193 | } 194 | resource "aws_cloudwatch_log_metric_filter" "CIS_S3_Bucket_Policy_Change_Metric_Filter" { 195 | name = "CIS-S3BucketPolicyChanges" 196 | pattern = "{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = PutBucketCors) || ($.eventName = PutBucketLifecycle) || ($.eventName = PutBucketReplication) || ($.eventName = DeleteBucketPolicy) || ($.eventName = DeleteBucketCors) || ($.eventName = DeleteBucketLifecycle) || ($.eventName = DeleteBucketReplication)) }" 197 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 198 | 199 | metric_transformation { 200 | name = "CIS-S3BucketPolicyChanges" 201 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 202 | value = "1" 203 | } 204 | } 205 | resource "aws_cloudwatch_metric_alarm" "CIS_S3_Bucket_Policy_Change_CW_Alarm" { 206 | alarm_name = "CIS-3.8-S3BucketPolicyChanges" 207 | comparison_operator = "GreaterThanOrEqualToThreshold" 208 | evaluation_periods = "1" 209 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_S3_Bucket_Policy_Change_Metric_Filter.id}" 210 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 211 | period = "300" 212 | statistic = "Sum" 213 | threshold = "1" 214 | alarm_description = "Monitoring changes to S3 bucket policies may reduce time to detect and correct permissive policies on sensitive S3 buckets." 215 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 216 | insufficient_data_actions = [] 217 | } 218 | resource "aws_cloudwatch_log_metric_filter" "CIS_AWS_Config_Change_Metric_Filter" { 219 | name = "CIS-AWSConfigChanges" 220 | pattern = "{ ($.eventSource = config.amazonaws.com) && (($.eventName=StopConfigurationRecorder)||($.eventName=DeleteDeliveryChannel)||($.eventName=PutDeliveryChannel)||($.eventName=PutConfigurationRecorder)) }" 221 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 222 | 223 | metric_transformation { 224 | name = "CIS-AWSConfigChanges" 225 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 226 | value = "1" 227 | } 228 | } 229 | resource "aws_cloudwatch_metric_alarm" "CIS_AWS_Config_Change_CW_Alarm" { 230 | alarm_name = "CIS-3.9-AWSConfigChanges" 231 | comparison_operator = "GreaterThanOrEqualToThreshold" 232 | evaluation_periods = "1" 233 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_AWS_Config_Change_Metric_Filter.id}" 234 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 235 | period = "300" 236 | statistic = "Sum" 237 | threshold = "1" 238 | alarm_description = "Monitoring changes to AWS Config configuration will help ensure sustained visibility of configuration items within the AWS account." 239 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 240 | insufficient_data_actions = [] 241 | } 242 | resource "aws_cloudwatch_log_metric_filter" "CIS_Security_Group_Changes_Metric_Filter" { 243 | name = "CIS-SecurityGroupChanges" 244 | pattern = "{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) || ($.eventName = CreateSecurityGroup) || ($.eventName = DeleteSecurityGroup)}" 245 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 246 | 247 | metric_transformation { 248 | name = "CIS-SecurityGroupChanges" 249 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 250 | value = "1" 251 | } 252 | } 253 | resource "aws_cloudwatch_metric_alarm" "CIS_Security_Group_Changes_CW_Alarm" { 254 | alarm_name = "CIS-3.10-SecurityGroupChanges" 255 | comparison_operator = "GreaterThanOrEqualToThreshold" 256 | evaluation_periods = "1" 257 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Security_Group_Changes_Metric_Filter.id}" 258 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 259 | period = "300" 260 | statistic = "Sum" 261 | threshold = "1" 262 | alarm_description = "Monitoring changes to security group will help ensure that resources and services are not unintentionally exposed." 263 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 264 | insufficient_data_actions = [] 265 | } 266 | resource "aws_cloudwatch_log_metric_filter" "CIS_Network_ACL_Changes_Metric_Filter" { 267 | name = "CIS-NetworkACLChanges" 268 | pattern = "{ ($.eventName = CreateNetworkAcl) || ($.eventName = CreateNetworkAclEntry) || ($.eventName = DeleteNetworkAcl) || ($.eventName = DeleteNetworkAclEntry) || ($.eventName = ReplaceNetworkAclEntry) || ($.eventName = ReplaceNetworkAclAssociation) }" 269 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 270 | 271 | metric_transformation { 272 | name = "CIS-NetworkACLChanges" 273 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 274 | value = "1" 275 | } 276 | } 277 | resource "aws_cloudwatch_metric_alarm" "CIS_Network_ACL_Changes_CW_Alarm" { 278 | alarm_name = "CIS-3.11-NetworkACLChanges" 279 | comparison_operator = "GreaterThanOrEqualToThreshold" 280 | evaluation_periods = "1" 281 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Network_ACL_Changes_Metric_Filter.id}" 282 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 283 | period = "300" 284 | statistic = "Sum" 285 | threshold = "1" 286 | alarm_description = "Monitoring changes to NACLs will help ensure that AWS resources and services are not unintentionally exposed." 287 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 288 | insufficient_data_actions = [] 289 | } 290 | resource "aws_cloudwatch_log_metric_filter" "CIS_Network_Gateway_Changes_Metric_Filter" { 291 | name = "CIS-NetworkGatewayChanges" 292 | pattern = "{ ($.eventName = CreateCustomerGateway) || ($.eventName = DeleteCustomerGateway) || ($.eventName = AttachInternetGateway) || ($.eventName = CreateInternetGateway) || ($.eventName = DeleteInternetGateway) || ($.eventName = DetachInternetGateway) }" 293 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 294 | 295 | metric_transformation { 296 | name = "CIS-NetworkGatewayChanges" 297 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 298 | value = "1" 299 | } 300 | } 301 | resource "aws_cloudwatch_metric_alarm" "CIS_Network_Gateway_Changes_CW_Alarm" { 302 | alarm_name = "CIS-3.12-NetworkGatewayChanges" 303 | comparison_operator = "GreaterThanOrEqualToThreshold" 304 | evaluation_periods = "1" 305 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Network_Gateway_Changes_Metric_Filter.id}" 306 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 307 | period = "300" 308 | statistic = "Sum" 309 | threshold = "1" 310 | alarm_description = "Monitoring changes to network gateways will help ensure that all ingress/egress traffic traverses the VPC border via a controlled path." 311 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 312 | insufficient_data_actions = [] 313 | } 314 | resource "aws_cloudwatch_log_metric_filter" "CIS_Route_Table_Changes_Metric_Filter" { 315 | name = "CIS-RouteTableChanges" 316 | pattern = "{ ($.eventName = CreateRoute) || ($.eventName = CreateRouteTable) || ($.eventName = ReplaceRoute) || ($.eventName = ReplaceRouteTableAssociation) || ($.eventName = DeleteRouteTable) || ($.eventName = DeleteRoute) || ($.eventName = DisassociateRouteTable) }" 317 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 318 | 319 | metric_transformation { 320 | name = "CIS-RouteTableChanges" 321 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 322 | value = "1" 323 | } 324 | } 325 | resource "aws_cloudwatch_metric_alarm" "CIS_Route_Table_Changes_CW_Alarm" { 326 | alarm_name = "CIS-3.13-RouteTableChanges" 327 | comparison_operator = "GreaterThanOrEqualToThreshold" 328 | evaluation_periods = "1" 329 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_Route_Table_Changes_Metric_Filter.id}" 330 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 331 | period = "300" 332 | statistic = "Sum" 333 | threshold = "1" 334 | alarm_description = "Monitoring changes to route tables will help ensure that all VPC traffic flows through an expected path." 335 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 336 | insufficient_data_actions = [] 337 | } 338 | resource "aws_cloudwatch_log_metric_filter" "CIS_VPC_Changes_Metric_Filter" { 339 | name = "CIS-VPCChanges" 340 | pattern = "{ ($.eventName = CreateVpc) || ($.eventName = DeleteVpc) || ($.eventName = ModifyVpcAttribute) || ($.eventName = AcceptVpcPeeringConnection) || ($.eventName = CreateVpcPeeringConnection) || ($.eventName = DeleteVpcPeeringConnection) || ($.eventName = RejectVpcPeeringConnection) || ($.eventName = AttachClassicLinkVpc) || ($.eventName = DetachClassicLinkVpc) || ($.eventName = DisableVpcClassicLink) || ($.eventName = EnableVpcClassicLink) }" 341 | log_group_name = "${aws_cloudwatch_log_group.CIS_CloudWatch_LogsGroup.name}" 342 | 343 | metric_transformation { 344 | name = "CIS-VPCChanges" 345 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 346 | value = "1" 347 | } 348 | } 349 | resource "aws_cloudwatch_metric_alarm" "CIS_VPC_Changes_CW_Alarm" { 350 | alarm_name = "CIS-3.14-VPCChanges" 351 | comparison_operator = "GreaterThanOrEqualToThreshold" 352 | evaluation_periods = "1" 353 | metric_name = "${aws_cloudwatch_log_metric_filter.CIS_VPC_Changes_Metric_Filter.id}" 354 | namespace = "${var.CIS_Metric_Alarm_Namespace}" 355 | period = "300" 356 | statistic = "Sum" 357 | threshold = "1" 358 | alarm_description = "Monitoring changes to VPC will help ensure that all VPC traffic flows through an expected path." 359 | alarm_actions = ["${aws_sns_topic.CIS_Alerts_SNS_Topic.arn}"] 360 | insufficient_data_actions = [] 361 | } 362 | -------------------------------------------------------------------------------- /aws-security-hub-boostrap-and-operationalization/cis_baseline_infrastructure.tf: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: MIT-0 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this 5 | # software and associated documentation files (the "Software"), to deal in the Software 6 | # without restriction, including without limitation the rights to use, copy, modify, 7 | # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 8 | # permit persons to whom the Software is furnished to do so. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 11 | # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 12 | # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 13 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 14 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 15 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | 17 | # create KMS key with default cloudtrail policy 18 | resource "aws_kms_key" "Cloudtrail_KMS_CMK" { 19 | description = "For CloudTrail - Managed by Terraform" 20 | deletion_window_in_days = 7 21 | is_enabled = true 22 | enable_key_rotation = true 23 | policy = <