├── .cfn-nag-blacklist.yml ├── .gitignore ├── .taskcat.yml ├── .taskcat_overrides.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── buildspec.yml ├── pipeline └── basic-pipeline.yaml └── wordpress ├── input.json ├── wordpress-single-instance-final.yaml └── wordpress-single-instance.yaml /.cfn-nag-blacklist.yml: -------------------------------------------------------------------------------- 1 | --- 2 | RulesToSuppress: 3 | - id: F1000 4 | reason: F1000 is something we never care about at enterprise X 5 | - id: W2 6 | reason: F1000 is something we never care about at enterprise X 7 | - id: W9 8 | reason: F1000 is something we never care about at enterprise X 9 | - id: W36 10 | reason: F1000 is something we never care about at enterprise X -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | taskcat_outputs/ 2 | pipeline/ 3 | .DS_Store -------------------------------------------------------------------------------- /.taskcat.yml: -------------------------------------------------------------------------------- 1 | project: 2 | name: wordpress-single-instance 3 | regions: 4 | - 5 | tests: 6 | default: 7 | template: wordpress/wordpress-single-instance.yaml -------------------------------------------------------------------------------- /.taskcat_overrides.yml: -------------------------------------------------------------------------------- 1 | DBName: TestWordPressDB 2 | DBPassword: TestDBRootPassword 3 | DBRootPassword: TestDBRootPassword 4 | DBUser: TestDBuser 5 | KeyName: ejanicas -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## DevSecOps on AWS 2 | 3 | ### [Building a Pipeline for Test and Production Stacks]() 4 | This walkthrough builds a pipeline for a sample WordPress site in a stack. The pipeline is separated into four stages. Each stage must contain at least one action, which is a task the pipeline performs on your artifacts (your input). A stage organizes actions in a pipeline. CodePipeline must complete all actions in a stage before the stage processes new artifacts, for example, if you submitted new input to rerun the pipeline. 5 | 6 | By the end of this walkthrough, you'll have a pipeline that performs the following workflow: 7 | 8 | 1. The first stage of the pipeline retrieves a source artifact (an AWS CloudFormation template) from a repository. You'll prepare an artifact that includes a sample WordPress template and upload it to an S3 bucket. 9 | 10 | 3. In the second stage, the pipeline performs a series of validation tests to the AWS CloudFormation template. These include cfn-validate-template, cfn_nag and taskcat, and then the pipeline continues to the next stage. 11 | 12 | 3. In the third stage, the pipeline creates a test stack and then waits for your approval. 13 | After you review the test stack, you can choose to continue with the original pipeline or create and submit another artifact to make changes. If you approve, this stage deletes the test stack, and then the pipeline continues to the next stage. 14 | 15 | 4. In the fourth stage, the pipeline creates a change set against a production stack, and then waits for your approval. 16 | In your initial run, you won't have a production stack. The change set shows you all of the resources that AWS CloudFormation will create. If you approve, this stage executes the change set and builds your production stack. 17 | 18 | ### How to run 19 | 20 | 1. [Clone](https://help.github.com/articles/cloning-a-repository/) this repository. From your terminal application, execute the following command: 21 | 22 | `git clone https://github.com/aws-samples/aws-devsecops-workshop` 23 | 24 | This creates a directory named aws-devsecops-workshop in your current directory. 25 | 26 | 2. [Create AWS CodeCommit repository](http://docs.aws.amazon.com/codecommit/latest/userguide/getting-started.html#getting-started-create-repo) in your AWS account and [set up AWS CLI](http://docs.aws.amazon.com/codecommit/latest/userguide/how-to-create-repository.html#how-to-create-repository-cli). Name your repository wordpress-cfn. Alternatively, from your terminal application, execute the following command: 27 | 28 | `aws codecommit create-repository --repository-name wordpress-cfn --repository-description "This template installs WordPress with a local MySQL database for storage"` 29 | 30 | Note the `cloneUrlHttp URL` in the response from the CLI. 31 | 32 | 3. Add a new remote. From your terminal application, within the wordpress-dfn directory, execute the following command: 33 | 34 | `git init && git remote add AWSCodeCommit HTTP_CLONE_URL_FROM_STEP_2` 35 | 36 | [Create the local git setup](http://docs.aws.amazon.com/codecommit/latest/userguide/setting-up.html) required to push code to CodeCommit repository. 37 | 38 | 39 | 4. Initialise the parameters Wordpress fetches from SSM. Example: 40 | ``` 41 | aws ssm put-parameter --name dbName --type String --value "WordPressDB" 42 | aws secretsmanager create-secret --name dbPassword --secret-string DBPassword 43 | aws secretsmanager create-secret --name dbRootPassword --secret-string DBRootPassword 44 | aws ssm put-parameter --name dbUser --type String --value "DBuser" 45 | ``` 46 | 47 | 5. Launch the CFN templates that create the [pipeline](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=devsecops-wordpress-pipeline&templateURL=https://artifact-store-ejanicas.s3-eu-west-1.amazonaws.com/basic-pipeline.yaml) and the [config rules](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=config&templateURL=https://artifact-store-ejanicas.s3-eu-west-1.amazonaws.com/config.yaml). 48 | 49 | 50 | ## Tools used in this Workshop 51 | 52 | #### Pre. [git-secrets](https://github.com/awslabs/git-secrets) 53 | `git-secrets` scans commits, commit messages, and `--no-ff` merges to prevent adding secrets into your git repositories. If a commit, commit message, or any commit in a `--no-ff` merge history matches one of your configured prohibited regular expression patterns, then the commit is rejected. 54 | 55 | #### Pre. [Secrets Manager](https://aws.amazon.com/secrets-manager/) 56 | AWS Secrets Manager helps you protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle. Users and applications retrieve secrets with a call to Secrets Manager APIs, eliminating the need to hardcode sensitive information in plain text. Secrets Manager offers secret rotation with built-in integration for Amazon RDS, Amazon Redshift, and Amazon DocumentDB. Also, the service is extensible to other types of secrets, including API keys and OAuth tokens. In addition, Secrets Manager enables you to control access to secrets using fine-grained permissions and audit secret rotation centrally for resources in the AWS Cloud, third-party services, and on-premises. 57 | 58 | #### Pre. [CodeGuru Reviewer](https://aws.amazon.com/codeguru/) 59 | Amazon CodeGuru is a machine learning service for automated code reviews and application performance recommendations. It helps you find the most expensive lines of code that hurt application performance and keep you up all night troubleshooting, then gives you specific recommendations to fix or improve your code. CodeGuru is powered by machine learning, best practices, and hard-learned lessons across millions of code reviews and thousands of applications profiled on open source projects and internally at Amazon. With CodeGuru, you can find and fix code issues such as resource leaks, potential concurrency race conditions, and wasted CPU cycles. And with low, on-demand pricing, it is inexpensive enough to use for every code review and application you run. CodeGuru supports Java applications today, with support for more languages coming soon. CodeGuru helps you catch problems faster and earlier, so you can build and run better software. 60 | 61 | 62 | #### 0. [cfn-validate-template](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-validate-template.html) 63 | The aws cloudformation validate-template command is designed to check only the syntax of your template. It does not ensure that the property values that you have specified for a resource are valid for that resource. Nor does it determine the number of resources that will exist when the stack is created. 64 | 65 | 66 | #### 1. [cfn_nag](https://github.com/stelligent/cfn_nag) 67 | The cfn-nag tool looks for patterns in CloudFormation templates that may indicate insecure infrastructure. Roughly speaking it will look for: 68 | 69 | - IAM rules that are too permissive (wildcards) 70 | - Security group rules that are too permissive (wildcards) 71 | - Access logs that aren't enabled 72 | - Encryption that isn't enabled 73 | - Password literals 74 | 75 | 76 | #### 2. [taskcat](https://github.com/aws-quickstart/taskcat) 77 | **taskcat** is a tool that tests AWS CloudFormation templates. It deploys your AWS CloudFormation template in multiple AWS Regions and generates a report with a pass/fail grade for each region. You can specify the regions and number of Availability Zones you want to include in the test, and pass in parameter values from your AWS CloudFormation template. taskcat is implemented as a Python class that you import, instantiate, and run. 78 | 79 | https://aws.amazon.com/blogs/infrastructure-and-automation/up-your-aws-cloudformation-testing-game-using-taskcat/ 80 | 81 | 82 | ### 3. [Continuous integration and evaluation of security controls](https://aws.amazon.com/blogs/security/how-to-manage-security-governance-using-devops-methodologies/) 83 | After you write multiple action statements and scenarios supporting the user story (both positive and negative), you can write them up as a runbook, an AWS Config rule, or a combination of both as required. 84 | 85 | The second example acceptance criteria above would need to be written as a runbook, as it’s a responsive control. You wouldn’t want to generate a stream of emails to your security operations manager to validate that it’s working. 86 | 87 | The other two examples could be written as AWS Config rules using a call to the iam:simulate-custom-policy API, since they are related to preventative controls. An AWS Config rule allows your entire account to be continuously evaluated for compliance, essentially evaluating your control adherence on a <15min basis, rather than from a yearly audit. 88 | 89 | Committing those runbook and AWS Config rules to a central code repository fosters the agility of the controls. In the case of runbooks, you may want to adopt a light-weight markup format, such as markdown, that you are able to check in like code. The defined controls can then sit in a CI/CD pipeline, allowing the security controls to be as agile as your pace of innovation. 90 | 91 | ##### 3.1. [AWS Config](https://aws.amazon.com/config/) 92 | You can use AWS Config as your framework for creating and deploying governance and compliance rules across your AWS accounts and regions. You can codify your compliance requirements as AWS Config rules and author remediation actions using AWS Systems Manager Automation documents and package them together within a conformance pack that can be easily deployed across an organization. Therefore, using AWS Config, you can automate assessment of your resource configurations and resource changes to help you ensure continuous compliance and self-governance across your AWS infrastructure. 93 | 94 | ##### 3.2. [Amazon Inspector](https://aws.amazon.com/inspector/?nc2=h_ql_prod_se_in) 95 | Amazon Inspector is an API-driven service that analyzes network configurations in your AWS account and uses an optional agent for visibility into your Amazon EC2 instances. This makes it easy for you to build Inspector assessments right into your existing DevOps process, decentralizing and automating vulnerability assessments, and empowering your development and operations teams to make security assessments an integral part of the deployment process. 96 | 97 | ## License 98 | This library is licensed under the MIT-0 License. See the LICENSE file. -------------------------------------------------------------------------------- /buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | phases: 3 | install: 4 | runtime-versions: 5 | python: 3.7 6 | ruby: 2.6 7 | commands: 8 | # Install CFN-Lint, taskcat, YAMLLint 9 | - pip3 install cfn-lint taskcat yamllint 10 | # Install cfn-nag 11 | - gem install cfn-nag 12 | build: 13 | commands: 14 | # Validate Template 15 | - aws cloudformation validate-template --template-body file://./wordpress/wordpress-single-instance.yaml 16 | # Run CFN Nag 17 | - cfn_nag --output-format txt wordpress/wordpress-single-instance.yaml -b .cfn-nag-blacklist.yml --fail-on-warnings 18 | # Run taskcat, strip color escape codes, output taskcat log files on STDOUT, and exit with result of taskcat 19 | - | 20 | taskcat test run | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" 21 | TASKCAT_RESULT=${PIPESTATUS[0]} 22 | ls -1 taskcat_outputs/*.txt | while read LOG 23 | do 24 | echo 25 | echo "> $LOG" 26 | cat ${LOG} 27 | done 28 | exit $TASKCAT_RESULT -------------------------------------------------------------------------------- /pipeline/basic-pipeline.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | 3 | Description: > 4 | AWS CloudFormation Sample Template Continuous Delievery: This template 5 | builds an AWS CodePipeline pipeline that implements a continuous delivery release 6 | process for AWS CloudFormation stacks. Submit a CloudFormation source artifact 7 | to an Amazon S3 location before building the pipeline. The pipeline uses the 8 | artifact to automatically create stacks and change sets. 9 | **WARNING** This template creates an Amazon EC2 instance. You will be billed 10 | for the AWS resources used when you create a stack using this template. 11 | 12 | Parameters: 13 | PipelineName: 14 | Default: DevSecOps-Wordpress 15 | Description: A name for pipeline 16 | Type: String 17 | RepositoryName: 18 | Default: wordpress-cfn 19 | Description: The name of the CodeComit repository that contains the source templates, which must be in the same region as this stack 20 | Type: String 21 | TemplateFileName: 22 | Default: wordpress-single-instance.yaml 23 | Description: The file name of the WordPress template 24 | Type: String 25 | TestStackName: 26 | Default: Test-MyWordPressSite 27 | Description: A name for the test WordPress stack 28 | Type: String 29 | ProdStackName: 30 | Default: Prod-MyWordPressSite 31 | Description: A name for the production WordPress stack 32 | Type: String 33 | ChangeSetName: 34 | Default: UpdatePreview-MyWordPressSite 35 | Description: A name for the production WordPress stack change set 36 | Type: String 37 | Email: 38 | Description: The email address where CodePipeline sends pipeline notifications 39 | Type: String 40 | DeliveryChannelExists: 41 | Default: "False" 42 | Description: Whether an AWS Config Delivery Channel already exists on this account. 43 | Type: String 44 | AllowedValues: 45 | - "True" 46 | - "False" 47 | 48 | Conditions: 49 | CreateDeliveryChannel: !Equals 50 | - !Ref DeliveryChannelExists 51 | - "False" 52 | 53 | Metadata: 54 | AWS::CloudFormation::Interface: 55 | ParameterGroups: 56 | - Label: 57 | default: "CodePipeline Settings" 58 | Parameters: 59 | - PipelineName 60 | - RepositoryName 61 | - Email 62 | - Label: 63 | default: "Test Stack Settings" 64 | Parameters: 65 | - TestStackName 66 | - TemplateFileName 67 | - Label: 68 | default: "Production Stack Settings" 69 | Parameters: 70 | - ChangeSetName 71 | - ProdStackName 72 | 73 | Resources: 74 | ArtifactStoreBucket: 75 | Type: AWS::S3::Bucket 76 | Properties: 77 | VersioningConfiguration: 78 | Status: Enabled 79 | 80 | CodePipelineSNSTopic: 81 | Type: AWS::SNS::Topic 82 | Properties: 83 | Subscription: 84 | - Endpoint: !Ref Email 85 | Protocol: email 86 | 87 | Project: 88 | Type: AWS::CodeBuild::Project 89 | Properties: 90 | Name: validate-template 91 | Description: Validate CFN Template 92 | ServiceRole: !Ref CodeBuildRole 93 | Artifacts: 94 | Type: CODEPIPELINE 95 | Environment: 96 | Type: LINUX_CONTAINER 97 | ComputeType: BUILD_GENERAL1_SMALL 98 | Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0 99 | Source: 100 | Type: CODEPIPELINE 101 | TimeoutInMinutes: 10 102 | 103 | Pipeline: 104 | Type: AWS::CodePipeline::Pipeline 105 | Properties: 106 | ArtifactStore: 107 | Location: !Ref "ArtifactStoreBucket" 108 | Type: S3 109 | DisableInboundStageTransitions: [] 110 | Name: !Ref PipelineName 111 | RoleArn: !GetAtt [PipelineRole, Arn] 112 | Stages: 113 | - Name: CodeCommitSource 114 | Actions: 115 | - Name: TemplateSource 116 | ActionTypeId: 117 | Category: Source 118 | Owner: AWS 119 | Provider: CodeCommit 120 | Version: "1" 121 | Configuration: 122 | RepositoryName: !Ref "RepositoryName" 123 | BranchName: main 124 | OutputArtifacts: 125 | - Name: TemplateSource 126 | RunOrder: 1 127 | - Name: ValidateTemplate 128 | Actions: 129 | - Name: PackageExport 130 | ActionTypeId: 131 | Category: Test 132 | Owner: AWS 133 | Provider: CodeBuild 134 | Version: "1" 135 | RunOrder: 1 136 | Configuration: 137 | ProjectName: validate-template 138 | InputArtifacts: 139 | - Name: TemplateSource 140 | - Name: TestStage 141 | Actions: 142 | - Name: CreateStack 143 | ActionTypeId: 144 | Category: Deploy 145 | Owner: AWS 146 | Provider: CloudFormation 147 | Version: "1" 148 | InputArtifacts: 149 | - Name: TemplateSource 150 | Configuration: 151 | ActionMode: REPLACE_ON_FAILURE 152 | RoleArn: !GetAtt [CFNRole, Arn] 153 | StackName: !Ref TestStackName 154 | TemplatePath: !Sub "TemplateSource::wordpress/${TemplateFileName}" 155 | RunOrder: 1 156 | - Name: ApproveTestStack 157 | ActionTypeId: 158 | Category: Approval 159 | Owner: AWS 160 | Provider: Manual 161 | Version: "1" 162 | Configuration: 163 | NotificationArn: !Ref CodePipelineSNSTopic 164 | CustomData: !Sub "Do you want to create a change set against the production stack and delete the ${TestStackName} stack?" 165 | RunOrder: 2 166 | - Name: DeleteTestStack 167 | ActionTypeId: 168 | Category: Deploy 169 | Owner: AWS 170 | Provider: CloudFormation 171 | Version: "1" 172 | Configuration: 173 | ActionMode: DELETE_ONLY 174 | RoleArn: !GetAtt [CFNRole, Arn] 175 | StackName: !Ref TestStackName 176 | RunOrder: 3 177 | - Name: ProdStage 178 | Actions: 179 | - Name: CreateChangeSet 180 | ActionTypeId: 181 | Category: Deploy 182 | Owner: AWS 183 | Provider: CloudFormation 184 | Version: "1" 185 | InputArtifacts: 186 | - Name: TemplateSource 187 | Configuration: 188 | ActionMode: CHANGE_SET_REPLACE 189 | RoleArn: !GetAtt [CFNRole, Arn] 190 | StackName: !Ref ProdStackName 191 | ChangeSetName: !Ref ChangeSetName 192 | TemplatePath: !Sub "TemplateSource::wordpress/${TemplateFileName}" 193 | RunOrder: 1 194 | - Name: ExecuteChangeSet 195 | ActionTypeId: 196 | Category: Deploy 197 | Owner: AWS 198 | Provider: CloudFormation 199 | Version: "1" 200 | Configuration: 201 | ActionMode: CHANGE_SET_EXECUTE 202 | ChangeSetName: !Ref ChangeSetName 203 | RoleArn: !GetAtt [CFNRole, Arn] 204 | StackName: !Ref ProdStackName 205 | RunOrder: 2 206 | CFNRole: 207 | Type: AWS::IAM::Role 208 | Properties: 209 | AssumeRolePolicyDocument: 210 | Statement: 211 | - Action: ["sts:AssumeRole"] 212 | Effect: Allow 213 | Principal: 214 | Service: [cloudformation.amazonaws.com] 215 | Version: "2012-10-17" 216 | Path: / 217 | Policies: 218 | - PolicyName: CloudFormationRole 219 | PolicyDocument: 220 | Version: "2012-10-17" 221 | Statement: 222 | - Action: 223 | - "ec2:*" 224 | - "ssm:GetParameters" 225 | Effect: Allow 226 | Resource: "*" 227 | 228 | PipelineRole: 229 | Type: AWS::IAM::Role 230 | Properties: 231 | AssumeRolePolicyDocument: 232 | Statement: 233 | - Action: ["sts:AssumeRole"] 234 | Effect: Allow 235 | Principal: 236 | Service: [codepipeline.amazonaws.com] 237 | Version: "2012-10-17" 238 | Path: / 239 | Policies: 240 | - PolicyName: CodePipelineAccess 241 | PolicyDocument: 242 | Version: "2012-10-17" 243 | Statement: 244 | - Action: 245 | - "s3:*" 246 | - "codecommit:*" 247 | - "codebuild:*" 248 | - "cloudformation:CreateStack" 249 | - "cloudformation:DescribeStacks" 250 | - "cloudformation:DeleteStack" 251 | - "cloudformation:UpdateStack" 252 | - "cloudformation:CreateChangeSet" 253 | - "cloudformation:ExecuteChangeSet" 254 | - "cloudformation:DeleteChangeSet" 255 | - "cloudformation:DescribeChangeSet" 256 | - "cloudformation:SetStackPolicy" 257 | - "iam:PassRole" 258 | - "sns:Publish" 259 | - "ssm:GetParameters" 260 | Effect: Allow 261 | Resource: "*" 262 | 263 | CodeBuildRole: 264 | Type: AWS::IAM::Role 265 | Properties: 266 | AssumeRolePolicyDocument: 267 | Version: "2012-10-17" 268 | Statement: 269 | Effect: Allow 270 | Principal: 271 | Service: codebuild.amazonaws.com 272 | Action: sts:AssumeRole 273 | ManagedPolicyArns: 274 | - arn:aws:iam::aws:policy/AdministratorAccess 275 | 276 | ConfigSNSTopic: 277 | Type: AWS::SNS::Topic 278 | Properties: 279 | Subscription: 280 | - Endpoint: !Ref Email 281 | Protocol: email 282 | 283 | AWSConfigRule: 284 | DependsOn: WaitCondition 285 | Type: AWS::Config::ConfigRule 286 | Properties: 287 | ConfigRuleName: vpc-default-security-group-closed 288 | Description: 289 | Checks that the default security group of any Amazon Virtual Private 290 | Cloud (VPC) does not allow inbound or outbound traffic. The rule is non-compliant 291 | if the default security group has one or more inbound or outbound traffic. 292 | InputParameters: {} 293 | Scope: 294 | ComplianceResourceTypes: 295 | - AWS::EC2::SecurityGroup 296 | Source: 297 | Owner: AWS 298 | SourceIdentifier: VPC_DEFAULT_SECURITY_GROUP_CLOSED 299 | 300 | SSMRole: 301 | Type: "AWS::IAM::Role" 302 | Properties: 303 | AssumeRolePolicyDocument: 304 | Version: "2012-10-17" 305 | Statement: 306 | - Effect: Allow 307 | Principal: 308 | Service: 309 | - ssm.amazonaws.com 310 | - ec2.amazonaws.com 311 | Action: 312 | - "sts:AssumeRole" 313 | ManagedPolicyArns: 314 | - arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole 315 | - arn:aws:iam::aws:policy/AmazonSNSFullAccess 316 | Policies: 317 | - PolicyDocument: 318 | { 319 | "Version": "2012-10-17", 320 | "Statement": 321 | [ 322 | { 323 | "Sid": "VisualEditor0", 324 | "Effect": "Allow", 325 | "Action": "iam:PassRole", 326 | "Resource": "arn:aws:iam::800970383220:role/AutomationRole", 327 | }, 328 | ], 329 | } 330 | PolicyName: PassRole 331 | 332 | ConfigAutoRemediation: 333 | DependsOn: AWSConfigRule 334 | Type: "AWS::Config::RemediationConfiguration" 335 | Properties: 336 | Automatic: true 337 | ConfigRuleName: vpc-default-security-group-closed 338 | ResourceType: "AWS::EC2::SecurityGroup" 339 | TargetId: "AWS-PublishSNSNotification" 340 | TargetType: "SSM_DOCUMENT" 341 | TargetVersion: "1" 342 | MaximumAutomaticAttempts: 5 343 | RetryAttemptSeconds: 60 344 | Parameters: 345 | AutomationAssumeRole: 346 | StaticValue: 347 | Values: 348 | - !GetAtt SSMRole.Arn 349 | Message: 350 | StaticValue: 351 | Values: 352 | - "A Config rule is not compliant in your environment. Please open the Config Dashboard for further details." 353 | TopicArn: 354 | StaticValue: 355 | Values: 356 | - Ref: ConfigSNSTopic 357 | 358 | CreateDeliveryChannelWaitHandle: 359 | Condition: CreateDeliveryChannel 360 | DependsOn: ConfigDeliveryChannel 361 | Type: "AWS::CloudFormation::WaitConditionHandle" 362 | 363 | WaitHandle: 364 | Type: "AWS::CloudFormation::WaitConditionHandle" 365 | 366 | WaitCondition: 367 | Type: "AWS::CloudFormation::WaitCondition" 368 | Properties: 369 | Handle: !If [CreateDeliveryChannel, !Ref CreateDeliveryChannelWaitHandle, !Ref WaitHandle] 370 | Timeout: "1" 371 | Count: 0 372 | 373 | ConfigRecorder: 374 | Condition: CreateDeliveryChannel 375 | Type: AWS::Config::ConfigurationRecorder 376 | Properties: 377 | RoleARN: !GetAtt ConfigRecorderRole.Arn 378 | 379 | ConfigRecorderRole: 380 | Condition: CreateDeliveryChannel 381 | Type: "AWS::IAM::Role" 382 | Properties: 383 | AssumeRolePolicyDocument: 384 | Version: "2012-10-17" 385 | Statement: 386 | - Effect: Allow 387 | Principal: 388 | Service: config.amazonaws.com 389 | Action: 390 | - "sts:AssumeRole" 391 | ManagedPolicyArns: 392 | - arn:aws:iam::aws:policy/service-role/AWS_ConfigRole 393 | Policies: 394 | - PolicyName: root 395 | PolicyDocument: 396 | Version: '2012-10-17' 397 | Statement: 398 | - Effect: Allow 399 | Action: s3:GetBucketAcl 400 | Resource: !Join ['', ['arn:aws:s3:::', !Ref 'ConfigBucket']] 401 | - Effect: Allow 402 | Action: s3:PutObject 403 | Resource: !Join ['', ['arn:aws:s3:::', !Ref 'ConfigBucket', /AWSLogs/, !Ref 'AWS::AccountId', /*]] 404 | Condition: 405 | StringEquals: 406 | s3:x-amz-acl: bucket-owner-full-control 407 | - Effect: Allow 408 | Action: config:Put* 409 | Resource: '*' 410 | 411 | ConfigBucket: 412 | Condition: CreateDeliveryChannel 413 | Type: AWS::S3::Bucket 414 | Properties: 415 | VersioningConfiguration: 416 | Status: Enabled 417 | 418 | ConfigDeliveryChannel: 419 | Condition: CreateDeliveryChannel 420 | Type: AWS::Config::DeliveryChannel 421 | Properties: 422 | S3BucketName: !Ref "ConfigBucket" 423 | -------------------------------------------------------------------------------- /wordpress/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "Parameters" : { 3 | "DBName" : "TestWordPressDB", 4 | "DBPassword" : "TestDBRootPassword", 5 | "DBRootPassword" : "TestDBRootPassword", 6 | "DBUser" : "TestDBuser", 7 | "KeyName" : "ejanicas" 8 | } 9 | } -------------------------------------------------------------------------------- /wordpress/wordpress-single-instance-final.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: "2010-09-09" 2 | Description: 3 | "AWS CloudFormation Sample Template WordPress_Single_Instance: WordPress 4 | is web software you can use to create a beautiful website or blog. This template 5 | installs WordPress with a local MySQL database for storage. It demonstrates using 6 | the AWS CloudFormation bootstrap scripts to deploy WordPress. **WARNING** This template 7 | creates an Amazon EC2 instance. You will be billed for the AWS resources used if 8 | you create a stack from this template." 9 | Parameters: 10 | DBName: 11 | Description: The WordPress database name 12 | Default: "{{resolve:ssm:dbName:1}}" 13 | Type: String 14 | DBPassword: 15 | Description: The WordPress database admin account password 16 | Default: "{{resolve:secretsmanager:dbPassword}}" 17 | Type: String 18 | DBRootPassword: 19 | Description: MySQL root password 20 | Default: "{{resolve:secretsmanager:dbRootPassword}}" 21 | Type: String 22 | DBUser: 23 | Description: The WordPress database admin account username 24 | Default: "{{resolve:ssm:dbUser:1}}" 25 | Type: String 26 | InstanceType: 27 | Default: t3.small 28 | Description: WebServer EC2 instance type 29 | Type: String 30 | LatestAmiId: 31 | Type: "AWS::SSM::Parameter::Value" 32 | Default: "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2" 33 | Resources: 34 | WebServer: 35 | Type: AWS::EC2::Instance 36 | CreationPolicy: 37 | ResourceSignal: 38 | Timeout: PT15M 39 | Metadata: 40 | AWS::CloudFormation::Init: 41 | configSets: 42 | wordpress_install: 43 | - install_cfn 44 | - install_wordpress 45 | - configure_wordpress 46 | configure_wordpress: 47 | commands: 48 | 01_set_mysql_root_password: 49 | command: !Sub | 50 | mysqladmin -u root password '${DBRootPassword}' 51 | test: !Sub | 52 | $(mysql ${DBName} -u root --password='${DBRootPassword}' >/dev/null 2>&1 /dev/null 2>&1 " 32 | Default: "/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2" 33 | Resources: 34 | WebServer: 35 | Type: AWS::EC2::Instance 36 | CreationPolicy: 37 | ResourceSignal: 38 | Timeout: PT15M 39 | Metadata: 40 | AWS::CloudFormation::Init: 41 | configSets: 42 | wordpress_install: 43 | - install_cfn 44 | - install_wordpress 45 | - configure_wordpress 46 | configure_wordpress: 47 | commands: 48 | 01_set_mysql_root_password: 49 | command: !Sub | 50 | mysqladmin -u root password '${DBRootPassword}' 51 | test: !Sub | 52 | $(mysql ${DBName} -u root --password='${DBRootPassword}' >/dev/null 2>&1 /dev/null 2>&1