├── .github ├── pull_request_template.md └── workflows │ ├── lint.yml │ └── test.yml ├── .yamllint ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── examples ├── asg-singleton-ssm │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-ebs │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-efs │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-mysql │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-postgres │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-ssh-bastion │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── ec2-ssm │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── fargate-alb-ambassador-pattern │ └── README.md ├── fargate-alb-auth-cognito │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── fargate-alb-proxy-pattern │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── fargate-alb-service-to-service │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── fargate-alb-single-container │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── msk-cluster │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── serverless-cron │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── lambda-src │ │ └── cron.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── serverless-iam │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── lambda-src │ │ └── example.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── serverless-image-resize │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── lambda-src │ │ └── resize.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js ├── serverless-sqs-queue │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── lambda-src │ │ └── example.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.yml │ │ ├── eslint.config.cjs │ │ ├── package-lock.json │ │ ├── package.json │ │ └── test.js └── serverless-webhook │ ├── .gitignore │ ├── README.md │ ├── example.yml │ ├── lambda-src │ └── webhook.js │ ├── package-lock.json │ ├── package.json │ └── test │ ├── .eslintrc.yml │ ├── eslint.config.cjs │ ├── package-lock.json │ ├── package.json │ └── test.js ├── icon.png ├── logo-transparent.png ├── logo.afdesign ├── logo.png ├── renovate.json └── test ├── package-lock.json ├── package.json └── test.sh /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 2 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: [master] 5 | pull_request: 6 | jobs: 7 | build: 8 | runs-on: 'ubuntu-latest' 9 | steps: 10 | - uses: 'actions/checkout@v2' 11 | - uses: 'actions/setup-python@v2' 12 | with: 13 | python-version: '3.8' 14 | - name: yamlllint 15 | run: | 16 | pip install yamllint==1.26.3 17 | find examples -type f -name example.yml | while read file; do set -ex && yamllint "$file"; done; 18 | - name: cfn-lint 19 | run: | 20 | pip install cfn-lint==0.59.1 21 | find examples -type f -name example.yml | while read file; do set -ex && cfn-lint -t "$file"; done; 22 | - name: license 23 | run: | 24 | find examples -type f -name example.yml -not -name .eslintrc.yml | while read file; do set -ex && grep -q "LICENSE-2.0" "$file"; done; -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: [master] 5 | pull_request: 6 | permissions: 7 | id-token: write 8 | contents: read 9 | concurrency: 10 | group: test 11 | cancel-in-progress: false 12 | jobs: 13 | build: 14 | runs-on: ['ubuntu-latest'] 15 | steps: 16 | - uses: 'actions/checkout@v2' 17 | - uses: aws-actions/configure-aws-credentials@v4 18 | with: 19 | role-to-assume: 'arn:aws:iam::068189904525:role/github-openid-connect' 20 | aws-region: 'eu-west-1' 21 | role-duration-seconds: 21600 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version: '18.x' 25 | - name: test 26 | run: | 27 | cd test 28 | ./test.sh -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | indentation: 5 | indent-sequences: false 6 | line-length: 7 | max: 999 8 | comments: 9 | min-spaces-from-content: 1 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # cfn-modules Contributor Guide 2 | This document is only for module developers. If you want to use `cfn-modules`, check out the [README.md](./README.md). 3 | 4 | ## Interfaces 5 | Modules can implement interfaces. At the moment, interfaces are not "checked" but we plan to do this later. 6 | 7 | ### ExposeArn 8 | 9 | #### Parameters 10 | none 11 | 12 | #### Outputs 13 | * `Arn` 14 | 15 | ### ExposeName 16 | 17 | #### Parameters 18 | none 19 | 20 | #### Outputs 21 | * `Name` 22 | 23 | ### ExposeId 24 | 25 | #### Parameters 26 | none 27 | 28 | #### Outputs 29 | * `Id` 30 | 31 | ### ExposeSecurityGroupId 32 | 33 | #### Parameters 34 | none 35 | 36 | #### Outputs 37 | * `SecurityGroupId` 38 | 39 | ### ExposeDnsName 40 | 41 | #### Parameters 42 | none 43 | 44 | #### Outputs 45 | * `DnsName` 46 | 47 | ### LambdaDependency (extends ExposeArn) 48 | 49 | #### Parameters 50 | none 51 | 52 | #### Outputs 53 | * `IamActions` 54 | * `IamResources` 55 | 56 | ### Bastion (extends ExposeSecurityGroupId) 57 | 58 | #### Parameters 59 | none 60 | 61 | #### Outputs 62 | none 63 | 64 | ### HostedZone (extends: ExposeName, ExposeId) 65 | 66 | #### Parameters 67 | none 68 | 69 | #### Outputs 70 | none 71 | 72 | ### LoadBalancer (extends: ExposeDnsName) 73 | 74 | ### Parameters 75 | none 76 | 77 | #### Outputs 78 | * `CanonicalHostedZoneId` 79 | 80 | ### Target (extends: ExposeArn, ExposeName, ExposeSecurityGroupId) 81 | 82 | #### Parameters 83 | none 84 | 85 | #### Outputs 86 | * `FullName` 87 | 88 | 89 | ## How to 90 | 91 | ### Add a cfn-module as a dependency to a cfn-module 92 | 93 | Unfortunately, we can not rely on `npm` to add cfn-modules as dependencies to other cfn-modules. `npm` will mess up the paths inside `node_modules/`. Therfore, we have to use git submodules to achieve the same. 94 | 95 | 1. Add the git submodule: `git submodule add https://github.com/cfn-modules/lambda-function node_modules/@cfn-modules/lambda-function` 96 | 2. Add the module name to the `bundledDependencies` in `package.json`: `"bundledDependencies": ["@cfn-modules/lambda-function"]` 97 | 98 | ### Update a cfn-module dependency 99 | 100 | 1. Change into the dependency directory: `cd node_modules/@cfn-modules/lambda-function` 101 | 2. Fetch latest git information: `git fetch` 102 | 3. Update the version: `git merge vx.y.z` 103 | 4. `cd ../../../` 104 | 4. `rm test/package-lock.json` 105 | 5. `cd test/ && npm i` 106 | 107 | ### Pull all cfn-module dependencies 108 | 109 | 1. `git pull` 110 | 2. `git submodule update --init --recursive` 111 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![cfn-modules](./logo.png) 2 | 3 | # cfn-modules User Guide 4 | 5 | Rapid CloudFormation: Modular, production ready, open source. 6 | 7 | ## Why cfn-modules? 8 | We started with [aws-cf-templates](https://github.com/widdix/aws-cf-templates) in 2015. Three years later, we believe that we have learned enough to come up with a new approach to use CloudFormation more efficient. 9 | 10 | ### Modular 11 | Reusing CloudFormation templates is hard. Most often, templates are initially copied and then modified. 12 | 13 | Two problems arise. First, updates to the copy are not applied to the original. Second, updates to the original are not applied to the copy. **In essence: we do not learn from each other!** 14 | 15 | By using an easy to use package manager ([npm](https://www.npmjs.com/)) you can install and update `cfn-modules` to spin up complex infrastructure in minutes that just works. 16 | 17 | ### Production ready 18 | All modules are production-ready. If no other limitations are documented, they are: 19 | 20 | * Highly available 21 | * no single point of failure 22 | * Scalable 23 | * increase or decrease the capacity based on utilization 24 | * Secure 25 | * using the latest operating systems and software components 26 | * follow the least privilege principle (e.g., IAM policies and Security Groups) 27 | * backups of state (not configuration) enabled 28 | * encryption at-rest enabled 29 | * encryption in-transit enabled and preferred 30 | * Operator-friendly 31 | * logging enabled 32 | * alerting enabled 33 | * updatable 34 | 35 | ### Open source 36 | All modules are licensed under [Apache-2.0](./LICENSE). Commercial use is allowed. 37 | 38 | ## Prerequisites 39 | * AWS CLI installed ([install](https://docs.aws.amazon.com/cli/latest/userguide/installing.html)) 40 | * npm >=5.6 installed ([install Node.js 10.x](https://nodejs.org/)) 41 | 42 | ## Getting started 43 | 44 | `cfn-modules` are installed and updated with the package manager [npm](https://www.npmjs.com/). The [module catalog](https://www.npmjs.com/org/cfn-modules) contains all available modules. Let's start with a simple example: An EC2 instance launched into a VPC. 45 | 46 | > [Install Node.js 10.x](https://nodejs.org/) if `npm` is not installed on your system 47 | 48 | Install the modules using npm: 49 | 50 | ``` 51 | npm i @cfn-modules/vpc@1.0.0 52 | npm i @cfn-modules/ec2-instance-amazon-linux@1.0.0 53 | ``` 54 | 55 | Use the modules as nested stacks in your CloudFormation template. The [vpc](https://www.npmjs.com/package/@cfn-modules/vpc) module comes with no required parameters. The [ec2-instance-amazon-linux](https://www.npmjs.com/package/@cfn-modules/ec2-instance-amazon-linux) module comes with the required `VpcModule` parameter to make the connection with the `vpc` module. The `UserData` [parameter](https://www.npmjs.com/package/@cfn-modules/ec2-instance-amazon-linux#parameters) is optional. Use it to install additional software like the Apache HTTP Server. Create a file named `example.yml` with the following content: 56 | 57 | ``` 58 | --- 59 | AWSTemplateFormatVersion: '2010-09-09' 60 | Resources: 61 | Vpc: 62 | Type: 'AWS::CloudFormation::Stack' 63 | Properties: 64 | Parameters: 65 | S3Endpoint: 'false' # speed up the example 66 | DynamoDBEndpoint: 'false' # speed up the example 67 | FlowLog: 'false' # speed up the example 68 | NatGateways: 'false' # speed up the example 69 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 70 | Instance: 71 | Type: 'AWS::CloudFormation::Stack' 72 | Properties: 73 | Parameters: 74 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' # reference the vpc module 75 | UserData: | 76 | yum install -y httpd24 77 | service httpd start 78 | echo "cfn-modules" > /var/www/html/index.html 79 | IngressTcpPort1: '80' # open up port 80 to the world 80 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 81 | Outputs: 82 | Url: 83 | Value: !Sub 'http://${Instance.Outputs.PublicIpAddress}' 84 | ``` 85 | 86 | Upload the CloudFormation template and the dependencies to S3 with the `aws cloudformation package` command. 87 | 88 | > [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) if `aws` is not installed on your system 89 | 90 | If you use `cfn-modules` the first time, create an S3 bucket to store the artifacts first (otherwise, skip this step). Choose a unique bucket name, e.g. `cfn-modules-$Name-$Region`. 91 | 92 | In the following command, replace `$Name` with a unique name (e.g. your initials or company name), and replace `$Region` with your AWS default region (e.g. `us-east-1`) to create an S3 bucket: 93 | 94 | ``` 95 | aws s3 mb s3://cfn-modules-$Name-$Region 96 | ``` 97 | 98 | Now you can upload all artifacts to S3: 99 | 100 | ``` 101 | aws cloudformation package --template-file example.yml --s3-bucket cfn-modules-$Name-$Region --output-template-file packaged.yml 102 | ``` 103 | 104 | Finally, you can create a CloudFormation stack with `aws cloudformation deploy`: 105 | 106 | ``` 107 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-example --capabilities CAPABILITY_IAM 108 | ``` 109 | 110 | Creating the stack will take about 10 minutes. You can find the URL to the demo page in the stack outputs: 111 | 112 | ``` 113 | aws cloudformation describe-stacks --stack-name ec2-example --query "Stacks[0].Outputs" 114 | ``` 115 | 116 | Don't forget to delete the stack: 117 | 118 | ``` 119 | aws cloudformation delete-stack --stack-name ec2-example 120 | aws cloudformation wait stack-delete-complete --stack-name ec2-example 121 | ``` 122 | 123 | Fin. Check out our examples next. 124 | 125 | ## Examples 126 | * Auto Scaling Group (singleton) 127 | * [SSM](./examples/asg-singleton-ssm/) 128 | * EC2 129 | * [Mount EBS volume](./examples/ec2-ebs/) 130 | * [Mount EFS file system](./examples/ec2-efs/) 131 | * [Connect to MySQL](./examples/ec2-mysql/) 132 | * [Connect to Postgres](./examples/ec2-postgres/) 133 | * [SSH bastion](./examples/ec2-ssh-bastion/) 134 | * [SSM](./examples/ec2-ssm/) 135 | * Fargate 136 | * [ALB with Cognito auth](./examples/fargate-alb-auth-cognito/) 137 | * [ALB with proxy pattern](./examples/fargate-alb-proxy-pattern/) 138 | * [ALB service to service](./examples/fargate-alb-service-to-service/) 139 | * [ALB to single container](./examples/fargate-alb-single-container/) 140 | * [MSK cluster](./examples/msk-cluster/) 141 | * Serverless 142 | * [Cron](./examples/serverless-cron/) 143 | * [Auto IAM policies](./examples/serverless-iam/) 144 | * [Image resize](./examples/serverless-image-resize/) 145 | * [SQS queue](./examples/serverless-sqs-queue/) 146 | * [Webhook](./examples/serverless-webhook/) 147 | 148 | Check out the [examples](./examples/) folder to see all examples. 149 | 150 | ## Modules 151 | 152 | * [acm-wildcard-certificate-public](https://github.com/cfn-modules/acm-wildcard-certificate-public) 153 | * [alerting](https://github.com/cfn-modules/alerting) 154 | * Load Balancer 155 | * [alb](https://github.com/cfn-modules/alb) 156 | * [alb-listener](https://github.com/cfn-modules/alb-listener) 157 | * [alb-redirect-to-https](https://github.com/cfn-modules/alb-redirect-to-https) 158 | * [nlb](https://github.com/cfn-modules/nlb) 159 | * [lb-dns-record](https://github.com/cfn-modules/lb-dns-record) 160 | * Auto Scaling Group (singleton) 161 | * [asg-singleton-amazon-linux2](https://github.com/cfn-modules/asg-singleton-amazon-linux2) 162 | * [client-sg](https://github.com/cfn-modules/client-sg) 163 | * [cloudwatch-dashboard](https://github.com/cfn-modules/cloudwatch-dashboard) 164 | * [cognito-userpool](https://github.com/cfn-modules/cognito-userpool) 165 | * [dynamodb-table](https://github.com/cfn-modules/dynamodb-table) 166 | * [ebs-volume](https://github.com/cfn-modules/ebs-volume) 167 | * EC2 instance 168 | * [ec2-instance-amazon-linux](https://github.com/cfn-modules/ec2-instance-amazon-linux) 169 | * [ec2-instance-amazon-linux2](https://github.com/cfn-modules/ec2-instance-amazon-linux2) 170 | * ECS 171 | * [ecs-cluster](https://github.com/cfn-modules/ecs-cluster) 172 | * [ecs-alb-target](https://github.com/cfn-modules/ecs-alb-target) 173 | * [ecs-nlb-listener-and-target](https://github.com/cfn-modules/ecs-nlb-listener-and-target) 174 | * Fargate 175 | * [fargate-scheduled-task](https://github.com/cfn-modules/fargate-scheduled-task) 176 | * [fargate-service](https://github.com/cfn-modules/fargate-service) 177 | * [efs-file-system](https://github.com/cfn-modules/efs-file-system) 178 | * [elasticache-redis](https://github.com/cfn-modules/elasticache-redis) 179 | * [kinesis-data-stream](https://github.com/cfn-modules/kinesis-data-stream) 180 | * [kms-key](https://github.com/cfn-modules/kms-key) 181 | * Lambda 182 | * [lambda-event-source-cron](https://github.com/cfn-modules/lambda-event-source-cron) 183 | * [lambda-event-source-dynamodb-stream](https://github.com/cfn-modules/lambda-event-source-dynamodb-stream) 184 | * [lambda-event-source-kinesis-data-stream](https://github.com/cfn-modules/lambda-event-source-kinesis-data-stream) 185 | * [lambda-event-source-sqs-queue](https://github.com/cfn-modules/lambda-event-source-sqs-queue) 186 | * [lambda-event-source-webhook](https://github.com/cfn-modules/lambda-event-source-webhook) 187 | * [lambda-function](https://github.com/cfn-modules/lambda-function) 188 | * [msk-cluster](https://github.com/cfn-modules/msk-cluster) 189 | * RDS 190 | * [rds-aurora-serverless](https://github.com/cfn-modules/rds-aurora-serverless) 191 | * [rds-aurora-serverless-postgres](https://github.com/cfn-modules/rds-aurora-serverless-postgres) 192 | * [rds-mysql](https://github.com/cfn-modules/rds-mysql) 193 | * [rds-postgres](https://github.com/cfn-modules/rds-postgres) 194 | * Route53 195 | * [route53-hosted-zone-private](https://github.com/cfn-modules/route53-hosted-zone-private) 196 | * [route53-hosted-zone-public](https://github.com/cfn-modules/route53-hosted-zone-public) 197 | * [route53-hosted-zone-wrapper](https://github.com/cfn-modules/route53-hosted-zone-wrapper) 198 | * [s3-bucket](https://github.com/cfn-modules/s3-bucket) 199 | * [secret](https://github.com/cfn-modules/secret) 200 | * [sqs-queue](https://github.com/cfn-modules/sqs-queue) 201 | * [ssh-bastion](https://github.com/cfn-modules/ssh-bastion) 202 | * [vpc](https://github.com/cfn-modules/vpc) 203 | 204 | Check out the [module catalog](https://www.npmjs.com/org/cfn-modules) to browse all modules. 205 | 206 | ## About 207 | A [cloudonaut.io](https://cloudonaut.io) project. Engineered by [widdix](https://widdix.net). 208 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: ASG singleton SSM example 2 | 3 | This example project demonstrates how an ASG singleton can be managed by SSM. Every hour, SSM fetches the software inventory and the installed patches and displays them in the [SSM inventory](https://console.aws.amazon.com/systems-manager/inventory). 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name asg-singleton-ssm-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Open the [SSM inventory](https://console.aws.amazon.com/systems-manager/inventory) and search for the EC2 instance. Have a look at the Inventory and Patch tab of the Instance. 23 | 24 | Don't forget to delete the stack once you are done with the demo: 25 | 26 | ``` 27 | aws cloudformation delete-stack --stack-name asg-singleton-ssm-example 28 | ``` 29 | 30 | ## Modules 31 | 32 | Find all modules here: https://www.npmjs.com/org/cfn-modules 33 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: ASG singleton SSM example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | AsgPolicy: 36 | Type: 'AWS::IAM::ManagedPolicy' 37 | Properties: 38 | PolicyDocument: 39 | Version: '2012-10-17' 40 | Statement: 41 | - Effect: Allow 42 | Action: 43 | - 'ssm:ListInstanceAssociations' # State Manager by https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html 44 | - 'ssm:GetDeployablePatchSnapshotForInstance' # Patch Manager by trial and error 45 | Resource: '*' 46 | - Effect: Allow # Patch Manager by trial and error 47 | Action: 'ssm:PutInventory' 48 | Resource: '*' 49 | - Effect: Allow # Patch Manager by https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-minimum-s3-permissions.html 50 | Action: 's3:GetObject' 51 | Resource: 52 | - !Sub 'arn:aws:s3:::aws-ssm-${AWS::Region}/*' 53 | - !Sub 'arn:aws:s3:::amazon-ssm-${AWS::Region}/*' 54 | - !Sub 'arn:aws:s3:::amazon-ssm-packages-${AWS::Region}/*' 55 | - !Sub 'arn:aws:s3:::${AWS::Region}-birdwatcher-prod/*' 56 | - !Sub 'arn:aws:s3:::patch-baseline-snapshot-${AWS::Region}/*' 57 | - Effect: Allow # AWS-GatherSoftwareInventory 58 | Action: 'ssm:GetDocument' 59 | Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-GatherSoftwareInventory' 60 | - Effect: Allow # AWS-GatherSoftwareInventory 61 | Action: 'ssm:UpdateInstanceAssociationStatus' 62 | Resource: '*' 63 | AsgSingleton: 64 | Type: 'AWS::CloudFormation::Stack' 65 | Properties: 66 | Parameters: 67 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 68 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 69 | AmazonLinux2Version: '2.0.20181114' 70 | ManagedPolicyArns: !Ref AsgPolicy 71 | TemplateURL: './node_modules/@cfn-modules/asg-singleton-amazon-linux2/module.yml' 72 | AssociationGatherSoftwareInventory: 73 | Type: 'AWS::SSM::Association' 74 | Properties: 75 | Name: 'AWS-GatherSoftwareInventory' 76 | ScheduleExpression: 'rate(1 hour)' 77 | Targets: 78 | - Key: 'tag:aws:autoscaling:groupName' 79 | Values: [!GetAtt 'AsgSingleton.Outputs.Name'] 80 | AssociationRunPatchBaselineScan: 81 | Type: 'AWS::SSM::Association' 82 | Properties: 83 | Name: 'AWS-RunPatchBaseline' 84 | Parameters: 85 | Operation: [Scan] 86 | ScheduleExpression: 'rate(1 hour)' 87 | Targets: 88 | - Key: 'tag:aws:autoscaling:groupName' 89 | Values: [!GetAtt 'AsgSingleton.Outputs.Name'] 90 | AssociationRunPatchBaselineInstall: 91 | Type: 'AWS::SSM::Association' 92 | Properties: 93 | Name: 'AWS-RunPatchBaseline' 94 | Parameters: 95 | Operation: [Install] 96 | ScheduleExpression: 'rate(1 hour)' 97 | Targets: 98 | - Key: 'tag:aws:autoscaling:groupName' 99 | Values: [!GetAtt 'AsgSingleton.Outputs.Name'] 100 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-asg-singleton-ssm-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/asg-singleton-amazon-linux2": { 13 | "version": "2.4.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/asg-singleton-amazon-linux2/-/asg-singleton-amazon-linux2-2.4.0.tgz", 15 | "integrity": "sha512-w+AU2C47QHtXPjswW/63ABJiE1nzLZCqOJp7gA/MvFzQUzXP5nipvcaMI/MDUhN4anDBt7IelrBfbF/FpiFrfw==" 16 | }, 17 | "@cfn-modules/vpc": { 18 | "version": "2.3.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 20 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 21 | "requires": { 22 | "@cfn-modules/vpc-flow-log": "2.0.0", 23 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 24 | "@cfn-modules/vpc-plain": "2.0.1", 25 | "@cfn-modules/vpc-subnet": "2.1.0" 26 | }, 27 | "dependencies": { 28 | "@cfn-modules/vpc-flow-log": { 29 | "version": "2.0.0", 30 | "bundled": true 31 | }, 32 | "@cfn-modules/vpc-nat-gateway": { 33 | "version": "2.0.0", 34 | "bundled": true 35 | }, 36 | "@cfn-modules/vpc-plain": { 37 | "version": "2.0.1", 38 | "bundled": true 39 | }, 40 | "@cfn-modules/vpc-subnet": { 41 | "version": "2.1.0", 42 | "bundled": true 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-asg-singleton-ssm-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: ASG singleton SSM example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/asg-singleton-amazon-linux2": "2.4.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/asg-singleton-ssm/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-ebs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-ebs/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 EBS example project 2 | 3 | This example project demonstrates how an EC2 instance can mount an EBS volume. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-ebs-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name ec2-ebs-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/ec2-ebs/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 EBS example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | Volume: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 40 | TemplateURL: './node_modules/@cfn-modules/ebs-volume/module.yml' 41 | Instance: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 47 | VolumeModule1: !GetAtt 'Volume.Outputs.StackName' 48 | AmazonLinuxVersion: '2018.03.0.20181116' 49 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 50 | Outputs: 51 | PublicIpAddress: 52 | Value: !GetAtt 'Instance.Outputs.PublicIpAddress' 53 | -------------------------------------------------------------------------------- /examples/ec2-ebs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ebs-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/ebs-volume": { 13 | "version": "1.2.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/ebs-volume/-/ebs-volume-1.2.0.tgz", 15 | "integrity": "sha512-uUbCY+bSCq+Vh8ZQS3HUFABL5TWBBmtXdZh0M89jTDkpghWlQhHkLVr8K49GrUkS1TEcTybXoR7Mp34WvJ/uIg==" 16 | }, 17 | "@cfn-modules/ec2-instance-amazon-linux": { 18 | "version": "2.4.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 20 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 21 | }, 22 | "@cfn-modules/vpc": { 23 | "version": "2.3.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 25 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 26 | "requires": { 27 | "@cfn-modules/vpc-flow-log": "2.0.0", 28 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 29 | "@cfn-modules/vpc-plain": "2.0.1", 30 | "@cfn-modules/vpc-subnet": "2.1.0" 31 | }, 32 | "dependencies": { 33 | "@cfn-modules/vpc-flow-log": { 34 | "version": "2.0.0", 35 | "bundled": true 36 | }, 37 | "@cfn-modules/vpc-nat-gateway": { 38 | "version": "2.0.0", 39 | "bundled": true 40 | }, 41 | "@cfn-modules/vpc-plain": { 42 | "version": "2.0.1", 43 | "bundled": true 44 | }, 45 | "@cfn-modules/vpc-subnet": { 46 | "version": "2.1.0", 47 | "bundled": true 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /examples/ec2-ebs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ebs-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 EBS example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ebs-volume": "1.2.0", 12 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/ec2-ebs/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-ebs/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-ebs/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-ebs/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-efs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-efs/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 EFS example project 2 | 3 | This example project demonstrates how an EC2 instance can mount an EFS file system. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-efs-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name ec2-efs-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/ec2-efs/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 EFS example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | ClientSg: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 40 | TemplateURL: './node_modules/@cfn-modules/client-sg/module.yml' 41 | FileSystem: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | ClientSgModule: !GetAtt 'ClientSg.Outputs.StackName' 47 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 48 | NumberOfAvailabilityZones: !GetAtt 'Vpc.Outputs.NumberOfAvailabilityZones' 49 | TemplateURL: './node_modules/@cfn-modules/efs-file-system/module.yml' 50 | Instance: 51 | Type: 'AWS::CloudFormation::Stack' 52 | Properties: 53 | Parameters: 54 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 55 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 56 | ClientSgModule1: !GetAtt 'ClientSg.Outputs.StackName' 57 | FileSystemModule1: !GetAtt 'FileSystem.Outputs.StackName' 58 | AmazonLinuxVersion: '2018.03.0.20181116' 59 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 60 | Outputs: 61 | PublicIpAddress: 62 | Value: !GetAtt 'Instance.Outputs.PublicIpAddress' 63 | -------------------------------------------------------------------------------- /examples/ec2-efs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-efs-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/client-sg": { 13 | "version": "1.0.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 15 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 16 | }, 17 | "@cfn-modules/ec2-instance-amazon-linux": { 18 | "version": "2.4.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 20 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 21 | }, 22 | "@cfn-modules/efs-file-system": { 23 | "version": "1.3.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/efs-file-system/-/efs-file-system-1.3.0.tgz", 25 | "integrity": "sha512-7Bzdj+K/SQ6lwNpW1IF0iePADepJ+dfnb+9SkQOPk6iU2y8OoQI/W7zccNOVmcHBlNbhvQwi5f27WLhBr9R22Q==" 26 | }, 27 | "@cfn-modules/vpc": { 28 | "version": "2.3.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 30 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 31 | "requires": { 32 | "@cfn-modules/vpc-flow-log": "2.0.0", 33 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 34 | "@cfn-modules/vpc-plain": "2.0.1", 35 | "@cfn-modules/vpc-subnet": "2.1.0" 36 | }, 37 | "dependencies": { 38 | "@cfn-modules/vpc-flow-log": { 39 | "version": "2.0.0", 40 | "bundled": true 41 | }, 42 | "@cfn-modules/vpc-nat-gateway": { 43 | "version": "2.0.0", 44 | "bundled": true 45 | }, 46 | "@cfn-modules/vpc-plain": { 47 | "version": "2.0.1", 48 | "bundled": true 49 | }, 50 | "@cfn-modules/vpc-subnet": { 51 | "version": "2.1.0", 52 | "bundled": true 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ec2-efs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-efs-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 EFS example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/efs-file-system": "1.3.0", 12 | "@cfn-modules/client-sg": "1.0.0", 13 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ec2-efs/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-efs/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-efs/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-efs/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-mysql/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-mysql/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 MySQL example project 2 | 3 | This example project demonstrates how an EC2 instance can communicate with an RDS MySQL database. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-mysql-example --capabilities CAPABILITY_IAM 20 | aws cloudformation describe-stacks --stack-name ec2-mysql-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 21 | ``` 22 | 23 | Open the URL in your web browser, login with the password `insecure`, and you will see [a database management tool](https://www.adminer.org/). 24 | 25 | Don't forget to delete the stack once you are done with the demo: 26 | 27 | ``` 28 | aws cloudformation delete-stack --stack-name ec2-mysql-example 29 | ``` 30 | 31 | ## Modules 32 | 33 | Find all modules here: https://www.npmjs.com/org/cfn-modules 34 | -------------------------------------------------------------------------------- /examples/ec2-mysql/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 MySQL example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | ClientSg: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 40 | TemplateURL: './node_modules/@cfn-modules/client-sg/module.yml' 41 | Database: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | ClientSgModule: !GetAtt 'ClientSg.Outputs.StackName' 47 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 48 | EngineVersion: '8.4.3' 49 | DBMasterUserPassword: insecure 50 | DBBackupRetentionPeriod: '0' # speed up the example (do not set to 0 in production!) 51 | DBMultiAZ: 'false' # speed up the example (do not set to false in production!) 52 | TemplateURL: './node_modules/@cfn-modules/rds-mysql/module.yml' 53 | Instance: 54 | Type: 'AWS::CloudFormation::Stack' 55 | Properties: 56 | Parameters: 57 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 58 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 59 | UserData: | 60 | yum install -y httpd24 php70 php70-mysqlnd 61 | wget -O /var/www/html/index.php https://github.com/vrana/adminer/releases/download/v4.6.3/adminer-4.6.3.php 62 | service httpd start 63 | chkconfig httpd on 64 | IngressTcpPort1: '80' 65 | ClientSgModule1: !GetAtt 'ClientSg.Outputs.StackName' 66 | AmazonLinuxVersion: '2018.03.0.20181116' 67 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 68 | Outputs: 69 | Url: 70 | Value: !Sub 'http://${Instance.Outputs.PublicIpAddress}/?server=${Database.Outputs.DnsName}&username=master' 71 | -------------------------------------------------------------------------------- /examples/ec2-mysql/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-mysql-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/client-sg": { 13 | "version": "1.0.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 15 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 16 | }, 17 | "@cfn-modules/ec2-instance-amazon-linux": { 18 | "version": "2.4.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 20 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 21 | }, 22 | "@cfn-modules/rds-mysql": { 23 | "version": "2.0.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/rds-mysql/-/rds-mysql-2.0.0.tgz", 25 | "integrity": "sha512-FA+QOD4DgFwx8q7OCgPtZZ2/RaDTLZxMyVhWH8NKnCkMx8sZV5edOoKYN/qXpvs8xUIw7HmFiZQs+P1Wt2jPWg==", 26 | "requires": { 27 | "@cfn-modules/rds-instance": "*" 28 | }, 29 | "dependencies": { 30 | "@cfn-modules/rds-instance": { 31 | "version": "1.4.0", 32 | "bundled": true 33 | } 34 | } 35 | }, 36 | "@cfn-modules/vpc": { 37 | "version": "2.3.0", 38 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 39 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 40 | "requires": { 41 | "@cfn-modules/vpc-flow-log": "2.0.0", 42 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 43 | "@cfn-modules/vpc-plain": "2.0.1", 44 | "@cfn-modules/vpc-subnet": "2.1.0" 45 | }, 46 | "dependencies": { 47 | "@cfn-modules/vpc-flow-log": { 48 | "version": "2.0.0", 49 | "bundled": true 50 | }, 51 | "@cfn-modules/vpc-nat-gateway": { 52 | "version": "2.0.0", 53 | "bundled": true 54 | }, 55 | "@cfn-modules/vpc-plain": { 56 | "version": "2.0.1", 57 | "bundled": true 58 | }, 59 | "@cfn-modules/vpc-subnet": { 60 | "version": "2.1.0", 61 | "bundled": true 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/ec2-mysql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-mysql-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 MySQL example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/rds-mysql": "2.0.0", 12 | "@cfn-modules/client-sg": "1.0.0", 13 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ec2-mysql/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-mysql/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-mysql/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-mysql/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-postgres/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-postgres/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 PostgreSQL example project 2 | 3 | This example project demonstrates how an EC2 instance can communicate with an RDS PostgreSQL database. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-postgres-example --capabilities CAPABILITY_IAM 20 | aws cloudformation describe-stacks --stack-name ec2-postgres-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 21 | ``` 22 | 23 | Open the URL in your web browser, login with the password `insecure`, and you will see [a database management tool](https://www.adminer.org/). 24 | 25 | Don't forget to delete the stack once you are done with the demo: 26 | 27 | ``` 28 | aws cloudformation delete-stack --stack-name ec2-postgres-example 29 | ``` 30 | 31 | ## Modules 32 | 33 | Find all modules here: https://www.npmjs.com/org/cfn-modules 34 | -------------------------------------------------------------------------------- /examples/ec2-postgres/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 PostgreSQL example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | ClientSg: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 40 | TemplateURL: './node_modules/@cfn-modules/client-sg/module.yml' 41 | Database: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | ClientSgModule: !GetAtt 'ClientSg.Outputs.StackName' 47 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 48 | DBInstanceClass: 'db.t3.micro ' 49 | DBMasterUserPassword: insecure 50 | DBBackupRetentionPeriod: '0' # speed up the example (do not set to 0 in production!) 51 | DBMultiAZ: 'false' # speed up the example (do not set to false in production!) 52 | EngineVersion: '17.2' 53 | TemplateURL: './node_modules/@cfn-modules/rds-postgres/module.yml' 54 | Instance: 55 | Type: 'AWS::CloudFormation::Stack' 56 | Properties: 57 | Parameters: 58 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 59 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 60 | UserData: | 61 | yum install -y httpd24 php70 php70-pgsql 62 | wget -O /var/www/html/index.php https://github.com/vrana/adminer/releases/download/v4.6.3/adminer-4.6.3.php 63 | service httpd start 64 | chkconfig httpd on 65 | IngressTcpPort1: '80' 66 | ClientSgModule1: !GetAtt 'ClientSg.Outputs.StackName' 67 | AmazonLinuxVersion: '2018.03.0.20181116' 68 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 69 | Outputs: 70 | Url: 71 | Value: !Sub 'http://${Instance.Outputs.PublicIpAddress}/?pgsql=${Database.Outputs.DnsName}&username=master' 72 | -------------------------------------------------------------------------------- /examples/ec2-postgres/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-postgres-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cfn-modules-ec2-postgres-example", 9 | "version": "1.0.0", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "@cfn-modules/alerting": "1.2.2", 13 | "@cfn-modules/client-sg": "1.0.0", 14 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0", 15 | "@cfn-modules/rds-postgres": "2.4.6", 16 | "@cfn-modules/vpc": "2.3.0" 17 | } 18 | }, 19 | "node_modules/@cfn-modules/alerting": { 20 | "version": "1.2.2", 21 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 22 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 23 | }, 24 | "node_modules/@cfn-modules/client-sg": { 25 | "version": "1.0.0", 26 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 27 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 28 | }, 29 | "node_modules/@cfn-modules/ec2-instance-amazon-linux": { 30 | "version": "2.4.0", 31 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 32 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 33 | }, 34 | "node_modules/@cfn-modules/rds-postgres": { 35 | "version": "2.4.6", 36 | "resolved": "https://registry.npmjs.org/@cfn-modules/rds-postgres/-/rds-postgres-2.4.6.tgz", 37 | "integrity": "sha512-187UkVIsNYhxl9uHwW0dz2t/Q1XOWy4JByyt4a8UVMbP6mH8Ta5CP8MaPk6u89oQzvKb8tSGzR0u5EH4cG+KpA==", 38 | "bundleDependencies": [ 39 | "@cfn-modules/rds-instance" 40 | ], 41 | "license": "Apache-2.0", 42 | "dependencies": { 43 | "@cfn-modules/rds-instance": "^1.5.0" 44 | } 45 | }, 46 | "node_modules/@cfn-modules/rds-postgres/node_modules/@cfn-modules/rds-instance": { 47 | "version": "1.5.0", 48 | "inBundle": true, 49 | "license": "Apache-2.0" 50 | }, 51 | "node_modules/@cfn-modules/vpc": { 52 | "version": "2.3.0", 53 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 54 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 55 | "bundleDependencies": [ 56 | "@cfn-modules/vpc-flow-log", 57 | "@cfn-modules/vpc-nat-gateway", 58 | "@cfn-modules/vpc-plain", 59 | "@cfn-modules/vpc-subnet" 60 | ], 61 | "dependencies": { 62 | "@cfn-modules/vpc-flow-log": "2.0.0", 63 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 64 | "@cfn-modules/vpc-plain": "2.0.1", 65 | "@cfn-modules/vpc-subnet": "2.1.0" 66 | } 67 | }, 68 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-flow-log": { 69 | "version": "2.0.0", 70 | "inBundle": true, 71 | "license": "Apache-2.0" 72 | }, 73 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-nat-gateway": { 74 | "version": "2.0.0", 75 | "inBundle": true, 76 | "license": "Apache-2.0" 77 | }, 78 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-plain": { 79 | "version": "2.0.1", 80 | "inBundle": true, 81 | "license": "Apache-2.0" 82 | }, 83 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-subnet": { 84 | "version": "2.1.0", 85 | "inBundle": true, 86 | "license": "Apache-2.0" 87 | } 88 | }, 89 | "dependencies": { 90 | "@cfn-modules/alerting": { 91 | "version": "1.2.2", 92 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 93 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 94 | }, 95 | "@cfn-modules/client-sg": { 96 | "version": "1.0.0", 97 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 98 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 99 | }, 100 | "@cfn-modules/ec2-instance-amazon-linux": { 101 | "version": "2.4.0", 102 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 103 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 104 | }, 105 | "@cfn-modules/rds-postgres": { 106 | "version": "2.4.6", 107 | "resolved": "https://registry.npmjs.org/@cfn-modules/rds-postgres/-/rds-postgres-2.4.6.tgz", 108 | "integrity": "sha512-187UkVIsNYhxl9uHwW0dz2t/Q1XOWy4JByyt4a8UVMbP6mH8Ta5CP8MaPk6u89oQzvKb8tSGzR0u5EH4cG+KpA==", 109 | "requires": { 110 | "@cfn-modules/rds-instance": "^1.5.0" 111 | }, 112 | "dependencies": { 113 | "@cfn-modules/rds-instance": { 114 | "version": "1.5.0", 115 | "bundled": true 116 | } 117 | } 118 | }, 119 | "@cfn-modules/vpc": { 120 | "version": "2.3.0", 121 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 122 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 123 | "requires": { 124 | "@cfn-modules/vpc-flow-log": "2.0.0", 125 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 126 | "@cfn-modules/vpc-plain": "2.0.1", 127 | "@cfn-modules/vpc-subnet": "2.1.0" 128 | }, 129 | "dependencies": { 130 | "@cfn-modules/vpc-flow-log": { 131 | "version": "2.0.0", 132 | "bundled": true 133 | }, 134 | "@cfn-modules/vpc-nat-gateway": { 135 | "version": "2.0.0", 136 | "bundled": true 137 | }, 138 | "@cfn-modules/vpc-plain": { 139 | "version": "2.0.1", 140 | "bundled": true 141 | }, 142 | "@cfn-modules/vpc-subnet": { 143 | "version": "2.1.0", 144 | "bundled": true 145 | } 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /examples/ec2-postgres/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-postgres-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 PostgreSQL example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/rds-postgres": "2.4.6", 12 | "@cfn-modules/client-sg": "1.0.0", 13 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ec2-postgres/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-postgres/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-postgres/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-postgres/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 SSH bastion example project 2 | 3 | This example project demonstrates how an EC2 instance can be placed into a VPC with a bastion host for secure SSH access. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-ssh-bastion-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | To connect to the EC2 instance via SSH, run the following command. Replace: 23 | * `$IamUserName` with your IAM user name (requires that you upload a public SSH key for your IAM user under Security Credentials, [read this of your user name contains special characters](https://github.com/widdix/aws-ec2-ssh#iam-user-names-and-linux-user-names)) 24 | * `$BastionPublicIpAddress` with the output of `aws cloudformation describe-stacks --stack-name ec2-ssh-bastion-example --query "Stacks[0].Outputs[?OutputKey=='BastionPublicIpAddress'].OutputValue" --output text` 25 | * `$TargetPrivateIpAddress` with the output of `aws cloudformation describe-stacks --stack-name ec2-ssh-bastion-example --query "Stacks[0].Outputs[?OutputKey=='TargetPrivateIpAddress'].OutputValue" --output text` 26 | 27 | ``` 28 | ssh -J $IamUserName@$$BastionPublicIpAddress $TargetPrivateIpAddress 29 | ``` 30 | 31 | Don't forget to delete the stack once you are done with the demo: 32 | 33 | ``` 34 | aws cloudformation delete-stack --stack-name ec2-ssh-bastion-example 35 | ``` 36 | 37 | ## Modules 38 | 39 | Find all modules here: https://www.npmjs.com/org/cfn-modules 40 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 SSH bastion example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | HostedZone: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | Name: 'widdix.de' 40 | TemplateURL: './node_modules/@cfn-modules/route53-hosted-zone-public/module.yml' 41 | Bastion: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 47 | HostedZoneModule: !GetAtt 'HostedZone.Outputs.StackName' 48 | TemplateURL: './node_modules/@cfn-modules/ssh-bastion/module.yml' 49 | Instance: 50 | Type: 'AWS::CloudFormation::Stack' 51 | Properties: 52 | Parameters: 53 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 54 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 55 | BastionModule: !GetAtt 'Bastion.Outputs.StackName' 56 | HostedZoneModule: !GetAtt 'HostedZone.Outputs.StackName' 57 | AmazonLinuxVersion: '2018.03.0.20181116' 58 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux/module.yml' 59 | Outputs: 60 | BastionPublicIpAddress: 61 | Value: !GetAtt 'Bastion.Outputs.PublicIpAddress' 62 | TargetPrivateIpAddress: 63 | Value: !GetAtt 'Instance.Outputs.PrivateIpAddress' 64 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ssh-bastion-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/ec2-instance-amazon-linux": { 13 | "version": "2.4.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux/-/ec2-instance-amazon-linux-2.4.0.tgz", 15 | "integrity": "sha512-goPxpZ+viDjj7JfQ0ssktRZbOvQFsW7ZjIuu9Xu0BVp1gxL4I8LW1P1mJfdKPp1QxnTUB44l+ciI3lVm8MhRrw==" 16 | }, 17 | "@cfn-modules/route53-hosted-zone-public": { 18 | "version": "1.0.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/route53-hosted-zone-public/-/route53-hosted-zone-public-1.0.0.tgz", 20 | "integrity": "sha512-jB/k5gEQn0cMEPSCD7UU+MwYFyLZqNwsZ1JqZSS+8yzhbnZHURJOWodUETS28gpWv+4L7kSTIgLF1eeq/oHY8Q==" 21 | }, 22 | "@cfn-modules/ssh-bastion": { 23 | "version": "1.5.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/ssh-bastion/-/ssh-bastion-1.5.0.tgz", 25 | "integrity": "sha512-Wtv2FNv/2F8QQXG1tV9algQCTzsPY07UbntD/X7smKB3B6ZwjH+4VWZqSsCuMvQm2DAZz9NkUVL7ldD2NVDW0A==" 26 | }, 27 | "@cfn-modules/vpc": { 28 | "version": "2.3.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 30 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 31 | "requires": { 32 | "@cfn-modules/vpc-flow-log": "2.0.0", 33 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 34 | "@cfn-modules/vpc-plain": "2.0.1", 35 | "@cfn-modules/vpc-subnet": "2.1.0" 36 | }, 37 | "dependencies": { 38 | "@cfn-modules/vpc-flow-log": { 39 | "version": "2.0.0", 40 | "bundled": true 41 | }, 42 | "@cfn-modules/vpc-nat-gateway": { 43 | "version": "2.0.0", 44 | "bundled": true 45 | }, 46 | "@cfn-modules/vpc-plain": { 47 | "version": "2.0.1", 48 | "bundled": true 49 | }, 50 | "@cfn-modules/vpc-subnet": { 51 | "version": "2.1.0", 52 | "bundled": true 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ssh-bastion-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 SSH bastion example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ec2-instance-amazon-linux": "2.4.0", 12 | "@cfn-modules/route53-hosted-zone-public": "1.0.0", 13 | "@cfn-modules/ssh-bastion": "1.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-ssh-bastion/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/ec2-ssm/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/ec2-ssm/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: EC2 SSM example project 2 | 3 | This example project demonstrates how an EC2 instance can be managed by SSM. Every hour, SSM fetches the software inventory and the installed patches and displays them in the [SSM inventory](https://console.aws.amazon.com/systems-manager/inventory). 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name ec2-ssm-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Open the [SSM inventory](https://console.aws.amazon.com/systems-manager/inventory) and search for the EC2 instance. Have a look at the Inventory and Patch tab of the Instance. 23 | 24 | Don't forget to delete the stack once you are done with the demo: 25 | 26 | ``` 27 | aws cloudformation delete-stack --stack-name ec2-ssm-example 28 | ``` 29 | 30 | ## Modules 31 | 32 | Find all modules here: https://www.npmjs.com/org/cfn-modules 33 | -------------------------------------------------------------------------------- /examples/ec2-ssm/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: EC2 SSM example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | InstancePolicy: 36 | Type: 'AWS::IAM::ManagedPolicy' 37 | Properties: 38 | PolicyDocument: 39 | Version: '2012-10-17' 40 | Statement: 41 | - Effect: Allow 42 | Action: 43 | - 'ssm:ListInstanceAssociations' # State Manager by https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html 44 | - 'ssm:GetDeployablePatchSnapshotForInstance' # Patch Manager by trial and error 45 | Resource: '*' 46 | - Effect: Allow # Patch Manager by trial and error 47 | Action: 'ssm:PutInventory' 48 | Resource: '*' 49 | - Effect: Allow # Patch Manager by https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-minimum-s3-permissions.html 50 | Action: 's3:GetObject' 51 | Resource: 52 | - !Sub 'arn:aws:s3:::aws-ssm-${AWS::Region}/*' 53 | - !Sub 'arn:aws:s3:::amazon-ssm-${AWS::Region}/*' 54 | - !Sub 'arn:aws:s3:::amazon-ssm-packages-${AWS::Region}/*' 55 | - !Sub 'arn:aws:s3:::${AWS::Region}-birdwatcher-prod/*' 56 | - !Sub 'arn:aws:s3:::patch-baseline-snapshot-${AWS::Region}/*' 57 | - Effect: Allow # AWS-GatherSoftwareInventory 58 | Action: 'ssm:GetDocument' 59 | Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}::document/AWS-GatherSoftwareInventory' 60 | - Effect: Allow # AWS-GatherSoftwareInventory 61 | Action: 'ssm:UpdateInstanceAssociationStatus' 62 | Resource: '*' 63 | Instance: 64 | Type: 'AWS::CloudFormation::Stack' 65 | Properties: 66 | Parameters: 67 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 68 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 69 | AmazonLinux2Version: '2.0.20181114' 70 | ManagedPolicyArns: !Ref InstancePolicy 71 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux2/module.yml' 72 | AssociationGatherSoftwareInventory: 73 | Type: 'AWS::SSM::Association' 74 | Properties: 75 | Name: 'AWS-GatherSoftwareInventory' 76 | ScheduleExpression: 'rate(1 hour)' 77 | Targets: 78 | - Key: InstanceIds 79 | Values: [!GetAtt 'Instance.Outputs.Id'] 80 | AssociationRunPatchBaselineScan: 81 | Type: 'AWS::SSM::Association' 82 | Properties: 83 | Name: 'AWS-RunPatchBaseline' 84 | Parameters: 85 | Operation: [Scan] 86 | ScheduleExpression: 'rate(1 hour)' 87 | Targets: 88 | - Key: InstanceIds 89 | Values: [!GetAtt 'Instance.Outputs.Id'] 90 | AssociationRunPatchBaselineInstall: 91 | Type: 'AWS::SSM::Association' 92 | Properties: 93 | Name: 'AWS-RunPatchBaseline' 94 | Parameters: 95 | Operation: [Install] 96 | ScheduleExpression: 'rate(1 hour)' 97 | Targets: 98 | - Key: InstanceIds 99 | Values: [!GetAtt 'Instance.Outputs.Id'] 100 | -------------------------------------------------------------------------------- /examples/ec2-ssm/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ssm-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/ec2-instance-amazon-linux2": { 13 | "version": "2.5.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux2/-/ec2-instance-amazon-linux2-2.5.0.tgz", 15 | "integrity": "sha512-XH8ZCU+mhneW2FzKhn95ejCUOXiM7YcQhpdwOjv+hKfGX2ke8smI89kaNjA9n6JJk7ZWdiU/NNSSttzb42yhdA==" 16 | }, 17 | "@cfn-modules/vpc": { 18 | "version": "2.3.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 20 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 21 | "requires": { 22 | "@cfn-modules/vpc-flow-log": "2.0.0", 23 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 24 | "@cfn-modules/vpc-plain": "2.0.1", 25 | "@cfn-modules/vpc-subnet": "2.1.0" 26 | }, 27 | "dependencies": { 28 | "@cfn-modules/vpc-flow-log": { 29 | "version": "2.0.0", 30 | "bundled": true 31 | }, 32 | "@cfn-modules/vpc-nat-gateway": { 33 | "version": "2.0.0", 34 | "bundled": true 35 | }, 36 | "@cfn-modules/vpc-plain": { 37 | "version": "2.0.1", 38 | "bundled": true 39 | }, 40 | "@cfn-modules/vpc-subnet": { 41 | "version": "2.1.0", 42 | "bundled": true 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/ec2-ssm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-ec2-ssm-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: EC2 SSM example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ec2-instance-amazon-linux2": "2.5.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/ec2-ssm/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/ec2-ssm/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/ec2-ssm/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ec2-ssm/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/fargate-alb-ambassador-pattern/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Fargate ALB with ambassador pattern example 2 | 3 | Moved to [fargate-alb-proxy-pattern](https://github.com/cfn-modules/docs/tree/master/examples/fargate-alb-proxy-pattern) 4 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Fargate container behind ALB with authentication via Cognito User Pool example 2 | 3 | This example project demonstrates how an ALB can be placed in front of a single Docker container app running on Fargate. Cognito is used to add an authentication layer on top. The following diagram illustrates the high-level architecture. 4 | 5 | ``` 6 | ┌────────────┐ 7 | │ │ 8 | │ │ 9 | │ ALB │ 10 | │ │ 11 | │ │ 12 | └────────────┘ 13 | │ 14 | │ 15 | ┌─Service─▼────────┐ 16 | │ ┌──────────────┐ │ 17 | │ │ │ │ 18 | │ │ │ │ 19 | │ │ app │ │ 20 | │ │ container │ │ 21 | │ │ │ │ 22 | │ │ │ │ 23 | │ └──────────────┘ │ 24 | └──────────────────┘ 25 | ``` 26 | 27 | ## Prerequisites 28 | 29 | 1. [Install Node.js 10.x](https://nodejs.org/) 30 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 31 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 32 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 33 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 34 | 4. Create the bucket `aws s3 mb s3://$BucketName` 35 | 36 | ## Usage 37 | 38 | Replace `$HostedZone` and `$Subdomain`. 39 | 40 | ``` 41 | npm i 42 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 43 | aws cloudformation deploy --template-file packaged.yml --stack-name fargate-alb-auth-cognito-example --parameter-overrides HostedZoneId=$HostedZone SubDomainNameWithDot=$Subdomain --capabilities CAPABILITY_IAM 44 | aws cloudformation describe-stacks --stack-name fargate-alb-auth-cognito-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 45 | ``` 46 | 47 | Open the URL in your web browser. 48 | 49 | Don't forget to delete the stack once you are done with the demo: 50 | 51 | ``` 52 | aws cloudformation delete-stack --stack-name fargate-alb-auth-cognito-example 53 | ``` 54 | 55 | ## Modules 56 | 57 | Find all modules here: https://www.npmjs.com/org/cfn-modules 58 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Fargate ALB to single container example' 17 | Parameters: 18 | HostedZoneId: 19 | Type: String 20 | SubDomainNameWithDot: 21 | Type: String 22 | Resources: 23 | Alerting: 24 | Type: 'AWS::CloudFormation::Stack' 25 | Properties: 26 | Parameters: 27 | Email: 'email@domain.com' # replace with your email address to receive alerts 28 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 29 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 30 | Vpc: 31 | Type: 'AWS::CloudFormation::Stack' 32 | Properties: 33 | Parameters: 34 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 35 | S3Endpoint: 'false' # speed up the example 36 | DynamoDBEndpoint: 'false' # speed up the example 37 | FlowLog: 'false' # speed up the example 38 | NatGateways: 'false' # speed up the example 39 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 40 | Cluster: 41 | Type: 'AWS::CloudFormation::Stack' 42 | Properties: 43 | TemplateURL: './node_modules/@cfn-modules/ecs-cluster/module.yml' 44 | Alb: 45 | Type: 'AWS::CloudFormation::Stack' 46 | Properties: 47 | Parameters: 48 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 49 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 50 | TemplateURL: './node_modules/@cfn-modules/alb/module.yml' 51 | AlbListener: 52 | Type: 'AWS::CloudFormation::Stack' 53 | Properties: 54 | Parameters: 55 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 56 | Port: '443' 57 | CertificateArn: !GetAtt 'Certificate.Outputs.Arn' 58 | TemplateURL: './node_modules/@cfn-modules/alb-listener/module.yml' 59 | Target: 60 | Type: 'AWS::CloudFormation::Stack' 61 | Properties: 62 | Parameters: 63 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 64 | AlbListenerModule: !GetAtt 'AlbListener.Outputs.StackName' 65 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 66 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 67 | CognitoUserPoolModule: !GetAtt 'UserPool.Outputs.StackName' 68 | AuthCallbackDomain: !Sub '${SubDomainNameWithDot}${HostedZone.Outputs.Name}' 69 | TemplateURL: './node_modules/@cfn-modules/ecs-alb-target/module.yml' 70 | Service: 71 | Type: 'AWS::CloudFormation::Stack' 72 | Properties: 73 | Parameters: 74 | ClusterModule: !GetAtt 'Cluster.Outputs.StackName' 75 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 76 | TargetModule: !GetAtt 'Target.Outputs.StackName' 77 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 78 | AppImage: 'widdix/hello:v1' 79 | AppPort: '80' 80 | TemplateURL: './node_modules/@cfn-modules/fargate-service/module.yml' 81 | UserPool: 82 | Type: 'AWS::CloudFormation::Stack' 83 | Properties: 84 | TemplateURL: './node_modules/@cfn-modules/cognito-userpool/module.yml' 85 | HostedZone: 86 | Type: 'AWS::CloudFormation::Stack' 87 | Properties: 88 | Parameters: 89 | Id: !Ref HostedZoneId 90 | TemplateURL: './node_modules/@cfn-modules/route53-hosted-zone-wrapper/module.yml' 91 | Certificate: 92 | Type: 'AWS::CloudFormation::Stack' 93 | Properties: 94 | Parameters: 95 | HostedZoneModule: !GetAtt 'HostedZone.Outputs.StackName' 96 | TemplateURL: './node_modules/@cfn-modules/acm-wildcard-certificate-public/module.yml' 97 | CustomDomain: 98 | Type: 'AWS::CloudFormation::Stack' 99 | Properties: 100 | Parameters: 101 | HostedZoneModule: !GetAtt 'HostedZone.Outputs.StackName' 102 | LoadBalancerModule: !GetAtt 'Alb.Outputs.StackName' 103 | SubDomainNameWithDot: !Ref SubDomainNameWithDot 104 | TemplateURL: './node_modules/@cfn-modules/lb-dns-record/module.yml' 105 | Outputs: 106 | Url: 107 | Value: !Sub 'https://${SubDomainNameWithDot}${HostedZone.Outputs.Name}' 108 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-auth-cognito-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cfn-modules-fargate-alb-auth-cognito-example", 9 | "version": "1.0.0", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "@cfn-modules/acm-wildcard-certificate-public": "1.0.0", 13 | "@cfn-modules/alb": "1.2.0", 14 | "@cfn-modules/alb-listener": "1.4.0", 15 | "@cfn-modules/alerting": "1.2.2", 16 | "@cfn-modules/cognito-userpool": "2.0.0", 17 | "@cfn-modules/ecs-alb-target": "1.4.0", 18 | "@cfn-modules/ecs-cluster": "1.2.0", 19 | "@cfn-modules/fargate-service": "2.15.1", 20 | "@cfn-modules/lb-dns-record": "1.1.1", 21 | "@cfn-modules/route53-hosted-zone-wrapper": "1.11.0", 22 | "@cfn-modules/vpc": "2.3.0" 23 | } 24 | }, 25 | "node_modules/@cfn-modules/acm-wildcard-certificate-public": { 26 | "version": "1.0.0", 27 | "resolved": "https://registry.npmjs.org/@cfn-modules/acm-wildcard-certificate-public/-/acm-wildcard-certificate-public-1.0.0.tgz", 28 | "integrity": "sha512-L9mGth8GQLqW9+qrWaKmWiAyaq4m8UXzxan34SS+Paw+q8Mg4t2qAcJoe+RA64/Qwk6xyGOzoYgSqbvnuMLJGA==" 29 | }, 30 | "node_modules/@cfn-modules/alb": { 31 | "version": "1.2.0", 32 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb/-/alb-1.2.0.tgz", 33 | "integrity": "sha512-mUi0t1ryyHTk6Tr3o/cJg9XcFKCpnTcT4qyAojTC6VxEZ4QGyZzu+Q4d5NrZqr03O0LE5ybd8ORDTYmr+a4IjQ==" 34 | }, 35 | "node_modules/@cfn-modules/alb-listener": { 36 | "version": "1.4.0", 37 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb-listener/-/alb-listener-1.4.0.tgz", 38 | "integrity": "sha512-apjPXicmRXeufmKiCt9XqJiWeZLJ2VbbsZAzW4hub2Uy1ndE7rVi8P1Awi/JUYyS9UkGr08wzIODgviFlFgJXA==" 39 | }, 40 | "node_modules/@cfn-modules/alerting": { 41 | "version": "1.2.2", 42 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 43 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 44 | }, 45 | "node_modules/@cfn-modules/cognito-userpool": { 46 | "version": "2.0.0", 47 | "resolved": "https://registry.npmjs.org/@cfn-modules/cognito-userpool/-/cognito-userpool-2.0.0.tgz", 48 | "integrity": "sha512-38ltAheHmedSSPLjaEYRY4rzuejugo/zJ24bRvtoKXZn2J1epsQn67RWucnOs7T++jsu4e0ufiBTxc9CAXpsQA==" 49 | }, 50 | "node_modules/@cfn-modules/ecs-alb-target": { 51 | "version": "1.4.0", 52 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-alb-target/-/ecs-alb-target-1.4.0.tgz", 53 | "integrity": "sha512-N+NEBxt5lShLoP22QnOqIvbL0lworB5nKwbmNUNVbIDjTZ0xS/+OXkit+qNKoWEBuztj30QjK2kujJOjTCwjdg==" 54 | }, 55 | "node_modules/@cfn-modules/ecs-cluster": { 56 | "version": "1.2.0", 57 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-cluster/-/ecs-cluster-1.2.0.tgz", 58 | "integrity": "sha512-ZmE/fTKFGwM+bhtuFaFsMe8Sa/FA2Wt+1v9ahwg6CYNXlEPIWobOcWPC6MLKvkMaL4mhnh7k5xF2gKd27c39PA==" 59 | }, 60 | "node_modules/@cfn-modules/fargate-service": { 61 | "version": "2.15.1", 62 | "resolved": "https://registry.npmjs.org/@cfn-modules/fargate-service/-/fargate-service-2.15.1.tgz", 63 | "integrity": "sha512-c/sOiLH0qD7Ii2lSCj8+e1DAIaZKoABDJFH1BTjU/4kCgM90lPVDYZuEN03SpFOaf9iEeALS4u1bueO2f87e1A==" 64 | }, 65 | "node_modules/@cfn-modules/lb-dns-record": { 66 | "version": "1.1.1", 67 | "resolved": "https://registry.npmjs.org/@cfn-modules/lb-dns-record/-/lb-dns-record-1.1.1.tgz", 68 | "integrity": "sha512-2wjKJ+AOd3plIjUIwCsCAo1nObJbgW85uKhHQABd31amimqIkjAfDsdLqh0AoFPfBQHjcXjuVQ+RU+4DmEjQkA==" 69 | }, 70 | "node_modules/@cfn-modules/route53-hosted-zone-wrapper": { 71 | "version": "1.11.0", 72 | "resolved": "https://registry.npmjs.org/@cfn-modules/route53-hosted-zone-wrapper/-/route53-hosted-zone-wrapper-1.11.0.tgz", 73 | "integrity": "sha512-Xq8MCPsk+zKREmW37cnx/ScG7SHy1ta6eL27qKdgxnIEpFMtK4l06PN4QVRYKVj8UPBFOcz5S6cJvSSAizuFOg==", 74 | "bundleDependencies": [ 75 | "@cfn-modules/lambda-function" 76 | ], 77 | "dependencies": { 78 | "@cfn-modules/lambda-function": "^2.10.0" 79 | } 80 | }, 81 | "node_modules/@cfn-modules/route53-hosted-zone-wrapper/node_modules/@cfn-modules/lambda-function": { 82 | "version": "2.10.0", 83 | "inBundle": true, 84 | "license": "Apache-2.0" 85 | }, 86 | "node_modules/@cfn-modules/vpc": { 87 | "version": "2.3.0", 88 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 89 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 90 | "bundleDependencies": [ 91 | "@cfn-modules/vpc-flow-log", 92 | "@cfn-modules/vpc-nat-gateway", 93 | "@cfn-modules/vpc-plain", 94 | "@cfn-modules/vpc-subnet" 95 | ], 96 | "dependencies": { 97 | "@cfn-modules/vpc-flow-log": "2.0.0", 98 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 99 | "@cfn-modules/vpc-plain": "2.0.1", 100 | "@cfn-modules/vpc-subnet": "2.1.0" 101 | } 102 | }, 103 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-flow-log": { 104 | "version": "2.0.0", 105 | "inBundle": true, 106 | "license": "Apache-2.0" 107 | }, 108 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-nat-gateway": { 109 | "version": "2.0.0", 110 | "inBundle": true, 111 | "license": "Apache-2.0" 112 | }, 113 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-plain": { 114 | "version": "2.0.1", 115 | "inBundle": true, 116 | "license": "Apache-2.0" 117 | }, 118 | "node_modules/@cfn-modules/vpc/node_modules/@cfn-modules/vpc-subnet": { 119 | "version": "2.1.0", 120 | "inBundle": true, 121 | "license": "Apache-2.0" 122 | } 123 | }, 124 | "dependencies": { 125 | "@cfn-modules/acm-wildcard-certificate-public": { 126 | "version": "1.0.0", 127 | "resolved": "https://registry.npmjs.org/@cfn-modules/acm-wildcard-certificate-public/-/acm-wildcard-certificate-public-1.0.0.tgz", 128 | "integrity": "sha512-L9mGth8GQLqW9+qrWaKmWiAyaq4m8UXzxan34SS+Paw+q8Mg4t2qAcJoe+RA64/Qwk6xyGOzoYgSqbvnuMLJGA==" 129 | }, 130 | "@cfn-modules/alb": { 131 | "version": "1.2.0", 132 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb/-/alb-1.2.0.tgz", 133 | "integrity": "sha512-mUi0t1ryyHTk6Tr3o/cJg9XcFKCpnTcT4qyAojTC6VxEZ4QGyZzu+Q4d5NrZqr03O0LE5ybd8ORDTYmr+a4IjQ==" 134 | }, 135 | "@cfn-modules/alb-listener": { 136 | "version": "1.4.0", 137 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb-listener/-/alb-listener-1.4.0.tgz", 138 | "integrity": "sha512-apjPXicmRXeufmKiCt9XqJiWeZLJ2VbbsZAzW4hub2Uy1ndE7rVi8P1Awi/JUYyS9UkGr08wzIODgviFlFgJXA==" 139 | }, 140 | "@cfn-modules/alerting": { 141 | "version": "1.2.2", 142 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 143 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 144 | }, 145 | "@cfn-modules/cognito-userpool": { 146 | "version": "2.0.0", 147 | "resolved": "https://registry.npmjs.org/@cfn-modules/cognito-userpool/-/cognito-userpool-2.0.0.tgz", 148 | "integrity": "sha512-38ltAheHmedSSPLjaEYRY4rzuejugo/zJ24bRvtoKXZn2J1epsQn67RWucnOs7T++jsu4e0ufiBTxc9CAXpsQA==" 149 | }, 150 | "@cfn-modules/ecs-alb-target": { 151 | "version": "1.4.0", 152 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-alb-target/-/ecs-alb-target-1.4.0.tgz", 153 | "integrity": "sha512-N+NEBxt5lShLoP22QnOqIvbL0lworB5nKwbmNUNVbIDjTZ0xS/+OXkit+qNKoWEBuztj30QjK2kujJOjTCwjdg==" 154 | }, 155 | "@cfn-modules/ecs-cluster": { 156 | "version": "1.2.0", 157 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-cluster/-/ecs-cluster-1.2.0.tgz", 158 | "integrity": "sha512-ZmE/fTKFGwM+bhtuFaFsMe8Sa/FA2Wt+1v9ahwg6CYNXlEPIWobOcWPC6MLKvkMaL4mhnh7k5xF2gKd27c39PA==" 159 | }, 160 | "@cfn-modules/fargate-service": { 161 | "version": "2.15.1", 162 | "resolved": "https://registry.npmjs.org/@cfn-modules/fargate-service/-/fargate-service-2.15.1.tgz", 163 | "integrity": "sha512-c/sOiLH0qD7Ii2lSCj8+e1DAIaZKoABDJFH1BTjU/4kCgM90lPVDYZuEN03SpFOaf9iEeALS4u1bueO2f87e1A==" 164 | }, 165 | "@cfn-modules/lb-dns-record": { 166 | "version": "1.1.1", 167 | "resolved": "https://registry.npmjs.org/@cfn-modules/lb-dns-record/-/lb-dns-record-1.1.1.tgz", 168 | "integrity": "sha512-2wjKJ+AOd3plIjUIwCsCAo1nObJbgW85uKhHQABd31amimqIkjAfDsdLqh0AoFPfBQHjcXjuVQ+RU+4DmEjQkA==" 169 | }, 170 | "@cfn-modules/route53-hosted-zone-wrapper": { 171 | "version": "1.11.0", 172 | "resolved": "https://registry.npmjs.org/@cfn-modules/route53-hosted-zone-wrapper/-/route53-hosted-zone-wrapper-1.11.0.tgz", 173 | "integrity": "sha512-Xq8MCPsk+zKREmW37cnx/ScG7SHy1ta6eL27qKdgxnIEpFMtK4l06PN4QVRYKVj8UPBFOcz5S6cJvSSAizuFOg==", 174 | "requires": { 175 | "@cfn-modules/lambda-function": "^2.10.0" 176 | }, 177 | "dependencies": { 178 | "@cfn-modules/lambda-function": { 179 | "version": "2.10.0", 180 | "bundled": true 181 | } 182 | } 183 | }, 184 | "@cfn-modules/vpc": { 185 | "version": "2.3.0", 186 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 187 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 188 | "requires": { 189 | "@cfn-modules/vpc-flow-log": "2.0.0", 190 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 191 | "@cfn-modules/vpc-plain": "2.0.1", 192 | "@cfn-modules/vpc-subnet": "2.1.0" 193 | }, 194 | "dependencies": { 195 | "@cfn-modules/vpc-flow-log": { 196 | "version": "2.0.0", 197 | "bundled": true 198 | }, 199 | "@cfn-modules/vpc-nat-gateway": { 200 | "version": "2.0.0", 201 | "bundled": true 202 | }, 203 | "@cfn-modules/vpc-plain": { 204 | "version": "2.0.1", 205 | "bundled": true 206 | }, 207 | "@cfn-modules/vpc-subnet": { 208 | "version": "2.1.0", 209 | "bundled": true 210 | } 211 | } 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-auth-cognito-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Fargate container behind ALB with authentication via Cognito User Pool example", 5 | "author": "Andreas Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/acm-wildcard-certificate-public": "1.0.0", 10 | "@cfn-modules/alerting": "1.2.2", 11 | "@cfn-modules/cognito-userpool": "2.0.0", 12 | "@cfn-modules/vpc": "2.3.0", 13 | "@cfn-modules/ecs-cluster": "1.2.0", 14 | "@cfn-modules/alb": "1.2.0", 15 | "@cfn-modules/alb-listener": "1.4.0", 16 | "@cfn-modules/ecs-alb-target": "1.4.0", 17 | "@cfn-modules/fargate-service": "2.15.1", 18 | "@cfn-modules/lb-dns-record": "1.1.1", 19 | "@cfn-modules/route53-hosted-zone-wrapper": "1.11.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/fargate-alb-auth-cognito/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, { 8 | 'HostedZoneId': 'Z06496441UUZUWB5DC4QT', 9 | 'SubDomainNameWithDot': 'fargate-alb-auth-cognito.' 10 | })); 11 | const outputs = await cfntest.getStackOutputs(stackName); 12 | t.log(outputs); 13 | const res = await cfntest.probeHttpGet(outputs.Url); 14 | t.true(res.data.includes('Sign in with your email and password')); 15 | t.is(res.status, 200); 16 | } finally { 17 | t.log(await cfntest.deleteStack(stackName)); 18 | t.pass(); 19 | } 20 | }); -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Fargate ALB with proxy pattern example 2 | 3 | This example project demonstrates how an ALB can be placed in front of two Docker containers running on Fargate. The following diagram illustrates the high-level architecture. 4 | 5 | ``` 6 | ┌────────────┐ 7 | │ │ 8 | │ │ 9 | │ ALB │ 10 | │ │ 11 | │ │ 12 | └────────────┘ 13 | │ 14 | ┌──────────┘ 15 | ┌─Service─▼───────────────────────────────┐ 16 | │ ┌──────────────┐ ┌──────────────┐ │ 17 | │ │ │ │ │ │ 18 | │ │ │ │ │ │ 19 | │ │ proxy │ │ app │ │ 20 | │ │ container │──────▶│ container │ │ 21 | │ │ │ │ │ │ 22 | │ │ │ │ │ │ 23 | │ └──────────────┘ └──────────────┘ │ 24 | └─────────────────────────────────────────┘ 25 | ``` 26 | 27 | ## Prerequisites 28 | 29 | 1. [Install Node.js 10.x](https://nodejs.org/) 30 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 31 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 32 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 33 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 34 | 4. Create the bucket `aws s3 mb s3://$BucketName` 35 | 36 | ## Usage 37 | 38 | ``` 39 | npm i 40 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 41 | aws cloudformation deploy --template-file packaged.yml --stack-name fargate-alb-proxy-pattern-example --capabilities CAPABILITY_IAM 42 | aws cloudformation describe-stacks --stack-name fargate-alb-proxy-pattern-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 43 | ``` 44 | 45 | Open the URL in your web browser. 46 | 47 | Don't forget to delete the stack once you are done with the demo: 48 | 49 | ``` 50 | aws cloudformation delete-stack --stack-name fargate-alb-proxy-pattern-example 51 | ``` 52 | 53 | ## Modules 54 | 55 | Find all modules here: https://www.npmjs.com/org/cfn-modules 56 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Fargate ALB with proxy pattern example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | Cluster: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | TemplateURL: './node_modules/@cfn-modules/ecs-cluster/module.yml' 39 | Alb: 40 | Type: 'AWS::CloudFormation::Stack' 41 | Properties: 42 | Parameters: 43 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 44 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 45 | TemplateURL: './node_modules/@cfn-modules/alb/module.yml' 46 | AlbListener: 47 | Type: 'AWS::CloudFormation::Stack' 48 | Properties: 49 | Parameters: 50 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 51 | TemplateURL: './node_modules/@cfn-modules/alb-listener/module.yml' 52 | Target: 53 | Type: 'AWS::CloudFormation::Stack' 54 | Properties: 55 | Parameters: 56 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 57 | AlbListenerModule: !GetAtt 'AlbListener.Outputs.StackName' 58 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 59 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 60 | TemplateURL: './node_modules/@cfn-modules/ecs-alb-target/module.yml' 61 | Service: 62 | Type: 'AWS::CloudFormation::Stack' 63 | Properties: 64 | Parameters: 65 | ClusterModule: !GetAtt 'Cluster.Outputs.StackName' 66 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 67 | TargetModule: !GetAtt 'Target.Outputs.StackName' 68 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 69 | ProxyImage: 'eeacms/varnish:4.1-6.2' 70 | ProxyPort: '6081' 71 | ProxyEnvironment1Key: 'BACKENDS' 72 | ProxyEnvironment1Value: 'localhost' 73 | ProxyEnvironment2Key: 'BACKENDS_PORT' 74 | ProxyEnvironment2Value: '80' 75 | AppImage: 'widdix/hello:v1' 76 | AppPort: '80' 77 | TemplateURL: './node_modules/@cfn-modules/fargate-service/module.yml' 78 | Outputs: 79 | Url: 80 | Value: !Sub 'http://${Alb.Outputs.DnsName}' 81 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-proxy-pattern-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alb": { 8 | "version": "1.2.0", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb/-/alb-1.2.0.tgz", 10 | "integrity": "sha512-mUi0t1ryyHTk6Tr3o/cJg9XcFKCpnTcT4qyAojTC6VxEZ4QGyZzu+Q4d5NrZqr03O0LE5ybd8ORDTYmr+a4IjQ==" 11 | }, 12 | "@cfn-modules/alb-listener": { 13 | "version": "1.4.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb-listener/-/alb-listener-1.4.0.tgz", 15 | "integrity": "sha512-apjPXicmRXeufmKiCt9XqJiWeZLJ2VbbsZAzW4hub2Uy1ndE7rVi8P1Awi/JUYyS9UkGr08wzIODgviFlFgJXA==" 16 | }, 17 | "@cfn-modules/alerting": { 18 | "version": "1.2.2", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 20 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 21 | }, 22 | "@cfn-modules/ecs-alb-target": { 23 | "version": "1.4.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-alb-target/-/ecs-alb-target-1.4.0.tgz", 25 | "integrity": "sha512-N+NEBxt5lShLoP22QnOqIvbL0lworB5nKwbmNUNVbIDjTZ0xS/+OXkit+qNKoWEBuztj30QjK2kujJOjTCwjdg==" 26 | }, 27 | "@cfn-modules/ecs-cluster": { 28 | "version": "1.2.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-cluster/-/ecs-cluster-1.2.0.tgz", 30 | "integrity": "sha512-ZmE/fTKFGwM+bhtuFaFsMe8Sa/FA2Wt+1v9ahwg6CYNXlEPIWobOcWPC6MLKvkMaL4mhnh7k5xF2gKd27c39PA==" 31 | }, 32 | "@cfn-modules/fargate-service": { 33 | "version": "2.15.1", 34 | "resolved": "https://registry.npmjs.org/@cfn-modules/fargate-service/-/fargate-service-2.15.1.tgz", 35 | "integrity": "sha512-c/sOiLH0qD7Ii2lSCj8+e1DAIaZKoABDJFH1BTjU/4kCgM90lPVDYZuEN03SpFOaf9iEeALS4u1bueO2f87e1A==" 36 | }, 37 | "@cfn-modules/vpc": { 38 | "version": "2.3.0", 39 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 40 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 41 | "requires": { 42 | "@cfn-modules/vpc-flow-log": "2.0.0", 43 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 44 | "@cfn-modules/vpc-plain": "2.0.1", 45 | "@cfn-modules/vpc-subnet": "2.1.0" 46 | }, 47 | "dependencies": { 48 | "@cfn-modules/vpc-flow-log": { 49 | "version": "2.0.0", 50 | "bundled": true 51 | }, 52 | "@cfn-modules/vpc-nat-gateway": { 53 | "version": "2.0.0", 54 | "bundled": true 55 | }, 56 | "@cfn-modules/vpc-plain": { 57 | "version": "2.0.1", 58 | "bundled": true 59 | }, 60 | "@cfn-modules/vpc-subnet": { 61 | "version": "2.1.0", 62 | "bundled": true 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-proxy-pattern-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Fargate ALB with proxy pattern example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ecs-cluster": "1.2.0", 12 | "@cfn-modules/alb": "1.2.0", 13 | "@cfn-modules/alb-listener": "1.4.0", 14 | "@cfn-modules/ecs-alb-target": "1.4.0", 15 | "@cfn-modules/fargate-service": "2.15.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/fargate-alb-proxy-pattern/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | const outputs = await cfntest.getStackOutputs(stackName); 9 | t.log(outputs); 10 | const res = await cfntest.probeHttpGet(outputs.Url); 11 | t.is(res.headers.server, 'Apache/2.4.23 (Unix)'); 12 | t.true('x-varnish' in res.headers); 13 | t.true(res.data.includes('It works!')); 14 | } finally { 15 | t.log(await cfntest.deleteStack(stackName)); 16 | t.pass(); 17 | } 18 | }); -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Fargate ALB service to service example 2 | 3 | This example project demonstrates how two services can communicate with each other using public and private ALBs. The following diagram illustrates the high-level architecture. 4 | 5 | ``` 6 | ┌────────────┐ 7 | │ │ 8 | │ │ 9 | │ ALB │ 10 | │ Public │ 11 | │ │ 12 | └────────────┘ 13 | │ 14 | │ 15 | ┌─Service─▼────────┐ 16 | │ ┌──────────────┐ │ 17 | │ │ │ │ 18 | │ │ │ │ 19 | │ │ app │ │ 20 | │ │ container │ │ 21 | │ │ │ │ 22 | │ │ │ │ 23 | │ └──────────────┘ │ 24 | └──────────────────┘ 25 | │ 26 | │ 27 | ┌──────▼─────┐ 28 | │ │ 29 | │ │ 30 | │ ALB │ 31 | │ Private │ 32 | │ │ 33 | └────────────┘ 34 | │ 35 | │ 36 | ┌─Service─▼────────┐ 37 | │ ┌──────────────┐ │ 38 | │ │ │ │ 39 | │ │ │ │ 40 | │ │ app │ │ 41 | │ │ container │ │ 42 | │ │ │ │ 43 | │ │ │ │ 44 | │ └──────────────┘ │ 45 | └──────────────────┘ 46 | ``` 47 | 48 | ## Prerequisites 49 | 50 | 1. [Install Node.js 10.x](https://nodejs.org/) 51 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 52 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 53 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 54 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 55 | 4. Create the bucket `aws s3 mb s3://$BucketName` 56 | 57 | ## Usage 58 | 59 | ``` 60 | npm i 61 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 62 | aws cloudformation deploy --template-file packaged.yml --stack-name fargate-alb-service-to-service-example --capabilities CAPABILITY_IAM 63 | aws cloudformation describe-stacks --stack-name fargate-alb-service-to-service-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 64 | ``` 65 | 66 | Open the URL in your web browser. 67 | 68 | Don't forget to delete the stack once you are done with the demo: 69 | 70 | ``` 71 | aws cloudformation delete-stack --stack-name fargate-alb-service-to-service-example 72 | ``` 73 | 74 | ## Modules 75 | 76 | Find all modules here: https://www.npmjs.com/org/cfn-modules 77 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Fargate ALB service to service example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | Cluster: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | TemplateURL: './node_modules/@cfn-modules/ecs-cluster/module.yml' 39 | PublicAlb: 40 | Type: 'AWS::CloudFormation::Stack' 41 | Properties: 42 | Parameters: 43 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 44 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 45 | TemplateURL: './node_modules/@cfn-modules/alb/module.yml' 46 | PublicAlbListener: 47 | Type: 'AWS::CloudFormation::Stack' 48 | Properties: 49 | Parameters: 50 | AlbModule: !GetAtt 'PublicAlb.Outputs.StackName' 51 | TemplateURL: './node_modules/@cfn-modules/alb-listener/module.yml' 52 | PublicTarget: 53 | Type: 'AWS::CloudFormation::Stack' 54 | Properties: 55 | Parameters: 56 | AlbModule: !GetAtt 'PublicAlb.Outputs.StackName' 57 | AlbListenerModule: !GetAtt 'PublicAlbListener.Outputs.StackName' 58 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 59 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 60 | TemplateURL: './node_modules/@cfn-modules/ecs-alb-target/module.yml' 61 | PublicService: 62 | Type: 'AWS::CloudFormation::Stack' 63 | Properties: 64 | Parameters: 65 | ClusterModule: !GetAtt 'Cluster.Outputs.StackName' 66 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 67 | TargetModule: !GetAtt 'PublicTarget.Outputs.StackName' 68 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 69 | ClientSgModule1: !GetAtt 'PrivateServiceClientSg.Outputs.StackName' 70 | AppImage: 'instal/nginx-proxy-pass-dockerize:1.2' 71 | AppPort: '8080' 72 | AppEnvironment1Key: 'NGINX_UPSTREAM_SERVER' 73 | AppEnvironment1Value: !Sub '${PrivateAlb.Outputs.DnsName}:80' 74 | TemplateURL: './node_modules/@cfn-modules/fargate-service/module.yml' 75 | PrivateServiceClientSg: 76 | Type: 'AWS::CloudFormation::Stack' 77 | Properties: 78 | Parameters: 79 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 80 | TemplateURL: './node_modules/@cfn-modules/client-sg/module.yml' 81 | PrivateAlb: 82 | Type: 'AWS::CloudFormation::Stack' 83 | Properties: 84 | Parameters: 85 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 86 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 87 | Scheme: internal 88 | TemplateURL: './node_modules/@cfn-modules/alb/module.yml' 89 | PrivateAlbListener: 90 | Type: 'AWS::CloudFormation::Stack' 91 | Properties: 92 | Parameters: 93 | AlbModule: !GetAtt 'PrivateAlb.Outputs.StackName' 94 | ClientSgModule: !GetAtt 'PrivateServiceClientSg.Outputs.StackName' 95 | TemplateURL: './node_modules/@cfn-modules/alb-listener/module.yml' 96 | PrivateTarget: 97 | Type: 'AWS::CloudFormation::Stack' 98 | Properties: 99 | Parameters: 100 | AlbModule: !GetAtt 'PrivateAlb.Outputs.StackName' 101 | AlbListenerModule: !GetAtt 'PrivateAlbListener.Outputs.StackName' 102 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 103 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 104 | TemplateURL: './node_modules/@cfn-modules/ecs-alb-target/module.yml' 105 | PrivateService: 106 | Type: 'AWS::CloudFormation::Stack' 107 | Properties: 108 | Parameters: 109 | ClusterModule: !GetAtt 'Cluster.Outputs.StackName' 110 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 111 | TargetModule: !GetAtt 'PrivateTarget.Outputs.StackName' 112 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 113 | AppImage: 'widdix/hello:v1' 114 | AppPort: '80' 115 | TemplateURL: './node_modules/@cfn-modules/fargate-service/module.yml' 116 | Outputs: 117 | Url: 118 | Value: !Sub 'http://${PublicAlb.Outputs.DnsName}' 119 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-service-to-service-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alb": { 8 | "version": "1.2.0", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb/-/alb-1.2.0.tgz", 10 | "integrity": "sha512-mUi0t1ryyHTk6Tr3o/cJg9XcFKCpnTcT4qyAojTC6VxEZ4QGyZzu+Q4d5NrZqr03O0LE5ybd8ORDTYmr+a4IjQ==" 11 | }, 12 | "@cfn-modules/alb-listener": { 13 | "version": "1.4.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb-listener/-/alb-listener-1.4.0.tgz", 15 | "integrity": "sha512-apjPXicmRXeufmKiCt9XqJiWeZLJ2VbbsZAzW4hub2Uy1ndE7rVi8P1Awi/JUYyS9UkGr08wzIODgviFlFgJXA==" 16 | }, 17 | "@cfn-modules/alerting": { 18 | "version": "1.2.2", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 20 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 21 | }, 22 | "@cfn-modules/client-sg": { 23 | "version": "1.0.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 25 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 26 | }, 27 | "@cfn-modules/ecs-alb-target": { 28 | "version": "1.4.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-alb-target/-/ecs-alb-target-1.4.0.tgz", 30 | "integrity": "sha512-N+NEBxt5lShLoP22QnOqIvbL0lworB5nKwbmNUNVbIDjTZ0xS/+OXkit+qNKoWEBuztj30QjK2kujJOjTCwjdg==" 31 | }, 32 | "@cfn-modules/ecs-cluster": { 33 | "version": "1.2.0", 34 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-cluster/-/ecs-cluster-1.2.0.tgz", 35 | "integrity": "sha512-ZmE/fTKFGwM+bhtuFaFsMe8Sa/FA2Wt+1v9ahwg6CYNXlEPIWobOcWPC6MLKvkMaL4mhnh7k5xF2gKd27c39PA==" 36 | }, 37 | "@cfn-modules/fargate-service": { 38 | "version": "2.15.1", 39 | "resolved": "https://registry.npmjs.org/@cfn-modules/fargate-service/-/fargate-service-2.15.1.tgz", 40 | "integrity": "sha512-c/sOiLH0qD7Ii2lSCj8+e1DAIaZKoABDJFH1BTjU/4kCgM90lPVDYZuEN03SpFOaf9iEeALS4u1bueO2f87e1A==" 41 | }, 42 | "@cfn-modules/vpc": { 43 | "version": "2.3.0", 44 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 45 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 46 | "requires": { 47 | "@cfn-modules/vpc-flow-log": "2.0.0", 48 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 49 | "@cfn-modules/vpc-plain": "2.0.1", 50 | "@cfn-modules/vpc-subnet": "2.1.0" 51 | }, 52 | "dependencies": { 53 | "@cfn-modules/vpc-flow-log": { 54 | "version": "2.0.0", 55 | "bundled": true 56 | }, 57 | "@cfn-modules/vpc-nat-gateway": { 58 | "version": "2.0.0", 59 | "bundled": true 60 | }, 61 | "@cfn-modules/vpc-plain": { 62 | "version": "2.0.1", 63 | "bundled": true 64 | }, 65 | "@cfn-modules/vpc-subnet": { 66 | "version": "2.1.0", 67 | "bundled": true 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-service-to-service-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Fargate ALB service to service example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ecs-cluster": "1.2.0", 12 | "@cfn-modules/alb": "1.2.0", 13 | "@cfn-modules/alb-listener": "1.4.0", 14 | "@cfn-modules/ecs-alb-target": "1.4.0", 15 | "@cfn-modules/fargate-service": "2.15.1", 16 | "@cfn-modules/client-sg": "1.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/fargate-alb-service-to-service/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | const outputs = await cfntest.getStackOutputs(stackName); 9 | t.log(outputs); 10 | const res = await cfntest.probeHttpGet(outputs.Url); 11 | t.is(res.headers.server, 'nginx/1.13.5'); 12 | t.true(res.data.includes('It works!')); 13 | } finally { 14 | t.log(await cfntest.deleteStack(stackName)); 15 | t.pass(); 16 | } 17 | }); -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Fargate ALB to single container example 2 | 3 | This example project demonstrates how an ALB can be placed in front of a single Docker container app running on Fargate. The following diagram illustrates the high-level architecture. 4 | 5 | ``` 6 | ┌────────────┐ 7 | │ │ 8 | │ │ 9 | │ ALB │ 10 | │ │ 11 | │ │ 12 | └────────────┘ 13 | │ 14 | │ 15 | ┌─Service─▼────────┐ 16 | │ ┌──────────────┐ │ 17 | │ │ │ │ 18 | │ │ │ │ 19 | │ │ app │ │ 20 | │ │ container │ │ 21 | │ │ │ │ 22 | │ │ │ │ 23 | │ └──────────────┘ │ 24 | └──────────────────┘ 25 | ``` 26 | 27 | ## Prerequisites 28 | 29 | 1. [Install Node.js 10.x](https://nodejs.org/) 30 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 31 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 32 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 33 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 34 | 4. Create the bucket `aws s3 mb s3://$BucketName` 35 | 36 | ## Usage 37 | 38 | ``` 39 | npm i 40 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 41 | aws cloudformation deploy --template-file packaged.yml --stack-name fargate-alb-single-container-example --capabilities CAPABILITY_IAM 42 | aws cloudformation describe-stacks --stack-name fargate-alb-single-container-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 43 | ``` 44 | 45 | Open the URL in your web browser. 46 | 47 | Don't forget to delete the stack once you are done with the demo: 48 | 49 | ``` 50 | aws cloudformation delete-stack --stack-name fargate-alb-single-container-example 51 | ``` 52 | 53 | ## Modules 54 | 55 | Find all modules here: https://www.npmjs.com/org/cfn-modules 56 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Fargate ALB to single container example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | Cluster: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | TemplateURL: './node_modules/@cfn-modules/ecs-cluster/module.yml' 39 | Alb: 40 | Type: 'AWS::CloudFormation::Stack' 41 | Properties: 42 | Parameters: 43 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 44 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 45 | TemplateURL: './node_modules/@cfn-modules/alb/module.yml' 46 | AlbListener: 47 | Type: 'AWS::CloudFormation::Stack' 48 | Properties: 49 | Parameters: 50 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 51 | TemplateURL: './node_modules/@cfn-modules/alb-listener/module.yml' 52 | Target: 53 | Type: 'AWS::CloudFormation::Stack' 54 | Properties: 55 | Parameters: 56 | AlbModule: !GetAtt 'Alb.Outputs.StackName' 57 | AlbListenerModule: !GetAtt 'AlbListener.Outputs.StackName' 58 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 59 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 60 | TemplateURL: './node_modules/@cfn-modules/ecs-alb-target/module.yml' 61 | Service: 62 | Type: 'AWS::CloudFormation::Stack' 63 | Properties: 64 | Parameters: 65 | ClusterModule: !GetAtt 'Cluster.Outputs.StackName' 66 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 67 | TargetModule: !GetAtt 'Target.Outputs.StackName' 68 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 69 | AppImage: 'widdix/hello:v1' 70 | AppPort: '80' 71 | TemplateURL: './node_modules/@cfn-modules/fargate-service/module.yml' 72 | Outputs: 73 | Url: 74 | Value: !Sub 'http://${Alb.Outputs.DnsName}' 75 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-single-container-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alb": { 8 | "version": "1.2.0", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb/-/alb-1.2.0.tgz", 10 | "integrity": "sha512-mUi0t1ryyHTk6Tr3o/cJg9XcFKCpnTcT4qyAojTC6VxEZ4QGyZzu+Q4d5NrZqr03O0LE5ybd8ORDTYmr+a4IjQ==" 11 | }, 12 | "@cfn-modules/alb-listener": { 13 | "version": "1.4.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/alb-listener/-/alb-listener-1.4.0.tgz", 15 | "integrity": "sha512-apjPXicmRXeufmKiCt9XqJiWeZLJ2VbbsZAzW4hub2Uy1ndE7rVi8P1Awi/JUYyS9UkGr08wzIODgviFlFgJXA==" 16 | }, 17 | "@cfn-modules/alerting": { 18 | "version": "1.2.2", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 20 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 21 | }, 22 | "@cfn-modules/ecs-alb-target": { 23 | "version": "1.4.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-alb-target/-/ecs-alb-target-1.4.0.tgz", 25 | "integrity": "sha512-N+NEBxt5lShLoP22QnOqIvbL0lworB5nKwbmNUNVbIDjTZ0xS/+OXkit+qNKoWEBuztj30QjK2kujJOjTCwjdg==" 26 | }, 27 | "@cfn-modules/ecs-cluster": { 28 | "version": "1.2.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/ecs-cluster/-/ecs-cluster-1.2.0.tgz", 30 | "integrity": "sha512-ZmE/fTKFGwM+bhtuFaFsMe8Sa/FA2Wt+1v9ahwg6CYNXlEPIWobOcWPC6MLKvkMaL4mhnh7k5xF2gKd27c39PA==" 31 | }, 32 | "@cfn-modules/fargate-service": { 33 | "version": "2.15.1", 34 | "resolved": "https://registry.npmjs.org/@cfn-modules/fargate-service/-/fargate-service-2.15.1.tgz", 35 | "integrity": "sha512-c/sOiLH0qD7Ii2lSCj8+e1DAIaZKoABDJFH1BTjU/4kCgM90lPVDYZuEN03SpFOaf9iEeALS4u1bueO2f87e1A==" 36 | }, 37 | "@cfn-modules/vpc": { 38 | "version": "2.3.0", 39 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 40 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 41 | "requires": { 42 | "@cfn-modules/vpc-flow-log": "2.0.0", 43 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 44 | "@cfn-modules/vpc-plain": "2.0.1", 45 | "@cfn-modules/vpc-subnet": "2.1.0" 46 | }, 47 | "dependencies": { 48 | "@cfn-modules/vpc-flow-log": { 49 | "version": "2.0.0", 50 | "bundled": true 51 | }, 52 | "@cfn-modules/vpc-nat-gateway": { 53 | "version": "2.0.0", 54 | "bundled": true 55 | }, 56 | "@cfn-modules/vpc-plain": { 57 | "version": "2.0.1", 58 | "bundled": true 59 | }, 60 | "@cfn-modules/vpc-subnet": { 61 | "version": "2.1.0", 62 | "bundled": true 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-fargate-alb-single-container-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Fargate ALB to single container example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/ecs-cluster": "1.2.0", 12 | "@cfn-modules/alb": "1.2.0", 13 | "@cfn-modules/alb-listener": "1.4.0", 14 | "@cfn-modules/ecs-alb-target": "1.4.0", 15 | "@cfn-modules/fargate-service": "2.15.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/fargate-alb-single-container/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | const outputs = await cfntest.getStackOutputs(stackName); 9 | t.log(outputs); 10 | const res = await cfntest.probeHttpGet(outputs.Url); 11 | t.is(res.headers.server, 'Apache/2.4.23 (Unix)'); 12 | t.true(res.data.includes('It works!')); 13 | } finally { 14 | t.log(await cfntest.deleteStack(stackName)); 15 | t.pass(); 16 | } 17 | }); -------------------------------------------------------------------------------- /examples/msk-cluster/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/msk-cluster/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: MSK cluster example project 2 | 3 | This example project demonstrates how an EC2 instance can communicate with an RDS MySQL database. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name msk-cluster-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name msk-cluster-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/msk-cluster/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2021 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: MSK cluster example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | # Parameters: 22 | # Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Vpc: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | S3Endpoint: 'false' # speed up the example 31 | DynamoDBEndpoint: 'false' # speed up the example 32 | FlowLog: 'false' # speed up the example 33 | NatGateways: 'false' # speed up the example 34 | TemplateURL: './node_modules/@cfn-modules/vpc/module.yml' 35 | ClientSg: 36 | Type: 'AWS::CloudFormation::Stack' 37 | Properties: 38 | Parameters: 39 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 40 | TemplateURL: './node_modules/@cfn-modules/client-sg/module.yml' 41 | Cluster: 42 | Type: 'AWS::CloudFormation::Stack' 43 | Properties: 44 | Parameters: 45 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 46 | ClientSgModule: !GetAtt 'ClientSg.Outputs.StackName' 47 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 48 | NumberOfBrokerNodes: !GetAtt 'Vpc.Outputs.NumberOfAvailabilityZones' 49 | KafkaVersion: '3.7.x' 50 | InstanceType: 'kafka.t3.small' 51 | EBSVolumeSize: '10' 52 | TemplateURL: './node_modules/@cfn-modules/msk-cluster/module.yml' 53 | InstancePolicy: 54 | Type: 'AWS::IAM::ManagedPolicy' 55 | Properties: 56 | PolicyDocument: 57 | Version: '2012-10-17' 58 | Statement: 59 | - Effect: Allow 60 | Action: 61 | - 'kafka:DescribeCluster' 62 | - 'kafka:GetBootstrapBrokers' 63 | Resource: '*' 64 | Instance: 65 | Type: 'AWS::CloudFormation::Stack' 66 | Properties: 67 | Parameters: 68 | VpcModule: !GetAtt 'Vpc.Outputs.StackName' 69 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 70 | ClientSgModule1: !GetAtt 'ClientSg.Outputs.StackName' 71 | AmazonLinux2Version: '2.0.20190508' 72 | InstanceType: 't3.small' 73 | ManagedPolicyArns: !Ref InstancePolicy 74 | TemplateURL: './node_modules/@cfn-modules/ec2-instance-amazon-linux2/module.yml' 75 | Outputs: 76 | ClusterArn: 77 | Value: !GetAtt 'Cluster.Outputs.Arn' 78 | -------------------------------------------------------------------------------- /examples/msk-cluster/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-msk-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/client-sg": { 13 | "version": "1.0.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/client-sg/-/client-sg-1.0.0.tgz", 15 | "integrity": "sha512-onauCbqqXYn/coJhdwvpcZU8XK9WZwA66AChsSQwSBBj+JLvByTXXRep7x/hWL11JQ7eIjOuDKsF8GK1D22Tjw==" 16 | }, 17 | "@cfn-modules/ec2-instance-amazon-linux2": { 18 | "version": "2.5.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/ec2-instance-amazon-linux2/-/ec2-instance-amazon-linux2-2.5.0.tgz", 20 | "integrity": "sha512-XH8ZCU+mhneW2FzKhn95ejCUOXiM7YcQhpdwOjv+hKfGX2ke8smI89kaNjA9n6JJk7ZWdiU/NNSSttzb42yhdA==" 21 | }, 22 | "@cfn-modules/msk-cluster": { 23 | "version": "1.0.1", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/msk-cluster/-/msk-cluster-1.0.1.tgz", 25 | "integrity": "sha512-ihXvga+I1MZ/N3bhwNzREuBGXMrgzZqYkxVrIrI1PTyzykjZ3pMIJADELZhoW+4wN4UYoAJy9tIpXocworAfyQ==" 26 | }, 27 | "@cfn-modules/vpc": { 28 | "version": "2.3.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/vpc/-/vpc-2.3.0.tgz", 30 | "integrity": "sha512-vdGOrOvPon0A2D1XJAFn7oB6FKO25474kAjyhMS1NGAsEXGuiXBf916kwVOvZE9aMyBPQrdzUYHZHvBPnJnpfA==", 31 | "requires": { 32 | "@cfn-modules/vpc-flow-log": "2.0.0", 33 | "@cfn-modules/vpc-nat-gateway": "2.0.0", 34 | "@cfn-modules/vpc-plain": "2.0.1", 35 | "@cfn-modules/vpc-subnet": "2.1.0" 36 | }, 37 | "dependencies": { 38 | "@cfn-modules/vpc-flow-log": { 39 | "version": "2.0.0", 40 | "bundled": true 41 | }, 42 | "@cfn-modules/vpc-nat-gateway": { 43 | "version": "2.0.0", 44 | "bundled": true 45 | }, 46 | "@cfn-modules/vpc-plain": { 47 | "version": "2.0.1", 48 | "bundled": true 49 | }, 50 | "@cfn-modules/vpc-subnet": { 51 | "version": "2.1.0", 52 | "bundled": true 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/msk-cluster/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-msk-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: MSK cluster example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/vpc": "2.3.0", 11 | "@cfn-modules/msk-cluster": "1.0.1", 12 | "@cfn-modules/client-sg": "1.0.0", 13 | "@cfn-modules/ec2-instance-amazon-linux2": "2.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/msk-cluster/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/msk-cluster/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/msk-cluster/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/msk-cluster/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/serverless-cron/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/serverless-cron/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Serverless cron example project 2 | 3 | This example project demonstrates how a Lambda function can be triggered periodically. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name serverless-cron-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name serverless-cron-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/serverless-cron/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Serverless cron example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Cron: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | LambdaModule: !GetAtt 'Function.Outputs.StackName' 30 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 31 | ScheduleExpression: 'rate(1 minute)' 32 | TemplateURL: './node_modules/@cfn-modules/lambda-event-source-cron/module.yml' 33 | Function: 34 | Type: 'AWS::CloudFormation::Stack' 35 | Properties: 36 | Parameters: 37 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 38 | Handler: 'cron.handler' 39 | Runtime: 'nodejs16.x' 40 | TemplateURL: './node_modules/@cfn-modules/lambda-function/module.yml' 41 | -------------------------------------------------------------------------------- /examples/serverless-cron/lambda-src/cron.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event, context) { 2 | console.log(JSON.stringify(event)); 3 | return true; 4 | }; 5 | -------------------------------------------------------------------------------- /examples/serverless-cron/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-cron-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/lambda-event-source-cron": { 13 | "version": "1.1.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-event-source-cron/-/lambda-event-source-cron-1.1.0.tgz", 15 | "integrity": "sha512-7x/KDC0RkD3y/0OWNtpASudFwwDHoOJtCxtEUg5c2ofY3thl7uhfFp8ixMB7mPeh7QGQkFd9lEQOZQhn4bwG2Q==" 16 | }, 17 | "@cfn-modules/lambda-function": { 18 | "version": "2.10.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-function/-/lambda-function-2.10.0.tgz", 20 | "integrity": "sha512-ilK4xZfJn71oMrAPz2BkXBMR0FhYtqqxhhve0XjkPGLGkw/gyEkbDhUxtPNa1/N18XnaUtn3s8bcdKMjJE5yaA==" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/serverless-cron/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-cron-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Serverless cron example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/lambda-function": "2.10.0", 11 | "@cfn-modules/lambda-event-source-cron": "1.1.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/serverless-cron/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/serverless-cron/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/serverless-cron/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/serverless-cron/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/serverless-iam/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/serverless-iam/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Serverless IAM example project 2 | 3 | This example project demonstrates how IAM policies for Lambda functions are automatically created when `cfn-modules` are combined. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name serverless-iam-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Checkout the IAM role attached to the Lambda function (Get the role name with `aws cloudformation describe-stacks --stack-name serverless-iam-example --query "Stacks[0].Outputs[?OutputKey=='RoleName'].OutputValue" --output text`). The Lambda function is allowed to talk to the SQS queue, DynamoDB table, and S3 bucket because of the `DependencyModule1`, `DependencyModule2`, and `DependencyModule3` parameter. The generated policy looks like this: 23 | 24 | ``` 25 | { 26 | "Statement": [ 27 | { 28 | "Action": [ 29 | "logs:CreateLogStream", 30 | "logs:PutLogEvents" 31 | ], 32 | "Resource": "arn:aws:logs:u-west-1:***:log-group:serverless-iam-example-LogGroup-YLDPFNGG00XX:*", 33 | "Effect": "Allow" 34 | }, 35 | { 36 | "Action": [ 37 | "sqs:ChangeMessageVisibility*", 38 | "sqs:DeleteMessage*", 39 | "sqs:ReceiveMessage", 40 | "sqs:SendMessage*" 41 | ], 42 | "Resource": [ 43 | "arn:aws:sqs:eu-west-1:***:serverless-iam-example-Queue-1KUL6CHQ72L11-Queue-YLDPFNGG00JJ" 44 | ], 45 | "Effect": "Allow" 46 | }, 47 | { 48 | "Action": [ 49 | "dynamodb:Batch*Item", 50 | "dynamodb:DeleteItem", 51 | "dynamodb:GetItem", 52 | "dynamodb:PutItem" 53 | ], 54 | "Resource": [ 55 | "arn:aws:dynamodb:eu-west-1:***:table/serverless-iam-example-Table-1ES8PX0YZ1UE1-Table-OFBM6RPW27KD" 56 | ], 57 | "Effect": "Allow" 58 | }, 59 | { 60 | "Action": [ 61 | "s3:DeleteObject*", 62 | "s3:GetObject*", 63 | "s3:ListBucket*", 64 | "s3:ListMultipartUploadParts", 65 | "s3:PutObject*" 66 | ], 67 | "Resource": [ 68 | "arn:aws:s3:::serverless-iam-example-bucket-1pwiud7lmras-bucket-191m2vgi3rwz2", 69 | "arn:aws:s3:::serverless-iam-example-bucket-1pwiud7lmras-bucket-191m2vgi3rwz2/*" 70 | ], 71 | "Effect": "Allow" 72 | } 73 | ] 74 | } 75 | ``` 76 | 77 | Don't forget to delete the stack once you are done with the demo: 78 | 79 | ``` 80 | aws cloudformation delete-stack --stack-name serverless-iam-example 81 | ``` 82 | 83 | ## Modules 84 | 85 | Find all modules here: https://www.npmjs.com/org/cfn-modules 86 | -------------------------------------------------------------------------------- /examples/serverless-iam/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Serverless IAM example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Queue: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | DelaySeconds: '60' 31 | TemplateURL: './node_modules/@cfn-modules/sqs-queue/module.yml' 32 | Table: 33 | Type: 'AWS::CloudFormation::Stack' 34 | Properties: 35 | Parameters: 36 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 37 | TemplateURL: './node_modules/@cfn-modules/dynamodb-table/module.yml' 38 | Bucket: 39 | Type: 'AWS::CloudFormation::Stack' 40 | Properties: 41 | Parameters: 42 | Versioning: 'false' 43 | TemplateURL: './node_modules/@cfn-modules/s3-bucket/module.yml' 44 | Function: 45 | Type: 'AWS::CloudFormation::Stack' 46 | Properties: 47 | Parameters: 48 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 49 | Handler: 'example.handler' 50 | Runtime: 'nodejs16.x' 51 | DependencyModule1: !GetAtt 'Queue.Outputs.StackName' 52 | DependencyModule2: !GetAtt 'Table.Outputs.StackName' 53 | DependencyModule3: !GetAtt 'Bucket.Outputs.StackName' 54 | TemplateURL: './node_modules/@cfn-modules/lambda-function/module.yml' 55 | Outputs: 56 | RoleName: 57 | Value: !GetAtt 'Function.Outputs.RoleName' 58 | -------------------------------------------------------------------------------- /examples/serverless-iam/lambda-src/example.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event, context) { 2 | console.log(JSON.stringify(event)); 3 | //TODO use DependencyModule1 (SQS queue), DependencyModule2 (DynamoDB table), and DependencyModule3 4 | return { 5 | Dependency1: process.env.DEPENDENCY1_ARN, 6 | Dependency2: process.env.DEPENDENCY2_ARN, 7 | Dependency3: process.env.DEPENDENCY3_ARN 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /examples/serverless-iam/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-iam-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/dynamodb-table": { 13 | "version": "1.6.1", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/dynamodb-table/-/dynamodb-table-1.6.1.tgz", 15 | "integrity": "sha512-DaBZ+JMIkLi8nXOdy5chwqNl19IA/9prH04Uy9XaRxyKe42xoVhHii72Pe+Ab5gCBJH7A2XhBFz1cxAfwyO2Ew==" 16 | }, 17 | "@cfn-modules/lambda-function": { 18 | "version": "2.10.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-function/-/lambda-function-2.10.0.tgz", 20 | "integrity": "sha512-ilK4xZfJn71oMrAPz2BkXBMR0FhYtqqxhhve0XjkPGLGkw/gyEkbDhUxtPNa1/N18XnaUtn3s8bcdKMjJE5yaA==" 21 | }, 22 | "@cfn-modules/s3-bucket": { 23 | "version": "1.8.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/s3-bucket/-/s3-bucket-1.8.0.tgz", 25 | "integrity": "sha512-VcENP/dwUhc3PdL8AfFyvP32oThSkpd4t+cnJBTW8wC14jQNnjhD2/C2ZZNTPweg19aCjnA+SY5Ho3Z7kYS51g==" 26 | }, 27 | "@cfn-modules/sqs-queue": { 28 | "version": "1.2.0", 29 | "resolved": "https://registry.npmjs.org/@cfn-modules/sqs-queue/-/sqs-queue-1.2.0.tgz", 30 | "integrity": "sha512-6PbaEzQcP6Ye896UHFAVO4n39yisHruiUR3cr6aYpUnc6ihBMYlX/UVC1VcvpuhSZxz+YnkjArC8x/ouqm3YoA==" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/serverless-iam/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-iam-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Serverless IAM example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/dynamodb-table": "1.6.1", 11 | "@cfn-modules/lambda-function": "2.10.0", 12 | "@cfn-modules/sqs-queue": "1.2.0", 13 | "@cfn-modules/s3-bucket": "1.8.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/serverless-iam/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/serverless-iam/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/serverless-iam/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/serverless-iam/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/serverless-image-resize/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Serverless image resize example project 2 | 3 | This example project demonstrates how a Lambda function can resize a image uploaded to an S3 bucket automatically. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name serverless-image-resize-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name serverless-image-resize-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Serverless image resize example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | BucketRaw: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | Versioning: 'false' 30 | LambdaEventTargetLambdaModule1: !GetAtt 'FunctionResize.Outputs.StackName' 31 | TemplateURL: './node_modules/@cfn-modules/s3-bucket/module.yml' 32 | BucketResized: 33 | Type: 'AWS::CloudFormation::Stack' 34 | Properties: 35 | Parameters: 36 | Versioning: 'false' 37 | TemplateURL: './node_modules/@cfn-modules/s3-bucket/module.yml' 38 | FunctionResize: 39 | Type: 'AWS::CloudFormation::Stack' 40 | Properties: 41 | Parameters: 42 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 43 | Handler: 'resize.handler' 44 | Runtime: 'nodejs16.x' 45 | DependencyModule1: !GetAtt 'BucketResized.Outputs.StackName' 46 | TemplateURL: './node_modules/@cfn-modules/lambda-function/module.yml' 47 | Outputs: 48 | BucketNameRaw: 49 | Value: !GetAtt 'BucketRaw.Outputs.Name' 50 | BucketNameResized: 51 | Value: !GetAtt 'BucketResized.Outputs.Name' 52 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/lambda-src/resize.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event, context) { 2 | console.log(JSON.stringify(event)); 3 | // TODO implement resize 4 | return true; 5 | }; 6 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-image-resize-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/lambda-function": { 13 | "version": "2.10.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-function/-/lambda-function-2.10.0.tgz", 15 | "integrity": "sha512-ilK4xZfJn71oMrAPz2BkXBMR0FhYtqqxhhve0XjkPGLGkw/gyEkbDhUxtPNa1/N18XnaUtn3s8bcdKMjJE5yaA==" 16 | }, 17 | "@cfn-modules/s3-bucket": { 18 | "version": "1.8.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/s3-bucket/-/s3-bucket-1.8.0.tgz", 20 | "integrity": "sha512-VcENP/dwUhc3PdL8AfFyvP32oThSkpd4t+cnJBTW8wC14jQNnjhD2/C2ZZNTPweg19aCjnA+SY5Ho3Z7kYS51g==" 21 | }, 22 | "@cfn-modules/sqs-queue": { 23 | "version": "1.2.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/sqs-queue/-/sqs-queue-1.2.0.tgz", 25 | "integrity": "sha512-6PbaEzQcP6Ye896UHFAVO4n39yisHruiUR3cr6aYpUnc6ihBMYlX/UVC1VcvpuhSZxz+YnkjArC8x/ouqm3YoA==" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-image-resize-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Serverless image resize example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/lambda-function": "2.10.0", 11 | "@cfn-modules/s3-bucket": "1.8.0", 12 | "@cfn-modules/sqs-queue": "1.2.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/serverless-image-resize/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/serverless-image-resize/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Serverless SQS queue example project 2 | 3 | This example project demonstrates how a Lambda function can be triggered by a SQS queue. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name serverless-sqs-queue-example --capabilities CAPABILITY_IAM 20 | ``` 21 | 22 | Don't forget to delete the stack once you are done with the demo: 23 | 24 | ``` 25 | aws cloudformation delete-stack --stack-name serverless-sqs-queue-example 26 | ``` 27 | 28 | ## Modules 29 | 30 | Find all modules here: https://www.npmjs.com/org/cfn-modules 31 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Serverless SQS queue example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Queue: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 30 | TemplateURL: './node_modules/@cfn-modules/sqs-queue/module.yml' 31 | QueueEventSource: 32 | Type: 'AWS::CloudFormation::Stack' 33 | Properties: 34 | Parameters: 35 | LambdaModule: !GetAtt 'Function.Outputs.StackName' 36 | QueueModule: !GetAtt 'Queue.Outputs.StackName' 37 | TemplateURL: './node_modules/@cfn-modules/lambda-event-source-sqs-queue/module.yml' 38 | Function: 39 | Type: 'AWS::CloudFormation::Stack' 40 | Properties: 41 | Parameters: 42 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 43 | Handler: 'example.handler' 44 | Runtime: 'nodejs16.x' 45 | ReservedConcurrentExecutions: '5' 46 | TemplateURL: './node_modules/@cfn-modules/lambda-function/module.yml' 47 | Outputs: 48 | QueueName: 49 | Value: !GetAtt 'Queue.Outputs.Name' 50 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/lambda-src/example.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event, context) { 2 | console.log(JSON.stringify(event)); 3 | return true; 4 | }; 5 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-sqs-queue", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/lambda-event-source-sqs-queue": { 13 | "version": "1.0.0", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-event-source-sqs-queue/-/lambda-event-source-sqs-queue-1.0.0.tgz", 15 | "integrity": "sha512-yg5Vtv+iA8JpgLGkSAagCXbV9vkc+nA7ehcX0TCvCXP4LOswq0wRJJf4r+JUS200a3DlwNQQbf+wVHxCrTlxOQ==" 16 | }, 17 | "@cfn-modules/lambda-function": { 18 | "version": "2.10.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-function/-/lambda-function-2.10.0.tgz", 20 | "integrity": "sha512-ilK4xZfJn71oMrAPz2BkXBMR0FhYtqqxhhve0XjkPGLGkw/gyEkbDhUxtPNa1/N18XnaUtn3s8bcdKMjJE5yaA==" 21 | }, 22 | "@cfn-modules/sqs-queue": { 23 | "version": "1.2.0", 24 | "resolved": "https://registry.npmjs.org/@cfn-modules/sqs-queue/-/sqs-queue-1.2.0.tgz", 25 | "integrity": "sha512-6PbaEzQcP6Ye896UHFAVO4n39yisHruiUR3cr6aYpUnc6ihBMYlX/UVC1VcvpuhSZxz+YnkjArC8x/ouqm3YoA==" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-sqs-queue", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Serverless SQS queue example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/lambda-function": "2.10.0", 11 | "@cfn-modules/sqs-queue": "1.2.0", 12 | "@cfn-modules/lambda-event-source-sqs-queue": "1.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/serverless-sqs-queue/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /examples/serverless-webhook/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | packaged.yml 3 | -------------------------------------------------------------------------------- /examples/serverless-webhook/README.md: -------------------------------------------------------------------------------- 1 | # cfn-modules: Serverless webhook example project 2 | 3 | This example project demonstrates how a Lambda function can be triggered periodically. 4 | 5 | ## Prerequisites 6 | 7 | 1. [Install Node.js 10.x](https://nodejs.org/) 8 | 2. Create an S3 bucket where [aws cloudformation package](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/package.html) uploads the artifacts. 9 | 1. Choose a unique bucket name, e.g. `BucketName=cfn-modules-$Name-$Region` 10 | 2. Replace `$Name` with a unique name (e.g. your initials or company name) 11 | 3. Replace `$Region` with your AWS default region (e.g. `us-east-1`) 12 | 4. Create the bucket `aws s3 mb s3://$BucketName` 13 | 14 | ## Usage 15 | 16 | ``` 17 | npm i 18 | aws cloudformation package --template-file example.yml --s3-bucket $BucketName --output-template-file packaged.yml 19 | aws cloudformation deploy --template-file packaged.yml --stack-name serverless-webhook-example --capabilities CAPABILITY_IAM 20 | aws cloudformation describe-stacks --stack-name serverless-webhook-example --query "Stacks[0].Outputs[?OutputKey=='Url'].OutputValue" --output text 21 | ``` 22 | 23 | Open the URL in your web browser and you will see the string cfn-modules. 24 | 25 | Don't forget to delete the stack once you are done with the demo: 26 | 27 | ``` 28 | aws cloudformation delete-stack --stack-name serverless-webhook-example 29 | ``` 30 | 31 | ## Modules 32 | 33 | Find all modules here: https://www.npmjs.com/org/cfn-modules 34 | -------------------------------------------------------------------------------- /examples/serverless-webhook/example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright 2018 widdix GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | AWSTemplateFormatVersion: '2010-09-09' 16 | Description: 'cfn-modules: Serverless webhook example' 17 | Resources: 18 | Alerting: 19 | Type: 'AWS::CloudFormation::Stack' 20 | Properties: 21 | Parameters: 22 | Email: 'email@domain.com' # replace with your email address to receive alerts 23 | # HttpsEndpoint: 'https://api.marbot.io/v1/endpoint/xyz' # or uncommnet and receive alerts in Slack or Microsoft Teams using marbot.io 24 | TemplateURL: './node_modules/@cfn-modules/alerting/module.yml' 25 | Webhook: 26 | Type: 'AWS::CloudFormation::Stack' 27 | Properties: 28 | Parameters: 29 | LambdaModule: !GetAtt 'Function.Outputs.StackName' 30 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 31 | TemplateURL: './node_modules/@cfn-modules/lambda-event-source-webhook/module.yml' 32 | Function: 33 | Type: 'AWS::CloudFormation::Stack' 34 | Properties: 35 | Parameters: 36 | AlertingModule: !GetAtt 'Alerting.Outputs.StackName' 37 | Handler: 'webhook.handler' 38 | Runtime: 'nodejs16.x' 39 | TemplateURL: './node_modules/@cfn-modules/lambda-function/module.yml' 40 | Outputs: 41 | Url: 42 | Value: !GetAtt 'Webhook.Outputs.Url' 43 | -------------------------------------------------------------------------------- /examples/serverless-webhook/lambda-src/webhook.js: -------------------------------------------------------------------------------- 1 | exports.handler = async function(event, context) { 2 | console.log(JSON.stringify(event)); 3 | return {statusCode: 200, headers: {'Content-Type': 'text/plain'}, body: 'cfn-modules'}; 4 | }; 5 | -------------------------------------------------------------------------------- /examples/serverless-webhook/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-webhook-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@cfn-modules/alerting": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/@cfn-modules/alerting/-/alerting-1.2.2.tgz", 10 | "integrity": "sha512-IcATzZdaYtjuiwuxFG0hNoTXn33T5Zkgf6P97P8LW59dgYTbmcuT4Vo5xgTnyPGrcbB+V0eHFpFtpiT1JDhU5w==" 11 | }, 12 | "@cfn-modules/lambda-event-source-webhook": { 13 | "version": "2.0.1", 14 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-event-source-webhook/-/lambda-event-source-webhook-2.0.1.tgz", 15 | "integrity": "sha512-tXlmpC6Ifh7qj8BwGCblTOiq5GyAt/JDejnj+dKdn5hLtwDDwRCfTChYrVAfEkoKpq9twFBAbJrUUBZK/h6Ymg==" 16 | }, 17 | "@cfn-modules/lambda-function": { 18 | "version": "2.10.0", 19 | "resolved": "https://registry.npmjs.org/@cfn-modules/lambda-function/-/lambda-function-2.10.0.tgz", 20 | "integrity": "sha512-ilK4xZfJn71oMrAPz2BkXBMR0FhYtqqxhhve0XjkPGLGkw/gyEkbDhUxtPNa1/N18XnaUtn3s8bcdKMjJE5yaA==" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/serverless-webhook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cfn-modules-serverless-webhook-example", 3 | "version": "1.0.0", 4 | "description": "cfn-modules: Serverless webhook example", 5 | "author": "Michael Wittig ", 6 | "license": "Apache-2.0", 7 | "private": true, 8 | "dependencies": { 9 | "@cfn-modules/alerting": "1.2.2", 10 | "@cfn-modules/lambda-function": "2.10.0", 11 | "@cfn-modules/lambda-event-source-webhook": "2.0.1" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/serverless-webhook/test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | ecmaVersion: 2017 7 | rules: 8 | no-console: 0 9 | indent: 10 | - error 11 | - 2 12 | linebreak-style: 13 | - error 14 | - unix 15 | quotes: 16 | - error 17 | - single 18 | semi: 19 | - error 20 | - always 21 | -------------------------------------------------------------------------------- /examples/serverless-webhook/test/eslint.config.cjs: -------------------------------------------------------------------------------- 1 | const globals = require('globals'); 2 | 3 | module.exports = [{ 4 | languageOptions: { 5 | globals: globals.node, 6 | ecmaVersion: 2017, 7 | sourceType: 'commonjs', 8 | }, 9 | 10 | rules: { 11 | indent: ['error', 2], 12 | 'linebreak-style': ['error', 'unix'], 13 | quotes: ['error', 'single'], 14 | semi: ['error', 'always'], 15 | }, 16 | }]; -------------------------------------------------------------------------------- /examples/serverless-webhook/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "eslint": "9.20.1", 5 | "ava": "6.2.0", 6 | "@cfn-modules/test": "0.9.1" 7 | }, 8 | "scripts": { 9 | "test": "eslint . && ava -c 4 *.js" 10 | }, 11 | "ava": { 12 | "files": [ 13 | "*.js" 14 | ], 15 | "concurrency": 4, 16 | "timeout": "2h" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/serverless-webhook/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava'); 2 | const cfntest = require('@cfn-modules/test'); 3 | 4 | test.serial('example', async t => { 5 | const stackName = cfntest.stackName(); 6 | try { 7 | t.log(await cfntest.createStack(`${__dirname}/../example.yml`, stackName, {})); 8 | // what could we test here? 9 | } finally { 10 | t.log(await cfntest.deleteStack(stackName)); 11 | t.pass(); 12 | } 13 | }); -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfn-modules/docs/40beb598eae87640d45e6facd2b073543941946d/icon.png -------------------------------------------------------------------------------- /logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfn-modules/docs/40beb598eae87640d45e6facd2b073543941946d/logo-transparent.png -------------------------------------------------------------------------------- /logo.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfn-modules/docs/40beb598eae87640d45e6facd2b073543941946d/logo.afdesign -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cfn-modules/docs/40beb598eae87640d45e6facd2b073543941946d/logo.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /test/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "test": "./test.sh" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | for example in ../examples/*; do 6 | ( 7 | echo "$example" 8 | cd $example 9 | if [ -d "test" ]; then 10 | npm ci 11 | cd test/ 12 | npm ci 13 | CFN_PACKAGE_BUCKET_NAME=cf-templates-1a2zmgbg9ut4o-eu-west-1 npm test 14 | fi 15 | ) 16 | done 17 | --------------------------------------------------------------------------------