├── nestedstack.png ├── nist-high-on-aws-architecture.png ├── .github └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── README.md ├── CONTRIBUTING.md ├── elastic ├── wazuh_cf_elastic.sh └── wazuh_cf_kibana.sh ├── iam.template ├── config-rules.template ├── wazuh └── cluster │ ├── wazuh_cf_worker.sh │ └── wazuh_cf_master.sh ├── logging.template ├── wazuh_template.yml ├── LICENSE ├── vpc-management.template ├── main.template └── vpc-production.template /nestedstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/HEAD/nestedstack.png -------------------------------------------------------------------------------- /nist-high-on-aws-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/HEAD/nist-high-on-aws-architecture.png -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AWS Cloudformation Security Automation For Wazuh 2 | 3 | NIST based Open Source security automation delivered as AWS Cloudformation 4 | 5 | This project is based upon the open source security project Wazuh (which itself is a fork of OSSEC) https://github.com/wazuh and a modified version of the AWS NIST High Quickstart https://aws.amazon.com/quickstart/architecture/compliance-nist-high-impact/. 6 | 7 | This implementation is intended to show a reference architecture using cloudformation to instantiate an Elastic Stack, Kibana, the Wazuh Manager, and a sample multi-tier application. This set of templates will take up to 30 minutes to deploy. 8 | 9 | What is Wazuh? https://documentation.wazuh.com/current/installation-guide/index.html 10 | 11 | Wazuh provides a security solution capable of monitoring your infrastructure, detecting threats, intrusion attempts, system anomalies, poorly configured applications and unauthorized user actions. It also provides a framework for incident response and regulatory compliance. 12 | The primary use cases for Wazuh include: Security Analytics, Host Based Intrusion Detection, Log Data Analysis, File Integrity Monitoring, and Incident Response. 13 | 14 | Why leverage the AWS NIST High Impact template? https://aws.amazon.com/quickstart/architecture/compliance-nist/ 15 | The AWS NIST High Impact components provide security-focused architectural elements for cloud provisioning teams, developers, integrators, and information security teams who need to leverage strict security, compliance, and risk management controls. NIST SP 800-53 (Rev. 4) high-impact security controls baseline 16 | 17 | What are we deploying? 18 | ![](nist-high-on-aws-architecture.png) 19 | ## Pre-requisites: You will need the ability to deploy up to 7 EIP's. (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html#eip-basics) This may require an account increase. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html 20 | We are leveraging cloudformation to deploy a nested stack. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-nested-stacks.html 21 | The nested stacks allow us to configure and independantly modify resources within the stacks. This type of automation allows us to replace, extend, or maintain stacks independently. 22 | 23 | ![](nestedstack.png) 24 | 25 | Main Template -Coordinates the other templates 26 | 27 | IAM Template -Give us roles and permissions 28 | 29 | Config-Rules Template -Can be extended to include rules important to your business 30 | 31 | Logging Template -Sets the logging parameters and the necessary storage locations 32 | 33 | VPC-Management -Creates the bastion host and network used to access the environment 34 | 35 | VPC-Production -Creates the required VPC, gateways, and networking components for the environment 36 | 37 | Application -Deploys a sample application leveraging Linux and Amazon RDS. 38 | 39 | Wazuh -Configures the security tools and Wazuh managers. 40 | 41 | ## Acknowledgements: 42 | This project is based on work from two other projects. The Wazuh project (https://github.com/wazuh) and the AWS NIST High Quickstart (https://aws.amazon.com/quickstart/architecture/compliance-nist-high-impact/). I would like to thank those who have contributed to those projects and encourage you to review them as well. 43 | 44 | ## License 45 | 46 | This library is licensed under the GPL 2.0 Only. 47 | -------------------------------------------------------------------------------- /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](https://github.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/issues), or [recently closed](https://github.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), 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'](https://github.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/labels/help%20wanted) 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](https://github.com/aws-samples/aws-cloudformation-security-automation-for-wazuh/blob/master/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 | -------------------------------------------------------------------------------- /elastic/wazuh_cf_elastic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Install Elastic data node using Cloudformation template 3 | # Support for Amazon Linux 4 | touch /tmp/log 5 | echo "Starting process." > /tmp/log 6 | ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2) 7 | ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2) 8 | elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1) 9 | wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2) 10 | eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2) 11 | echo "Added env vars." >> /tmp/log 12 | 13 | # Check if running as root 14 | if [[ $EUID -ne 0 ]]; then 15 | echo "NOT running as root. Exiting" >> /tmp/log 16 | echo "This script must be run as root" 17 | exit 1 18 | fi 19 | echo "Running as root." >> /tmp/log 20 | 21 | # Creating SSH user 22 | if ! id -u ${ssh_username} > /dev/null 2>&1; then adduser ${ssh_username}; fi 23 | echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers 24 | usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username} 25 | echo "Created SSH user." >> /tmp/log 26 | 27 | sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config 28 | service sshd restart 29 | echo "Started SSH service." >> /tmp/log 30 | 31 | # Mounting ephemeral partition 32 | mkdir /mnt/ephemeral 33 | echo "Created /mnt/ephemeral folder." >> /tmp/log 34 | 35 | # Uninstall OpenJDK 1.7 if exists 36 | if rpm -q java-1.7.0-openjdk > /dev/null; then yum -y remove java-1.7.0-openjdk; fi 37 | 38 | # Install OpenJDK 1.8 39 | yum -y install java-1.8.0-openjdk 40 | 41 | # Configuring Elastic repository 42 | rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch 43 | elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1) 44 | cat > /etc/yum.repos.d/elastic.repo << EOF 45 | [elasticsearch-${elastic_major_version}.x] 46 | name=Elasticsearch repository for ${elastic_major_version}.x packages 47 | baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum 48 | gpgcheck=1 49 | gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch 50 | enabled=1 51 | autorefresh=1 52 | type=rpm-md 53 | EOF 54 | echo "Added Elasticsearch repo." >> /tmp/log 55 | 56 | # Installing Elasticsearch 57 | yum -y install elasticsearch-${elastic_version} 58 | chkconfig --add elasticsearch 59 | echo "Installed Elasticsearch." >> /tmp/log 60 | 61 | # Installing Elasticsearch plugin for EC2 62 | /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch discovery-ec2 63 | echo "Installed EC2 plugin." >> /tmp/log 64 | 65 | # Creating data and logs directories 66 | mkdir -p /mnt/ephemeral/elasticsearch/lib 67 | mkdir -p /mnt/ephemeral/elasticsearch/log 68 | chown -R elasticsearch:elasticsearch /mnt/ephemeral/elasticsearch 69 | echo "Created volumes in ephemeral." >> /tmp/log 70 | 71 | # Configuration file created by AWS Cloudformation template 72 | # Because of it we set the right owner/group for the file 73 | mv -f /tmp/wazuh_cf_elasticsearch.yml /etc/elasticsearch/elasticsearch.yml 74 | echo "mv -f /tmp/wazuh_cf_elasticsearch.yml /etc/elasticsearch/elasticsearch.yml" >> /tmp/log 75 | 76 | chown elasticsearch:elasticsearch /etc/elasticsearch/elasticsearch.yml 77 | echo "Setting permissions." >> /tmp/log 78 | 79 | # Calculating RAM for Elasticsearch 80 | ram_gb=$(free -g | awk '/^Mem:/{print $2}') 81 | ram=$(( ${ram_gb} / 2 )) 82 | if [ $ram -eq "0" ]; then ram=1; fi 83 | echo "Setting RAM." >> /tmp/log 84 | 85 | # Configuring jvm.options 86 | cat > /etc/elasticsearch/jvm.options << EOF 87 | -Xms${ram}g 88 | -Xmx${ram}g 89 | -XX:+UseConcMarkSweepGC 90 | -XX:CMSInitiatingOccupancyFraction=75 91 | -XX:+UseCMSInitiatingOccupancyOnly 92 | -XX:+AlwaysPreTouch 93 | -Xss1m 94 | -Djava.awt.headless=true 95 | -Dfile.encoding=UTF-8 96 | -Djna.nosys=true 97 | -XX:-OmitStackTraceInFastThrow 98 | -Dio.netty.noUnsafe=true 99 | -Dio.netty.noKeySetOptimization=true 100 | -Dio.netty.recycler.maxCapacityPerThread=0 101 | -Dlog4j.shutdownHookEnabled=false 102 | -Dlog4j2.disable.jmx=true 103 | -Djava.io.tmpdir=\${ES_TMPDIR} 104 | -XX:+HeapDumpOnOutOfMemoryError 105 | -XX:HeapDumpPath=/var/lib/elasticsearch 106 | -XX:ErrorFile=/var/log/elasticsearch/hs_err_pid%p.log 107 | 8:-XX:+PrintGCDetails 108 | 8:-XX:+PrintGCDateStamps 109 | 8:-XX:+PrintTenuringDistribution 110 | 8:-XX:+PrintGCApplicationStoppedTime 111 | 8:-Xloggc:/var/log/elasticsearch/gc.log 112 | 8:-XX:+UseGCLogFileRotation 113 | 8:-XX:NumberOfGCLogFiles=32 114 | 8:-XX:GCLogFileSize=64m 115 | 9-:-Xlog:gc*,gc+age=trace,safepoint:file=/var/log/elasticsearch/gc.log:utctime,pid,tags:filecount=32,filesize=64m 116 | 9-:-Djava.locale.providers=COMPAT 117 | EOF 118 | echo "Setting JVM options." >> /tmp/log 119 | 120 | mkdir -p /etc/systemd/system/elasticsearch.service.d/ 121 | echo '[Service]' > /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf 122 | echo 'LimitMEMLOCK=infinity' >> /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf 123 | 124 | 125 | # Allowing unlimited memory allocation 126 | echo 'elasticsearch soft memlock unlimited' >> /etc/security/limits.conf 127 | echo 'elasticsearch hard memlock unlimited' >> /etc/security/limits.conf 128 | echo "Setting memory lock options." >> /tmp/log 129 | 130 | systemctl daemon-reload 131 | # Starting Elasticsearch 132 | echo "daemon-reload." >> /tmp/log 133 | 134 | service elasticsearch start 135 | echo "starting service." >> /tmp/log 136 | 137 | #Installing Logstash 138 | yum -y install logstash-${elastic_version} 139 | echo "Installed logstash." >> /tmp/log 140 | 141 | #Wazuh configuration for Logstash 142 | curl -so /etc/logstash/conf.d/01-wazuh.conf "https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/logstash/01-wazuh-remote.conf" 143 | sed -i "s/localhost:9200/${eth0_ip}:9200/" /etc/logstash/conf.d/01-wazuh.conf 144 | 145 | # Creating data and logs directories 146 | mkdir -p /mnt/ephemeral/logstash/lib 147 | mkdir -p /mnt/ephemeral/logstash/log 148 | chown -R logstash:logstash /mnt/ephemeral/logstash 149 | echo "Options and volumes for logstash." >> /tmp/log 150 | 151 | # Configuring logstash.yml 152 | cat > /etc/logstash/logstash.yml << 'EOF' 153 | path.data: /mnt/ephemeral/logstash/lib 154 | path.logs: /mnt/ephemeral/logstash/log 155 | path.config: /etc/logstash/conf.d/*.conf 156 | EOF 157 | 158 | # Calculating RAM for Logstash 159 | ram_gb=$(free -g | awk '/^Mem:/{print $2}') 160 | ram=$(( ${ram_gb} / 4 )) 161 | if [ $ram -eq "0" ]; then ram=1; fi 162 | 163 | # Configuring jvm.options 164 | cat > /etc/logstash/jvm.options << EOF 165 | -Xms${ram}g 166 | -Xmx${ram}g 167 | -XX:+UseParNewGC 168 | -XX:+UseConcMarkSweepGC 169 | -XX:CMSInitiatingOccupancyFraction=75 170 | -XX:+UseCMSInitiatingOccupancyOnly 171 | -Djava.awt.headless=true 172 | -Dfile.encoding=UTF-8 173 | -Djruby.compile.invokedynamic=true 174 | -Djruby.jit.threshold=0 175 | -XX:+HeapDumpOnOutOfMemoryError 176 | -Djava.security.egd=file:/dev/urandom 177 | EOF 178 | 179 | # Starting Logstash 180 | service logstash restart 181 | echo "Started logstash." >> /tmp/log 182 | 183 | # Disable repositories 184 | sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo 185 | -------------------------------------------------------------------------------- /iam.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Provides the base security, IAM, and access configuration for the AWS 4 | account (qs-1nb14cqc0) 5 | Metadata: 6 | Stack: 7 | Value: 1 8 | VersionDate: 9 | Value: 20160510 10 | Identifier: 11 | Value: template-iam 12 | Input: 13 | Description: CloudTrail bucket name 14 | Output: 15 | Description: Outputs ID of all deployed resources 16 | Resources: 17 | rSysAdminRole: 18 | Type: AWS::IAM::Role 19 | Properties: 20 | AssumeRolePolicyDocument: 21 | Statement: 22 | - Effect: Allow 23 | Principal: 24 | Service: 25 | - ec2.amazonaws.com 26 | Action: 27 | - sts:AssumeRole 28 | rSysAdminProfile: 29 | Type: AWS::IAM::InstanceProfile 30 | DependsOn: rSysAdminRole 31 | Properties: 32 | Path: / 33 | Roles: 34 | - !Ref rSysAdminRole 35 | rSysAdmin: 36 | Type: AWS::IAM::Group 37 | Properties: 38 | Path: / 39 | rSysAdminPolicy: 40 | Type: AWS::IAM::ManagedPolicy 41 | Properties: 42 | PolicyDocument: 43 | Version: 2012-10-17 44 | Statement: 45 | - Effect: Allow 46 | NotAction: iam:* 47 | Resource: '*' 48 | Condition: 49 | Bool: 50 | aws:MultiFactorAuthPresent: true 51 | - Effect: Deny 52 | Action: aws-portal:*Billing 53 | Resource: '*' 54 | - Effect: Deny 55 | Action: 56 | - cloudtrail:DeleteTrail 57 | - cloudtrail:StopLogging 58 | - cloudtrail:UpdateTrail 59 | Resource: '*' 60 | - Effect: Deny 61 | Action: 62 | - kms:Create* 63 | - kms:Revoke* 64 | - kms:Enable* 65 | - kms:Get* 66 | - kms:Disable* 67 | - kms:Delete* 68 | - kms:Put* 69 | - kms:Update* 70 | Resource: '*' 71 | Roles: 72 | - !Ref rSysAdminRole 73 | Groups: 74 | - !Ref rSysAdmin 75 | rIAMAdminGroup: 76 | Type: AWS::IAM::Group 77 | Properties: 78 | Path: / 79 | rIAMAdminRole: 80 | Type: AWS::IAM::Role 81 | Properties: 82 | AssumeRolePolicyDocument: 83 | Statement: 84 | - Effect: Allow 85 | Principal: 86 | Service: 87 | - ec2.amazonaws.com 88 | Action: 89 | - sts:AssumeRole 90 | rIAMAdminProfile: 91 | Type: AWS::IAM::InstanceProfile 92 | DependsOn: rIAMAdminRole 93 | Properties: 94 | Path: / 95 | Roles: 96 | - !Ref rIAMAdminRole 97 | rIAMAdminPolicy: 98 | Type: AWS::IAM::ManagedPolicy 99 | Properties: 100 | PolicyDocument: 101 | Version: 2012-10-17 102 | Statement: 103 | - Effect: Allow 104 | Action: iam:* 105 | Resource: '*' 106 | Condition: 107 | Bool: 108 | aws:MultiFactorAuthPresent: true 109 | - Effect: Deny 110 | Action: aws-portal:*Billing 111 | Resource: '*' 112 | Roles: 113 | - !Ref rIAMAdminRole 114 | Groups: 115 | - !Ref rIAMAdminGroup 116 | rInstanceOpsGroup: 117 | Type: AWS::IAM::Group 118 | Properties: 119 | Path: / 120 | rInstanceOpsRole: 121 | Type: AWS::IAM::Role 122 | Properties: 123 | AssumeRolePolicyDocument: 124 | Statement: 125 | - Effect: Allow 126 | Principal: 127 | Service: 128 | - ec2.amazonaws.com 129 | Action: 130 | - sts:AssumeRole 131 | rInstanceOpsProfile: 132 | Type: AWS::IAM::InstanceProfile 133 | DependsOn: rIAMAdminRole 134 | Properties: 135 | Path: / 136 | Roles: 137 | - !Ref rInstanceOpsRole 138 | rInstanceOpsPolicy: 139 | Type: AWS::IAM::ManagedPolicy 140 | Properties: 141 | PolicyDocument: 142 | Version: 2012-10-17 143 | Statement: 144 | - Action: ec2:* 145 | Effect: Allow 146 | Resource: '*' 147 | - Effect: Allow 148 | Action: elasticloadbalancing:* 149 | Resource: '*' 150 | - Effect: Allow 151 | Action: cloudwatch:* 152 | Resource: '*' 153 | - Effect: Allow 154 | Action: autoscaling:* 155 | Resource: '*' 156 | - Effect: Deny 157 | Action: 158 | - ec2:CreateVpc* 159 | - ec2:DeleteVpc* 160 | - ec2:ModifyVpc* 161 | - ec2:CreateSubnet* 162 | - ec2:DeleteSubnet* 163 | - ec2:ModifySubnet* 164 | - ec2:Create*Route* 165 | - ec2:DeleteRoute* 166 | - ec2:AssociateRoute* 167 | - ec2:ReplaceRoute* 168 | - ec2:CreateVpn* 169 | - ec2:DeleteVpn* 170 | - ec2:AttachVpn* 171 | - ec2:DetachVpn* 172 | - ec2:CreateNetworkAcl* 173 | - ec2:DeleteNetworkAcl* 174 | - ec2:ReplaceNetworkAcl* 175 | - ec2:*Gateway* 176 | - ec2:*PeeringConnection* 177 | Resource: '*' 178 | - Effect: Deny 179 | Action: aws-portal:*Billing 180 | Resource: '*' 181 | - Effect: Deny 182 | Action: 183 | - kms:Create* 184 | - kms:Revoke* 185 | - kms:Enable* 186 | - kms:Get* 187 | - kms:Disable* 188 | - kms:Delete* 189 | - kms:Put* 190 | - kms:Update* 191 | Resource: '*' 192 | Roles: 193 | - !Ref rInstanceOpsRole 194 | Groups: 195 | - !Ref rInstanceOpsGroup 196 | rReadOnlyAdminGroup: 197 | Type: AWS::IAM::Group 198 | Properties: 199 | Path: / 200 | rReadOnlyAdminRole: 201 | Type: AWS::IAM::Role 202 | Properties: 203 | AssumeRolePolicyDocument: 204 | Statement: 205 | - Effect: Allow 206 | Principal: 207 | Service: 208 | - ec2.amazonaws.com 209 | Action: 210 | - sts:AssumeRole 211 | rReadOnlyAdminProfile: 212 | Type: AWS::IAM::InstanceProfile 213 | DependsOn: rReadOnlyAdminRole 214 | Properties: 215 | Path: / 216 | Roles: 217 | - !Ref rReadOnlyAdminRole 218 | rReadOnlyAdminPolicy: 219 | Type: AWS::IAM::ManagedPolicy 220 | DependsOn: rReadOnlyAdminProfile 221 | Properties: 222 | PolicyDocument: 223 | Version: 2012-10-17 224 | Statement: 225 | - Action: 226 | - appstream:Get* 227 | - autoscaling:Describe* 228 | - cloudformation:DescribeStacks 229 | - cloudformation:DescribeStackEvents 230 | - cloudformation:DescribeStackResource 231 | - cloudformation:DescribeStackResources 232 | - cloudformation:GetTemplate 233 | - cloudformation:List* 234 | - cloudfront:Get* 235 | - cloudfront:List* 236 | - cloudtrail:DescribeTrails 237 | - cloudtrail:GetTrailStatus 238 | - cloudwatch:Describe* 239 | - cloudwatch:Get* 240 | - cloudwatch:List* 241 | - directconnect:Describe* 242 | - dynamodb:GetItem 243 | - dynamodb:BatchGetItem 244 | - dynamodb:Query 245 | - dynamodb:Scan 246 | - dynamodb:DescribeTable 247 | - dynamodb:ListTables 248 | - ec2:Describe* 249 | - elasticache:Describe* 250 | - elasticbeanstalk:Check* 251 | - elasticbeanstalk:Describe* 252 | - elasticbeanstalk:List* 253 | - elasticbeanstalk:RequestEnvironmentInfo 254 | - elasticbeanstalk:RetrieveEnvironmentInfo 255 | - elasticloadbalancing:Describe* 256 | - elastictranscoder:Read* 257 | - elastictranscoder:List* 258 | - iam:List* 259 | - iam:Get* 260 | - kinesis:Describe* 261 | - kinesis:Get* 262 | - kinesis:List* 263 | - opsworks:Describe* 264 | - opsworks:Get* 265 | - route53:Get* 266 | - route53:List* 267 | - redshift:Describe* 268 | - redshift:ViewQueriesInConsole 269 | - rds:Describe* 270 | - rds:ListTagsForResource 271 | - s3:Get* 272 | - s3:List* 273 | - sdb:GetAttributes 274 | - sdb:List* 275 | - sdb:Select* 276 | - ses:Get* 277 | - ses:List* 278 | - sns:Get* 279 | - sns:List* 280 | - sqs:GetQueueAttributes 281 | - sqs:ListQueues 282 | - sqs:ReceiveMessage 283 | - storagegateway:List* 284 | - storagegateway:Describe* 285 | - trustedadvisor:Describe* 286 | Effect: Allow 287 | Resource: '*' 288 | - Effect: Deny 289 | Action: aws-portal:*Billing 290 | Resource: '*' 291 | Roles: 292 | - !Ref rReadOnlyAdminRole 293 | Groups: 294 | - !Ref rReadOnlyAdminGroup 295 | rReadOnlyBillingGroup: 296 | Type: AWS::IAM::Group 297 | Properties: 298 | Path: / 299 | rReadOnlyBillingPolicy: 300 | Type: AWS::IAM::ManagedPolicy 301 | Properties: 302 | PolicyDocument: 303 | Version: 2012-10-17 304 | Statement: 305 | - Effect: Allow 306 | Action: aws-portal:View* 307 | Resource: '*' 308 | - Effect: Deny 309 | Action: aws-portal:*Account 310 | Resource: '*' 311 | Groups: 312 | - !Ref rReadOnlyBillingGroup 313 | Outputs: 314 | rSysAdmin: 315 | Value: !Ref rSysAdmin 316 | rIAMAdminGroup: 317 | Value: !Ref rIAMAdminGroup 318 | rInstanceOpsGroup: 319 | Value: !Ref rInstanceOpsGroup 320 | rReadOnlyBillingGroup: 321 | Value: !Ref rReadOnlyBillingGroup 322 | rReadOnlyAdminGroup: 323 | Value: !Ref rReadOnlyAdminGroup 324 | ... -------------------------------------------------------------------------------- /elastic/wazuh_cf_kibana.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Install Kibana instance using Cloudformation template 3 | # Support for Amazon Linux 4 | touch /tmp/log 5 | echo "Starting process." > /tmp/log 6 | 7 | ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2) 8 | ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2) 9 | elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1) 10 | wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2) 11 | wazuh_major=`echo ${wazuh_version} | cut -d'.' -f 1` 12 | kibana_port=$(cat /tmp/wazuh_cf_settings | grep '^KibanaPort:' | cut -d' ' -f2) 13 | kibana_username=$(cat /tmp/wazuh_cf_settings | grep '^KibanaUsername:' | cut -d' ' -f2) 14 | kibana_password=$(cat /tmp/wazuh_cf_settings | grep '^KibanaPassword:' | cut -d' ' -f2) 15 | eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2) 16 | wazuh_master_ip=$(cat /tmp/wazuh_cf_settings | grep '^WazuhMasterIP:' | cut -d' ' -f2) 17 | wazuh_api_user=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminUsername:' | cut -d' ' -f2) 18 | wazuh_api_password=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminPassword:' | cut -d' ' -f2) 19 | wazuh_api_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiPort:' | cut -d' ' -f2) 20 | echo "Added env vars." >> /tmp/log 21 | 22 | # Check if running as root 23 | if [[ $EUID -ne 0 ]]; then 24 | echo "This script must be run as root" 25 | exit 1 26 | fi 27 | echo "Running as root." >> /tmp/log 28 | 29 | # Creating SSH user 30 | if ! id -u ${ssh_username} > /dev/null 2>&1; then adduser ${ssh_username}; fi 31 | echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers 32 | usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username} 33 | sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config 34 | service sshd restart 35 | 36 | # Uninstall OpenJDK 1.7 if exists 37 | if rpm -q java-1.7.0-openjdk > /dev/null; then yum -y remove java-1.7.0-openjdk; fi 38 | 39 | # Install OpenJDK 1.8 40 | yum -y install java-1.8.0-openjdk 41 | 42 | # Configuring Elastic repository 43 | rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch 44 | elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1) 45 | cat > /etc/yum.repos.d/elastic.repo << EOF 46 | [elasticsearch-${elastic_major_version}.x] 47 | name=Elasticsearch repository for ${elastic_major_version}.x packages 48 | baseurl=https://artifacts.elastic.co/packages/${elastic_major_version}.x/yum 49 | gpgcheck=1 50 | gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch 51 | enabled=1 52 | autorefresh=1 53 | type=rpm-md 54 | EOF 55 | echo "Added Elasticsearch repo." >> /tmp/log 56 | 57 | # Installing Elasticsearch 58 | yum -y install elasticsearch-${elastic_version} 59 | chkconfig --add elasticsearch 60 | echo "Installed Elasticsearch." >> /tmp/log 61 | 62 | # Installing Elasticsearch plugin for EC2 63 | /usr/share/elasticsearch/bin/elasticsearch-plugin install --batch discovery-ec2 64 | echo "Installed EC2 plugin." >> /tmp/log 65 | 66 | # Configuration file created by AWS Cloudformation template 67 | mv -f /tmp/wazuh_cf_elasticsearch.yml /etc/elasticsearch/elasticsearch.yml 68 | chown elasticsearch:elasticsearch /etc/elasticsearch/elasticsearch.yml 69 | echo "Copying YML to elasticsearch folder." >> /tmp/log 70 | 71 | # Calculating RAM for Elasticsearch 72 | ram_gb=$(free -g | awk '/^Mem:/{print $2}') 73 | ram=$(( ${ram_gb} / 2 )) 74 | if [ $ram -eq "0" ]; then ram=1; fi 75 | echo "RAM parameters." >> /tmp/log 76 | 77 | # Configuring jvm.options 78 | cat > /etc/elasticsearch/jvm.options << EOF 79 | -Xms${ram}g 80 | -Xmx${ram}g 81 | -XX:+UseConcMarkSweepGC 82 | -XX:CMSInitiatingOccupancyFraction=75 83 | -XX:+UseCMSInitiatingOccupancyOnly 84 | -XX:+AlwaysPreTouch 85 | -Xss1m 86 | -Djava.awt.headless=true 87 | -Dfile.encoding=UTF-8 88 | -Djna.nosys=true 89 | -XX:-OmitStackTraceInFastThrow 90 | -Dio.netty.noUnsafe=true 91 | -Dio.netty.noKeySetOptimization=true 92 | -Dio.netty.recycler.maxCapacityPerThread=0 93 | -Dlog4j.shutdownHookEnabled=false 94 | -Dlog4j2.disable.jmx=true 95 | -Djava.io.tmpdir=\${ES_TMPDIR} 96 | -XX:+HeapDumpOnOutOfMemoryError 97 | -XX:HeapDumpPath=/var/lib/elasticsearch 98 | -XX:ErrorFile=/var/log/elasticsearch/hs_err_pid%p.log 99 | 8:-XX:+PrintGCDetails 100 | 8:-XX:+PrintGCDateStamps 101 | 8:-XX:+PrintTenuringDistribution 102 | 8:-XX:+PrintGCApplicationStoppedTime 103 | 8:-Xloggc:/var/log/elasticsearch/gc.log 104 | 8:-XX:+UseGCLogFileRotation 105 | 8:-XX:NumberOfGCLogFiles=32 106 | 8:-XX:GCLogFileSize=64m 107 | 9-:-Xlog:gc*,gc+age=trace,safepoint:file=/var/log/elasticsearch/gc.log:utctime,pid,tags:filecount=32,filesize=64m 108 | 9-:-Djava.locale.providers=COMPAT 109 | EOF 110 | 111 | mkdir -p /etc/systemd/system/elasticsearch.service.d/ 112 | echo '[Service]' > /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf 113 | echo 'LimitMEMLOCK=infinity' >> /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf 114 | 115 | # Allowing unlimited memory allocation 116 | echo 'elasticsearch soft memlock unlimited' >> /etc/security/limits.conf 117 | echo 'elasticsearch hard memlock unlimited' >> /etc/security/limits.conf 118 | echo "Setting memory lock options." >> /tmp/log 119 | 120 | systemctl daemon-reload 121 | echo "daemon-reload." >> /tmp/log 122 | 123 | # Starting Elasticsearch 124 | service elasticsearch start 125 | sleep 60 126 | echo "Started service." >> /tmp/log 127 | 128 | # Loading and tuning Wazuh alerts template 129 | url_alerts_template="https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/elasticsearch/wazuh-elastic6-template-alerts.json" 130 | alerts_template="/tmp/wazuh-elastic6-template-alerts.json" 131 | curl -Lo ${alerts_template} ${url_alerts_template} 132 | curl -XPUT "http://${eth0_ip}:9200/_template/wazuh" -H 'Content-Type: application/json' -d@${alerts_template} 133 | curl -XDELETE "http://${eth0_ip}:9200/wazuh-alerts-*" 134 | echo "Added template." >> /tmp/log 135 | 136 | # Installing Kibana 137 | yum -y install kibana-${elastic_version} 138 | chkconfig --add kibana 139 | echo "Kibana installed." >> /tmp/log 140 | 141 | # Configuring kibana.yml 142 | cat > /etc/kibana/kibana.yml << EOF 143 | elasticsearch.url: "http://${eth0_ip}:9200" 144 | server.port: 5601 145 | server.host: "localhost" 146 | server.ssl.enabled: false 147 | EOF 148 | echo "Kibana.yml configured." >> /tmp/log 149 | 150 | # Allow Kibana to listen on privileged ports 151 | setcap 'CAP_NET_BIND_SERVICE=+eip' /usr/share/kibana/node/bin/node 152 | echo "Setcap executed" >> /tmp/log 153 | 154 | # Configuring Kibana default settings 155 | cat > /etc/default/kibana << 'EOF' 156 | ser="kibana" 157 | group="kibana" 158 | chroot="/" 159 | chdir="/" 160 | nice="" 161 | KILL_ON_STOP_TIMEOUT=0 162 | NODE_OPTIONS="--max-old-space-size=4096" 163 | EOF 164 | echo "/etc/default/kibana completed" >> /tmp/log 165 | 166 | # Installing Wazuh plugin for Kibana 167 | plugin_url="https://packages.wazuh.com/wazuhapp/wazuhapp-3.8.2_6.7.0.zip" 168 | NODE_OPTIONS="--max-old-space-size=4096" /usr/share/kibana/bin/kibana-plugin install ${plugin_url} 169 | cat >> /usr/share/kibana/plugins/wazuh/config.yml << 'EOF' 170 | wazuh.shards: 1 171 | wazuh.replicas: 1 172 | wazuh-version.shards: 1 173 | wazuh-version.replicas: 1 174 | wazuh.monitoring.shards: 1 175 | wazuh.monitoring.replicas: 1 176 | EOF 177 | echo "App installed!" >> /tmp/log 178 | 179 | # Configuring Wazuh API for Kibana plugin 180 | api_config="/tmp/api_config.json" 181 | api_time=$(($(date +%s%N)/1000000)) 182 | wazuh_api_password_base64=`echo -n ${wazuh_api_password} | base64` 183 | 184 | # Enabling extensions 185 | sed -i "s/#extensions.docker : false/extensions.docker : true/" /usr/share/kibana/plugins/wazuh/config.yml 186 | sed -i "s/#extensions.aws : false/extensions.aws : true/" /usr/share/kibana/plugins/wazuh/config.yml 187 | sed -i "s/#extensions.osquery : false/extensions.osquery : true/" /usr/share/kibana/plugins/wazuh/config.yml 188 | sed -i "s/#extensions.oscap : false/extensions.oscap : true/" /usr/share/kibana/plugins/wazuh/config.yml 189 | sed -i "s/#extensions.virustotal : false/extensions.virustotal : true/" /usr/share/kibana/plugins/wazuh/config.yml 190 | 191 | cat > ${api_config} << EOF 192 | { 193 | "api_user": "${wazuh_api_user}", 194 | "api_password": "${wazuh_api_password_base64}", 195 | "url": "https://${wazuh_master_ip}", 196 | "api_port": "${wazuh_api_port}", 197 | "insecure": "false", 198 | "component": "API", 199 | "cluster_info": { 200 | "manager": "wazuh-manager", 201 | "cluster": "disabled", 202 | "status": "disabled" 203 | } 204 | } 205 | EOF 206 | 207 | curl -s -XPUT "http://${eth0_ip}:9200/.wazuh/wazuh-configuration/${api_time}" -H 'Content-Type: application/json' -d@${api_config} 208 | rm -f ${api_config} 209 | echo "Configured API" >> /tmp/log 210 | 211 | # Starting Kibana 212 | service kibana start 213 | sleep 60 214 | echo "Started Kibana" >> /tmp/log 215 | 216 | # Configuring default index pattern for Kibana 217 | default_index="/tmp/default_index.json" 218 | 219 | cat > ${default_index} << EOF 220 | { 221 | "changes": { 222 | "defaultIndex": "wazuh-alerts-3.x-*" 223 | } 224 | } 225 | EOF 226 | 227 | curl -POST "http://localhost:5601/api/kibana/settings" -H "Content-Type: application/json" -H "kbn-xsrf: true" -d@${default_index} 228 | rm -f ${default_index} 229 | 230 | # Configuring Kibana TimePicker 231 | curl -POST "http://localhost:5601/api/kibana/settings" -H "Content-Type: application/json" -H "kbn-xsrf: true" -d \ 232 | '{"changes":{"timepicker:timeDefaults":"{\n \"from\": \"now-24h\",\n \"to\": \"now\",\n \"mode\": \"quick\"}"}}' 233 | 234 | # Do not ask user to help providing usage statistics to Elastic 235 | curl -POST "http://localhost:5601/api/telemetry/v1/optIn" -H "Content-Type: application/json" -H "kbn-xsrf: true" -d '{"enabled":false}' 236 | 237 | # Disable Elastic repository 238 | sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo 239 | echo "Configured Kibana" >> /tmp/log 240 | echo "Installing NGINX..." >> /tmp/log 241 | 242 | # Install Nginx ang generate certificates 243 | sudo amazon-linux-extras install nginx1.12 244 | mkdir -p /etc/ssl/certs /etc/ssl/private 245 | openssl req -x509 -batch -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/kibana.key -out /etc/ssl/certs/kibana.pem 246 | echo "Installed NGINX." >> /tmp/log 247 | 248 | # Installing htpasswd (needed for Amazon Linux) 249 | yum install httpd-tools-2.4.33-2.amzn2.0.2.x86_64 -y 250 | 251 | # Configure Nginx 252 | htpasswd -b -c /etc/nginx/conf.d/kibana.htpasswd ${kibana_username} ${kibana_password} 253 | cat > /etc/nginx/conf.d/kibana.conf << EOF 254 | server { 255 | listen ${kibana_port} default_server; 256 | listen [::]:${kibana_port}; 257 | access_log /var/log/nginx/nginx.access.log; 258 | error_log /var/log/nginx/nginx.error.log; 259 | location / { 260 | auth_basic "Restricted"; 261 | auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd; 262 | proxy_pass http://127.0.0.1:5601/; 263 | } 264 | } 265 | EOF 266 | 267 | # Starting Nginx 268 | service nginx restart 269 | echo "Restarted NGINX..." >> /tmp/log 270 | -------------------------------------------------------------------------------- /config-rules.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Sets up AWS Config Rules (qs-1nb14cqcq) 4 | Metadata: 5 | Stack: 6 | Value: 0 7 | VersionDate: 8 | Value: 4012016 9 | Identifier: 10 | Value: template-config-rules 11 | Input: 12 | Description: optional tag key 13 | Output: 14 | Description: Outputs ID of all deployed resources 15 | RegionSupport: 16 | Value: NOTGOVCLOUD 17 | Parameters: 18 | pRequiredTagKey: 19 | Description: Tag key to check for with EC2/EBS REQUIRED_TAGS rule (optional, leave 20 | blank to ignore) 21 | Type: String 22 | Conditions: 23 | cRequiredTagsRule: 24 | !Not 25 | - !Equals 26 | - '' 27 | - !Ref pRequiredTagKey 28 | cApprovedAMIsRule: 29 | !Not 30 | - !Equals 31 | - '' 32 | - '' 33 | Resources: 34 | rConfigRuleForSSH: 35 | Type: AWS::Config::ConfigRule 36 | Properties: 37 | ConfigRuleName: check-for-unrestricted-ssh-access 38 | Description: Checks whether security groups that are in use disallow unrestricted 39 | incoming SSH traffic. 40 | Scope: 41 | ComplianceResourceTypes: 42 | - AWS::EC2::SecurityGroup 43 | Source: 44 | Owner: AWS 45 | SourceIdentifier: INCOMING_SSH_DISABLED 46 | rConfigRuleForRequiredTags: 47 | Type: AWS::Config::ConfigRule 48 | Condition: cRequiredTagsRule 49 | Properties: 50 | ConfigRuleName: check-ec2-for-required-tag 51 | Description: Checks whether EC2 instances and volumes use the required tag. 52 | InputParameters: 53 | tag1Key: !Ref pRequiredTagKey 54 | Scope: 55 | ComplianceResourceTypes: 56 | - AWS::EC2::Volume 57 | - AWS::EC2::Instance 58 | Source: 59 | Owner: AWS 60 | SourceIdentifier: REQUIRED_TAGS 61 | rConfigRuleForUnrestrictedPorts: 62 | Type: AWS::Config::ConfigRule 63 | Condition: cRequiredTagsRule 64 | Properties: 65 | ConfigRuleName: check-for-unrestricted-ports 66 | Description: Checks whether security groups that are in use disallow unrestricted 67 | incoming TCP traffic to the specified ports. 68 | InputParameters: 69 | blockedPort1: 3389 70 | Scope: 71 | ComplianceResourceTypes: 72 | - AWS::EC2::SecurityGroup 73 | Source: 74 | Owner: AWS 75 | SourceIdentifier: RESTRICTED_INCOMING_TRAFFIC 76 | rConfigRulesLambdaRole: 77 | Type: AWS::IAM::Role 78 | Properties: 79 | AssumeRolePolicyDocument: 80 | Version: 2012-10-17 81 | Statement: 82 | - Effect: Allow 83 | Principal: 84 | Service: 85 | - lambda.amazonaws.com 86 | Action: 87 | - sts:AssumeRole 88 | Path: / 89 | rConfigRulesLambdaPolicy: 90 | Type: AWS::IAM::Policy 91 | Properties: 92 | PolicyName: configrules 93 | PolicyDocument: 94 | Version: 2012-10-17 95 | Statement: 96 | - Effect: Allow 97 | Action: '*' 98 | Resource: '*' 99 | Roles: 100 | - !Ref rConfigRulesLambdaRole 101 | rConfigRulesLambdaProfile: 102 | Type: AWS::IAM::InstanceProfile 103 | Properties: 104 | Path: / 105 | Roles: 106 | - !Ref rConfigRulesLambdaRole 107 | rAMIComplianceFunction: 108 | Type: AWS::Lambda::Function 109 | DependsOn: rConfigRulesLambdaRole 110 | Condition: cApprovedAMIsRule 111 | Properties: 112 | Code: 113 | ZipFile: | 114 | var aws = require('aws-sdk'); 115 | var config = new aws.ConfigService(); 116 | 117 | // Custom rule for evaluating pre-approved AMI use 118 | function evaluateCompliance(configurationItem, ruleParameters, context) { 119 | if(configurationItem.resourceType !== 'AWS::EC2::Instance') 120 | return 'NOT_APPLICABLE'; 121 | 122 | var amiIDs = ruleParameters.amiList.split(','); 123 | if (amiIDs.indexOf(configurationItem.configuration.imageId) > -1) { 124 | return 'COMPLIANT'; 125 | } 126 | else return 'NON_COMPLIANT'; 127 | } 128 | 129 | function isApplicable(configurationItem, event) { 130 | var status = configurationItem.configurationItemStatus; 131 | var eventLeftScope = event.eventLeftScope; 132 | return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false; 133 | } 134 | 135 | exports.handler = function(event, context) { 136 | var invokingEvent = JSON.parse(event.invokingEvent); 137 | var ruleParameters = JSON.parse(event.ruleParameters); 138 | var compliance = 'NOT_APPLICABLE'; 139 | 140 | if (isApplicable(invokingEvent.configurationItem, event)) 141 | compliance = evaluateCompliance(invokingEvent.configurationItem, ruleParameters, context); // Invoke the compliance checking function. 142 | 143 | var putEvaluationsRequest = { 144 | Evaluations: [ 145 | { 146 | ComplianceResourceType: invokingEvent.configurationItem.resourceType, 147 | ComplianceResourceId: invokingEvent.configurationItem.resourceId, 148 | ComplianceType: compliance, 149 | OrderingTimestamp: invokingEvent.configurationItem.configurationItemCaptureTime 150 | } 151 | ], 152 | ResultToken: event.resultToken 153 | }; 154 | 155 | config.putEvaluations(putEvaluationsRequest, function (err, data) { 156 | if (err) { 157 | context.fail(err); 158 | } else { 159 | context.succeed(data); 160 | } 161 | }); 162 | }; 163 | Handler: index.handler 164 | Runtime: nodejs8.10 165 | Timeout: 30 166 | Role: 167 | !GetAtt 168 | - rConfigRulesLambdaRole 169 | - Arn 170 | rConfigRuleForAMICompliance: 171 | Type: AWS::Config::ConfigRule 172 | Condition: cApprovedAMIsRule 173 | Properties: 174 | ConfigRuleName: check-for-ami-compliance 175 | Description: Checks whether approved AMIs are used. 176 | Scope: 177 | ComplianceResourceTypes: 178 | - AWS::EC2::Instance 179 | InputParameters: 180 | amiList: '' 181 | Source: 182 | Owner: CUSTOM_LAMBDA 183 | SourceDetails: 184 | - EventSource: aws.config 185 | MessageType: ConfigurationItemChangeNotification 186 | SourceIdentifier: 187 | !GetAtt 188 | - rAMIComplianceFunction 189 | - Arn 190 | DependsOn: rConfigPermissionToCallLambdaAMICompliance 191 | rConfigPermissionToCallLambdaAMICompliance: 192 | Type: AWS::Lambda::Permission 193 | Condition: cApprovedAMIsRule 194 | Properties: 195 | FunctionName: 196 | !GetAtt 197 | - rAMIComplianceFunction 198 | - Arn 199 | Action: lambda:InvokeFunction 200 | Principal: config.amazonaws.com 201 | rCloudTrailValidationFunction: 202 | Type: AWS::Lambda::Function 203 | DependsOn: rConfigRulesLambdaRole 204 | Properties: 205 | Code: 206 | ZipFile: | 207 | var aws = require('aws-sdk'); 208 | var config = new aws.ConfigService(); 209 | 210 | // Custom rule for evaluating CloudTrail configuration compliance 211 | // 3 config parameters for Trail must be true: Multi-Region, Global Services Events, and Log File Validation 212 | function evaluateCompliance(configurationItem, ruleParameters, context) { 213 | if(configurationItem.resourceType !== 'AWS::CloudTrail::Trail') 214 | return 'NOT_APPLICABLE'; 215 | 216 | if((configurationItem.configuration.logFileValidationEnabled) && (configurationItem.configuration.includeGlobalServiceEvents) && (configurationItem.configuration.isMultiRegionTrail)) { 217 | return 'COMPLIANT'; 218 | } 219 | else return 'NON_COMPLIANT'; 220 | } 221 | 222 | function isApplicable(configurationItem, event) { 223 | var status = configurationItem.configurationItemStatus; 224 | var eventLeftScope = event.eventLeftScope; 225 | return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false; 226 | } 227 | 228 | exports.handler = function(event, context) { 229 | var invokingEvent = JSON.parse(event.invokingEvent); 230 | var ruleParameters = JSON.parse(event.ruleParameters); 231 | var compliance = 'NOT_APPLICABLE'; 232 | 233 | if (isApplicable(invokingEvent.configurationItem, event)) 234 | compliance = evaluateCompliance(invokingEvent.configurationItem, ruleParameters, context); // Invoke the compliance checking function. 235 | 236 | var putEvaluationsRequest = { 237 | Evaluations: [ 238 | { 239 | ComplianceResourceType: invokingEvent.configurationItem.resourceType, 240 | ComplianceResourceId: invokingEvent.configurationItem.resourceId, 241 | ComplianceType: compliance, 242 | OrderingTimestamp: invokingEvent.configurationItem.configurationItemCaptureTime 243 | } 244 | ], 245 | ResultToken: event.resultToken 246 | }; 247 | config.putEvaluations(putEvaluationsRequest, function (err, data) { 248 | if (err) { 249 | context.fail(err); 250 | } else { 251 | context.succeed(data); 252 | } 253 | }); 254 | }; 255 | Handler: index.handler 256 | Runtime: nodejs8.10 257 | Timeout: 30 258 | Role: 259 | !GetAtt 260 | - rConfigRulesLambdaRole 261 | - Arn 262 | rConfigRuleForCloudTrail: 263 | Type: AWS::Config::ConfigRule 264 | Properties: 265 | ConfigRuleName: check-whether-cloudtrail-is-enabled 266 | Description: Checks whether CloudTrail is enabled in this region. 267 | Scope: 268 | ComplianceResourceTypes: 269 | - AWS::EC2::Instance 270 | Source: 271 | Owner: CUSTOM_LAMBDA 272 | SourceDetails: 273 | - EventSource: aws.config 274 | MessageType: ConfigurationItemChangeNotification 275 | SourceIdentifier: 276 | !GetAtt 277 | - rCloudTrailValidationFunction 278 | - Arn 279 | DependsOn: rConfigPermissionToCallLambdaCloudTrail 280 | rConfigPermissionToCallLambdaCloudTrail: 281 | Type: AWS::Lambda::Permission 282 | Properties: 283 | FunctionName: 284 | !GetAtt 285 | - rCloudTrailValidationFunction 286 | - Arn 287 | Action: lambda:InvokeFunction 288 | Principal: config.amazonaws.com 289 | ... -------------------------------------------------------------------------------- /wazuh/cluster/wazuh_cf_worker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Install Wazuh worker instance using Cloudformation template 3 | # Support for Amazon Linux 4 | touch /tmp/log 5 | echo "Starting process." >> /tmp/log 6 | 7 | ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2) 8 | ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2) 9 | elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1) 10 | wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2) 11 | wazuh_server_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhServerPort:' | cut -d' ' -f2) 12 | wazuh_cluster_key=$(cat /tmp/wazuh_cf_settings | grep '^WazuhClusterKey:' | cut -d' ' -f2) 13 | wazuh_master_ip=$(cat /tmp/wazuh_cf_settings | grep '^WazuhMasterIP:' | cut -d' ' -f2) 14 | elb_logstash=$(cat /tmp/wazuh_cf_settings | grep '^ElbLogstashDNS:' | cut -d' ' -f2) 15 | VirusTotalKey=$(cat /tmp/wazuh_cf_settings | grep '^VirusTotalKey:' | cut -d' ' -f2) 16 | AwsSecretKey=$(cat /tmp/wazuh_cf_settings | grep '^AwsSecretKey:' | cut -d' ' -f2) 17 | AwsAccessKey=$(cat /tmp/wazuh_cf_settings | grep '^AwsAccessKey:' | cut -d' ' -f2) 18 | SlackHook=$(cat /tmp/wazuh_cf_settings | grep '^SlackHook:' | cut -d' ' -f2) 19 | EnvironmentType=$(cat /tmp/wazuh_cf_settings | grep '^EnvironmentType:' | cut -d' ' -f2) 20 | 21 | # Check if running as root 22 | if [[ $EUID -ne 0 ]]; then 23 | echo "This script must be run as root" 24 | exit 1 25 | fi 26 | 27 | # Creating SSH user 28 | adduser ${ssh_username} 29 | echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers 30 | usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username} 31 | sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config 32 | service sshd restart 33 | echo "Created SSH user." >> /tmp/log 34 | 35 | if [[ ${EnvironmentType} == 'staging' ]] 36 | then 37 | # Adding Wazuh pre_release repository 38 | echo -e '[wazuh_pre_release]\ngpgcheck=1\ngpgkey=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/key/GPG-KEY-WAZUH\nenabled=1\nname=EL-$releasever - Wazuh\nbaseurl=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/pre-release/yum/\nprotect=1' | tee /etc/yum.repos.d/wazuh_pre.repo 39 | elif [[ ${EnvironmentType} == 'production' ]] 40 | then 41 | cat > /etc/yum.repos.d/wazuh.repo <<\EOF 42 | [wazuh_repo] 43 | gpgcheck=1 44 | gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH 45 | enabled=1 46 | name=Wazuh repository 47 | baseurl=https://packages.wazuh.com/3.x/yum/ 48 | protect=1 49 | EOF 50 | elif [[ ${EnvironmentType} == 'devel' ]] 51 | then 52 | echo -e '[wazuh_staging]\ngpgcheck=1\ngpgkey=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/key/GPG-KEY-WAZUH\nenabled=1\nname=EL-$releasever - Wazuh\nbaseurl=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/staging/yum/\nprotect=1' | tee /etc/yum.repos.d/wazuh_staging.repo 53 | else 54 | echo 'no repo' >> /tmp/stage 55 | fi 56 | 57 | # Configuring Elastic repository 58 | rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch 59 | elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1) 60 | cat > /etc/yum.repos.d/elastic.repo << EOF 61 | [elasticsearch-6.x] 62 | name=Elasticsearch repository for 6.x packages 63 | baseurl=https://artifacts.elastic.co/packages/6.x/yum 64 | gpgcheck=1 65 | gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch 66 | enabled=1 67 | autorefresh=1 68 | type=rpm-md 69 | EOF 70 | 71 | # Installing wazuh-manager 72 | yum -y install wazuh-manager 73 | chkconfig --add wazuh-manager 74 | manager_config="/var/ossec/etc/ossec.conf" 75 | # Install dependencies 76 | yum -y install openscap-scanner 77 | 78 | echo "Installed wazuh manager package" >> /tmp/log 79 | 80 | # Change manager protocol to tcp, to be used by Amazon ELB 81 | sed -i "s/udp<\/protocol>/tcp<\/protocol>/" ${manager_config} 82 | 83 | # Set manager ports for agents communication 84 | sed -i "s/1514<\/port>/${wazuh_server_port}<\/port>/" ${manager_config} 85 | 86 | # Installing Python Cryptography module for the cluster 87 | pip install cryptography 88 | echo "Installed cryptography with pip" >> /tmp/log 89 | 90 | # Configuring cluster section 91 | sed -i '//,/<\/cluster>/d' ${manager_config} 92 | 93 | cat >> ${manager_config} << EOF 94 | 95 | 96 | wazuh 97 | wazuh-worker 98 | worker 99 | ${wazuh_cluster_key} 100 | 1516 101 | 0.0.0.0 102 | 103 | ${wazuh_master_ip} 104 | 105 | no 106 | no 107 | 108 | 109 | EOF 110 | 111 | # Restart for receiving cluster data 112 | service wazuh-manager restart 113 | # Wait for cluster information to be received (rules,lists...) 114 | sleep 60 115 | 116 | # Disabling agent components and cleaning configuration file 117 | sed -i '//,/<\/wodle>/d' ${manager_config} 118 | sed -i '//,/<\/wodle>/d' ${manager_config} 119 | sed -i '//,/<\/ruleset>/d' ${manager_config} 120 | sed -i '//,/<\/auth>/d' ${manager_config} 121 | sed -i '//,/<\/wodle>/d' ${manager_config} 122 | sed -i '//,/<\/wodle>/d' ${manager_config} 123 | sed -i '//,/<\/localfile>/d' ${manager_config} 124 | sed -i '//d' ${manager_config} 125 | sed -i '//d' ${manager_config} 126 | sed -i '/^$/d' ${manager_config} 127 | 128 | 129 | # Add ruleset and lists 130 | cat >> ${manager_config} << EOF 131 | 132 | 133 | 134 | ruleset/decoders 135 | ruleset/rules 136 | 0215-policy_rules.xml 137 | etc/lists/audit-keys 138 | etc/lists/amazon/aws-eventnames 139 | etc/lists/security-eventchannel 140 | etc/lists/blacklist-alienvault 141 | 142 | etc/decoders 143 | etc/rules 144 | 145 | 146 | EOF 147 | 148 | cat >> ${manager_config} << EOF 149 | 150 | 151 | no 152 | 1800 153 | 1d 154 | yes 155 | 156 | xccdf_org.ssgproject.content_profile_pci-dss 157 | xccdf_org.ssgproject.content_profile_common 158 | 159 | 160 | 161 | 162 | EOF 163 | 164 | # Add VirusTotal integration if key already set 165 | if [ "x${VirusTotalKey}" != "x" ]; then 166 | cat >> ${manager_config} << EOF 167 | 168 | 169 | virustotal 170 | ${VirusTotalKey} 171 | 100200 172 | json 173 | 174 | 175 | EOF 176 | fi 177 | 178 | 179 | # Slack integration 180 | if [ "x${SlackHook}" != "x" ]; then 181 | cat >> ${manager_config} << EOF 182 | 183 | 184 | slack 185 | ${SlackHook} 186 | 10 187 | json 188 | 189 | 190 | EOF 191 | fi 192 | 193 | # AWS integration if key already set 194 | if [ "x${AwsAccessKey}" != "x" ]; then 195 | cat >> ${manager_config} << EOF 196 | 197 | 198 | no 199 | no 200 | 30m 201 | yes 202 | no 203 | 204 | wazuh-cloudtrail 205 | ${AwsAccessKey} 206 | ${AwsSecretKey} 207 | 2019-MAR-24 208 | 209 | 210 | wazuh-aws-wodle 211 | guardduty 212 | ${AwsAccessKey} 213 | ${AwsSecretKey} 214 | 2019-MAR-24 215 | 216 | 217 | wazuh-aws-wodle 218 | macie 219 | ${AwsAccessKey} 220 | ${AwsSecretKey} 221 | 2019-MAR-24 222 | 223 | 224 | wazuh-aws-wodle 225 | vpc 226 | XXXX 227 | XXXX 228 | 2019-MAR-24 229 | 230 | 231 | XXXX 232 | XXXX 233 | 234 | 235 | 236 | EOF 237 | fi 238 | 239 | UID=$(id -u `whoami`) 240 | 241 | # Audit rules 242 | cat >> /etc/audit/rules.d/audit.rules << EOF 243 | -a exit,always -F euid=0 -F arch=b32 -S execve -k audit-wazuh-c 244 | -a exit,always -F euid=0 -F arch=b64 -S execve -k audit-wazuh-c 245 | -a exit,always -F euid=1003 -F arch=b32 -S execve -k audit-wazuh-c 246 | -a exit,always -F euid=1003 -F arch=b64 -S execve -k audit-wazuh-c 247 | -a exit,always -F euid=1002 -F arch=b32 -S execve -k audit-wazuh-c 248 | -a exit,always -F euid=1002 -F arch=b64 -S execve -k audit-wazuh-c 249 | -a exit,always -F euid=1003 -F arch=b32 -S execve -k audit-wazuh-c 250 | -a exit,always -F euid=1003 -F arch=b64 -S execve -k audit-wazuh-c 251 | -a exit,always -F euid=${UID} -F arch=b32 -S execve -k audit-wazuh-c 252 | -a exit,always -F euid=${UID} -F arch=b64 -S execve -k audit-wazuh-c 253 | EOF 254 | 255 | auditctl -D 256 | auditctl -R /etc/audit/rules.d/audit.rules 257 | systemctl restart audit 258 | 259 | # Localfiles 260 | cat >> ${manager_config} << EOF 261 | 262 | 263 | full_command 264 | process list 265 | ps -e -o pid,uname,command 266 | 30 267 | 268 | 269 | firewall-drop 270 | firewall-drop.sh 271 | srcip 272 | yes 273 | 274 | 275 | 276 | firewall-drop 277 | local 278 | 100100 279 | 60 280 | 281 | 282 | EOF 283 | 284 | # Vuln detector 285 | cat >> ${manager_config} << EOF 286 | 287 | 288 | no 289 | 12m 290 | 6h 291 | yes 292 | 293 | no 294 | 1h 295 | 296 | 297 | no 298 | 2010 299 | 1h 300 | 301 | 302 | no 303 | 1h 304 | 305 | 306 | 307 | EOF 308 | 309 | 310 | echo "Cluster configuration" >> /tmp/log 311 | 312 | # Restart wazuh-manager 313 | service wazuh-manager restart 314 | 315 | # Installing Filebeat 316 | yum -y install filebeat 317 | chkconfig --add filebeat 318 | echo "Installed Filebeat" >> /tmp/log 319 | 320 | # Configuring Filebeat 321 | curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/filebeat/filebeat.yml 322 | sed -i "s/YOUR_ELASTIC_SERVER_IP/${elb_logstash}/" /etc/filebeat/filebeat.yml 323 | service filebeat start 324 | echo "Started Filebeat" >> /tmp/log 325 | echo "Done" >> /tmp/log 326 | -------------------------------------------------------------------------------- /logging.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Initializes global resources and logging/monitoring capabilities (qs-1nb14cqc5) 4 | Metadata: 5 | Stack: 6 | Value: 0 7 | VersionDate: 8 | Value: 20160510 9 | Identifier: 10 | Value: template-logging 11 | Input: 12 | Description: CloudTrail bucket name 13 | Output: 14 | Description: Outputs ID of all deployed resources 15 | Parameters: 16 | pNotifyEmail: 17 | Description: Notification email for security events 18 | Type: String 19 | Default: '' 20 | pSupportsGlacier: 21 | Description: Determines hether this region supports Glacier (passed in from Main 22 | template) 23 | Type: String 24 | Default: true 25 | Conditions: 26 | IsGovCloud: 27 | !Equals 28 | - us-gov-west-1 29 | - !Ref AWS::Region 30 | SupportsGlacier: 31 | !Equals 32 | - true 33 | - !Ref pSupportsGlacier 34 | Resources: 35 | rSecurityAlarmTopic: 36 | Type: AWS::SNS::Topic 37 | Properties: 38 | Subscription: 39 | - Endpoint: !Ref pNotifyEmail 40 | Protocol: email 41 | rArchiveLogsBucket: 42 | Type: AWS::S3::Bucket 43 | DeletionPolicy: Retain 44 | Properties: 45 | AccessControl: LogDeliveryWrite 46 | LifecycleConfiguration: 47 | Rules: 48 | - Id: Transition90daysRetain7yrs 49 | Status: Enabled 50 | ExpirationInDays: 2555 51 | Transition: 52 | TransitionInDays: 90 53 | StorageClass: 54 | !If 55 | - SupportsGlacier 56 | - GLACIER 57 | - STANDARD_IA 58 | VersioningConfiguration: 59 | Status: Enabled 60 | rArchiveLogsBucketPolicy: 61 | Type: AWS::S3::BucketPolicy 62 | DependsOn: rArchiveLogsBucket 63 | Properties: 64 | Bucket: !Ref rArchiveLogsBucket 65 | PolicyDocument: 66 | Statement: 67 | - Sid: Enforce HTTPS Connections 68 | Action: s3:* 69 | Effect: Deny 70 | Principal: '*' 71 | Resource: 72 | !Sub 73 | - arn:${Partition}:s3:::${rArchiveLogsBucket}/* 74 | - Partition: 75 | !If 76 | - IsGovCloud 77 | - aws-us-gov 78 | - aws 79 | Condition: 80 | Bool: 81 | aws:SecureTransport: false 82 | - Sid: Restrict Delete* Actions 83 | Action: s3:Delete* 84 | Effect: Deny 85 | Principal: '*' 86 | Resource: 87 | !Sub 88 | - arn:${Partition}:s3:::${rArchiveLogsBucket}/* 89 | - Partition: 90 | !If 91 | - IsGovCloud 92 | - aws-us-gov 93 | - aws 94 | - Sid: DenyUnEncryptedObjectUploads 95 | Effect: Deny 96 | Principal: '*' 97 | Action: s3:PutObject 98 | Resource: 99 | !Sub 100 | - arn:${Partition}:s3:::${rArchiveLogsBucket}/* 101 | - Partition: 102 | !If 103 | - IsGovCloud 104 | - aws-us-gov 105 | - aws 106 | Condition: 107 | StringNotEquals: 108 | s3:x-amz-server-side-encryption: AES256 109 | rCloudTrailBucket: 110 | Type: AWS::S3::Bucket 111 | DeletionPolicy: Retain 112 | Properties: 113 | AccessControl: Private 114 | VersioningConfiguration: 115 | Status: Enabled 116 | LoggingConfiguration: 117 | DestinationBucketName: !Ref rArchiveLogsBucket 118 | LogFilePrefix: cloudtraillogs 119 | rCloudTrailS3Policy: 120 | Type: AWS::S3::BucketPolicy 121 | DependsOn: rCloudTrailBucket 122 | Properties: 123 | Bucket: !Ref rCloudTrailBucket 124 | PolicyDocument: 125 | Statement: 126 | - Sid: AWSCloudTrailAclCheck20150319 127 | Effect: Allow 128 | Principal: 129 | Service: cloudtrail.amazonaws.com 130 | Action: s3:GetBucketAcl 131 | Resource: 132 | !Sub 133 | - arn:${Partition}:s3:::${rCloudTrailBucket} 134 | - Partition: 135 | !If 136 | - IsGovCloud 137 | - aws-us-gov 138 | - aws 139 | - Sid: AWSCloudTrailWrite20150319 140 | Effect: Allow 141 | Principal: 142 | Service: cloudtrail.amazonaws.com 143 | Action: s3:PutObject 144 | Resource: 145 | !Sub 146 | - arn:${Partition}:s3:::${rCloudTrailBucket}/* 147 | - Partition: 148 | !If 149 | - IsGovCloud 150 | - aws-us-gov 151 | - aws 152 | Condition: 153 | StringEquals: 154 | s3:x-amz-acl: bucket-owner-full-control 155 | - Sid: Enforce HTTPS Connections 156 | Action: s3:* 157 | Effect: Deny 158 | Principal: '*' 159 | Resource: 160 | !Sub 161 | - arn:${Partition}:s3:::${rCloudTrailBucket}/* 162 | - Partition: 163 | !If 164 | - IsGovCloud 165 | - aws-us-gov 166 | - aws 167 | Condition: 168 | Bool: 169 | aws:SecureTransport: false 170 | - Sid: Restrict Delete* Actions 171 | Action: s3:Delete* 172 | Effect: Deny 173 | Principal: '*' 174 | Resource: 175 | !Sub 176 | - arn:${Partition}:s3:::${rCloudTrailBucket}/* 177 | - Partition: 178 | !If 179 | - IsGovCloud 180 | - aws-us-gov 181 | - aws 182 | - Sid: DenyUnEncryptedObjectUploads 183 | Effect: Deny 184 | Principal: '*' 185 | Action: s3:PutObject 186 | Resource: 187 | !Sub 188 | - arn:${Partition}:s3:::${rCloudTrailBucket}/* 189 | - Partition: 190 | !If 191 | - IsGovCloud 192 | - aws-us-gov 193 | - aws 194 | Condition: 195 | StringNotEquals: 196 | s3:x-amz-server-side-encryption: AES256 197 | rCloudTrailLoggingLocal: 198 | Type: AWS::CloudTrail::Trail 199 | DependsOn: rCloudTrailS3Policy 200 | Properties: 201 | S3BucketName: !Ref rCloudTrailBucket 202 | IsLogging: true 203 | EnableLogFileValidation: true 204 | IncludeGlobalServiceEvents: true 205 | CloudWatchLogsLogGroupArn: 206 | !GetAtt 207 | - rCloudTrailLogGroup 208 | - Arn 209 | CloudWatchLogsRoleArn: 210 | !GetAtt 211 | - rCloudWatchLogsRole 212 | - Arn 213 | rCloudWatchLogsRole: 214 | Type: AWS::IAM::Role 215 | Properties: 216 | AssumeRolePolicyDocument: 217 | Statement: 218 | - Effect: Allow 219 | Principal: 220 | Service: 221 | - cloudtrail.amazonaws.com 222 | Action: 223 | - sts:AssumeRole 224 | Path: / 225 | Policies: 226 | - PolicyName: cloudwatchlogsrole 227 | PolicyDocument: 228 | Version: 2012-10-17 229 | Statement: 230 | - Sid: AWSCloudTrailCreateLogStream20141101 231 | Effect: Allow 232 | Action: 233 | - logs:CreateLogStream 234 | Resource: 235 | !Sub 236 | - arn:${Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rCloudTrailLogGroup}:log-stream:* 237 | - Partition: 238 | !If 239 | - IsGovCloud 240 | - aws-us-gov 241 | - aws 242 | - Sid: AWSCloudTrailPutLogEvents20141101 243 | Effect: Allow 244 | Action: 245 | - logs:PutLogEvents 246 | Resource: 247 | !Sub 248 | - arn:${Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:${rCloudTrailLogGroup}:log-stream:* 249 | - Partition: 250 | !If 251 | - IsGovCloud 252 | - aws-us-gov 253 | - aws 254 | rCloudTrailRole: 255 | Type: AWS::IAM::Role 256 | Properties: 257 | AssumeRolePolicyDocument: 258 | Statement: 259 | - Effect: Allow 260 | Principal: 261 | Service: 262 | - ec2.amazonaws.com 263 | Action: 264 | - sts:AssumeRole 265 | Path: / 266 | Policies: 267 | - PolicyName: cloudtrail-limited-actions 268 | PolicyDocument: 269 | Version: 2012-10-17 270 | Statement: 271 | - Effect: Allow 272 | Action: 273 | - s3:ListBucket 274 | Resource: 275 | !Sub 276 | - arn:${Partition}:s3:::${rCloudTrailBucket} 277 | - Partition: 278 | !If 279 | - IsGovCloud 280 | - aws-us-gov 281 | - aws 282 | - Effect: Allow 283 | Action: 284 | - s3:PutObject 285 | - s3:GetObject 286 | Resource: 287 | !Sub 288 | - arn:${Partition}:s3:::${rCloudTrailBucket}/* 289 | - Partition: 290 | !If 291 | - IsGovCloud 292 | - aws-us-gov 293 | - aws 294 | rCloudTrailProfile: 295 | Type: AWS::IAM::InstanceProfile 296 | DependsOn: rCloudTrailRole 297 | Properties: 298 | Path: / 299 | Roles: 300 | - !Ref rCloudTrailRole 301 | rCloudTrailLogGroup: 302 | Type: AWS::Logs::LogGroup 303 | Properties: 304 | RetentionInDays: 90 305 | rIAMPolicyChangesMetricFilter: 306 | Type: AWS::Logs::MetricFilter 307 | Properties: 308 | LogGroupName: !Ref rCloudTrailLogGroup 309 | FilterPattern: |- 310 | { 311 | ($.eventName=DeleteGroupPolicy) || 312 | ($.eventName=DeleteRolePolicy) || 313 | ($.eventName=DeleteUserPolicy) || 314 | ($.eventName=PutGroupPolicy) || 315 | ($.eventName=PutRolePolicy) || 316 | ($.eventName=PutUserPolicy) || 317 | ($.eventName=CreatePolicy) || 318 | ($.eventName=DeletePolicy) || 319 | ($.eventName=CreatePolicyVersion) || 320 | ($.eventName=DeletePolicyVersion) || 321 | ($.eventName=AttachRolePolicy) || 322 | ($.eventName=DetachRolePolicy) || 323 | ($.eventName=AttachUserPolicy) || 324 | ($.eventName=DetachUserPolicy) || 325 | ($.eventName=AttachGroupPolicy) || 326 | ($.eventName=DetachGroupPolicy) 327 | } 328 | MetricTransformations: 329 | - MetricNamespace: CloudTrailMetrics 330 | MetricName: IAMPolicyEventCount 331 | MetricValue: 1 332 | rNetworkAclChangesMetricFilter: 333 | Type: AWS::Logs::MetricFilter 334 | Properties: 335 | LogGroupName: !Ref rCloudTrailLogGroup 336 | FilterPattern: |- 337 | { 338 | ($.eventName = CreateNetworkAcl) || 339 | ($.eventName = CreateNetworkAclEntry) || 340 | ($.eventName = DeleteNetworkAcl) || 341 | ($.eventName = DeleteNetworkAclEntry) || 342 | ($.eventName = ReplaceNetworkAclEntry) || 343 | ($.eventName = ReplaceNetworkAclAssociation) 344 | } 345 | MetricTransformations: 346 | - MetricNamespace: CloudTrailMetrics 347 | MetricName: NetworkAclEventCount 348 | MetricValue: 1 349 | rNetworkAclChangesAlarm: 350 | Type: AWS::CloudWatch::Alarm 351 | Properties: 352 | AlarmDescription: Alarms when an API call is made to create, update or delete 353 | a Network ACL. 354 | AlarmActions: 355 | - !Ref rSecurityAlarmTopic 356 | MetricName: NetworkAclEventCount 357 | Namespace: CloudTrailMetrics 358 | ComparisonOperator: GreaterThanOrEqualToThreshold 359 | EvaluationPeriods: 1 360 | Period: 300 361 | Statistic: Sum 362 | Threshold: 1 363 | rSecurityGroupChangesMetricFilter: 364 | Type: AWS::Logs::MetricFilter 365 | Properties: 366 | LogGroupName: !Ref rCloudTrailLogGroup 367 | FilterPattern: |- 368 | { 369 | ($.eventName = AuthorizeSecurityGroupIngress) || 370 | ($.eventName = AuthorizeSecurityGroupEgress) || 371 | ($.eventName = RevokeSecurityGroupIngress) || 372 | ($.eventName = RevokeSecurityGroupEgress) || 373 | ($.eventName = CreateSecurityGroup) || 374 | ($.eventName = DeleteSecurityGroup) 375 | } 376 | MetricTransformations: 377 | - MetricNamespace: CloudTrailMetrics 378 | MetricName: SecurityGroupEventCount 379 | MetricValue: 1 380 | rSecurityGroupChangesAlarm: 381 | Type: AWS::CloudWatch::Alarm 382 | DependsOn: rNetworkAclChangesAlarm 383 | Properties: 384 | AlarmDescription: Alarms when an API call is made to create, update or delete 385 | a Security Group. 386 | AlarmActions: 387 | - !Ref rSecurityAlarmTopic 388 | MetricName: SecurityGroupEventCount 389 | Namespace: CloudTrailMetrics 390 | ComparisonOperator: GreaterThanOrEqualToThreshold 391 | EvaluationPeriods: 1 392 | Period: 300 393 | Statistic: Sum 394 | Threshold: 1 395 | rIAMRootActivity: 396 | Type: AWS::Logs::MetricFilter 397 | Properties: 398 | LogGroupName: !Ref rCloudTrailLogGroup 399 | FilterPattern: |- 400 | { 401 | ($.userIdentity.type = "Root") && 402 | ($.userIdentity.invokedBy NOT EXISTS) && 403 | ($.eventType != "AwsServiceEvent") 404 | } 405 | MetricTransformations: 406 | - MetricNamespace: CloudTrailMetrics 407 | MetricName: RootUserPolicyEventCount 408 | MetricValue: 1 409 | rRootActivityAlarm: 410 | Type: AWS::CloudWatch::Alarm 411 | DependsOn: rSecurityGroupChangesAlarm 412 | Properties: 413 | AlarmDescription: Root user activity detected! 414 | AlarmActions: 415 | - !Ref rSecurityAlarmTopic 416 | MetricName: RootUserPolicyEventCount 417 | Namespace: CloudTrailMetrics 418 | ComparisonOperator: GreaterThanOrEqualToThreshold 419 | EvaluationPeriods: 1 420 | Period: 300 421 | Statistic: Sum 422 | Threshold: 1 423 | rUnauthorizedAttempts: 424 | Type: AWS::Logs::MetricFilter 425 | Properties: 426 | LogGroupName: !Ref rCloudTrailLogGroup 427 | FilterPattern: |- 428 | { 429 | ($.errorCode=AccessDenied) || 430 | ($.errorCode=UnauthorizedOperation) 431 | } 432 | MetricTransformations: 433 | - MetricNamespace: CloudTrailMetrics 434 | MetricName: UnauthorizedAttemptCount 435 | MetricValue: 1 436 | rUnauthorizedAttemptAlarm: 437 | Type: AWS::CloudWatch::Alarm 438 | DependsOn: rRootActivityAlarm 439 | Properties: 440 | AlarmDescription: Multiple unauthorized actions or logins attempted! 441 | AlarmActions: 442 | - !Ref rSecurityAlarmTopic 443 | MetricName: UnauthorizedAttemptCount 444 | Namespace: CloudTrailMetrics 445 | ComparisonOperator: GreaterThanOrEqualToThreshold 446 | EvaluationPeriods: 1 447 | Period: 300 448 | Statistic: Sum 449 | Threshold: 5 450 | rIAMPolicyChangesAlarm: 451 | Type: AWS::CloudWatch::Alarm 452 | DependsOn: rUnauthorizedAttemptAlarm 453 | Properties: 454 | AlarmDescription: IAM Configuration changes detected! 455 | AlarmActions: 456 | - !Ref rSecurityAlarmTopic 457 | MetricName: IAMPolicyEventCount 458 | Namespace: CloudTrailMetrics 459 | ComparisonOperator: GreaterThanOrEqualToThreshold 460 | EvaluationPeriods: 1 461 | Period: 300 462 | Statistic: Sum 463 | Threshold: 1 464 | rIAMCreateAccessKeyAlarm: 465 | Type: AWS::CloudWatch::Alarm 466 | DependsOn: rIAMPolicyChangesAlarm 467 | Properties: 468 | AlarmDescription: 'Warning: New IAM access key was created. Please be sure this 469 | action was neccessary.' 470 | AlarmActions: 471 | - !Ref rSecurityAlarmTopic 472 | MetricName: NewAccessKeyCreated 473 | Namespace: CloudTrailMetrics 474 | ComparisonOperator: GreaterThanOrEqualToThreshold 475 | EvaluationPeriods: 1 476 | Period: 300 477 | Statistic: Sum 478 | Threshold: 1 479 | rIAMCreateAccessKey: 480 | Type: AWS::Logs::MetricFilter 481 | DependsOn: rIAMCreateAccessKeyAlarm 482 | Properties: 483 | LogGroupName: !Ref rCloudTrailLogGroup 484 | FilterPattern: |- 485 | { 486 | ($.eventName=CreateAccessKey) 487 | } 488 | MetricTransformations: 489 | - MetricNamespace: CloudTrailMetrics 490 | MetricName: NewAccessKeyCreated 491 | MetricValue: 1 492 | rCloudTrailChangeAlarm: 493 | Type: AWS::CloudWatch::Alarm 494 | DependsOn: rIAMCreateAccessKeyAlarm 495 | Properties: 496 | AlarmDescription: 'Warning: Changes to CloudTrail log configuration detected 497 | in this account' 498 | AlarmActions: 499 | - !Ref rSecurityAlarmTopic 500 | MetricName: CloudTrailChangeCount 501 | Namespace: CloudTrailMetrics 502 | ComparisonOperator: GreaterThanOrEqualToThreshold 503 | EvaluationPeriods: 1 504 | Period: 300 505 | Statistic: Sum 506 | Threshold: 1 507 | rCloudTrailChange: 508 | Type: AWS::Logs::MetricFilter 509 | Properties: 510 | LogGroupName: !Ref rCloudTrailLogGroup 511 | FilterPattern: |- 512 | { 513 | ($.eventSource = cloudtrail.amazonaws.com) && 514 | ( 515 | ($.eventName != Describe*) && 516 | ($.eventName != Get*) && 517 | ($.eventName != Lookup*) && 518 | ($.eventName != List*) 519 | ) 520 | } 521 | MetricTransformations: 522 | - MetricNamespace: CloudTrailMetrics 523 | MetricName: CloudTrailChangeCount 524 | MetricValue: 1 525 | Outputs: 526 | rArchiveLogsBucket: 527 | Value: !Ref rArchiveLogsBucket 528 | rSecurityAlarmTopic: 529 | Value: !Ref rSecurityAlarmTopic 530 | rCloudTrailLogGroup: 531 | Value: !Ref rCloudTrailLogGroup 532 | ... -------------------------------------------------------------------------------- /wazuh_template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Mappings: 4 | RegionMap: 5 | us-east-1: 6 | HVM64: ami-0ff8a91507f77f867 7 | us-east-2: 8 | HVM64: ami-0b59bfac6be064b78 9 | us-west-1: 10 | HVM64: ami-0019ef04ac50be30f 11 | us-west-2: 12 | HVM64: ami-a0cfeed8 13 | ca-central-1: 14 | HVM64: ami-0b18956f 15 | eu-central-1: 16 | HVM64: ami-0233214e13e500f77 17 | eu-west-1: 18 | HVM64: ami-047bb4163c506cd98 19 | eu-west-2: 20 | HVM64: ami-f976839e 21 | eu-west-3: 22 | HVM64: ami-0ebc281c20e89ba4b 23 | ap-northeast-1: 24 | HVM64: ami-06cd52961ce9f0d85 25 | ap-northeast-2: 26 | HVM64: ami-0a10b2721688ce9d2 27 | ap-southeast-1: 28 | HVM64: ami-08569b978cc4dfa10 29 | ap-southeast-2: 30 | HVM64: ami-09b42976632b27e9b 31 | ap-south-1: 32 | HVM64: ami-0912f71e06545ad88 33 | sa-east-1: 34 | HVM64: ami-07b14488da8ea02a0 35 | SubnetConfig: 36 | WazuhVpc: 37 | CIDR: 10.0.0.0/16 38 | SubnetWazuh: 39 | CIDR: 10.0.2.0/24 40 | 41 | Metadata: 42 | AWS::CloudFormation::Interface: 43 | ParameterGroups: 44 | - 45 | Label: 46 | default: "Environment type" 47 | Parameters: 48 | - EnvironmentType 49 | - 50 | Label: 51 | default: "AWS environment" 52 | Parameters: 53 | - WazuhVpc 54 | - AvailabilityZone 55 | - KeyPairName 56 | - pSubnetWazuh 57 | - 58 | Label: 59 | default: "Version and instance types" 60 | Parameters: 61 | - ElasticWazuhVersion 62 | - WazuhInstanceType 63 | - ElasticInstanceType 64 | - KibanaInstanceType 65 | - SshUsername 66 | - SshPassword 67 | - 68 | Label: 69 | default: "Wazuh configuration" 70 | Parameters: 71 | - WazuhServerPort 72 | - WazuhRegistrationPort 73 | - WazuhApiPort 74 | - WazuhApiAdminUsername 75 | - WazuhApiAdminPassword 76 | - WazuhClusterKey 77 | - 78 | Label: 79 | default: "Kibana configuration" 80 | Parameters: 81 | - KibanaPort 82 | - KibanaUsername 83 | - KibanaPassword 84 | - 85 | Label: 86 | default: "Integration keys" 87 | Parameters: 88 | - AwsSecretKey 89 | - AwsAccessKey 90 | - 91 | Label: 92 | default: "SSL Certificate" 93 | Parameters: 94 | - SSLCertificateARN 95 | 96 | Parameters: 97 | 98 | WazuhVpc: 99 | Description: The VPC where the infrastructure will be isolated. 100 | Type: AWS::EC2::VPC::Id 101 | pSubnetWazuh: 102 | Description: The Subnet where resources will be located 103 | Type: AWS::EC2::Subnet::Id 104 | # AWS environment 105 | AvailabilityZone: 106 | Description: Select an availability zone for the VPC 107 | Type: 'List' 108 | KeyPairName: 109 | Description: Existing EC2 key pair for SSH access 110 | Type: 'AWS::EC2::KeyPair::KeyName' 111 | SshUsername: 112 | Default: wazuh 113 | Description: SSH username 114 | Type: String 115 | MinLength: '5' 116 | MaxLength: '32' 117 | AllowedPattern: '[a-zA-Z0-9]*' 118 | ConstraintDescription: Only alphanumeric characters. Minimum length 5. Maximum length 32. 119 | SshPassword: 120 | Description: SSH Password 121 | NoEcho: 'True' 122 | Type: String 123 | MinLength: '8' 124 | MaxLength: '64' 125 | AllowedPattern: '[a-zA-Z0-9]*' 126 | ConstraintDescription: Only alphanumeric characters. Minimum length 8. Maximum length 64. 127 | 128 | # Version and instance types 129 | ElasticWazuhVersion: 130 | AllowedValues: 131 | - 6.5.0_3.7.0 132 | - 6.5.1_3.7.1 133 | - 6.5.2_3.7.1 134 | - 6.5.3_3.7.2 135 | - 6.5.4_3.7.2 136 | - 6.6.2_3.9.0 137 | - 6.7.0_3.9.0 138 | - 6.7.1_3.9.0 139 | - 6.8.0_3.9.2 140 | ConstraintDescription: Format is ElasticVersion_WazuhVersion 141 | Default: 6.8.0_3.9.2 142 | Description: Elastic and Wazuh versions to be installed 143 | Type: String 144 | WazuhInstanceType: 145 | AllowedValues: 146 | - t2.micro 147 | - t2.medium 148 | - t2.large 149 | - m5.large 150 | - m5.xlarge 151 | - m5.2xlarge 152 | 153 | ConstraintDescription: Must contain valid instance type 154 | Default: t2.medium 155 | Description: Type of EC2 instance for Wazuh instance 156 | Type: String 157 | EnvironmentType: 158 | AllowedValues: 159 | - production 160 | - staging 161 | - devel 162 | ConstraintDescription: Must contain valid instance type 163 | Default: production 164 | Description: Select a stage 165 | Type: String 166 | 167 | ElasticInstanceType: 168 | AllowedValues: 169 | - t2.medium 170 | - t2.large 171 | - i3.large 172 | - i3.xlarge 173 | - i3.2xlarge 174 | 175 | ConstraintDescription: Must contain valid instance type 176 | Default: t2.medium 177 | Description: Type of EC2 instance for Elastic instance 178 | Type: String 179 | KibanaInstanceType: 180 | AllowedValues: 181 | - t2.medium 182 | - t2.large 183 | - m5.large 184 | - m5.xlarge 185 | - m5.2xlarge 186 | - r5.large 187 | 188 | ConstraintDescription: Must contain valid instance type 189 | Default: t2.medium 190 | Description: Type of EC2 instance for Kibana instance 191 | Type: String 192 | # Wazuh configuration 193 | WazuhServerPort: 194 | Default: '1514' 195 | Description: Port for agents connection with Wazuh server 196 | Type: String 197 | WazuhRegistrationPort: 198 | Default: '1515' 199 | Description: Port for agents registration with Wazuh server 200 | Type: String 201 | WazuhApiPort: 202 | Default: '55000' 203 | Description: Port for Wazuh server API 204 | Type: String 205 | WazuhApiAdminUsername: 206 | Default: admin 207 | Description: Admin username for Wazuh API 208 | Type: String 209 | MinLength: '1' 210 | MaxLength: '16' 211 | AllowedPattern: '[a-zA-Z0-9]*' 212 | ConstraintDescription: Only alphanumeric characters 213 | WazuhApiAdminPassword: 214 | Description: Admin password for Wazuh API 215 | NoEcho: 'True' 216 | Type: String 217 | MinLength: '1' 218 | MaxLength: '48' 219 | AllowedPattern: '[a-zA-Z0-9]*' 220 | ConstraintDescription: Only alphanumeric characters 221 | WazuhClusterKey: 222 | Description: Key used for Wazuh servers cluster 223 | Default: 'abcdefghijklmnopqrstuvwxyz012345' 224 | Type: String 225 | MinLength: '32' 226 | MaxLength: '32' 227 | AllowedPattern: '[a-zA-Z0-9]*' 228 | ConstraintDescription: Any alphanumeric string of 32 characters 229 | # Kibana configuration 230 | KibanaPort: 231 | Default: '443' 232 | Description: Port for Kibana WUI 233 | Type: String 234 | KibanaUsername: 235 | Default: wazuh 236 | Description: Username for Kibana access 237 | Type: String 238 | MinLength: '1' 239 | MaxLength: '16' 240 | AllowedPattern: '[a-zA-Z0-9]*' 241 | ConstraintDescription: Only alphanumeric characters 242 | KibanaPassword: 243 | Description: Password for Kibana access 244 | NoEcho: 'True' 245 | Type: String 246 | MinLength: '1' 247 | MaxLength: '48' 248 | AllowedPattern: '[a-zA-Z0-9]*' 249 | ConstraintDescription: Only alphanumeric characters 250 | AwsSecretKey: 251 | Description: (Optional) Secret key for AWS integration 252 | Type: String 253 | 254 | AwsAccessKey: 255 | Description: (Optional) Access key for AWS integration 256 | Type: String 257 | 258 | SSLCertificateARN: 259 | Description: 'Used for HTTPS access to WUI. Existent certificate, identified by its Amazon Resource Name (ARN).' 260 | Type: String 261 | 262 | Resources: 263 | 264 | # Instance security groups 265 | ElasticSecurityGroup: 266 | Type: 'AWS::EC2::SecurityGroup' 267 | Properties: 268 | GroupDescription: Elasticsearch security group 269 | VpcId: !Ref WazuhVpc 270 | SecurityGroupIngress: 271 | - IpProtocol: tcp 272 | FromPort: 22 273 | ToPort: 22 274 | CidrIp: 0.0.0.0/0 275 | - IpProtocol: tcp 276 | FromPort: 5000 277 | ToPort: 5000 278 | CidrIp: !FindInMap 279 | - SubnetConfig 280 | - WazuhVpc 281 | - CIDR 282 | - IpProtocol: tcp 283 | FromPort: 9200 284 | ToPort: 9400 285 | CidrIp: !FindInMap 286 | - SubnetConfig 287 | - WazuhVpc 288 | - CIDR 289 | Tags: 290 | - Key: Name 291 | Value: !Sub '${AWS::StackName}-ElasticSecurityGroup' 292 | KibanaSecurityGroup: 293 | Type: 'AWS::EC2::SecurityGroup' 294 | Properties: 295 | GroupDescription: Kibana security group 296 | VpcId: !Ref WazuhVpc 297 | SecurityGroupIngress: 298 | - IpProtocol: tcp 299 | FromPort: 22 300 | ToPort: 22 301 | CidrIp: 0.0.0.0/0 302 | - IpProtocol: tcp 303 | FromPort: !Ref KibanaPort 304 | ToPort: !Ref KibanaPort 305 | CidrIp: 0.0.0.0/0 306 | - IpProtocol: tcp 307 | FromPort: 9200 308 | ToPort: 9400 309 | CidrIp: !FindInMap 310 | - SubnetConfig 311 | - WazuhVpc 312 | - CIDR 313 | Tags: 314 | - Key: Name 315 | Value: !Sub '${AWS::StackName}-KibanaSecurityGroup' 316 | WazuhSecurityGroup: 317 | Type: 'AWS::EC2::SecurityGroup' 318 | Properties: 319 | GroupDescription: Wazuh security group 320 | VpcId: !Ref WazuhVpc 321 | SecurityGroupIngress: 322 | - IpProtocol: tcp 323 | FromPort: 22 324 | ToPort: 22 325 | CidrIp: 0.0.0.0/0 326 | - IpProtocol: tcp 327 | FromPort: 3389 328 | ToPort: 3389 329 | CidrIp: 0.0.0.0/0 330 | - IpProtocol: tcp 331 | FromPort: 80 332 | ToPort: 80 333 | CidrIp: 0.0.0.0/0 334 | - IpProtocol: icmp 335 | FromPort: -1 336 | ToPort: -1 337 | CidrIp: 0.0.0.0/0 338 | - IpProtocol: tcp 339 | FromPort: !Ref WazuhServerPort 340 | ToPort: !Ref WazuhServerPort 341 | CidrIp: 0.0.0.0/0 342 | - IpProtocol: tcp 343 | FromPort: !Ref WazuhRegistrationPort 344 | ToPort: !Ref WazuhRegistrationPort 345 | CidrIp: 0.0.0.0/0 346 | - IpProtocol: tcp 347 | FromPort: 1516 348 | ToPort: 1516 349 | CidrIp: !FindInMap 350 | - SubnetConfig 351 | - WazuhVpc 352 | - CIDR 353 | - IpProtocol: tcp 354 | FromPort: !Ref WazuhApiPort 355 | ToPort: !Ref WazuhApiPort 356 | CidrIp: !FindInMap 357 | - SubnetConfig 358 | - WazuhVpc 359 | - CIDR 360 | Tags: 361 | - Key: Name 362 | Value: !Sub '${AWS::StackName}-WazuhSecurityGroup' 363 | 364 | # Elasticsearch load balancer 365 | ElbElasticSecurityGroup: 366 | Type: 'AWS::EC2::SecurityGroup' 367 | Properties: 368 | GroupDescription: ELB Elasticsearch security group 369 | VpcId: !Ref WazuhVpc 370 | SecurityGroupIngress: 371 | - IpProtocol: tcp 372 | FromPort: 9200 373 | ToPort: 9200 374 | CidrIp: !FindInMap 375 | - SubnetConfig 376 | - WazuhVpc 377 | - CIDR 378 | Tags: 379 | - Key: Name 380 | Value: !Sub '${AWS::StackName}-ElbElasticSecurityGroup' 381 | # Logstash load balancer 382 | ElbLogstashSecurityGroup: 383 | Type: 'AWS::EC2::SecurityGroup' 384 | Properties: 385 | GroupDescription: ELB Logstash security group 386 | VpcId: !Ref WazuhVpc 387 | SecurityGroupIngress: 388 | - IpProtocol: tcp 389 | FromPort: 5000 390 | ToPort: 5000 391 | CidrIp: !FindInMap 392 | - SubnetConfig 393 | - WazuhVpc 394 | - CIDR 395 | Tags: 396 | - Key: Name 397 | Value: !Sub '${AWS::StackName}-ElbLogstashSecurityGroup' 398 | 399 | # IAM role and profile 400 | InstanceRole: 401 | Type: 'AWS::IAM::Role' 402 | Properties: 403 | AssumeRolePolicyDocument: 404 | Statement: 405 | - Effect: Allow 406 | Principal: 407 | Service: 408 | - ec2.amazonaws.com 409 | - cloudformation.amazonaws.com 410 | Action: 411 | - 'sts:AssumeRole' 412 | Policies: 413 | - PolicyName: !Sub '${AWS::StackName}-GetCloudformation' 414 | PolicyDocument: 415 | Statement: 416 | - Action: 417 | - 'cloudformation:DescribeStack*' 418 | - 'cloudformation:DescribeStackResource*' 419 | - 'cloudformation:List*' 420 | Resource: '*' 421 | Effect: Allow 422 | - PolicyName: !Sub '${AWS::StackName}-DescribeInstances' 423 | PolicyDocument: 424 | Statement: 425 | - Action: 426 | - 'ec2:DescribeInstances' 427 | Resource: '*' 428 | Effect: Allow 429 | InstanceProfile: 430 | Type: 'AWS::IAM::InstanceProfile' 431 | Properties: 432 | Roles: 433 | - !Ref InstanceRole 434 | 435 | # Wazuh master instance 436 | WazuhMasterInstance: 437 | Type: AWS::EC2::Instance 438 | Metadata: 439 | 'AWS::CloudFormation::Init': 440 | configSets: 441 | WazuhInstallationSet: 442 | - WazuhFiles 443 | - WazuhInstall 444 | WazuhFiles: 445 | files: 446 | /tmp/wazuh_cf_settings: 447 | content: !Sub | 448 | SshUsername: ${SshUsername} 449 | SshPassword: ${SshPassword} 450 | mode: '000600' 451 | owner: root 452 | group: root 453 | /tmp/wazuh_cf_master.sh: 454 | source: !Sub >- 455 | https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/aws-nist/wazuh/cluster/wazuh_cf_master.sh 456 | mode: '000700' 457 | owner: root 458 | group: root 459 | WazuhInstall: 460 | commands: 461 | 01_RunInstallationScript: 462 | command: /tmp/wazuh_cf_master.sh 463 | Properties: 464 | ImageId: !FindInMap 465 | - "RegionMap" 466 | - Ref: "AWS::Region" 467 | - HVM64 468 | InstanceType: !Ref WazuhInstanceType 469 | IamInstanceProfile: !Ref InstanceProfile 470 | KeyName: !Ref KeyPairName 471 | BlockDeviceMappings: 472 | - DeviceName: /dev/xvda 473 | Ebs: 474 | VolumeSize: 200 475 | VolumeType: gp2 476 | 477 | NetworkInterfaces: 478 | - AssociatePublicIpAddress: "true" 479 | DeviceIndex: "0" 480 | GroupSet: 481 | - Ref: "WazuhSecurityGroup" 482 | SubnetId: 483 | Ref: "pSubnetWazuh" 484 | Tags: 485 | - Key: Name 486 | Value: WazuhMaster 487 | UserData: 488 | Fn::Base64: !Sub | 489 | #!/bin/bash -xe 490 | /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WazuhMasterInstance --configsets WazuhInstallationSet --region ${AWS::Region} 491 | /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WazuhMasterInstance --region ${AWS::Region} 492 | WazuhMasterEth0: 493 | Type: AWS::EC2::NetworkInterface 494 | Properties: 495 | SubnetId: !Ref pSubnetWazuh 496 | GroupSet: [!Ref 'WazuhSecurityGroup'] 497 | WazuhMasterEIP: 498 | Type: AWS::EC2::EIP 499 | Properties: 500 | Domain: vpc 501 | WazuhMasterEIPAssociation: 502 | Type: 'AWS::EC2::EIPAssociation' 503 | Properties: 504 | NetworkInterfaceId: !Ref WazuhMasterEth0 505 | AllocationId: !GetAtt 506 | - WazuhMasterEIP 507 | - AllocationId 508 | 509 | # Wazuh worker instance 510 | WazuhWorkerInstance: 511 | Type: AWS::EC2::Instance 512 | Metadata: 513 | 'AWS::CloudFormation::Init': 514 | configSets: 515 | WazuhInstallationSet: 516 | - WazuhFiles 517 | - WazuhInstall 518 | WazuhFiles: 519 | files: 520 | /tmp/wazuh_cf_settings: 521 | content: !Sub | 522 | SshUsername: ${SshUsername} 523 | SshPassword: ${SshPassword} 524 | mode: '000600' 525 | owner: root 526 | group: root 527 | /tmp/wazuh_cf_worker.sh: 528 | source: !Sub >- 529 | https://raw.githubusercontent.com/wazuh/wazuh-cloudformation/aws-nist/wazuh/cluster/wazuh_cf_worker.sh 530 | mode: '000700' 531 | owner: root 532 | group: root 533 | WazuhInstall: 534 | commands: 535 | 01_RunInstallationScript: 536 | command: /tmp/wazuh_cf_worker.sh 537 | Properties: 538 | ImageId: !FindInMap 539 | - "RegionMap" 540 | - Ref: "AWS::Region" 541 | - HVM64 542 | InstanceType: !Ref WazuhInstanceType 543 | IamInstanceProfile: !Ref InstanceProfile 544 | KeyName: !Ref KeyPairName 545 | BlockDeviceMappings: 546 | - DeviceName: /dev/xvda 547 | Ebs: 548 | VolumeSize: 200 549 | VolumeType: gp2 550 | NetworkInterfaces: 551 | - NetworkInterfaceId: !Ref WazuhWorkerEth0 552 | DeviceIndex: 0 553 | Tags: 554 | - Key: Name 555 | Value: WazuhWorker 556 | UserData: 557 | Fn::Base64: !Sub | 558 | #!/bin/bash -xe 559 | /opt/aws/bin/cfn-init --stack ${AWS::StackName} --resource WazuhWorkerInstance --configsets WazuhInstallationSet --region ${AWS::Region} 560 | /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WazuhWorkerInstance --region ${AWS::Region} 561 | WazuhWorkerEth0: 562 | Type: AWS::EC2::NetworkInterface 563 | Properties: 564 | SubnetId: !Ref pSubnetWazuh 565 | GroupSet: [!Ref 'WazuhSecurityGroup'] 566 | WazuhWorkerEIP: 567 | Type: AWS::EC2::EIP 568 | Properties: 569 | Domain: vpc 570 | WazuhWorkerEIPAssociation: 571 | Type: 'AWS::EC2::EIPAssociation' 572 | Properties: 573 | NetworkInterfaceId: !Ref WazuhWorkerEth0 574 | AllocationId: !GetAtt 575 | - WazuhWorkerEIP 576 | - AllocationId 577 | 578 | Outputs: 579 | WazuhMasterIp: 580 | Description: Wazuh Master instance IP 581 | Value: ${WazuhMasterInstance.PrivateIp} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /vpc-management.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Provides networking configuration for a standard management VPC (qs-1nb14cqcg) 4 | Metadata: 5 | Stack: 6 | Value: 2 7 | VersionDate: 8 | Value: 20160510 9 | Identifier: 10 | Value: template-vpc-management 11 | Input: 12 | Description: CIDR blocks, VPC names, KeyName, EC2 instance size 13 | Output: 14 | Description: Outputs ID of all deployed resources 15 | AWS::CloudFormation::Interface: 16 | ParameterGroups: 17 | - Label: 18 | default: Region Config 19 | Parameters: 20 | - pRegionAZ1Name 21 | - pRegionAZ2Name 22 | - Label: 23 | default: Management VPC Configuration 24 | Parameters: 25 | - pManagementVPCName 26 | - pManagementCIDR 27 | - pManagementDMZSubnetACIDR 28 | - pManagementDMZSubnetBCIDR 29 | - pManagementDMZSubnetPublicIP 30 | - pVPCTenancy 31 | - Label: 32 | default: AWS Quick Start Configuration 33 | Parameters: 34 | - QSS3BucketName 35 | - QSS3KeyPrefix 36 | - Label: 37 | default: Optional Components - Bastion 38 | Parameters: 39 | - pCreateBastionHost 40 | - pEC2KeyPairBastion 41 | - pBastionInstanceType 42 | - pBastionAmi 43 | - pBastionSSHCIDR 44 | ParameterLabels: 45 | pManagementVPCName: 46 | default: Name of Management VPC to create 47 | pManagementCIDR: 48 | default: CIDR block of Management VPC 49 | pManagementDMZSubnetACIDR: 50 | default: CIDR block of Management DMZ SubnetA 51 | pManagementDMZSubnetBCIDR: 52 | default: CIDR block of Management DMZ SubnetB 53 | pManagementDMZSubnetPublicIP: 54 | default: Configure DMZ Subnet(s) for public ip. 55 | pVPCTenancy: 56 | default: Instance tenancy 57 | QSS3BucketName: 58 | default: Quick Start S3 Bucket Name 59 | QSS3KeyPrefix: 60 | default: Quick Start S3 Key Prefix 61 | pCreateBastionHost: 62 | default: Create Bastion Host 63 | pEC2KeyPairBastion: 64 | default: Bastion KeyPair 65 | pBastionInstanceType: 66 | default: Bastion Instance Type 67 | pBastionAmi: 68 | default: Bastion AMI 69 | pBastionSSHCIDR: 70 | default: Bastion SSH CIDR 71 | Parameters: 72 | pCreateBastionHost: 73 | Description: Should a Bastion host be created inside the DMZ Subnet(s)? 74 | Type: String 75 | Default: true 76 | AllowedValues: 77 | - true 78 | - false 79 | pManagementDMZSubnetPublicIP: 80 | Description: Should Public IPs be auto-assigned to instances launched in the DMZ subnet(s)? 81 | Type: String 82 | Default: false 83 | AllowedValues: 84 | - true 85 | - false 86 | pProductionVPC: 87 | Description: Production VPC to peer with (optional) 88 | Type: String 89 | Default: '' 90 | pProductionCIDR: 91 | Description: CIDR of Production VPC 92 | Type: String 93 | Default: '' 94 | pRouteTableProdPrivate: 95 | Description: Route Table ID for Prod VPC Private 96 | Type: String 97 | Default: '' 98 | pRouteTableProdPublic: 99 | Description: Route Table ID for Prod VPC Public 100 | Type: String 101 | Default: '' 102 | pRegionAZ1Name: 103 | Description: Availability Zone 1 Name in Region 104 | Type: String 105 | Default: us-east-1b 106 | pRegionAZ2Name: 107 | Description: Availability Zone 2 Name in Region 108 | Type: String 109 | Default: us-west-1c 110 | pEC2KeyPairBastion: 111 | Description: Name of existing EC2 key pair for BASTION hosts 112 | Type: String 113 | Default: '' 114 | pBastionInstanceType: 115 | Description: Bastion EC2 instance type 116 | Type: String 117 | Default: m3.large 118 | pManagementVPCName: 119 | Description: Management VPC Name 120 | Type: String 121 | Default: Management VPC 122 | pManagementCIDR: 123 | Description: CIDR block for Management VPC 124 | Type: String 125 | Default: 10.10.0.0/16 126 | pManagementDMZSubnetACIDR: 127 | Description: CIDR block for Management AZ-1a subnet 128 | Type: String 129 | Default: 10.10.10.0/24 130 | pManagementDMZSubnetBCIDR: 131 | Description: CIDR block for Management AZ-1b subnet 132 | Type: String 133 | Default: 10.10.20.0/24 134 | pManagementPrivateSubnetACIDR: 135 | Description: CIDR block for Management AZ-1a subnet 136 | Type: String 137 | Default: 10.10.10.0/24 138 | pManagementPrivateSubnetBCIDR: 139 | Description: CIDR block for Management AZ-1b subnet 140 | Type: String 141 | Default: 10.10.20.0/24 142 | pVPCTenancy: 143 | Description: Instance tenancy behavior for this VPC 144 | Type: String 145 | Default: default 146 | AllowedValues: 147 | - default 148 | - dedicated 149 | pBastionSSHCIDR: 150 | Type: String 151 | Default: 0.0.0.0/0 152 | Description: The CIDR Allowed SSH access to the bastion host 153 | pBastionAmi: 154 | Description: AMI to use for bastion host 155 | Type: String 156 | Default: '' 157 | pEC2KeyPair: 158 | Description: Name of existing EC2 key pair for production hosts 159 | Type: String 160 | Default: '' 161 | pEnvironment: 162 | Description: Environment (development, test, or production) 163 | Type: String 164 | Default: development 165 | pSupportsNatGateway: 166 | Description: Specifies whether this region supports NAT Gateway (this value is 167 | determined by the main stack if it is invoked from there) 168 | Type: String 169 | Default: true 170 | pNatInstanceType: 171 | Description: Instance type to use for the NAT intstance if the region does not 172 | support NAT Gateway (this value is determined by the main stack if it is invoked 173 | from there) 174 | Type: String 175 | Default: '' 176 | pNatAmi: 177 | Description: AMI to use for the NAT intstance if the region does not support NAT 178 | Gateway (this value is determined by the main stack if it is invoked from there) 179 | Type: String 180 | Default: '' 181 | pFlowLogGroup: 182 | Description: Log Group for capturing VPC Flow Logs 183 | Type: String 184 | Default: '' 185 | QSS3BucketName: 186 | AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z\-\.]*[0-9a-zA-Z])*$ 187 | ConstraintDescription: Quick Start bucket name can include numbers, lowercase 188 | letters, uppercase letters, periods (.), and hyphens (-). It cannot start or 189 | end with a hyphen (-). 190 | Default: aws-quickstart 191 | Description: S3 bucket name for the Quick Start assets. Quick Start bucket name 192 | can include numbers, lowercase letters, uppercase letters, periods (.), and 193 | hyphens (-). It cannot start or end with a hyphen (-). 194 | Type: String 195 | QSS3KeyPrefix: 196 | AllowedPattern: ^[0-9a-zA-Z-/]*$ 197 | ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, 198 | uppercase letters, hyphens (-), and forward slash (/). 199 | Default: quickstart-compliance-nist/ 200 | Description: S3 key prefix for the Quick Start assets. Quick Start key prefix 201 | can include numbers, lowercase letters, uppercase letters, hyphens (-), and 202 | orward slash (/). 203 | Type: String 204 | Conditions: 205 | cGovCloudCondition: 206 | !Equals 207 | - !Ref AWS::Region 208 | - us-gov-west-1 209 | cCreateBastionHost: 210 | !Equals 211 | - true 212 | - !Ref pCreateBastionHost 213 | cCreatePeeringProduction: 214 | !Not 215 | - !Equals 216 | - '' 217 | - !Ref pProductionVPC 218 | cNeedNatInstance: 219 | !Equals 220 | - false 221 | - !Ref pSupportsNatGateway 222 | cSupportsNatGateway: 223 | !Equals 224 | - true 225 | - !Ref pSupportsNatGateway 226 | cEnableFlowLogs: 227 | !Not 228 | - !Equals 229 | - !Ref pFlowLogGroup 230 | - '' 231 | cManagementSubnetDefaultRoute: 232 | !Equals 233 | - true 234 | - !Ref pManagementDMZSubnetPublicIP 235 | Resources: 236 | rVPCManagement: 237 | Type: AWS::EC2::VPC 238 | Properties: 239 | CidrBlock: !Ref pManagementCIDR 240 | InstanceTenancy: !Ref pVPCTenancy 241 | EnableDnsSupport: true 242 | EnableDnsHostnames: true 243 | Tags: 244 | - Key: Name 245 | Value: !Ref pManagementVPCName 246 | rNatInstanceTemplate: 247 | Type: AWS::CloudFormation::Stack 248 | Condition: cNeedNatInstance 249 | Properties: 250 | TemplateURL: 251 | !Sub 252 | - https://${QSS3BucketName}.${QSS3Region}.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-compliance-common/templates/nat-instance.template 253 | - QSS3Region: 254 | !If 255 | - cGovCloudCondition 256 | - s3-us-gov-west-1 257 | - s3 258 | TimeoutInMinutes: 20 259 | Parameters: 260 | pDMZSubnetA: !Ref rManagementDMZSubnetA 261 | pSecurityGroupSSHFromVpc: !Ref rSecurityGroupSSHFromMgmt 262 | pSecurityGroupVpcNat: !Ref rSecurityGroupVpcNat 263 | pNatInstanceType: !Ref pNatInstanceType 264 | pNatAmi: !Ref pNatAmi 265 | pEC2KeyPair: !Ref pEC2KeyPair 266 | pVpcId: !Ref rVPCManagement 267 | pVpcName: !Ref pManagementVPCName 268 | pRouteTablePrivateA: !Ref rRouteTableMgmtPrivate 269 | pRouteTablePrivateB: '' 270 | pEipNatAllocationId: !GetAtt rEIPProdNAT.AllocationId 271 | rSecurityGroupVpcNat: 272 | Type: AWS::EC2::SecurityGroup 273 | Properties: 274 | GroupDescription: Allow NAT from Management VPC 275 | VpcId: !Ref rVPCManagement 276 | SecurityGroupIngress: 277 | - IpProtocol: tcp 278 | FromPort: 80 279 | ToPort: 80 280 | CidrIp: !Ref pManagementCIDR 281 | - IpProtocol: tcp 282 | FromPort: 443 283 | ToPort: 443 284 | CidrIp: !Ref pManagementCIDR 285 | Tags: 286 | - Key: Name 287 | Value: sg-web-access-ports-from-production 288 | - Key: Environment 289 | Value: !Ref pEnvironment 290 | rManagementDMZSubnetA: 291 | Type: AWS::EC2::Subnet 292 | Properties: 293 | CidrBlock: !Ref pManagementDMZSubnetACIDR 294 | AvailabilityZone: !Ref pRegionAZ1Name 295 | MapPublicIpOnLaunch: !Ref pManagementDMZSubnetPublicIP 296 | VpcId: !Ref rVPCManagement 297 | Tags: 298 | - Key: Name 299 | Value: Management DMZ Subnet A 300 | rManagementDMZSubnetB: 301 | Type: AWS::EC2::Subnet 302 | Properties: 303 | CidrBlock: !Ref pManagementDMZSubnetBCIDR 304 | AvailabilityZone: !Ref pRegionAZ2Name 305 | MapPublicIpOnLaunch: !Ref pManagementDMZSubnetPublicIP 306 | VpcId: !Ref rVPCManagement 307 | Tags: 308 | - Key: Name 309 | Value: Management DMZ Subnet B 310 | rManagementPrivateSubnetA: 311 | Type: AWS::EC2::Subnet 312 | Properties: 313 | CidrBlock: !Ref pManagementPrivateSubnetACIDR 314 | AvailabilityZone: !Ref pRegionAZ1Name 315 | VpcId: !Ref rVPCManagement 316 | Tags: 317 | - Key: Name 318 | Value: Management Private Subnet A 319 | rManagementPrivateSubnetB: 320 | Type: AWS::EC2::Subnet 321 | Properties: 322 | CidrBlock: !Ref pManagementPrivateSubnetBCIDR 323 | AvailabilityZone: !Ref pRegionAZ2Name 324 | VpcId: !Ref rVPCManagement 325 | Tags: 326 | - Key: Name 327 | Value: Management Private Subnet B 328 | rIGWManagement: 329 | Type: AWS::EC2::InternetGateway 330 | Properties: 331 | Tags: 332 | - Key: Name 333 | Value: igw-management 334 | rRouteTableMgmtPrivate: 335 | Type: AWS::EC2::RouteTable 336 | Properties: 337 | VpcId: !Ref rVPCManagement 338 | Tags: 339 | - Key: Name 340 | Value: Management Private Route 341 | rRouteTableMgmtDMZ: 342 | Type: AWS::EC2::RouteTable 343 | Properties: 344 | VpcId: !Ref rVPCManagement 345 | Tags: 346 | - Key: Name 347 | Value: Management DMZ Route 348 | rRouteMgmtIGW: 349 | DependsOn: 350 | - rGWAttachmentMgmtIGW 351 | Type: AWS::EC2::Route 352 | Properties: 353 | RouteTableId: !Ref rRouteTableMgmtDMZ 354 | GatewayId: !Ref rIGWManagement 355 | DestinationCidrBlock: 0.0.0.0/0 356 | rRouteAssocMgmtDMZA: 357 | Type: AWS::EC2::SubnetRouteTableAssociation 358 | Properties: 359 | RouteTableId: !Ref rRouteTableMgmtDMZ 360 | SubnetId: !Ref rManagementDMZSubnetA 361 | rRouteAssocMgmtDMZB: 362 | Type: AWS::EC2::SubnetRouteTableAssociation 363 | Properties: 364 | RouteTableId: !Ref rRouteTableMgmtDMZ 365 | SubnetId: !Ref rManagementDMZSubnetB 366 | rRouteAssocMgmtPrivA: 367 | Type: AWS::EC2::SubnetRouteTableAssociation 368 | Properties: 369 | RouteTableId: !Ref rRouteTableMgmtPrivate 370 | SubnetId: !Ref rManagementPrivateSubnetA 371 | rRouteAssocMgmtPrivB: 372 | Type: AWS::EC2::SubnetRouteTableAssociation 373 | Properties: 374 | RouteTableId: !Ref rRouteTableMgmtPrivate 375 | SubnetId: !Ref rManagementPrivateSubnetB 376 | rENIProductionBastion: 377 | Condition: cCreateBastionHost 378 | Type: AWS::EC2::NetworkInterface 379 | Properties: 380 | SubnetId: !Ref rManagementDMZSubnetA 381 | GroupSet: 382 | - !Ref rSecurityGroupBastion 383 | Description: Interface for Bastion device 384 | Tags: 385 | - Key: Network 386 | Value: MgmtBastionDevice 387 | rMgmtBastionInstance: 388 | Type: AWS::EC2::Instance 389 | Condition: cCreateBastionHost 390 | Properties: 391 | InstanceType: !Ref pBastionInstanceType 392 | KeyName: !Ref pEC2KeyPairBastion 393 | Tags: 394 | - Key: Name 395 | Value: Bastion Server 396 | ImageId: !Ref pBastionAmi 397 | NetworkInterfaces: 398 | - NetworkInterfaceId: !Ref rENIProductionBastion 399 | DeviceIndex: 0 400 | UserData: !Base64 | 401 | #!/bin/bash 402 | yum update -y 403 | rEIPProdBastion: 404 | Type: AWS::EC2::EIP 405 | Condition: cCreateBastionHost 406 | Properties: 407 | Domain: vpc 408 | AssociaterEIPProdBastion: 409 | Type: AWS::EC2::EIPAssociation 410 | Condition: cCreateBastionHost 411 | DependsOn: 412 | - rMgmtBastionInstance 413 | Properties: 414 | AllocationId: !GetAtt rEIPProdBastion.AllocationId 415 | NetworkInterfaceId: !Ref rENIProductionBastion 416 | rEIPManagementNAT: 417 | Type: AWS::EC2::EIP 418 | Properties: 419 | Domain: vpc 420 | rSecurityGroupSSHFromMgmt: 421 | Type: AWS::EC2::SecurityGroup 422 | Properties: 423 | GroupDescription: Enable SSH access via port 22 424 | VpcId: !Ref rVPCManagement 425 | SecurityGroupIngress: 426 | - IpProtocol: tcp 427 | FromPort: 22 428 | ToPort: 22 429 | CidrIp: !Ref pManagementCIDR 430 | Tags: 431 | - Key: Name 432 | Value: sg-ssh-access-from-management 433 | - Key: Environment 434 | Value: !Ref pEnvironment 435 | rManagementNATInstanceInterface: 436 | Type: AWS::EC2::NetworkInterface 437 | Properties: 438 | SubnetId: !Ref rManagementDMZSubnetA 439 | GroupSet: 440 | - !Ref rSecurityGroupSSHFromMgmt 441 | - !Ref rSecurityGroupVpcNat 442 | Description: Interface for Nat device 443 | Tags: 444 | - Key: Network 445 | Value: rManagementNATInstanceInterface 446 | AssociaterEIPManagementNAT: 447 | Type: AWS::EC2::EIPAssociation 448 | Properties: 449 | AllocationId: !GetAtt rEIPManagementNAT.AllocationId 450 | NetworkInterfaceId: !Ref rManagementNATInstanceInterface 451 | rEIPProdNAT: 452 | Type: AWS::EC2::EIP 453 | Properties: 454 | Domain: vpc 455 | rNATGateway: 456 | Type: AWS::EC2::NatGateway 457 | Condition: cSupportsNatGateway 458 | DependsOn: rIGWManagement 459 | Properties: 460 | AllocationId: !GetAtt rEIPProdNAT.AllocationId 461 | SubnetId: !Ref rManagementDMZSubnetA 462 | rGWAttachmentMgmtIGW: 463 | Type: AWS::EC2::VPCGatewayAttachment 464 | Properties: 465 | VpcId: !Ref rVPCManagement 466 | InternetGatewayId: !Ref rIGWManagement 467 | rSecurityGroupBastion: 468 | Type: AWS::EC2::SecurityGroup 469 | Condition: cCreateBastionHost 470 | Properties: 471 | GroupDescription: SG for Bastion Instances 472 | VpcId: !Ref rVPCManagement 473 | SecurityGroupIngress: 474 | - IpProtocol: tcp 475 | FromPort: 22 476 | ToPort: 22 477 | CidrIp: !Ref pBastionSSHCIDR 478 | SecurityGroupEgress: 479 | - IpProtocol: tcp 480 | FromPort: 1 481 | ToPort: 65535 482 | CidrIp: 0.0.0.0/0 483 | Tags: 484 | - Key: Name 485 | Value: sg-ssh-access-from-bastion 486 | - Key: Environment 487 | Value: !Ref pEnvironment 488 | rPeeringConnectionProduction: 489 | Type: AWS::EC2::VPCPeeringConnection 490 | Condition: cCreatePeeringProduction 491 | Properties: 492 | PeerVpcId: !Ref pProductionVPC 493 | VpcId: !Ref rVPCManagement 494 | Tags: 495 | - Key: Name 496 | Value: vpc-peer-production-management 497 | - Key: Environment 498 | Value: !Ref pEnvironment 499 | rRouteMgmtProdPrivate: 500 | Condition: cCreatePeeringProduction 501 | Type: AWS::EC2::Route 502 | Properties: 503 | RouteTableId: !Ref rRouteTableMgmtPrivate 504 | VpcPeeringConnectionId: !Ref rPeeringConnectionProduction 505 | DestinationCidrBlock: !Ref pProductionCIDR 506 | rRouteMgmtNGW: 507 | Condition: cSupportsNatGateway 508 | Type: AWS::EC2::Route 509 | Properties: 510 | RouteTableId: !Ref rRouteTableMgmtPrivate 511 | DestinationCidrBlock: 0.0.0.0/0 512 | NatGatewayId: !Ref rNATGateway 513 | rRouteProdMgmt: 514 | Condition: cCreatePeeringProduction 515 | Type: AWS::EC2::Route 516 | Properties: 517 | RouteTableId: !Ref pRouteTableProdPrivate 518 | VpcPeeringConnectionId: !Ref rPeeringConnectionProduction 519 | DestinationCidrBlock: !Ref pManagementCIDR 520 | rRouteProdMgmtPublic: 521 | Condition: cCreatePeeringProduction 522 | Type: AWS::EC2::Route 523 | Properties: 524 | RouteTableId: !Ref pRouteTableProdPublic 525 | VpcPeeringConnectionId: !Ref rPeeringConnectionProduction 526 | DestinationCidrBlock: !Ref pManagementCIDR 527 | rRouteMgmtProdDMZ: 528 | Condition: cCreatePeeringProduction 529 | Type: AWS::EC2::Route 530 | Properties: 531 | RouteTableId: !Ref rRouteTableMgmtDMZ 532 | VpcPeeringConnectionId: !Ref rPeeringConnectionProduction 533 | DestinationCidrBlock: !Ref pProductionCIDR 534 | rManagementVpcFlowLogsServiceRole: 535 | Condition: cEnableFlowLogs 536 | Type: AWS::IAM::Role 537 | Properties: 538 | AssumeRolePolicyDocument: 539 | Version: 2012-10-17 540 | Statement: 541 | - Sid: AllowFlowLogs 542 | Effect: Allow 543 | Principal: 544 | Service: vpc-flow-logs.amazonaws.com 545 | Action: sts:AssumeRole 546 | Path: / 547 | Policies: 548 | - PolicyName: cloudwatchlogsrole 549 | PolicyDocument: 550 | Version: 2012-10-17 551 | Statement: 552 | - Action: 553 | - logs:CreateLogGroup 554 | - logs:CreateLogStream 555 | - logs:PutLogEvents 556 | - logs:DescribeLogGroups 557 | - logs:DescribeLogStreams 558 | Effect: Allow 559 | Resource: '*' 560 | rManagementVpcFlowLog: 561 | Condition: cEnableFlowLogs 562 | Type: AWS::EC2::FlowLog 563 | Properties: 564 | DeliverLogsPermissionArn: !GetAtt rManagementVpcFlowLogsServiceRole.Arn 565 | LogGroupName: !Ref pFlowLogGroup 566 | ResourceId: !Ref rVPCManagement 567 | ResourceType: VPC 568 | TrafficType: ALL 569 | rManagementVpcFlowLogStream: 570 | Condition: cEnableFlowLogs 571 | Type: AWS::Logs::LogStream 572 | Properties: 573 | LogGroupName: !Ref pFlowLogGroup 574 | Outputs: 575 | rVPCManagement: 576 | Value: !Ref rVPCManagement 577 | rBastionInstanceIP: 578 | Condition: cCreateBastionHost 579 | Value: 580 | !If 581 | - cCreateBastionHost 582 | - !Ref rEIPProdBastion 583 | - '' 584 | rManagementDMZSubnetA: 585 | Value: !Ref rManagementDMZSubnetA 586 | rManagementDMZSubnetB: 587 | Value: !Ref rManagementDMZSubnetB 588 | rManagementPrivateSubnetA: 589 | Value: !Ref rManagementPrivateSubnetA 590 | rManagementPrivateSubnetB: 591 | Value: !Ref rManagementPrivateSubnetB 592 | rRouteTableMgmtPrivate: 593 | Value: !Ref rRouteTableMgmtPrivate 594 | rRouteTableMgmtDMZ: 595 | Value: !Ref rRouteTableMgmtDMZ 596 | rSecurityGroupVpcNat: 597 | Value: !Ref rSecurityGroupVpcNat 598 | rEIPManagementNAT: 599 | Value: !Ref rEIPProdNAT 600 | rSecurityGroupSSHFromMgmt: 601 | Value: !Ref rSecurityGroupSSHFromMgmt 602 | ... -------------------------------------------------------------------------------- /main.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Provides nesting for required stacks to deploy a full sample web application 4 | with reverse proxy, ELBs, IAM, and other resources (for demonstration/POC/testing) 5 | QS(0029) 6 | Metadata: 7 | Stack: 8 | Value: 0 9 | VersionDate: 10 | Value: 20160518 11 | Identifier: 12 | Value: main 13 | Input: 14 | Description: Input of all required parameters in nested stacks 15 | Output: 16 | Description: N/A 17 | AWS::CloudFormation::Interface: 18 | ParameterGroups: 19 | - Label: 20 | default: 'Please provide the following parameter values:' 21 | Parameters: 22 | - pDBPassword 23 | - pNotifyEmail 24 | - pEC2KeyPairBastion 25 | - pEC2KeyPair 26 | - pSupportsConfig 27 | - pAvailabilityZones 28 | - Label: 29 | default: Wazuh Cluster Configuration 30 | Parameters: 31 | - WazuhAdminName 32 | - WazuhAdminPass 33 | - Label: 34 | default: AWS Quick Start Configuration 35 | Parameters: 36 | - QSS3BucketName 37 | - QSS3KeyPrefix 38 | - Label: 39 | default: Wazuh required parameters 40 | Parameters: 41 | - pSshUsername 42 | - pSshPassword 43 | - pWazuhInstanceType 44 | - pWazuhApiAdminPassword 45 | - pKibanaPassword 46 | - pAwsSecretKey 47 | - pAwsAccessKey 48 | - pSSLCertificateARN 49 | 50 | ParameterLabels: 51 | pDBPassword: 52 | default: Database Password 53 | pNotifyEmail: 54 | default: Notification Email Address 55 | pEC2KeyPairBastion: 56 | default: Existing SSH Key for the Bastion Instance 57 | pEC2KeyPair: 58 | default: Existing SSH Key for Other Instances 59 | pSupportsConfig: 60 | default: Support Config 61 | pAvailabilityZones: 62 | default: Availability Zones 63 | pVPCTenancy: 64 | default: Instance tenancy 65 | QSS3BucketName: 66 | default: Quick Start S3 Bucket Name 67 | QSS3KeyPrefix: 68 | default: Quick Start S3 Key Prefix 69 | Parameters: 70 | pSshUsername: 71 | Default: wazuh 72 | Description: SSH username 73 | Type: String 74 | MinLength: '5' 75 | MaxLength: '32' 76 | AllowedPattern: '[a-zA-Z0-9]*' 77 | ConstraintDescription: Only alphanumeric characters. Minimum length 5. Maximum length 32. 78 | pSshPassword: 79 | Description: SSH Password 80 | NoEcho: 'True' 81 | Type: String 82 | MinLength: '8' 83 | MaxLength: '64' 84 | AllowedPattern: '[a-zA-Z0-9]*' 85 | ConstraintDescription: Only alphanumeric characters. Minimum length 8. Maximum length 64. 86 | pWazuhInstanceType: 87 | AllowedValues: 88 | - t2.micro 89 | - t2.medium 90 | - t2.large 91 | - m5.large 92 | - m5.xlarge 93 | - m5.2xlarge 94 | ConstraintDescription: Must contain valid instance type 95 | Default: t2.medium 96 | Description: Type of EC2 instance for Wazuh instance 97 | Type: String 98 | pWazuhApiAdminPassword: 99 | Description: Admin password for Wazuh API 100 | NoEcho: 'True' 101 | Type: String 102 | MinLength: '1' 103 | MaxLength: '48' 104 | AllowedPattern: '[a-zA-Z0-9]*' 105 | ConstraintDescription: Only alphanumeric characters 106 | pKibanaPassword: 107 | Description: Password for Kibana access 108 | NoEcho: 'True' 109 | Type: String 110 | MinLength: '1' 111 | MaxLength: '48' 112 | AllowedPattern: '[a-zA-Z0-9]*' 113 | ConstraintDescription: Only alphanumeric characters 114 | pAwsSecretKey: 115 | Description: (Optional) Secret key for AWS integration 116 | Type: String 117 | pAwsAccessKey: 118 | Description: (Optional) Access key for AWS integration 119 | Type: String 120 | pSSLCertificateARN: 121 | Description: 'Used for HTTPS access to WUI. Existent certificate, identified by its Amazon Resource Name (ARN).' 122 | Type: String 123 | pDBPassword: 124 | Description: Mixed alphanumeric and must be between 8 and 28 characters and contain 125 | at least one capital letter 126 | NoEcho: true 127 | Type: String 128 | MinLength: 8 129 | MaxLength: 28 130 | AllowedPattern: '[a-zA-Z0-9!^*\-_+]*' 131 | ConstraintDescription: Can only contain alphanumeric characters or the following 132 | special characters !^*-_+, between 8 and 28 characters 133 | pNotifyEmail: 134 | Description: Notification email address for security events (you will receive 135 | a confirmation email) 136 | Type: String 137 | Default: distlist@example.org 138 | pEC2KeyPairBastion: 139 | Description: The SSH key pair in your account to use for the bastion host login 140 | Type: AWS::EC2::KeyPair::KeyName 141 | pEC2KeyPair: 142 | Description: The SSH key pair in your account to use for all other EC2 instance 143 | logins 144 | Type: AWS::EC2::KeyPair::KeyName 145 | pSupportsConfig: 146 | Description: Is AWS Config Rules already configured for this region? Use ''false'' 147 | if you are uncertain. See AWS Config Management Console or Deployment Guide 148 | for details. 149 | AllowedValues: 150 | - 'true' 151 | - 'false' 152 | Default: 'false' 153 | Type: String 154 | pAvailabilityZones: 155 | Description: Availability Zones 156 | Type: List 157 | pVPCTenancy: 158 | Description: Instance tenancy behavior for this VPC 159 | Type: String 160 | Default: default 161 | AllowedValues: 162 | - default 163 | - dedicated 164 | QSS3BucketName: 165 | AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-.]*[0-9a-zA-Z])*$ 166 | ConstraintDescription: Quick Start bucket name can include numbers, lowercase 167 | letters, uppercase letters, periods (.), and hyphens (-). It cannot start or 168 | end with a hyphen (-). 169 | Default: aws-quickstart 170 | Description: S3 bucket name for the Quick Start assets. Quick Start bucket name 171 | can include numbers, lowercase letters, uppercase letters, and hyphens (-). 172 | It cannot start or end with a hyphen (-). 173 | Type: String 174 | QSS3KeyPrefix: 175 | AllowedPattern: ^[0-9a-zA-Z-/]*$ 176 | ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, 177 | uppercase letters, hyphens (-), and forward slash (/). 178 | Default: quickstart-compliance-nist-high/ 179 | Description: S3 key prefix for the Quick Start assets. Quick Start key prefix 180 | can include numbers, lowercase letters, uppercase letters, hyphens (-), and 181 | forward slash (/). 182 | Type: String 183 | Mappings: 184 | CustomVariables: 185 | vResourceEnvironmentTagKey: 186 | Value: Environment 187 | vResourceEnvironmentTagValue: 188 | Value: development 189 | RegionServiceSupport: 190 | ap-northeast-1: 191 | ConfigRules: 'true' 192 | NatGateway: 'true' 193 | Glacier: 'true' 194 | ap-northeast-2: 195 | ConfigRules: 'true' 196 | NatGateway: 'true' 197 | Glacier: 'true' 198 | ap-south-1: 199 | ConfigRules: 'true' 200 | NatGateway: 'true' 201 | Glacier: 'true' 202 | ap-southeast-1: 203 | ConfigRules: 'true' 204 | NatGateway: 'true' 205 | Glacier: 'true' 206 | ap-southeast-2: 207 | ConfigRules: 'true' 208 | NatGateway: 'true' 209 | Glacier: 'true' 210 | ca-central-1: 211 | ConfigRules: 'true' 212 | NatGateway: 'true' 213 | Glacier: 'true' 214 | eu-central-1: 215 | NatGateway: 'true' 216 | ConfigRules: 'true' 217 | Glacier: 'true' 218 | eu-west-1: 219 | ConfigRules: 'true' 220 | NatGateway: 'true' 221 | Glacier: 'true' 222 | eu-west-2: 223 | ConfigRules: 'true' 224 | NatGateway: 'true' 225 | Glacier: 'true' 226 | sa-east-1: 227 | ConfigRules: 'true' 228 | NatGateway: 'true' 229 | Glacier: 'false' 230 | us-east-1: 231 | ConfigRules: 'true' 232 | NatGateway: 'true' 233 | Glacier: 'true' 234 | us-east-2: 235 | ConfigRules: 'true' 236 | NatGateway: 'true' 237 | Glacier: 'true' 238 | us-gov-west-1: 239 | ConfigRules: 'true' 240 | NatGateway: 'true' 241 | Glacier: 'true' 242 | us-west-1: 243 | ConfigRules: 'true' 244 | NatGateway: 'true' 245 | Glacier: 'true' 246 | us-west-2: 247 | ConfigRules: 'true' 248 | NatGateway: 'true' 249 | Glacier: 'true' 250 | AWSAMIRegionMap: 251 | AMI: 252 | AMZNLINUXHVM: amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2 253 | ap-northeast-1: 254 | AMZNLINUXHVM: ami-00a5245b4816c38e6 255 | InstanceType: m4.large 256 | InstanceTypeDatabase: db.m4.large 257 | ap-northeast-2: 258 | AMZNLINUXHVM: ami-00dc207f8ba6dc919 259 | InstanceType: m4.large 260 | InstanceTypeDatabase: db.m4.large 261 | ap-south-1: 262 | AMZNLINUXHVM: ami-0ad42f4f66f6c1cc9 263 | InstanceType: m4.large 264 | InstanceTypeDatabase: db.m4.large 265 | ap-southeast-1: 266 | AMZNLINUXHVM: ami-05b3bcf7f311194b3 267 | InstanceType: m4.large 268 | InstanceTypeDatabase: db.m4.large 269 | ap-southeast-2: 270 | AMZNLINUXHVM: ami-02fd0b06f06d93dfc 271 | InstanceType: m4.large 272 | InstanceTypeDatabase: db.m4.large 273 | ca-central-1: 274 | AMZNLINUXHVM: ami-07423fb63ea0a0930 275 | InstanceType: m4.large 276 | InstanceTypeDatabase: db.m4.large 277 | eu-central-1: 278 | AMZNLINUXHVM: ami-0cfbf4f6db41068ac 279 | InstanceType: m4.large 280 | InstanceTypeDatabase: db.m4.large 281 | eu-west-1: 282 | AMZNLINUXHVM: ami-08935252a36e25f85 283 | InstanceType: m4.large 284 | InstanceTypeDatabase: db.m4.large 285 | eu-west-2: 286 | AMZNLINUXHVM: ami-01419b804382064e4 287 | InstanceType: m4.large 288 | InstanceTypeDatabase: db.m4.large 289 | sa-east-1: 290 | AMZNLINUXHVM: ami-05145e0b28ad8e0b2 291 | InstanceType: m4.large 292 | InstanceTypeDatabase: db.m3.large 293 | us-east-1: 294 | AMZNLINUXHVM: ami-0080e4c5bc078760e 295 | InstanceType: m4.large 296 | InstanceTypeDatabase: db.m4.large 297 | us-east-2: 298 | AMZNLINUXHVM: ami-0cd3dfa4e37921605 299 | InstanceType: m4.large 300 | InstanceTypeDatabase: db.m4.large 301 | us-gov-west-1: 302 | AMZNLINUXHVM: ami-ffa61d9e 303 | InstanceType: m4.large 304 | InstanceTypeDatabase: db.m3.large 305 | us-west-1: 306 | AMZNLINUXHVM: ami-0ec6517f6edbf8044 307 | InstanceType: m4.large 308 | InstanceTypeDatabase: db.m4.large 309 | us-west-2: 310 | AMZNLINUXHVM: ami-01e24be29428c15b2 311 | InstanceType: m4.large 312 | InstanceTypeDatabase: db.m4.large 313 | Conditions: 314 | GovCloudCondition: 315 | !Equals 316 | - !Ref AWS::Region 317 | - us-gov-west-1 318 | LoadConfigRulesTemplate: 319 | !Equals 320 | - !Ref pSupportsConfig 321 | - 'true' 322 | LaunchAsDedicatedInstance: 323 | !Equals 324 | - !Ref pVPCTenancy 325 | - dedicated 326 | Resources: 327 | IamTemplate: 328 | Type: AWS::CloudFormation::Stack 329 | Properties: 330 | TemplateURL: 331 | !Sub 332 | - https://aws-nist.s3-us-west-1.amazonaws.com/iam.template 333 | - QSS3Region: 334 | !If 335 | - GovCloudCondition 336 | - s3-us-gov-west-1 337 | - s3 338 | TimeoutInMinutes: 20 339 | 340 | LoggingTemplate: 341 | Type: AWS::CloudFormation::Stack 342 | Properties: 343 | TemplateURL: 344 | !Sub 345 | - https://aws-nist.s3-us-west-1.amazonaws.com/logging.template 346 | - QSS3Region: 347 | !If 348 | - GovCloudCondition 349 | - s3-us-gov-west-1 350 | - s3 351 | TimeoutInMinutes: 20 352 | Parameters: 353 | pNotifyEmail: !Ref pNotifyEmail 354 | pSupportsGlacier: 355 | !FindInMap 356 | - RegionServiceSupport 357 | - !Ref AWS::Region 358 | - Glacier 359 | 360 | ProductionVpcTemplate: 361 | Type: AWS::CloudFormation::Stack 362 | Properties: 363 | TemplateURL: 364 | !Sub 365 | - https://aws-nist.s3-us-west-1.amazonaws.com/vpc-production.template 366 | - QSS3Region: 367 | !If 368 | - GovCloudCondition 369 | - s3-us-gov-west-1 370 | - s3 371 | TimeoutInMinutes: 20 372 | Parameters: 373 | pRegionAZ1Name: !Select [ 0, !Ref pAvailabilityZones ] 374 | pRegionAZ2Name: !Select [ 1, !Ref pAvailabilityZones ] 375 | pProductionVPCName: Production VPC 376 | pBastionSSHCIDR: 0.0.0.0/0 377 | pDMZSubnetACIDR: 10.100.10.0/24 378 | pDMZSubnetBCIDR: 10.100.20.0/24 379 | pManagementCIDR: 10.10.0.0/16 380 | pAppPrivateSubnetACIDR: 10.100.96.0/21 381 | pAppPrivateSubnetBCIDR: 10.100.119.0/21 382 | pDBPrivateSubnetACIDR: 10.100.194.0/21 383 | pDBPrivateSubnetBCIDR: 10.100.212.0/21 384 | pVPCTenancy: !Ref pVPCTenancy 385 | pEnvironment: 386 | !FindInMap 387 | - CustomVariables 388 | - vResourceEnvironmentTagValue 389 | - Value 390 | pEC2KeyPair: !Ref pEC2KeyPair 391 | pSupportsNatGateway: 392 | !FindInMap 393 | - RegionServiceSupport 394 | - !Ref AWS::Region 395 | - NatGateway 396 | pNatAmi: 397 | !FindInMap 398 | - AWSAMIRegionMap 399 | - !Ref AWS::Region 400 | - AMZNLINUXHVM 401 | pNatInstanceType: 402 | !FindInMap 403 | - AWSAMIRegionMap 404 | - !Ref AWS::Region 405 | - InstanceType 406 | QSS3BucketName: !Ref QSS3BucketName 407 | QSS3KeyPrefix: !Sub ${QSS3KeyPrefix}submodules/quickstart-compliance-common/ 408 | 409 | ManagementVpcTemplate: 410 | Type: AWS::CloudFormation::Stack 411 | DependsOn: ProductionVpcTemplate 412 | Properties: 413 | TemplateURL: 414 | !Sub 415 | - https://aws-nist.s3-us-west-1.amazonaws.com/vpc-management.template 416 | - QSS3Region: 417 | !If 418 | - GovCloudCondition 419 | - s3-us-gov-west-1 420 | - s3 421 | TimeoutInMinutes: 20 422 | Parameters: 423 | pProductionVPC: 424 | !GetAtt 425 | - ProductionVpcTemplate 426 | - Outputs.rVPCProduction 427 | pRouteTableProdPrivate: 428 | !GetAtt 429 | - ProductionVpcTemplate 430 | - Outputs.rRouteTableProdPrivate 431 | pRouteTableProdPublic: 432 | !GetAtt 433 | - ProductionVpcTemplate 434 | - Outputs.rRouteTableProdPublic 435 | pProductionCIDR: 10.100.0.0/16 436 | pBastionSSHCIDR: 0.0.0.0/0 437 | pManagementCIDR: 10.10.0.0/16 438 | pManagementDMZSubnetACIDR: 10.10.1.0/24 439 | pManagementDMZSubnetBCIDR: 10.10.2.0/24 440 | pManagementPrivateSubnetACIDR: 10.10.20.0/24 441 | pManagementPrivateSubnetBCIDR: 10.10.30.0/24 442 | pManagementVPCName: Management VPC 443 | pEC2KeyPairBastion: !Ref pEC2KeyPairBastion 444 | pEC2KeyPair: !Ref pEC2KeyPair 445 | pVPCTenancy: !Ref pVPCTenancy 446 | pBastionAmi: 447 | !FindInMap 448 | - AWSAMIRegionMap 449 | - !Ref AWS::Region 450 | - AMZNLINUXHVM 451 | pRegionAZ1Name: !Select [ 0, !Ref pAvailabilityZones ] 452 | pRegionAZ2Name: !Select [ 1, !Ref pAvailabilityZones ] 453 | pEnvironment: 454 | !FindInMap 455 | - CustomVariables 456 | - vResourceEnvironmentTagValue 457 | - Value 458 | pBastionInstanceType: 459 | !If 460 | - LaunchAsDedicatedInstance 461 | - m4.large 462 | - t2.small 463 | pSupportsNatGateway: 464 | !FindInMap 465 | - RegionServiceSupport 466 | - !Ref AWS::Region 467 | - NatGateway 468 | pNatAmi: 469 | !FindInMap 470 | - AWSAMIRegionMap 471 | - !Ref AWS::Region 472 | - AMZNLINUXHVM 473 | pNatInstanceType: 474 | !FindInMap 475 | - AWSAMIRegionMap 476 | - !Ref AWS::Region 477 | - InstanceType 478 | QSS3BucketName: !Ref QSS3BucketName 479 | QSS3KeyPrefix: !Sub ${QSS3KeyPrefix}submodules/quickstart-compliance-common/ 480 | 481 | ConfigRulesTemplate: 482 | Type: AWS::CloudFormation::Stack 483 | Condition: LoadConfigRulesTemplate 484 | DependsOn: 485 | - IamTemplate 486 | - ProductionVpcTemplate 487 | - ManagementVpcTemplate 488 | - LoggingTemplate 489 | Properties: 490 | TemplateURL: 491 | !Sub 492 | - https://aws-nist.s3-us-west-1.amazonaws.com/config-rules.template 493 | - QSS3Region: 494 | !If 495 | - GovCloudCondition 496 | - s3-us-gov-west-1 497 | - s3 498 | TimeoutInMinutes: 20 499 | Parameters: 500 | pRequiredTagKey: 501 | !FindInMap 502 | - CustomVariables 503 | - vResourceEnvironmentTagKey 504 | - Value 505 | 506 | WazuhTemplate: 507 | Type: AWS::CloudFormation::Stack 508 | Properties: 509 | TemplateURL: https://aws-nist.s3-us-west-1.amazonaws.com/wazuh_template.yml 510 | TimeoutInMinutes: 30 511 | Parameters: 512 | pSubnetWazuh: 513 | !GetAtt 514 | - ProductionVpcTemplate 515 | - Outputs.rAppPrivateSubnetA 516 | AvailabilityZone: !Join 517 | - ',' 518 | - !Ref pAvailabilityZones 519 | KeyPairName: !Ref pEC2KeyPair 520 | WazuhVpc: 521 | !GetAtt 522 | - ProductionVpcTemplate 523 | - Outputs.rVPCProduction 524 | SshUsername: !Ref pSshUsername 525 | SshPassword: !Ref pSshPassword 526 | WazuhInstanceType: !Ref pWazuhInstanceType 527 | WazuhApiAdminPassword: !Ref pWazuhApiAdminPassword 528 | KibanaPassword: !Ref pKibanaPassword 529 | AwsSecretKey: !Ref pAwsSecretKey 530 | AwsAccessKey: !Ref pAwsAccessKey 531 | SSLCertificateARN: !Ref pSSLCertificateARN 532 | 533 | 534 | ApplicationTemplate: 535 | Type: AWS::CloudFormation::Stack 536 | DependsOn: WazuhTemplate 537 | Properties: 538 | TemplateURL: 539 | !Sub 540 | - https://aws-nist.s3-us-west-1.amazonaws.com/application.template 541 | - QSS3Region: 542 | !If 543 | - GovCloudCondition 544 | - s3-us-gov-west-1 545 | - s3 546 | TimeoutInMinutes: 30 547 | Parameters: 548 | pSecurityAlarmTopic: 549 | !GetAtt 550 | - LoggingTemplate 551 | - Outputs.rSecurityAlarmTopic 552 | pEC2KeyPair: !Ref pEC2KeyPair 553 | pProductionCIDR: 10.100.0.0/16 554 | pProductionVPC: 555 | !GetAtt 556 | - ProductionVpcTemplate 557 | - Outputs.rVPCProduction 558 | pDMZSubnetA: 559 | !GetAtt 560 | - ProductionVpcTemplate 561 | - Outputs.rDMZSubnetA 562 | pDMZSubnetB: 563 | !GetAtt 564 | - ProductionVpcTemplate 565 | - Outputs.rDMZSubnetB 566 | pAppPrivateSubnetA: 567 | !GetAtt 568 | - ProductionVpcTemplate 569 | - Outputs.rAppPrivateSubnetA 570 | pAppPrivateSubnetB: 571 | !GetAtt 572 | - ProductionVpcTemplate 573 | - Outputs.rAppPrivateSubnetB 574 | pWebInstanceType: 575 | !FindInMap 576 | - AWSAMIRegionMap 577 | - !Ref AWS::Region 578 | - InstanceType 579 | pAppInstanceType: 580 | !FindInMap 581 | - AWSAMIRegionMap 582 | - !Ref AWS::Region 583 | - InstanceType 584 | pDBPrivateSubnetA: 585 | !GetAtt 586 | - ProductionVpcTemplate 587 | - Outputs.rDBPrivateSubnetA 588 | pDBPrivateSubnetB: 589 | !GetAtt 590 | - ProductionVpcTemplate 591 | - Outputs.rDBPrivateSubnetB 592 | pManagementCIDR: 10.10.0.0/16 593 | pRegionAZ1Name: !Select [ 0, !Ref pAvailabilityZones ] 594 | pRegionAZ2Name: !Select [ 1, !Ref pAvailabilityZones ] 595 | pWebServerAMI: 596 | !FindInMap 597 | - AWSAMIRegionMap 598 | - !Ref AWS::Region 599 | - AMZNLINUXHVM 600 | pAppAmi: 601 | !FindInMap 602 | - AWSAMIRegionMap 603 | - !Ref AWS::Region 604 | - AMZNLINUXHVM 605 | pDBUser: testuserdb 606 | pDBName: testDB 607 | pDBPassword: !Ref pDBPassword 608 | pDBClass: 609 | !FindInMap 610 | - AWSAMIRegionMap 611 | - !Ref AWS::Region 612 | - InstanceTypeDatabase 613 | pDBAllocatedStorage: "10" 614 | pEnvironment: 615 | !FindInMap 616 | - CustomVariables 617 | - vResourceEnvironmentTagValue 618 | - Value 619 | pBastionSSHCIDR: 0.0.0.0/0 620 | pSupportsGlacier: 621 | !FindInMap 622 | - RegionServiceSupport 623 | - !Ref AWS::Region 624 | - Glacier 625 | WazuhManagerIp: 626 | !GetAtt 627 | - WazuhTemplate 628 | - Outputs.WazuhMasterIp 629 | QSS3BucketName: !Ref QSS3BucketName 630 | QSS3KeyPrefix: !Ref QSS3KeyPrefix 631 | 632 | Outputs: 633 | TemplateType: 634 | Value: Standard Multi-Tier Web Application 635 | TemplateVersion: 636 | Value: 2.0 637 | BastionIP: 638 | Description: Use this IP via SSH to connect to Bastion Instance 639 | Value: 640 | !GetAtt 641 | - ManagementVpcTemplate 642 | - Outputs.rBastionInstanceIP 643 | LandingPageURL: 644 | Value: 645 | !GetAtt 646 | - ApplicationTemplate 647 | - Outputs.LandingPageURL 648 | WebsiteURL: 649 | Value: 650 | !GetAtt 651 | - ApplicationTemplate 652 | - Outputs.WebsiteURL 653 | Help: 654 | Description: For assistance or questions regarding this quickstart please email 655 | compliance-accelerator@amazon.com 656 | Value: '' 657 | ... -------------------------------------------------------------------------------- /vpc-production.template: -------------------------------------------------------------------------------- 1 | --- 2 | AWSTemplateFormatVersion: 2010-09-09 3 | Description: Provides networking configuration for a standard, public facing application, 4 | separates private-public subnets and enforces traffic with NACL rules (qs-1nb14cqcl) 5 | Metadata: 6 | Stack: 7 | Value: 2 8 | VersionDate: 9 | Value: 20160510 10 | Identifier: 11 | Value: template-vpc-production 12 | Input: 13 | Description: CIDR blocks, VPC names, KeyName, EC2 instance size 14 | Output: 15 | Description: Outputs ID of all deployed resources 16 | AWS::CloudFormation::Interface: 17 | ParameterGroups: 18 | - Label: 19 | default: Region Config 20 | Parameters: 21 | - pRegionAZ1Name 22 | - pRegionAZ2Name 23 | - Label: 24 | default: Production VPC Config 25 | Parameters: 26 | - pBastionSSHCIDR 27 | - pProductionVPCName 28 | - pProductionCIDR 29 | - pDMZSubnetACIDR 30 | - pDMZSubnetBCIDR 31 | - pAppPrivateSubnetACIDR 32 | - pAppPrivateSubnetBCIDR 33 | - pDBPrivateSubnetACIDR 34 | - pDBPrivateSubnetBCIDR 35 | - pEC2KeyPair 36 | - pVPCTenancy 37 | - Label: 38 | default: AWS Quick Start Configuration 39 | Parameters: 40 | - QSS3BucketName 41 | - QSS3KeyPrefix 42 | ParameterLabels: 43 | pProductionVPCName: 44 | default: Name of Production VPC 45 | pProductionCIDR: 46 | default: Production VPC CIDR block 47 | pDMZSubnetACIDR: 48 | default: CIDR block of DMZ A subnet (internet facing) 49 | pDMZSubnetBCIDR: 50 | default: CIDR block of DMZ B subnet (internet facing) 51 | pAppPrivateSubnetACIDR: 52 | default: CIDR block of Application B subnet (private) 53 | pAppPrivateSubnetBCIDR: 54 | default: CIDR block of Application A subnet (private) 55 | pDBPrivateSubnetACIDR: 56 | default: CIDR block of Database A subnet (private) 57 | pDBPrivateSubnetBCIDR: 58 | default: CIDR block of Database B subnet (private) 59 | pEC2KeyPair: 60 | default: Name of existing SSH Key for NAT Instance 61 | pVPCTenancy: 62 | default: Instance tenancy 63 | QSS3BucketName: 64 | default: Quick Start S3 Bucket Name 65 | QSS3KeyPrefix: 66 | default: Quick Start S3 Key Prefix 67 | Parameters: 68 | pBastionSSHCIDR: 69 | Description: CIDR block to allow access to bastion SSH 70 | Type: String 71 | Default: 0.0.0.0/0 72 | pRegionAZ1Name: 73 | Description: Availability Zone 1 Name in Region 74 | Type: AWS::EC2::AvailabilityZone::Name 75 | pRegionAZ2Name: 76 | Description: Availability Zone 2 Name in Region 77 | Type: AWS::EC2::AvailabilityZone::Name 78 | pProductionVPCName: 79 | Description: Production VPC Name 80 | Type: String 81 | Default: CommandCentral-Production 82 | pProductionCIDR: 83 | Description: CIDR block for Production VPC 84 | Type: String 85 | Default: 10.100.0.0/16 86 | pManagementCIDR: 87 | Description: CIDR of Management VPC 88 | Type: String 89 | pDMZSubnetACIDR: 90 | Description: CIDR block for DMZ AZ-1b subnet 91 | Type: String 92 | Default: 10.100.10.0/24 93 | pDMZSubnetBCIDR: 94 | Description: CIDR block for DMZ AZ-1b subnet 95 | Type: String 96 | Default: 10.100.20.0/24 97 | pAppPrivateSubnetACIDR: 98 | Description: CIDR block for Application AZ-1a subnet 99 | Type: String 100 | Default: 10.100.96.0/21 101 | pAppPrivateSubnetBCIDR: 102 | Description: CIDR block for Application AZ-1b subnet 103 | Type: String 104 | Default: 10.100.119.0/21 105 | pDBPrivateSubnetACIDR: 106 | Description: CIDR block for Private AZ-1a subnet 107 | Type: String 108 | Default: 10.100.194.0/21 109 | pDBPrivateSubnetBCIDR: 110 | Description: CIDR block for Private AZ-1b subnet 111 | Type: String 112 | Default: 10.100.212.0/21 113 | pEC2KeyPair: 114 | Description: Name of existing EC2 key pair for production hosts 115 | Type: String 116 | Default: '' 117 | pVPCTenancy: 118 | Description: Instance tenancy behavior for this VPC 119 | Type: String 120 | Default: default 121 | AllowedValues: 122 | - default 123 | - dedicated 124 | pEnvironment: 125 | Description: Environment (development, test, or production) 126 | Type: String 127 | Default: development 128 | pSupportsNatGateway: 129 | Description: Specifies whether this region supports NAT Gateway (this value is 130 | determined by the main stack if it is invoked from there) 131 | Type: String 132 | Default: true 133 | pNatAmi: 134 | Description: AMI to use for the NAT intstance if the region does not support NAT 135 | Gateway (this value is determined by the main stack if it is invoked from there) 136 | Type: String 137 | Default: '' 138 | pNatInstanceType: 139 | Description: Instance type to use for the NAT intstance if the region does not 140 | support NAT Gateway (this value is determined by the main stack if it is invoked 141 | from there) 142 | Type: String 143 | Default: '' 144 | pFlowLogGroup: 145 | Description: Log Group for capturing VPC Flow Logs 146 | Type: String 147 | Default: '' 148 | QSS3BucketName: 149 | AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z\-\.]*[0-9a-zA-Z])*$ 150 | ConstraintDescription: Quick Start bucket name can include numbers, lowercase 151 | letters, uppercase letters, periods (.), and hyphens (-). It cannot start or 152 | end with a hyphen (-). 153 | Default: aws-quickstart 154 | Description: S3 bucket name for the Quick Start assets. Quick Start bucket name 155 | can include numbers, lowercase letters, uppercase letters, periods (.), and 156 | hyphens (-). It cannot start or end with a hyphen (-). 157 | Type: String 158 | QSS3KeyPrefix: 159 | AllowedPattern: ^[0-9a-zA-Z-/]*$ 160 | ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, 161 | uppercase letters, hyphens (-), and forward slash (/). 162 | Default: quickstart-compliance-nist/ 163 | Description: S3 key prefix for the Quick Start assets. Quick Start key prefix 164 | can include numbers, lowercase letters, uppercase letters, hyphens (-), and 165 | forward slash (/). 166 | Type: String 167 | Conditions: 168 | cGovCloudCondition: 169 | !Equals 170 | - !Ref AWS::Region 171 | - us-gov-west-1 172 | cNeedNatInstance: 173 | !Equals 174 | - false 175 | - !Ref pSupportsNatGateway 176 | cSupportsNatGateway: 177 | !Equals 178 | - true 179 | - !Ref pSupportsNatGateway 180 | cEnableFlowLogs: 181 | !Not 182 | - !Equals 183 | - !Ref pFlowLogGroup 184 | - '' 185 | Resources: 186 | rVPCProduction: 187 | Type: AWS::EC2::VPC 188 | Properties: 189 | CidrBlock: !Ref pProductionCIDR 190 | InstanceTenancy: !Ref pVPCTenancy 191 | EnableDnsSupport: true 192 | EnableDnsHostnames: true 193 | Tags: 194 | - Key: Name 195 | Value: !Ref pProductionVPCName 196 | - Key: Environment 197 | Value: !Ref pEnvironment 198 | rSecurityGroupVpcNat: 199 | Type: AWS::EC2::SecurityGroup 200 | Properties: 201 | GroupDescription: Allow NAT from production 202 | VpcId: !Ref rVPCProduction 203 | SecurityGroupIngress: 204 | - IpProtocol: tcp 205 | FromPort: 80 206 | ToPort: 80 207 | CidrIp: !Ref pProductionCIDR 208 | - IpProtocol: tcp 209 | FromPort: 443 210 | ToPort: 443 211 | CidrIp: !Ref pProductionCIDR 212 | Tags: 213 | - Key: Name 214 | Value: sg-web-access-ports-from-production 215 | - Key: Environment 216 | Value: !Ref pEnvironment 217 | rSecurityGroupMgmtBastion: 218 | Type: AWS::EC2::SecurityGroup 219 | Properties: 220 | GroupDescription: Allow Bastion from Management Network 221 | VpcId: !Ref rVPCProduction 222 | SecurityGroupIngress: 223 | - IpProtocol: tcp 224 | FromPort: 22 225 | ToPort: 22 226 | CidrIp: !Ref pBastionSSHCIDR 227 | Tags: 228 | - Key: Name 229 | Value: sg-ssh-access-from-management-vpc 230 | - Key: Environment 231 | Value: !Ref pEnvironment 232 | rSecurityGroupSSHFromProd: 233 | Type: AWS::EC2::SecurityGroup 234 | Properties: 235 | GroupDescription: Enable SSH access via port 22 236 | VpcId: !Ref rVPCProduction 237 | SecurityGroupIngress: 238 | - IpProtocol: tcp 239 | FromPort: 22 240 | ToPort: 22 241 | CidrIp: !Ref pProductionCIDR 242 | Tags: 243 | - Key: Name 244 | Value: sg-enable-ssh-access 245 | - Key: Environment 246 | Value: !Ref pEnvironment 247 | rDMZSubnetA: 248 | Type: AWS::EC2::Subnet 249 | Properties: 250 | CidrBlock: !Ref pDMZSubnetACIDR 251 | AvailabilityZone: !Ref pRegionAZ1Name 252 | VpcId: !Ref rVPCProduction 253 | Tags: 254 | - Key: Name 255 | Value: Production DMZ Subnet A 256 | - Key: Environment 257 | Value: !Ref pEnvironment 258 | rDMZSubnetB: 259 | Type: AWS::EC2::Subnet 260 | Properties: 261 | CidrBlock: !Ref pDMZSubnetBCIDR 262 | AvailabilityZone: !Ref pRegionAZ2Name 263 | VpcId: !Ref rVPCProduction 264 | Tags: 265 | - Key: Name 266 | Value: Production DMZ Subnet B 267 | - Key: Environment 268 | Value: !Ref pEnvironment 269 | rAppPrivateSubnetA: 270 | Type: AWS::EC2::Subnet 271 | Properties: 272 | CidrBlock: !Ref pAppPrivateSubnetACIDR 273 | AvailabilityZone: !Ref pRegionAZ1Name 274 | VpcId: !Ref rVPCProduction 275 | Tags: 276 | - Key: Name 277 | Value: Production App Subnet A 278 | - Key: Environment 279 | Value: !Ref pEnvironment 280 | rAppPrivateSubnetB: 281 | Type: AWS::EC2::Subnet 282 | Properties: 283 | CidrBlock: !Ref pAppPrivateSubnetBCIDR 284 | AvailabilityZone: !Ref pRegionAZ2Name 285 | VpcId: !Ref rVPCProduction 286 | Tags: 287 | - Key: Name 288 | Value: Production App Subnet B 289 | - Key: Environment 290 | Value: !Ref pEnvironment 291 | rDBPrivateSubnetA: 292 | Type: AWS::EC2::Subnet 293 | Properties: 294 | CidrBlock: !Ref pDBPrivateSubnetACIDR 295 | AvailabilityZone: !Ref pRegionAZ1Name 296 | VpcId: !Ref rVPCProduction 297 | Tags: 298 | - Key: Name 299 | Value: Production DB Subnet A 300 | - Key: Environment 301 | Value: !Ref pEnvironment 302 | rDBPrivateSubnetB: 303 | Type: AWS::EC2::Subnet 304 | Properties: 305 | CidrBlock: !Ref pDBPrivateSubnetBCIDR 306 | AvailabilityZone: !Ref pRegionAZ2Name 307 | VpcId: !Ref rVPCProduction 308 | Tags: 309 | - Key: Name 310 | Value: Production DB Subnet B 311 | - Key: Environment 312 | Value: !Ref pEnvironment 313 | rIGWProd: 314 | Type: AWS::EC2::InternetGateway 315 | Properties: 316 | Tags: 317 | - Key: Name 318 | Value: igw-production 319 | - Key: Environment 320 | Value: !Ref pEnvironment 321 | rNACLPublic: 322 | Type: AWS::EC2::NetworkAcl 323 | Properties: 324 | VpcId: !Ref rVPCProduction 325 | rNACLPrivate: 326 | Type: AWS::EC2::NetworkAcl 327 | Properties: 328 | VpcId: !Ref rVPCProduction 329 | rRouteTableMain: 330 | Type: AWS::EC2::RouteTable 331 | Properties: 332 | VpcId: !Ref rVPCProduction 333 | Tags: 334 | - Key: Name 335 | Value: Production DMZ Route 336 | rEIPProdNatA: 337 | Type: AWS::EC2::EIP 338 | Properties: 339 | Domain: vpc 340 | rNATGatewaySubnetA: 341 | Type: AWS::EC2::NatGateway 342 | DependsOn: rIGWProd 343 | Condition: cSupportsNatGateway 344 | Properties: 345 | AllocationId: !GetAtt rEIPProdNatA.AllocationId 346 | SubnetId: !Ref rDMZSubnetA 347 | rEIPProdNatB: 348 | Type: AWS::EC2::EIP 349 | Properties: 350 | Domain: vpc 351 | rNATGatewaySubnetB: 352 | Type: AWS::EC2::NatGateway 353 | DependsOn: rIGWProd 354 | Condition: cSupportsNatGateway 355 | Properties: 356 | AllocationId: !GetAtt rEIPProdNatB.AllocationId 357 | SubnetId: !Ref rDMZSubnetB 358 | rNatInstanceTemplate: 359 | Type: AWS::CloudFormation::Stack 360 | Condition: cNeedNatInstance 361 | Properties: 362 | TemplateURL: 363 | !Sub 364 | - https://${QSS3BucketName}.${QSS3Region}.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-compliance-common/templates/nat-instance.template 365 | - QSS3Region: 366 | !If 367 | - cGovCloudCondition 368 | - s3-us-gov-west-1 369 | - s3 370 | TimeoutInMinutes: 20 371 | Parameters: 372 | pDMZSubnetA: !Ref rDMZSubnetA 373 | pSecurityGroupSSHFromVpc: !Ref rSecurityGroupSSHFromProd 374 | pSecurityGroupVpcNat: !Ref rSecurityGroupVpcNat 375 | pNatAmi: !Ref pNatAmi 376 | pNatInstanceType: !Ref pNatInstanceType 377 | pEC2KeyPair: !Ref pEC2KeyPair 378 | pVpcId: !Ref rVPCProduction 379 | pVpcName: !Ref pProductionVPCName 380 | pRouteTablePrivateA: !Ref rRouteTableProdPrivateA 381 | pRouteTablePrivateB: !Ref rRouteTableProdPrivateB 382 | pEipNatAllocationId: !GetAtt rEIPProdNatA.AllocationId 383 | rRouteProdIGW: 384 | Type: AWS::EC2::Route 385 | DependsOn: rGWAttachmentProdIGW 386 | Properties: 387 | RouteTableId: !Ref rRouteTableMain 388 | GatewayId: !Ref rIGWProd 389 | DestinationCidrBlock: 0.0.0.0/0 390 | rRouteProdPrivateNatGatewayA: 391 | Type: AWS::EC2::Route 392 | Condition: cSupportsNatGateway 393 | Properties: 394 | DestinationCidrBlock: 0.0.0.0/0 395 | RouteTableId: !Ref rRouteTableProdPrivateA 396 | NatGatewayId: !Ref rNATGatewaySubnetA 397 | rRouteProdPrivateNatGatewayB: 398 | Type: AWS::EC2::Route 399 | Condition: cSupportsNatGateway 400 | Properties: 401 | DestinationCidrBlock: 0.0.0.0/0 402 | RouteTableId: !Ref rRouteTableProdPrivateB 403 | NatGatewayId: !Ref rNATGatewaySubnetB 404 | rRouteAssocProdDMZA: 405 | Type: AWS::EC2::SubnetRouteTableAssociation 406 | Properties: 407 | RouteTableId: !Ref rRouteTableMain 408 | SubnetId: !Ref rDMZSubnetA 409 | rRouteAssocProdDMZB: 410 | Type: AWS::EC2::SubnetRouteTableAssociation 411 | Properties: 412 | RouteTableId: !Ref rRouteTableMain 413 | SubnetId: !Ref rDMZSubnetB 414 | rAppPrivateSubnetAssociationA: 415 | Type: AWS::EC2::SubnetRouteTableAssociation 416 | Properties: 417 | RouteTableId: !Ref rRouteTableProdPrivateA 418 | SubnetId: !Ref rAppPrivateSubnetA 419 | rAppPrivateSubnetAssociationB: 420 | Type: AWS::EC2::SubnetRouteTableAssociation 421 | Properties: 422 | RouteTableId: !Ref rRouteTableProdPrivateB 423 | SubnetId: !Ref rAppPrivateSubnetB 424 | rRouteAssocDBPrivateA: 425 | Type: AWS::EC2::SubnetRouteTableAssociation 426 | Properties: 427 | RouteTableId: !Ref rRouteTableProdPrivateA 428 | SubnetId: !Ref rDBPrivateSubnetA 429 | rRouteAssocDBPrivateB: 430 | Type: AWS::EC2::SubnetRouteTableAssociation 431 | Properties: 432 | RouteTableId: !Ref rRouteTableProdPrivateB 433 | SubnetId: !Ref rDBPrivateSubnetB 434 | rRouteTableProdPrivateA: 435 | Type: AWS::EC2::RouteTable 436 | Properties: 437 | VpcId: !Ref rVPCProduction 438 | Tags: 439 | - Key: Name 440 | Value: Production Private Route A 441 | rRouteTableProdPrivateB: 442 | Type: AWS::EC2::RouteTable 443 | Properties: 444 | VpcId: !Ref rVPCProduction 445 | Tags: 446 | - Key: Name 447 | Value: Production Private Route B 448 | rNACLRuleAllowAllTCPInternal: 449 | Type: AWS::EC2::NetworkAclEntry 450 | Properties: 451 | CidrBlock: !Ref pProductionCIDR 452 | Protocol: 6 453 | PortRange: 454 | From: 1 455 | To: 65535 456 | RuleAction: allow 457 | RuleNumber: 120 458 | NetworkAclId: !Ref rNACLPrivate 459 | rNACLRuleAllowBastionSSHAccessPrivate: 460 | Type: AWS::EC2::NetworkAclEntry 461 | Properties: 462 | CidrBlock: 0.0.0.0/0 463 | Protocol: 6 464 | PortRange: 465 | From: 22 466 | To: 22 467 | RuleAction: allow 468 | RuleNumber: 130 469 | NetworkAclId: !Ref rNACLPrivate 470 | rNACLRuleAllowMgmtAccessSSHtoPrivate: 471 | Type: AWS::EC2::NetworkAclEntry 472 | Properties: 473 | CidrBlock: !Ref pManagementCIDR 474 | Protocol: 6 475 | PortRange: 476 | From: 22 477 | To: 22 478 | RuleAction: allow 479 | RuleNumber: 125 480 | NetworkAclId: !Ref rNACLPrivate 481 | rNACLRuleAllowReturnTCPPriv: 482 | Type: AWS::EC2::NetworkAclEntry 483 | Properties: 484 | CidrBlock: 0.0.0.0/0 485 | Protocol: 6 486 | PortRange: 487 | From: 1024 488 | To: 65535 489 | RuleAction: allow 490 | RuleNumber: 140 491 | NetworkAclId: !Ref rNACLPrivate 492 | rNACLRuleAllowALLfromPrivEgress: 493 | Type: AWS::EC2::NetworkAclEntry 494 | Properties: 495 | CidrBlock: 0.0.0.0/0 496 | Egress: true 497 | Protocol: 6 498 | PortRange: 499 | From: 1 500 | To: 65535 501 | RuleAction: allow 502 | RuleNumber: 120 503 | NetworkAclId: !Ref rNACLPrivate 504 | rNACLRuleAllowAllTCPInternalEgress: 505 | Type: AWS::EC2::NetworkAclEntry 506 | Properties: 507 | CidrBlock: 0.0.0.0/0 508 | Egress: true 509 | Protocol: 6 510 | PortRange: 511 | From: 1 512 | To: 65535 513 | RuleAction: allow 514 | RuleNumber: 100 515 | NetworkAclId: !Ref rNACLPrivate 516 | rNACLRuleAllowALLEgressPublic: 517 | Type: AWS::EC2::NetworkAclEntry 518 | Properties: 519 | CidrBlock: 0.0.0.0/0 520 | Egress: true 521 | Protocol: 6 522 | PortRange: 523 | From: 1 524 | To: 65535 525 | RuleAction: allow 526 | RuleNumber: 100 527 | NetworkAclId: !Ref rNACLPublic 528 | rNACLRuleAllowAllReturnTCP: 529 | Type: AWS::EC2::NetworkAclEntry 530 | Properties: 531 | CidrBlock: 0.0.0.0/0 532 | Protocol: 6 533 | PortRange: 534 | From: 1024 535 | To: 65535 536 | RuleAction: allow 537 | RuleNumber: 140 538 | NetworkAclId: !Ref rNACLPublic 539 | rNACLRuleAllowHTTPfromProd: 540 | Type: AWS::EC2::NetworkAclEntry 541 | Properties: 542 | CidrBlock: !Ref pProductionCIDR 543 | Protocol: 6 544 | PortRange: 545 | From: 80 546 | To: 80 547 | RuleAction: allow 548 | RuleNumber: 200 549 | NetworkAclId: !Ref rNACLPublic 550 | rNACLRuleAllowBastionSSHAccessPublic: 551 | Type: AWS::EC2::NetworkAclEntry 552 | Properties: 553 | CidrBlock: 0.0.0.0/0 554 | Protocol: 6 555 | PortRange: 556 | From: 22 557 | To: 22 558 | RuleAction: allow 559 | RuleNumber: 210 560 | NetworkAclId: !Ref rNACLPublic 561 | rNACLRuleAllowEgressReturnTCP: 562 | Type: AWS::EC2::NetworkAclEntry 563 | Properties: 564 | CidrBlock: 0.0.0.0/0 565 | Egress: true 566 | Protocol: 6 567 | PortRange: 568 | From: 1024 569 | To: 65535 570 | RuleAction: allow 571 | RuleNumber: 140 572 | NetworkAclId: !Ref rNACLPublic 573 | rNACLRuleAllowHTTPSPublic: 574 | Type: AWS::EC2::NetworkAclEntry 575 | Properties: 576 | CidrBlock: 0.0.0.0/0 577 | Protocol: 6 578 | PortRange: 579 | From: 443 580 | To: 443 581 | RuleAction: allow 582 | RuleNumber: 100 583 | NetworkAclId: !Ref rNACLPublic 584 | rNACLAssocAppPrivSubnetB: 585 | Type: AWS::EC2::SubnetNetworkAclAssociation 586 | Properties: 587 | NetworkAclId: !Ref rNACLPrivate 588 | SubnetId: !Ref rAppPrivateSubnetB 589 | rNACLAssocDMZPubSubnetA: 590 | Type: AWS::EC2::SubnetNetworkAclAssociation 591 | Properties: 592 | NetworkAclId: !Ref rNACLPublic 593 | SubnetId: !Ref rDMZSubnetA 594 | rNACLAssocDMZPubSubnetB: 595 | Type: AWS::EC2::SubnetNetworkAclAssociation 596 | Properties: 597 | NetworkAclId: !Ref rNACLPublic 598 | SubnetId: !Ref rDMZSubnetB 599 | rNACLAssocAppPrivSubnetA: 600 | Type: AWS::EC2::SubnetNetworkAclAssociation 601 | Properties: 602 | NetworkAclId: !Ref rNACLPrivate 603 | SubnetId: !Ref rAppPrivateSubnetA 604 | rNACLAssocDBPrivSubnetA: 605 | Type: AWS::EC2::SubnetNetworkAclAssociation 606 | Properties: 607 | NetworkAclId: !Ref rNACLPrivate 608 | SubnetId: !Ref rDBPrivateSubnetA 609 | rNACLAssocDBPrivSubnetB: 610 | Type: AWS::EC2::SubnetNetworkAclAssociation 611 | Properties: 612 | NetworkAclId: !Ref rNACLPrivate 613 | SubnetId: !Ref rDBPrivateSubnetB 614 | rGWAttachmentProdIGW: 615 | Type: AWS::EC2::VPCGatewayAttachment 616 | DependsOn: rIGWProd 617 | Properties: 618 | VpcId: !Ref rVPCProduction 619 | InternetGatewayId: !Ref rIGWProd 620 | rProductionVpcFlowLogsServiceRole: 621 | Condition: cEnableFlowLogs 622 | Type: AWS::IAM::Role 623 | Properties: 624 | AssumeRolePolicyDocument: 625 | Version: 2012-10-17 626 | Statement: 627 | - Sid: AllowFlowLogs 628 | Effect: Allow 629 | Principal: 630 | Service: vpc-flow-logs.amazonaws.com 631 | Action: sts:AssumeRole 632 | Path: / 633 | Policies: 634 | - PolicyName: cloudwatchlogsrole 635 | PolicyDocument: 636 | Version: 2012-10-17 637 | Statement: 638 | - Action: 639 | - logs:CreateLogGroup 640 | - logs:CreateLogStream 641 | - logs:PutLogEvents 642 | - logs:DescribeLogGroups 643 | - logs:DescribeLogStreams 644 | Effect: Allow 645 | Resource: '*' 646 | rProductionVpcFlowLog: 647 | Condition: cEnableFlowLogs 648 | Type: AWS::EC2::FlowLog 649 | Properties: 650 | DeliverLogsPermissionArn: !GetAtt rProductionVpcFlowLogsServiceRole.Arn 651 | LogGroupName: !Ref pFlowLogGroup 652 | ResourceId: !Ref rVPCProduction 653 | ResourceType: VPC 654 | TrafficType: ALL 655 | rProductionVpcFlowLogStream: 656 | Condition: cEnableFlowLogs 657 | Type: AWS::Logs::LogStream 658 | Properties: 659 | LogGroupName: !Ref pFlowLogGroup 660 | Outputs: 661 | rVPCProduction: 662 | Value: !Ref rVPCProduction 663 | rDMZSubnetA: 664 | Value: !Ref rDMZSubnetA 665 | rDMZSubnetB: 666 | Value: !Ref rDMZSubnetB 667 | rRouteTableProdPrivate: 668 | Value: !Ref rRouteTableProdPrivateA 669 | rRouteTableProdPrivateB: 670 | Value: !Ref rRouteTableProdPrivateB 671 | rRouteTableProdPublic: 672 | Value: !Ref rRouteTableMain 673 | rAppPrivateSubnetA: 674 | Value: !Ref rAppPrivateSubnetA 675 | rAppPrivateSubnetB: 676 | Value: !Ref rAppPrivateSubnetB 677 | rDBPrivateSubnetA: 678 | Value: !Ref rDBPrivateSubnetA 679 | rDBPrivateSubnetB: 680 | Value: !Ref rDBPrivateSubnetB 681 | rNACLPrivate: 682 | Value: !Ref rNACLPrivate 683 | rNACLPublic: 684 | Value: !Ref rNACLPublic 685 | rSecurityGroupSSHFromProd: 686 | Value: !Ref rSecurityGroupSSHFromProd 687 | rSecurityGroupVpcNat: 688 | Value: !Ref rSecurityGroupVpcNat 689 | ... -------------------------------------------------------------------------------- /wazuh/cluster/wazuh_cf_master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Install Wazuh master instance using Cloudformation template 3 | # Support for Amazon Linux 4 | touch /tmp/log 5 | echo "Starting process." > /tmp/log 6 | 7 | ssh_username=$(cat /tmp/wazuh_cf_settings | grep '^SshUsername:' | cut -d' ' -f2) 8 | ssh_password=$(cat /tmp/wazuh_cf_settings | grep '^SshPassword:' | cut -d' ' -f2) 9 | elastic_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f1) 10 | wazuh_version=$(cat /tmp/wazuh_cf_settings | grep '^Elastic_Wazuh:' | cut -d' ' -f2 | cut -d'_' -f2) 11 | wazuh_server_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhServerPort:' | cut -d' ' -f2) 12 | wazuh_registration_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhRegistrationPort:' | cut -d' ' -f2) 13 | wazuh_api_user=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminUsername:' | cut -d' ' -f2) 14 | wazuh_api_password=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiAdminPassword:' | cut -d' ' -f2) 15 | wazuh_api_port=$(cat /tmp/wazuh_cf_settings | grep '^WazuhApiPort:' | cut -d' ' -f2) 16 | wazuh_cluster_key=$(cat /tmp/wazuh_cf_settings | grep '^WazuhClusterKey:' | cut -d' ' -f2) 17 | elb_logstash=$(cat /tmp/wazuh_cf_settings | grep '^ElbLogstashDNS:' | cut -d' ' -f2) 18 | eth0_ip=$(/sbin/ifconfig eth0 | grep 'inet' | head -1 | sed -e 's/^[[:space:]]*//' | cut -d' ' -f2) 19 | splunk_username=$(cat /tmp/wazuh_cf_settings | grep '^KibanaUsername:' | cut -d' ' -f2) 20 | splunk_password=$(cat /tmp/wazuh_cf_settings | grep '^KibanaPassword:' | cut -d' ' -f2) 21 | splunk_ip=$(cat /tmp/wazuh_cf_settings | grep '^SplunkIP:' | cut -d' ' -f2) 22 | WindowsPublicIp=$(cat /tmp/wazuh_cf_settings | grep '^WindowsPublicIp:' | cut -d' ' -f2) 23 | VirusTotalKey=$(cat /tmp/wazuh_cf_settings | grep '^VirusTotalKey:' | cut -d' ' -f2) 24 | AwsSecretKey=$(cat /tmp/wazuh_cf_settings | grep '^AwsSecretKey:' | cut -d' ' -f2) 25 | AwsAccessKey=$(cat /tmp/wazuh_cf_settings | grep '^AwsAccessKey:' | cut -d' ' -f2) 26 | SlackHook=$(cat /tmp/wazuh_cf_settings | grep '^SlackHook:' | cut -d' ' -f2) 27 | EnvironmentType=$(cat /tmp/wazuh_cf_settings | grep '^EnvironmentType:' | cut -d' ' -f2) 28 | 29 | echo "Added env vars." >> /tmp/log 30 | 31 | # Check if running as root 32 | if [[ $EUID -ne 0 ]]; then 33 | echo "This script must be run as root" 34 | exit 1 35 | fi 36 | 37 | # Creating SSH user 38 | adduser ${ssh_username} 39 | echo "${ssh_username} ALL=(ALL)NOPASSWD:ALL" >> /etc/sudoers 40 | usermod --password $(openssl passwd -1 ${ssh_password}) ${ssh_username} 41 | sed -i 's|[#]*PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config 42 | service sshd restart 43 | 44 | echo "Created SSH user." >> /tmp/log 45 | 46 | if [[ ${EnvironmentType} == 'staging' ]] 47 | then 48 | # Adding Wazuh pre_release repository 49 | echo -e '[wazuh_pre_release]\ngpgcheck=1\ngpgkey=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/key/GPG-KEY-WAZUH\nenabled=1\nname=EL-$releasever - Wazuh\nbaseurl=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/pre-release/yum/\nprotect=1' | tee /etc/yum.repos.d/wazuh_pre.repo 50 | elif [[ ${EnvironmentType} == 'production' ]] 51 | then 52 | cat > /etc/yum.repos.d/wazuh.repo <<\EOF 53 | [wazuh_repo] 54 | gpgcheck=1 55 | gpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH 56 | enabled=1 57 | name=Wazuh repository 58 | baseurl=https://packages.wazuh.com/3.x/yum/ 59 | protect=1 60 | EOF 61 | elif [[ ${EnvironmentType} == 'devel' ]] 62 | then 63 | echo -e '[wazuh_staging]\ngpgcheck=1\ngpgkey=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/key/GPG-KEY-WAZUH\nenabled=1\nname=EL-$releasever - Wazuh\nbaseurl=https://s3-us-west-1.amazonaws.com/packages-dev.wazuh.com/staging/yum/\nprotect=1' | tee /etc/yum.repos.d/wazuh_staging.repo 64 | else 65 | echo 'no repo' >> /tmp/stage 66 | fi 67 | 68 | # Configuring Elastic repository 69 | rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch 70 | elastic_major_version=$(echo ${elastic_version} | cut -d'.' -f1) 71 | cat > /etc/yum.repos.d/elastic.repo << EOF 72 | [elasticsearch-6.x] 73 | name=Elasticsearch repository for 6.x packages 74 | baseurl=https://artifacts.elastic.co/packages/6.x/yum 75 | gpgcheck=1 76 | gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch 77 | enabled=1 78 | autorefresh=1 79 | type=rpm-md 80 | EOF 81 | 82 | # Installing wazuh-manager 83 | yum -y install wazuh-manager 84 | chkconfig --add wazuh-manager 85 | manager_config="/var/ossec/etc/ossec.conf" 86 | local_rules="/var/ossec/etc/rules/local_rules.xml" 87 | # Enable registration service (only for master node) 88 | 89 | echo "Installed wazuh manager package" >> /tmp/log 90 | 91 | ### Use case 1: IP reputation 92 | 93 | wget https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/alienvault_reputation.ipset -O /var/ossec/etc/lists/alienvault_reputation.ipset 94 | wget https://wazuh.com/resources/iplist-to-cdblist.py -O /var/ossec/etc/lists/iplist-to-cdblist.py 95 | # Add Windows public IP to the list 96 | echo ${WindowsPublicIp} >> /var/ossec/etc/lists/alienvault_reputation.ipset 97 | python /var/ossec/etc/lists/iplist-to-cdblist.py /var/ossec/etc/lists/alienvault_reputation.ipset /var/ossec/etc/lists/blacklist-alienvault 98 | 99 | # Delete ipset and python script 100 | rm -rf /var/ossec/etc/lists/alienvault_reputation.ipset 101 | rm -rf /var/ossec/etc/lists/iplist-to-cdblist.py 102 | /var/ossec/bin/ossec-makelists 103 | 104 | echo "Updated CDB list ,added Windows agent IP." >> /tmp/log 105 | 106 | # Change manager protocol to tcp, to be used by Amazon ELB 107 | sed -i "s/udp<\/protocol>/tcp<\/protocol>/" ${manager_config} 108 | 109 | # Set manager port for agent communications 110 | sed -i "s/1514<\/port>/${wazuh_server_port}<\/port>/" ${manager_config} 111 | 112 | # Configuring registration service 113 | sed -i '//,/<\/auth>/d' ${manager_config} 114 | 115 | cat >> ${manager_config} << EOF 116 | 117 | 118 | no 119 | ${wazuh_registration_port} 120 | no 121 | yes 122 | 0 123 | yes 124 | yes 125 | yes 126 | HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH 127 | 128 | no 129 | /var/ossec/etc/sslmanager.cert 130 | /var/ossec/etc/sslmanager.key 131 | no 132 | 133 | 134 | EOF 135 | 136 | # Setting password for agents registration 137 | echo "Set registration password." > /tmp/log 138 | 139 | # Installing Python Cryptography module for the cluster 140 | pip install cryptography 141 | 142 | # Configuring cluster section 143 | sed -i '//,/<\/cluster>/d' ${manager_config} 144 | 145 | cat >> ${manager_config} << EOF 146 | 147 | 148 | wazuh 149 | wazuh-master 150 | master 151 | ${wazuh_cluster_key} 152 | 1516 153 | 0.0.0.0 154 | 155 | ${eth0_ip} 156 | 157 | no 158 | no 159 | 160 | 161 | EOF 162 | 163 | # Disabling agent components and cleaning configuration file 164 | sed -i '//,/<\/wodle>/d' ${manager_config} 165 | sed -i '//,/<\/wodle>/d' ${manager_config} 166 | sed -i '//,/<\/ruleset>/d' ${manager_config} 167 | sed -i '//,/<\/wodle>/d' ${manager_config} 168 | sed -i '//,/<\/wodle>/d' ${manager_config} 169 | sed -i '//,/<\/localfile>/d' ${manager_config} 170 | sed -i '//d' ${manager_config} 171 | sed -i '//d' ${manager_config} 172 | sed -i '/^$/d' ${manager_config} 173 | 174 | # Add ruleset and lists 175 | cat >> ${manager_config} << EOF 176 | 177 | 178 | 179 | ruleset/decoders 180 | ruleset/rules 181 | 0215-policy_rules.xml 182 | etc/lists/audit-keys 183 | etc/lists/amazon/aws-eventnames 184 | etc/lists/security-eventchannel 185 | etc/lists/blacklist-alienvault 186 | 187 | etc/decoders 188 | etc/rules 189 | 190 | 191 | EOF 192 | 193 | # Use case: Open-SCAP configuration 194 | 195 | # Install dependencies 196 | yum -y install openscap-scanner 197 | 198 | # Configure wodles 199 | cat >> ${manager_config} << EOF 200 | 201 | 202 | no 203 | 1800 204 | 1d 205 | yes 206 | 207 | xccdf_org.ssgproject.content_profile_pci-dss 208 | xccdf_org.ssgproject.content_profile_common 209 | 210 | 211 | 212 | 213 | EOF 214 | 215 | # Add VirusTotal integration if key already set 216 | if [ "x${VirusTotalKey}" != "x" ]; then 217 | cat >> ${manager_config} << EOF 218 | 219 | 220 | virustotal 221 | ${VirusTotalKey} 222 | 100200 223 | json 224 | 225 | 226 | EOF 227 | fi 228 | 229 | cat >> ${local_rules} << EOF 230 | 231 | 232 | 550,553,554 233 | ^/tmp 234 | File modified or created in /tmp directory. 235 | 236 | 237 | 238 | 239 | 530 240 | ^ossec: output: 'process list' 241 | List of running processes. 242 | process_monitor, 243 | 244 | 245 | 100050 246 | nc -l 247 | Netcat listening for incoming connections. 248 | process_monitor, 249 | 250 | 251 | 252 | 253 | web|attack|attacks 254 | etc/lists/blacklist-alienvault 255 | IP address found in AlienVault reputation database. 256 | 257 | 258 | EOF 259 | 260 | # Slack integration 261 | if [ "x${SlackHook}" != "x" ]; then 262 | cat >> ${manager_config} << EOF 263 | 264 | 265 | slack 266 | ${SlackHook} 267 | 10 268 | json 269 | 270 | 271 | EOF 272 | fi 273 | 274 | # AWS integration if key already set 275 | if [ "x${AwsAccessKey}" != "x" ]; then 276 | cat >> ${manager_config} << EOF 277 | 278 | 279 | no 280 | no 281 | 30m 282 | yes 283 | no 284 | 285 | wazuh-cloudtrail 286 | ${AwsAccessKey} 287 | ${AwsSecretKey} 288 | 2019-MAR-24 289 | 290 | 291 | wazuh-aws-wodle 292 | guardduty 293 | ${AwsAccessKey} 294 | ${AwsSecretKey} 295 | 2019-MAR-24 296 | 297 | 298 | wazuh-aws-wodle 299 | macie 300 | ${AwsAccessKey} 301 | ${AwsSecretKey} 302 | 2019-MAR-24 303 | 304 | 305 | wazuh-aws-wodle 306 | vpc 307 | ${AwsAccessKey} 308 | ${AwsSecretKey} 309 | 2019-MAR-24 310 | 311 | 312 | ${AwsAccessKey} 313 | ${AwsSecretKey} 314 | 315 | 316 | 317 | EOF 318 | fi 319 | 320 | UID=$(id -u `whoami`) 321 | 322 | # Audit rules 323 | cat >> /etc/audit/rules.d/audit.rules << EOF 324 | -a exit,always -F euid=0 -F arch=b32 -S execve -k audit-wazuh-c 325 | -a exit,always -F euid=0 -F arch=b64 -S execve -k audit-wazuh-c 326 | -a exit,always -F euid=1003 -F arch=b32 -S execve -k audit-wazuh-c 327 | -a exit,always -F euid=1003 -F arch=b64 -S execve -k audit-wazuh-c 328 | -a exit,always -F euid=1002 -F arch=b32 -S execve -k audit-wazuh-c 329 | -a exit,always -F euid=1002 -F arch=b64 -S execve -k audit-wazuh-c 330 | -a exit,always -F euid=1003 -F arch=b32 -S execve -k audit-wazuh-c 331 | -a exit,always -F euid=1003 -F arch=b64 -S execve -k audit-wazuh-c 332 | -a exit,always -F euid=${UID} -F arch=b32 -S execve -k audit-wazuh-c 333 | -a exit,always -F euid=${UID} -F arch=b64 -S execve -k audit-wazuh-c 334 | EOF 335 | 336 | auditctl -D 337 | auditctl -R /etc/audit/rules.d/audit.rules 338 | systemctl restart audit 339 | 340 | # Localfiles 341 | cat >> ${manager_config} << EOF 342 | 343 | 344 | full_command 345 | process list 346 | ps -e -o pid,uname,command 347 | 30 348 | 349 | 350 | firewall-drop 351 | firewall-drop.sh 352 | srcip 353 | yes 354 | 355 | 356 | 357 | firewall-drop 358 | local 359 | 100100 360 | 60 361 | 362 | 363 | EOF 364 | 365 | # Vuln detector 366 | cat >> ${manager_config} << EOF 367 | 368 | 369 | no 370 | 12m 371 | 6h 372 | yes 373 | 374 | no 375 | 1h 376 | 377 | 378 | no 379 | 2010 380 | 1h 381 | 382 | 383 | no 384 | 1h 385 | 386 | 387 | 388 | EOF 389 | 390 | # Restart wazuh-manager 391 | service wazuh-manager restart 392 | echo "Restarted Wazuh manager." >> /tmp/log 393 | 394 | # Installing NodeJS 395 | curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - 396 | yum -y install nodejs 397 | echo "Installed NODEJS." >> /tmp/log 398 | 399 | # Installing wazuh-api 400 | yum -y install wazuh-api 401 | chkconfig --add wazuh-api 402 | echo "Installed Wazuh API." >> /tmp/log 403 | 404 | # Configuring Wazuh API user and password 405 | cd /var/ossec/api/configuration/auth 406 | node htpasswd -b -c user ${wazuh_api_user} ${wazuh_api_password} 407 | 408 | # Enable Wazuh API SSL and configure listening port 409 | api_ssl_dir="/var/ossec/api/configuration/ssl" 410 | openssl req -x509 -batch -nodes -days 3650 -newkey rsa:2048 -keyout ${api_ssl_dir}/server.key -out ${api_ssl_dir}/server.crt 411 | sed -i "s/config.https = \"no\";/config.https = \"yes\";/" /var/ossec/api/configuration/config.js 412 | sed -i "s/config.port = \"55000\";/config.port = \"${wazuh_api_port}\";/" /var/ossec/api/configuration/config.js 413 | echo "Setting port and SSL to Wazuh API." >> /tmp/log 414 | 415 | # Restart wazuh-api 416 | service wazuh-api restart 417 | echo "Restarted Wazuh API." >> /tmp/log 418 | 419 | # Installing Filebeat 420 | yum -y install filebeat-${elastic_version} 421 | chkconfig --add filebeat 422 | echo "Installed Filebeat." >> /tmp/log 423 | 424 | # Configuring Filebeat 425 | curl -so /etc/filebeat/filebeat.yml https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/filebeat/filebeat.yml 426 | sed -i "s/YOUR_ELASTIC_SERVER_IP/${elb_logstash}/" /etc/filebeat/filebeat.yml 427 | service filebeat restart 428 | echo "Restarted Filebeat." >> /tmp/log 429 | 430 | # Disable repositories 431 | sed -i "s/^enabled=1/enabled=0/" /etc/yum.repos.d/elastic.repo 432 | 433 | # Setting up Splunk Forwarder 434 | yum -y install wget 435 | # download splunkforwarder 436 | echo 'Downloading Splunk Forwarder...' 437 | wget -O splunkforwarder-7.2.3-06d57c595b80-linux-2.6-x86_64.rpm 'https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=7.2.3&product=universalforwarder&filename=splunkforwarder-7.2.3-06d57c595b80-linux-2.6-x86_64.rpm&wget=true' &> /dev/null 438 | 439 | # install splunkforwarder 440 | echo 'Installing Splunk Forwarder...' 441 | yum install splunkforwarder-7.2.3-06d57c595b80-linux-2.6-x86_64.rpm -y -q &> /dev/null 442 | 443 | echo "Setting up Splunk forwarder..." 444 | # props.conf 445 | curl -so /opt/splunkforwarder/etc/system/local/props.conf https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/splunk/props.conf 446 | 447 | # inputs.conf 448 | curl -so /opt/splunkforwarder/etc/system/local/inputs.conf https://raw.githubusercontent.com/wazuh/wazuh/3.9/extensions/splunk/inputs.conf 449 | 450 | # set hostname 451 | sed -i "s:MANAGER_HOSTNAME:$(hostname):g" /opt/splunkforwarder/etc/system/local/inputs.conf 452 | 453 | touch /opt/splunkforwarder/etc/system/local/user-seed.conf 454 | 455 | # create credential file 456 | touch /opt/splunk/etc/system/local/user-seed.conf 457 | 458 | # add admin user 459 | cat > /opt/splunk/etc/system/local/user-seed.conf <<\EOF 460 | [user_info] 461 | USERNAME = ${splunk_username} 462 | PASSWORD = ${splunk_password} 463 | EOF 464 | 465 | echo "Starting Splunk..." 466 | # accept license 467 | /opt/splunkforwarder/bin/splunk start --accept-license --answer-yes --auto-ports --no-prompt &> /dev/null 468 | 469 | # forward to index 470 | /opt/splunkforwarder/bin/splunk add forward-server ${splunk_ip}:9997 -auth admin:changeme &> /dev/null 471 | 472 | # restart service 473 | /opt/splunkforwarder/bin/splunk restart &> /dev/null 474 | echo "Done with Splunk." >> /tmp/log 475 | 476 | # Creating groups 477 | /var/ossec/bin/agent_groups -a -g apache -q 478 | /var/ossec/bin/agent_groups -a -g redhat -q 479 | /var/ossec/bin/agent_groups -a -g windows -q 480 | /var/ossec/bin/agent_groups -a -g mysql -q 481 | 482 | # Give time to the instances dependencies to be properly installed 483 | sleep 360 484 | 485 | # Write RHEL7 shared config 486 | redhat_conf='/var/ossec/etc/shared/redhat/agent.conf' 487 | sed -i '//,/<\/agent_config>/d' ${redhat_conf} 488 | cat >> ${redhat_conf} << EOF 489 | 490 | 491 | 10m 492 | 5 493 | yes 494 | no 495 | 496 | 497 | 498 | no 499 | 43200 500 | yes 501 | 502 | /usr/bin,/usr/sbin 503 | /bin,/sbin,/boot 504 | /etc/cron* 505 | /home,/root 506 | /tmp 507 | 508 | /etc/mtab 509 | /etc/hosts.deny 510 | /etc/mail/statistics 511 | /etc/random-seed 512 | /etc/random.seed 513 | /etc/adjtime 514 | /etc/httpd/logs 515 | /etc/utmpx 516 | /etc/wtmpx 517 | /etc/cups/certs 518 | /etc/dumpdates 519 | /etc/svc/volatile 520 | 521 | .log$|.tmp$|.swp$|.viminfo$ 522 | 523 | /etc/ssl/private.key 524 | 525 | yes 526 | 527 | 528 | 529 | no 530 | yes 531 | yes 532 | yes 533 | no 534 | no 535 | yes 536 | no 537 | no 538 | 539 | 60 540 | /var/ossec/etc/shared/rootkit_files.txt 541 | /var/ossec/etc/shared/rootkit_trojans.txt 542 | /var/ossec/etc/shared/system_audit_rcl.txt 543 | /var/ossec/etc/shared/system_audit_ssh.txt 544 | yes 545 | 546 | 547 | 548 | no 549 | 1800 550 | 1d 551 | yes 552 | 553 | xccdf_org.ssgproject.content_profile_pci-dss 554 | xccdf_org.ssgproject.content_profile_common 555 | 556 | 557 | 558 | 559 | 560 | no 561 | 1h 562 | yes 563 | yes 564 | yes 565 | yes 566 | yes 567 | yes 568 | yes 569 | 570 | 571 | no 572 | yes 573 | /usr/bin 574 | /var/log/osquery/osqueryd.results.log 575 | /etc/osquery/osquery.conf 576 | no 577 | 578 | 579 | 580 | command 581 | df -P 582 | 360 583 | 584 | 585 | full_command 586 | netstat -tulpn | sed 's/\([[:alnum:]]\+\)\ \+[[:digit:]]\+\ \+[[:digit:]]\+\ \+\(.*\):\([[:digit:]]*\)\ \+\([0-9\.\:\*]\+\).\+\ \([[:digit:]]*\/[[:alnum:]\-]*\).*/\1 \2 == \3 == \4 \5/' | sort -k 4 -g | sed 's/ == \(.*\) ==/:\1/' | sed 1,2d 587 | netstat listening ports 588 | 360 589 | 590 | 591 | full_command 592 | last -n 20 593 | 360 594 | 595 | 596 | apache 597 | /var/log/httpd/error_log* 598 | 599 | 600 | apache 601 | /var/log/httpd/access_log* 602 | 603 | 604 | audit 605 | /var/log/audit/audit.log 606 | 607 | 608 | syslog 609 | /var/ossec/logs/active-responses.log 610 | 611 | 612 | syslog 613 | /var/log/messages 614 | 615 | 616 | syslog 617 | /var/log/secure 618 | 619 | 620 | syslog 621 | /var/log/maillog 622 | 623 | 624 | syslog 625 | /var/log/suricata/eve.json 626 | 627 | 628 | full_command 629 | process list 630 | ps -e -o pid,uname,command 631 | 30 632 | 633 | 634 | EOF 635 | 636 | # Write Windows shared config 637 | windows_conf='/var/ossec/etc/shared/windows/agent.conf' 638 | sed -i '//,/<\/agent_config>/d' ${windows_conf} 639 | cat >> ${windows_conf} << EOF 640 | 641 | 642 | no 643 | 1h 644 | yes 645 | yes 646 | yes 647 | yes 648 | 649 | 650 | no 651 | yes 652 | C:\ProgramData\osquery\osqueryd 653 | C:\ProgramData\osquery\log\osqueryd.results.log 654 | C:\ProgramData\osquery\osquery.conf 655 | no 656 | 657 | 658 | C:\inetpub\logs\LogFiles\W3SVC1\u_ex%y%m%d.log 659 | iis 660 | 661 | 662 | yes 663 | C:\Santiago 664 | 665 | 666 | EOF 667 | 668 | # Write apache shared config 669 | apache_conf='/var/ossec/etc/shared/apache/agent.conf' 670 | sed -i '//,/<\/agent_config>/d' ${apache_conf} 671 | cat >> ${apache_conf} << EOF 672 | 673 | 674 | no 675 | 43200 676 | yes 677 | 678 | /etc/httpd 679 | 680 | .log$|.tmp$|.swp$|.viminfo$ 681 | 682 | 683 | EOF 684 | 685 | # Write mysql shared config 686 | mysql_conf='/var/ossec/etc/shared/mysql/agent.conf' 687 | sed -i '//,/<\/agent_config>/d' ${mysql_conf} 688 | cat >> ${mysql_conf} << EOF 689 | 690 | 691 | /var/lib/mysql 692 | 693 | 694 | EOF 695 | 696 | # Attach agents to groups 697 | rhel_id=`/var/ossec/bin/manage_agents -l | grep RHEL | cut -d':' -f2 | cut -d ',' -f1` 698 | #windows_id = /var/ossec/bin/manage_agents -l | grep Windows | cut -d':' -f2 | cut -d ',' -f1 699 | 700 | /var/ossec/bin/agent_groups -a -g redhat -i ${rhel_id} -q 701 | /var/ossec/bin/agent_groups -a -g mysql -i ${rhel_id} -q 702 | /var/ossec/bin/agent_groups -a -g apache -i ${rhel_id} -q 703 | #/var/ossec/bin/agent_groups -a -g windows -i ${windows_id} -q --------------------------------------------------------------------------------