├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── atmConsumer └── handler.js ├── atmProducer ├── events.js ├── handler.js ├── localTest.js ├── package-lock.json └── package.json └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/osx,node,linux,windows 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | ### Node ### 20 | # Logs 21 | logs 22 | *.log 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # Runtime data 28 | pids 29 | *.pid 30 | *.seed 31 | *.pid.lock 32 | 33 | # Directory for instrumented libs generated by jscoverage/JSCover 34 | lib-cov 35 | 36 | # Coverage directory used by tools like istanbul 37 | coverage 38 | 39 | # nyc test coverage 40 | .nyc_output 41 | 42 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | bower_components 47 | 48 | # node-waf configuration 49 | .lock-wscript 50 | 51 | # Compiled binary addons (http://nodejs.org/api/addons.html) 52 | build/Release 53 | 54 | # Dependency directories 55 | node_modules/ 56 | jspm_packages/ 57 | 58 | # Typescript v1 declaration files 59 | typings/ 60 | 61 | # Optional npm cache directory 62 | .npm 63 | 64 | # Optional eslint cache 65 | .eslintcache 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | 79 | 80 | ### OSX ### 81 | *.DS_Store 82 | .AppleDouble 83 | .LSOverride 84 | 85 | # Icon must end with two \r 86 | Icon 87 | 88 | # Thumbnails 89 | ._* 90 | 91 | # Files that might appear in the root of a volume 92 | .DocumentRevisions-V100 93 | .fseventsd 94 | .Spotlight-V100 95 | .TemporaryItems 96 | .Trashes 97 | .VolumeIcon.icns 98 | .com.apple.timemachine.donotpresent 99 | 100 | # Directories potentially created on remote AFP share 101 | .AppleDB 102 | .AppleDesktop 103 | Network Trash Folder 104 | Temporary Items 105 | .apdisk 106 | 107 | ### Windows ### 108 | # Windows thumbnail cache files 109 | Thumbs.db 110 | ehthumbs.db 111 | ehthumbs_vista.db 112 | 113 | # Folder config file 114 | Desktop.ini 115 | 116 | # Recycle Bin used on file shares 117 | $RECYCLE.BIN/ 118 | 119 | # Windows Installer files 120 | *.cab 121 | *.msi 122 | *.msm 123 | *.msp 124 | 125 | # Windows shortcuts 126 | *.lnk 127 | packaged.yaml 128 | .aws-sam 129 | samconfig.toml 130 | 131 | # End of https://www.gitignore.io/api/osx,node,linux,windows -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amazon EventBridge - Producer/Consumer example 2 | 3 | This example application creates two AWS Lambda functions - a producer and a consumer. The SAM template deploys these functions, together with an EventBridge rule that determines which events are routed to the consumer. 4 | 5 | The example shows how an ATM application at a bank could generate events, and the rule only passes 'approved' transactions to an event consuming application. 6 | 7 | Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. 8 | 9 | For more blogs and examples, visit [Serverless Land](https://serverlessland.com/). 10 | 11 | ```bash 12 | . 13 | ├── README.MD <-- This instructions file 14 | ├── atmProducer <-- Source code for a lambda function 15 | │ └── handler.js <-- Main Lambda handler 16 | │ └── events.js <-- Events 17 | │ └── localTest.js <-- Wrapper for local testing 18 | │ └── package.json <-- NodeJS dependencies and scripts 19 | ├── atmConsumer <-- Source code for a lambda function 20 | │ └── handler.js <-- Main Lambda handler 21 | ├── template.yaml <-- SAM template 22 | ``` 23 | 24 | ## Requirements 25 | 26 | * AWS CLI already configured with Administrator permission 27 | * AWS SAM CLI [latest version](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) 28 | * [NodeJS 18.x installed](https://nodejs.org/en/download/) 29 | 30 | ## Installation Instructions 31 | 32 | 1. [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and login. 33 | 34 | 1. [Install Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [install the AWS Serverless Application Model CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) on your local machine. 35 | 36 | 1. Create a new directory, navigate to that directory in a terminal and enter ```https://github.com/aws-samples/amazon-eventbridge-producer-consumer-example```. 37 | 38 | 1. From the command line, run: 39 | ``` 40 | cd ./amazon-eventbridge-producer-consumer-example 41 | sam deploy --guided 42 | ``` 43 | Choose a stack name, select the desired AWS Region, and allow SAM to create roles with the required permissions. Once you have run guided mode once, you can use `sam deploy` in future to use these defaults. 44 | 45 | ## How it works 46 | 47 | * Use the AWS CLI or AWS Lambda Console to invoke the Producer function. This places the events in `events.js` onto the default event bus in EventBridge. 48 | * The EventBridge rule specified in `template.yaml` filters the events based upon the criteria in the `EventPattern` section. 49 | * When the rule validates an event, it is routed to the Consumer function. This logs out the event, which you can see in CloudWatch Logs. 50 | 51 | ============================================== 52 | 53 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 54 | 55 | SPDX-License-Identifier: MIT-0 56 | -------------------------------------------------------------------------------- /atmConsumer/handler.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 9 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 10 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 11 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 12 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 13 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | */ 15 | 16 | // The consuming service (target) Lambda functions 17 | 18 | exports.case1Handler = async (event) => { 19 | console.log('--- Approved transactions ---') 20 | console.log(JSON.stringify(event, null, 2)) 21 | } 22 | 23 | exports.case2Handler = async (event) => { 24 | console.log('--- NY location transactions ---') 25 | console.log(JSON.stringify(event, null, 2)) 26 | } 27 | 28 | exports.case3Handler = async (event) => { 29 | console.log('--- Unapproved transactions ---') 30 | console.log(JSON.stringify(event, null, 2)) 31 | } 32 | -------------------------------------------------------------------------------- /atmProducer/events.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 9 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 10 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 11 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 12 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 13 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | */ 15 | 16 | // You can send up to 10 events to Amazon EventBridge simulataneously. 17 | 18 | module.exports.params = { 19 | Entries: [ 20 | { 21 | // Event envelope fields 22 | Source: 'custom.myATMapp', 23 | EventBusName: 'default', 24 | DetailType: 'transaction', 25 | Time: new Date(), 26 | 27 | // Main event body 28 | Detail: JSON.stringify({ 29 | action: 'withdrawal', 30 | location: 'MA-BOS-01', 31 | amount: 300, 32 | result: 'approved', 33 | transactionId: '123456', 34 | cardPresent: true, 35 | partnerBank: 'Example Bank', 36 | remainingFunds: 722.34 37 | }) 38 | }, 39 | { 40 | // Event envelope fields 41 | Source: 'custom.myATMapp', 42 | EventBusName: 'default', 43 | DetailType: 'transaction', 44 | Time: new Date(), 45 | 46 | // Main event body 47 | Detail: JSON.stringify({ 48 | action: 'withdrawal', 49 | location: 'NY-NYC-001', 50 | amount: 20, 51 | result: 'approved', 52 | transactionId: '123457', 53 | cardPresent: true, 54 | partnerBank: 'Example Bank', 55 | remainingFunds: 212.52 56 | }) 57 | }, 58 | { 59 | // Event envelope fields 60 | Source: 'custom.myATMapp', 61 | EventBusName: 'default', 62 | DetailType: 'transaction', 63 | Time: new Date(), 64 | 65 | // Main event body 66 | Detail: JSON.stringify({ 67 | action: 'withdrawal', 68 | location: 'NY-NYC-002', 69 | amount: 60, 70 | result: 'denied', 71 | transactionId: '123458', 72 | cardPresent: true, 73 | remainingFunds: 5.77 74 | }) 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /atmProducer/handler.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 9 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 10 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 11 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 12 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 13 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | */ 15 | 16 | const AWS = require('aws-sdk') 17 | AWS.config.region = process.env.AWS_REGION || 'us-east-1' 18 | const eventbridge = new AWS.EventBridge() 19 | 20 | exports.lambdaHandler = async (event, context) => { 21 | // Do some work... 22 | // And now create the event... 23 | 24 | const { params } = require('./events.js') 25 | 26 | console.log('--- Params ---') 27 | console.log(params) 28 | const result = await eventbridge.putEvents(params).promise() 29 | 30 | console.log('--- Response ---') 31 | console.log(result) 32 | } 33 | -------------------------------------------------------------------------------- /atmProducer/localTest.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | software and associated documentation files (the "Software"), to deal in the Software 5 | without restriction, including without limitation the rights to use, copy, modify, 6 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so. 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 9 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 10 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 11 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 12 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 13 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | */ 15 | 16 | // A simple wrapper for running the Lambda handler locally. 17 | 18 | const main = async function() { 19 | await require('./handler').lambdaHandler() 20 | } 21 | main() 22 | -------------------------------------------------------------------------------- /atmProducer/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "producer", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "producer", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "aws-sdk": "^2.716.0" 13 | } 14 | }, 15 | "node_modules/available-typed-arrays": { 16 | "version": "1.0.5", 17 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", 18 | "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", 19 | "engines": { 20 | "node": ">= 0.4" 21 | }, 22 | "funding": { 23 | "url": "https://github.com/sponsors/ljharb" 24 | } 25 | }, 26 | "node_modules/aws-sdk": { 27 | "version": "2.1518.0", 28 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1518.0.tgz", 29 | "integrity": "sha512-SknaBH0kvDNsdjGyt8wsAfVky688azgEoLKlPqnLWiA/tJPIpdZ3qUfSFXLO6O9s2aolM8JVAULRSEgBMy57iw==", 30 | "dependencies": { 31 | "buffer": "4.9.2", 32 | "events": "1.1.1", 33 | "ieee754": "1.1.13", 34 | "jmespath": "0.16.0", 35 | "querystring": "0.2.0", 36 | "sax": "1.2.1", 37 | "url": "0.10.3", 38 | "util": "^0.12.4", 39 | "uuid": "8.0.0", 40 | "xml2js": "0.5.0" 41 | }, 42 | "engines": { 43 | "node": ">= 10.0.0" 44 | } 45 | }, 46 | "node_modules/base64-js": { 47 | "version": "1.5.1", 48 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 49 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 50 | "funding": [ 51 | { 52 | "type": "github", 53 | "url": "https://github.com/sponsors/feross" 54 | }, 55 | { 56 | "type": "patreon", 57 | "url": "https://www.patreon.com/feross" 58 | }, 59 | { 60 | "type": "consulting", 61 | "url": "https://feross.org/support" 62 | } 63 | ] 64 | }, 65 | "node_modules/buffer": { 66 | "version": "4.9.2", 67 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 68 | "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", 69 | "dependencies": { 70 | "base64-js": "^1.0.2", 71 | "ieee754": "^1.1.4", 72 | "isarray": "^1.0.0" 73 | } 74 | }, 75 | "node_modules/call-bind": { 76 | "version": "1.0.5", 77 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", 78 | "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", 79 | "dependencies": { 80 | "function-bind": "^1.1.2", 81 | "get-intrinsic": "^1.2.1", 82 | "set-function-length": "^1.1.1" 83 | }, 84 | "funding": { 85 | "url": "https://github.com/sponsors/ljharb" 86 | } 87 | }, 88 | "node_modules/define-data-property": { 89 | "version": "1.1.1", 90 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", 91 | "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", 92 | "dependencies": { 93 | "get-intrinsic": "^1.2.1", 94 | "gopd": "^1.0.1", 95 | "has-property-descriptors": "^1.0.0" 96 | }, 97 | "engines": { 98 | "node": ">= 0.4" 99 | } 100 | }, 101 | "node_modules/events": { 102 | "version": "1.1.1", 103 | "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", 104 | "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", 105 | "engines": { 106 | "node": ">=0.4.x" 107 | } 108 | }, 109 | "node_modules/for-each": { 110 | "version": "0.3.3", 111 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 112 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 113 | "dependencies": { 114 | "is-callable": "^1.1.3" 115 | } 116 | }, 117 | "node_modules/function-bind": { 118 | "version": "1.1.2", 119 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 120 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 121 | "funding": { 122 | "url": "https://github.com/sponsors/ljharb" 123 | } 124 | }, 125 | "node_modules/get-intrinsic": { 126 | "version": "1.2.2", 127 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", 128 | "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", 129 | "dependencies": { 130 | "function-bind": "^1.1.2", 131 | "has-proto": "^1.0.1", 132 | "has-symbols": "^1.0.3", 133 | "hasown": "^2.0.0" 134 | }, 135 | "funding": { 136 | "url": "https://github.com/sponsors/ljharb" 137 | } 138 | }, 139 | "node_modules/gopd": { 140 | "version": "1.0.1", 141 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 142 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 143 | "dependencies": { 144 | "get-intrinsic": "^1.1.3" 145 | }, 146 | "funding": { 147 | "url": "https://github.com/sponsors/ljharb" 148 | } 149 | }, 150 | "node_modules/has-property-descriptors": { 151 | "version": "1.0.1", 152 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", 153 | "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", 154 | "dependencies": { 155 | "get-intrinsic": "^1.2.2" 156 | }, 157 | "funding": { 158 | "url": "https://github.com/sponsors/ljharb" 159 | } 160 | }, 161 | "node_modules/has-proto": { 162 | "version": "1.0.1", 163 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 164 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 165 | "engines": { 166 | "node": ">= 0.4" 167 | }, 168 | "funding": { 169 | "url": "https://github.com/sponsors/ljharb" 170 | } 171 | }, 172 | "node_modules/has-symbols": { 173 | "version": "1.0.3", 174 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 175 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 176 | "engines": { 177 | "node": ">= 0.4" 178 | }, 179 | "funding": { 180 | "url": "https://github.com/sponsors/ljharb" 181 | } 182 | }, 183 | "node_modules/has-tostringtag": { 184 | "version": "1.0.0", 185 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", 186 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", 187 | "dependencies": { 188 | "has-symbols": "^1.0.2" 189 | }, 190 | "engines": { 191 | "node": ">= 0.4" 192 | }, 193 | "funding": { 194 | "url": "https://github.com/sponsors/ljharb" 195 | } 196 | }, 197 | "node_modules/hasown": { 198 | "version": "2.0.0", 199 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", 200 | "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", 201 | "dependencies": { 202 | "function-bind": "^1.1.2" 203 | }, 204 | "engines": { 205 | "node": ">= 0.4" 206 | } 207 | }, 208 | "node_modules/ieee754": { 209 | "version": "1.1.13", 210 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 211 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 212 | }, 213 | "node_modules/inherits": { 214 | "version": "2.0.4", 215 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 216 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 217 | }, 218 | "node_modules/is-arguments": { 219 | "version": "1.1.1", 220 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", 221 | "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", 222 | "dependencies": { 223 | "call-bind": "^1.0.2", 224 | "has-tostringtag": "^1.0.0" 225 | }, 226 | "engines": { 227 | "node": ">= 0.4" 228 | }, 229 | "funding": { 230 | "url": "https://github.com/sponsors/ljharb" 231 | } 232 | }, 233 | "node_modules/is-callable": { 234 | "version": "1.2.7", 235 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 236 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 237 | "engines": { 238 | "node": ">= 0.4" 239 | }, 240 | "funding": { 241 | "url": "https://github.com/sponsors/ljharb" 242 | } 243 | }, 244 | "node_modules/is-generator-function": { 245 | "version": "1.0.10", 246 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", 247 | "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", 248 | "dependencies": { 249 | "has-tostringtag": "^1.0.0" 250 | }, 251 | "engines": { 252 | "node": ">= 0.4" 253 | }, 254 | "funding": { 255 | "url": "https://github.com/sponsors/ljharb" 256 | } 257 | }, 258 | "node_modules/is-typed-array": { 259 | "version": "1.1.12", 260 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", 261 | "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", 262 | "dependencies": { 263 | "which-typed-array": "^1.1.11" 264 | }, 265 | "engines": { 266 | "node": ">= 0.4" 267 | }, 268 | "funding": { 269 | "url": "https://github.com/sponsors/ljharb" 270 | } 271 | }, 272 | "node_modules/isarray": { 273 | "version": "1.0.0", 274 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 275 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" 276 | }, 277 | "node_modules/jmespath": { 278 | "version": "0.16.0", 279 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", 280 | "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", 281 | "engines": { 282 | "node": ">= 0.6.0" 283 | } 284 | }, 285 | "node_modules/punycode": { 286 | "version": "1.3.2", 287 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 288 | "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" 289 | }, 290 | "node_modules/querystring": { 291 | "version": "0.2.0", 292 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 293 | "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", 294 | "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", 295 | "engines": { 296 | "node": ">=0.4.x" 297 | } 298 | }, 299 | "node_modules/sax": { 300 | "version": "1.2.1", 301 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 302 | "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" 303 | }, 304 | "node_modules/set-function-length": { 305 | "version": "1.1.1", 306 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", 307 | "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", 308 | "dependencies": { 309 | "define-data-property": "^1.1.1", 310 | "get-intrinsic": "^1.2.1", 311 | "gopd": "^1.0.1", 312 | "has-property-descriptors": "^1.0.0" 313 | }, 314 | "engines": { 315 | "node": ">= 0.4" 316 | } 317 | }, 318 | "node_modules/url": { 319 | "version": "0.10.3", 320 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 321 | "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", 322 | "dependencies": { 323 | "punycode": "1.3.2", 324 | "querystring": "0.2.0" 325 | } 326 | }, 327 | "node_modules/util": { 328 | "version": "0.12.5", 329 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", 330 | "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", 331 | "dependencies": { 332 | "inherits": "^2.0.3", 333 | "is-arguments": "^1.0.4", 334 | "is-generator-function": "^1.0.7", 335 | "is-typed-array": "^1.1.3", 336 | "which-typed-array": "^1.1.2" 337 | } 338 | }, 339 | "node_modules/uuid": { 340 | "version": "8.0.0", 341 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", 342 | "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", 343 | "bin": { 344 | "uuid": "dist/bin/uuid" 345 | } 346 | }, 347 | "node_modules/which-typed-array": { 348 | "version": "1.1.13", 349 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", 350 | "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", 351 | "dependencies": { 352 | "available-typed-arrays": "^1.0.5", 353 | "call-bind": "^1.0.4", 354 | "for-each": "^0.3.3", 355 | "gopd": "^1.0.1", 356 | "has-tostringtag": "^1.0.0" 357 | }, 358 | "engines": { 359 | "node": ">= 0.4" 360 | }, 361 | "funding": { 362 | "url": "https://github.com/sponsors/ljharb" 363 | } 364 | }, 365 | "node_modules/xml2js": { 366 | "version": "0.5.0", 367 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", 368 | "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", 369 | "dependencies": { 370 | "sax": ">=0.6.0", 371 | "xmlbuilder": "~11.0.0" 372 | }, 373 | "engines": { 374 | "node": ">=4.0.0" 375 | } 376 | }, 377 | "node_modules/xmlbuilder": { 378 | "version": "11.0.1", 379 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 380 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 381 | "engines": { 382 | "node": ">=4.0" 383 | } 384 | } 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /atmProducer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "producer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "James Beswick, AWS Serverless", 11 | "license": "ISC", 12 | "dependencies": { 13 | "aws-sdk": "^2.1518.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: myATMapp 4 | 5 | Globals: 6 | Function: 7 | Timeout: 3 8 | 9 | Resources: 10 | atmProducerFn: 11 | Type: AWS::Serverless::Function 12 | Properties: 13 | CodeUri: atmProducer/ 14 | Handler: handler.lambdaHandler 15 | Runtime: nodejs18.x 16 | Policies: 17 | - Statement: 18 | - Effect: Allow 19 | Resource: '*' 20 | Action: 21 | - events:PutEvents 22 | 23 | atmConsumerCase1Fn: 24 | Type: AWS::Serverless::Function 25 | Properties: 26 | CodeUri: atmConsumer/ 27 | Handler: handler.case1Handler 28 | Runtime: nodejs18.x 29 | 30 | atmConsumerCase2Fn: 31 | Type: AWS::Serverless::Function 32 | Properties: 33 | CodeUri: atmConsumer/ 34 | Handler: handler.case2Handler 35 | Runtime: nodejs18.x 36 | Events: 37 | Trigger: 38 | Type: CloudWatchEvent 39 | Properties: 40 | Pattern: 41 | source: 42 | - custom.myATMapp 43 | detail-type: 44 | - transaction 45 | detail: 46 | location: 47 | - "prefix": "NY-" 48 | 49 | atmConsumerCase3Fn: 50 | Type: AWS::Serverless::Function 51 | Properties: 52 | CodeUri: atmConsumer/ 53 | Handler: handler.case3Handler 54 | Runtime: nodejs18.x 55 | Events: 56 | Trigger: 57 | Type: CloudWatchEvent 58 | Properties: 59 | Pattern: 60 | source: 61 | - custom.myATMapp 62 | detail-type: 63 | - transaction 64 | detail: 65 | result: 66 | - "anything-but": "approved" 67 | 68 | EventRuleCase1: 69 | Type: AWS::Events::Rule 70 | Properties: 71 | Description: "Approved transactions" 72 | EventPattern: 73 | source: 74 | - "custom.myATMapp" 75 | detail-type: 76 | - transaction 77 | detail: 78 | result: 79 | - "approved" 80 | State: "ENABLED" 81 | Targets: 82 | - 83 | Arn: 84 | Fn::GetAtt: 85 | - "atmConsumerCase1Fn" 86 | - "Arn" 87 | Id: "atmConsumerTarget1" 88 | 89 | PermissionForEventsToInvokeLambda: 90 | Type: AWS::Lambda::Permission 91 | Properties: 92 | FunctionName: 93 | Ref: "atmConsumerCase1Fn" 94 | Action: "lambda:InvokeFunction" 95 | Principal: "events.amazonaws.com" 96 | SourceArn: 97 | Fn::GetAtt: 98 | - "EventRuleCase1" 99 | - "Arn" 100 | --------------------------------------------------------------------------------