diff --git a/Makefile b/Makefile index b328b6434..0786e52e4 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # Makefile versions -MAKEFILE_VERSION := 2.3 +MAKEFILE_VERSION := 2.3.1 UPDATE_VERSION := make/latest # This Makefile requires Python version 3.9 or later @@ -129,7 +129,7 @@ version_report: report_versions build_deps: .venv ( \ . .venv/bin/activate; \ - pip install aws-sam-cli yq; \ + pip install aws-sam-cli yq packaging; \ ) deps: .venv diff --git a/samples/sample-fargate-node-app/package-lock.json b/samples/sample-fargate-node-app/package-lock.json index d5ae1b6af..8f9f9a009 100644 --- a/samples/sample-fargate-node-app/package-lock.json +++ b/samples/sample-fargate-node-app/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "ejs": "^3.1.10", - "express": "^4.19.2" + "express": "^4.21.0" } }, "node_modules/accepts": { @@ -55,9 +55,10 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -67,7 +68,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -90,6 +91,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -98,6 +100,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -163,14 +166,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -184,6 +188,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -192,6 +197,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -208,6 +214,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -216,6 +223,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -224,7 +232,8 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/ejs": { "version": "3.1.10", @@ -241,9 +250,10 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -252,6 +262,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -263,6 +274,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -270,47 +282,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -349,12 +363,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -377,6 +392,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -385,6 +401,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -393,6 +410,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -411,6 +429,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -430,6 +449,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -441,6 +461,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -452,6 +473,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -463,6 +485,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -474,6 +497,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -489,6 +513,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -499,7 +524,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -530,14 +556,19 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", @@ -551,6 +582,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -591,7 +623,8 @@ "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", @@ -602,9 +635,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -613,6 +650,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -624,14 +662,16 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -646,11 +686,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -663,6 +704,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -671,6 +713,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -703,12 +746,14 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -728,20 +773,31 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -751,6 +807,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -766,12 +823,14 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -789,6 +848,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -808,6 +868,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -816,6 +877,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -828,6 +890,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } diff --git a/samples/sample-fargate-node-app/package.json b/samples/sample-fargate-node-app/package.json index 57cb1930f..b48fa4f53 100644 --- a/samples/sample-fargate-node-app/package.json +++ b/samples/sample-fargate-node-app/package.json @@ -11,6 +11,6 @@ "license": "Apache-2.0", "dependencies": { "ejs": "^3.1.10", - "express": "^4.19.2" + "express": "^4.21.0" } } diff --git a/samples/sample-rdk-rules/.gitignore b/samples/sample-rdk-rules/.gitignore deleted file mode 100644 index 37833f8be..000000000 --- a/samples/sample-rdk-rules/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.swp -package-lock.json -__pycache__ -.pytest_cache -.venv -*.egg-info - -# CDK asset staging directory -.cdk.staging -cdk.out diff --git a/samples/sample-rdk-rules/README.md b/samples/sample-rdk-rules/README.md deleted file mode 100644 index 3bfff8dd5..000000000 --- a/samples/sample-rdk-rules/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# Sample RDK Rules pipeline - -This setup will allow you to deploy custom config rules created by the RDK via -ADF pipeline. - -## Architecture - -![Architecture](./meta/custom-configs.png) - -- As a first step it requires to have a Source code repository to store our - code. In this pattern we are using CodeCommit repository. This repository - created by as a part of the pipeline definition in the ADF's - `deployment_map.yml`. Example of the pipeline definition is in the ADF setup - section. -- ADF pipeline definition creates a pipeline that will deploy Lambda function(s) - into the compliance account and Custom Config rule(s) to Target accounts. -- When a Custom Config rule get pushed into the CodeCommit repository; - - CodeBuild will find the RDK rule(s) recursively in the `config-rules` - directory then zip each single rule one by one and upload into ADF bucket. - Buildspec is using a helper script called `lambda_helper.py` to achieve - this task. ADF populates bucket names into SSM Parameter store on the - installation. `lambda_helper.py` fetches the bucket name from the SSM - Parameter Store. Parameter name looks like - `/cross_region/s3_regional_bucket/{region}`. - - Then CodeBuild will generate 2 CloudFormation templates one for Lambda - function(s) deployment and other for the Custom Config rule(s) deployment. -- When a Lambda function get invokes by a Target account Custom config rule; it - will assume the Config role in the target account then put config Evaluations - into the Target account's Config rule. - -### ADF setup - -Sample pipeline definition looks like below: - -```yaml - - name: custom-config-rules-pipeline ## repo name - default_providers: - source: - provider: codecommit - properties: - account_id: - build: - provider: codebuild - properties: - image: "STANDARD_7_0" - deploy: - provider: cloudformation - targets: - - name: LambdaDeployment - regions: - target: - properties: - template_filename: "template-lambda.json" - - name: ConfigRulesDeployment - regions: - target: - - - properties: - template_filename: "template-config-rules.json" -``` - -## Development setup - -After you clone the repo following file/folder structure will be there; - -- `config-rules`: This folder will contain all the custom config rules created - by `rdk create ...`. Make sure to setup correct details in the - `parameters.json` file(ex: SourceRuntime) -- `params`: Contains parameters we need for the generated CloudFormation - templates. You must set the account id of the Compliance account in - `LambdaAccountId` and Target accounts Config role arn as a pattern in - `ConfigRoleArnToAssume`. These will be used as parameters when it deploys - config-rule into Target accounts to refer Lambda function from the Compliance - account. [Refer this - link](../../docs/user-guide.md#cloudformation-parameters-and-tagging) -- `templates`: This folder contains all the CloudFormation (CFn) template pieces - that required to build CFn template for the lambda function deployment. -- `buildspec.yml`: Buildspec file to generate CloudFormation templates for the - Lambda and Custom Config rules -- `lambda_helper.py`: This is the helper file that pack and upload the lambda - code recursively in the config-rules folder -- `requirements.txt`: Requirements for the `lambda_helper.py` script. - -## Lambda function implementation requirements - -In Lambda functions when you want to refer boto3 client or resource make sure - -- Set `ASSUME_ROLE_MODE` constant to `True` -- Use `get_client` method for client. -- Duplicate `get_client` and create the `get_resource` method. - -```py -def get_resource(service, event, region=None): - """Return the service boto resource. It should be used instead of directly - calling the resource. - - Keyword arguments: - service -- the service name used for calling the boto.resource() - event -- the event variable given in the lambda handler - region -- the region where the resource is called (default: None) - """ - if not ASSUME_ROLE_MODE: - return boto3.resource( - service, region - ) - credentials = get_assume_role_credentials( - get_execution_role_arn(event), - region - ) - return boto3.resource( - service, aws_access_key_id=credentials['AccessKeyId'], - aws_secret_access_key=credentials['SecretAccessKey'], - aws_session_token=credentials['SessionToken'], - region_name=region - ) -``` - -These methods use STS and config payload to assume the IAM role in the target -account. If not lambda execution will be failed. - -[More info](https://aws.amazon.com/blogs/mt/aws-config-rdk-multi-account-and-multi-region-deployment/) - -## Prerequisites/ Important bits - -- This solution does not setup config or config recorder. -- When this solution deploys the config-rule to a target account; it expects - config is enabled in the target account. -- Each target account's config role should be able assume by - `` to put evaluations into each target - account's config. AKA config role in the target account (`2222222222`) should - have the `lambda-function-account-id` (`1111111111`) as trusted entity as - below. - -![Trusted entity](./meta/lambda-account-id-trusted-entity.png) diff --git a/samples/sample-rdk-rules/buildspec.yml b/samples/sample-rdk-rules/buildspec.yml deleted file mode 100644 index 9a4a753b6..000000000 --- a/samples/sample-rdk-rules/buildspec.yml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. -# SPDX-License-Identifier: Apache-2.0 - -version: 0.2 -phases: - install: - runtime-versions: - python: 3.12 - nodejs: 20 - commands: - - aws s3 cp s3://$S3_BUCKET_NAME/adf-build/ adf-build/ --recursive --only-show-errors - - pip install -r adf-build/requirements.txt -q - - python adf-build/generate_params.py - - build: - commands: - - pip install rdk - - cd config-rules - - rdk create-rule-template --rules-only -a -o ../template-config-rules.json - - cd .. - - pip install -r requirements.txt - - python lambda_helper.py --template-name template-lambda.json - -artifacts: - files: '**/*' diff --git a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF.py b/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF.py deleted file mode 100644 index 49cdabbdf..000000000 --- a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF.py +++ /dev/null @@ -1,576 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. -# SPDX-License-Identifier: Apache-2.0 - -import json -import sys -import datetime -import boto3 -import botocore - -try: - import liblogging -except ImportError: - pass - -############## -# Parameters # -############## - -# Define the default resource to report to Config Rules -DEFAULT_RESOURCE_TYPE = "AWS::::Account" - -APPLICABLE_RESOURCES = ["AWS::EC2::Instance"] -VALID_ENVIRONMENTS = ["PROD", "UAT"] - -# Set to True to get the lambda to assume the Role attached on the Config Service (useful for cross-account). -ASSUME_ROLE_MODE = True - -# Other parameters (no change needed) -CONFIG_ROLE_TIMEOUT_SECONDS = 900 - -############# -# Main Code # -############# - - -def evaluate_compliance(event, configuration_item, valid_rule_parameters): - """Form the evaluation(s) to be return to Config Rules - - Return either: - None -- when no result needs to be displayed - a string -- either COMPLIANT, NON_COMPLIANT or NOT_APPLICABLE - a dictionary -- the evaluation dictionary, usually built by build_evaluation_from_config_item() - a list of dictionary -- a list of evaluation dictionary , usually built by build_evaluation() - - Keyword arguments: - event -- the event variable given in the lambda handler - configuration_item -- the configurationItem dictionary in the invokingEvent - valid_rule_parameters -- the output of the evaluate_parameters() representing validated parameters of the Config Rule - - Advanced Notes: - 1 -- if a resource is deleted and generate a configuration change with ResourceDeleted status, the Boilerplate code will put a NOT_APPLICABLE on this resource automatically. - 2 -- if a None or a list of dictionary is returned, the old evaluation(s) which are not returned in the new evaluation list are returned as NOT_APPLICABLE by the Boilerplate code - 3 -- if None or an empty string, list or dict is returned, the Boilerplate code will put a "shadow" evaluation to feedback that the evaluation took place properly - """ - - ############################### - # Add your custom logic here. # - ############################### - - if not is_applicable_ec2(configuration_item, event) or configuration_item is None: - return "NOT_APPLICABLE" - - # if termination protection is not enabled resource is not Compliant - if not is_termination_protection_on(configuration_item["resourceId"], event): - return "NON_COMPLIANT" - else: - return "COMPLIANT" - - -def is_applicable_ec2(configuration_item, event): - if configuration_item["resourceType"] not in APPLICABLE_RESOURCES: - return False - - # If instance is not in a valid environment its not applicable - if not is_valid_environment(configuration_item["resourceId"], event): - return False - - # Fetch about autoscaling - if is_part_of_asg(configuration_item["resourceId"], event): - return False - - return True - - -# If instance not in a valid environment its not applicable -def is_valid_environment(instance_id, event): - ec2 = get_resource("ec2", event) - instance = ec2.Instance(instance_id) - for tags in instance.tags or []: - if tags["Key"] == "Env": - return tags["Value"] in VALID_ENVIRONMENTS - - -# Checks is instance part of an Autoscaling Group -def is_part_of_asg(instance_id, event): - asg = get_client("autoscaling", event) - result = asg.describe_auto_scaling_instances(InstanceIds=[instance_id]) - return len(result["AutoScalingInstances"]) > 0 - - -# Checks DisableApiTermination is enabled or not -def is_termination_protection_on(instance_id, event): - client = get_client("ec2", event) - response = client.describe_instance_attribute( - Attribute="disableApiTermination", InstanceId=instance_id - ) - return response["DisableApiTermination"]["Value"] - - -def evaluate_parameters(rule_parameters): - """Evaluate the rule parameters dictionary validity. Raise a ValueError for invalid parameters. - - Return: - anything suitable for the evaluate_compliance() - - Keyword arguments: - rule_parameters -- the Key/Value dictionary of the Config Rules parameters - """ - valid_rule_parameters = rule_parameters - return valid_rule_parameters - - -#################### -# Helper Functions # -#################### - -# Build an error to be displayed in the logs when the parameter is invalid. -def build_parameters_value_error_response(ex): - """Return an error dictionary when the evaluate_parameters() raises a ValueError. - - Keyword arguments: - ex -- Exception text - """ - return build_error_response( - internal_error_message="Parameter value is invalid", - internal_error_details="An ValueError was raised during the validation of the Parameter value", - customer_error_code="InvalidParameterValueException", - customer_error_message=str(ex), - ) - - -# This gets the client after assuming the Config service role -# either in the same AWS account or cross-account. -def get_client(service, event, region=None): - """Return the service boto client. It should be used instead of directly calling the client. - - Keyword arguments: - service -- the service name used for calling the boto.client() - event -- the event variable given in the lambda handler - region -- the region where the client is called (default: None) - """ - if not ASSUME_ROLE_MODE: - return boto3.client(service, region) - credentials = get_assume_role_credentials(get_execution_role_arn(event), region) - return boto3.client( - service, - aws_access_key_id=credentials["AccessKeyId"], - aws_secret_access_key=credentials["SecretAccessKey"], - aws_session_token=credentials["SessionToken"], - region_name=region, - ) - - -def get_resource(service, event, region=None): - """Return the service boto client. It should be used instead of directly calling the client. - - Keyword arguments: - service -- the service name used for calling the boto.client() - event -- the event variable given in the lambda handler - region -- the region where the client is called (default: None) - """ - if not ASSUME_ROLE_MODE: - return boto3.resource(service, region) - credentials = get_assume_role_credentials(get_execution_role_arn(event), region) - return boto3.resource( - service, - aws_access_key_id=credentials["AccessKeyId"], - aws_secret_access_key=credentials["SecretAccessKey"], - aws_session_token=credentials["SessionToken"], - region_name=region, - ) - - -# This generate an evaluation for config -def build_evaluation( - resource_id, - compliance_type, - event, - resource_type=DEFAULT_RESOURCE_TYPE, - annotation=None, -): - """Form an evaluation as a dictionary. Usually suited to report on scheduled rules. - - Keyword arguments: - resource_id -- the unique id of the resource to report - compliance_type -- either COMPLIANT, NON_COMPLIANT or NOT_APPLICABLE - event -- the event variable given in the lambda handler - resource_type -- the CloudFormation resource type (or AWS::::Account) to report on the rule (default DEFAULT_RESOURCE_TYPE) - annotation -- an annotation to be added to the evaluation (default None). It will be truncated to 255 if longer. - """ - eval_cc = {} - if annotation: - eval_cc["Annotation"] = build_annotation(annotation) - eval_cc["ComplianceResourceType"] = resource_type - eval_cc["ComplianceResourceId"] = resource_id - eval_cc["ComplianceType"] = compliance_type - eval_cc["OrderingTimestamp"] = str( - json.loads(event["invokingEvent"])["notificationCreationTime"] - ) - return eval_cc - - -def build_evaluation_from_config_item( - configuration_item, compliance_type, annotation=None -): - """Form an evaluation as a dictionary. Usually suited to report on configuration change rules. - - Keyword arguments: - configuration_item -- the configurationItem dictionary in the invokingEvent - compliance_type -- either COMPLIANT, NON_COMPLIANT or NOT_APPLICABLE - annotation -- an annotation to be added to the evaluation (default None). It will be truncated to 255 if longer. - """ - eval_ci = {} - if annotation: - eval_ci["Annotation"] = build_annotation(annotation) - eval_ci["ComplianceResourceType"] = configuration_item["resourceType"] - eval_ci["ComplianceResourceId"] = configuration_item["resourceId"] - eval_ci["ComplianceType"] = compliance_type - eval_ci["OrderingTimestamp"] = configuration_item["configurationItemCaptureTime"] - return eval_ci - - -#################### -# Boilerplate Code # -#################### - -# Get execution role for Lambda function -def get_execution_role_arn(event): - role_arn = None - if "ruleParameters" in event: - rule_params = json.loads(event["ruleParameters"]) - role_name = rule_params.get("ExecutionRoleName") - if role_name: - execution_role_prefix = event["executionRoleArn"].split("/")[0] - role_arn = "{}/{}".format(execution_role_prefix, role_name) - - if not role_arn: - role_arn = event["executionRoleArn"] - - return role_arn - - -# Build annotation within Service constraints -def build_annotation(annotation_string): - if len(annotation_string) > 256: - return annotation_string[:244] + " [truncated]" - return annotation_string - - -# Helper function used to validate input -def check_defined(reference, reference_name): - if not reference: - raise Exception("Error: ", reference_name, "is not defined") - return reference - - -# Check whether the message is OversizedConfigurationItemChangeNotification or not -def is_oversized_changed_notification(message_type): - check_defined(message_type, "messageType") - return message_type == "OversizedConfigurationItemChangeNotification" - - -# Check whether the message is a ScheduledNotification or not. -def is_scheduled_notification(message_type): - check_defined(message_type, "messageType") - return message_type == "ScheduledNotification" - - -# Get configurationItem using getResourceConfigHistory API -# in case of OversizedConfigurationItemChangeNotification -def get_configuration(resource_type, resource_id, configuration_capture_time): - result = AWS_CONFIG_CLIENT.get_resource_config_history( - resourceType=resource_type, - resourceId=resource_id, - laterTime=configuration_capture_time, - limit=1, - ) - configuration_item = result["configurationItems"][0] - return convert_api_configuration(configuration_item) - - -# Convert from the API model to the original invocation model -def convert_api_configuration(configuration_item): - for k, v in configuration_item.items(): - if isinstance(v, datetime.datetime): - configuration_item[k] = str(v) - configuration_item["awsAccountId"] = configuration_item["accountId"] - configuration_item["ARN"] = configuration_item["arn"] - configuration_item["configurationStateMd5Hash"] = configuration_item[ - "configurationItemMD5Hash" - ] - configuration_item["configurationItemVersion"] = configuration_item["version"] - configuration_item["configuration"] = json.loads( - configuration_item["configuration"] - ) - if "relationships" in configuration_item: - for i in range(len(configuration_item["relationships"])): - configuration_item["relationships"][i]["name"] = configuration_item[ - "relationships" - ][i]["relationshipName"] - return configuration_item - - -# Based on the type of message get the configuration item -# either from configurationItem in the invoking event -# or using the getResourceConfigHistory API in getConfiguration function. -def get_configuration_item(invoking_event): - check_defined(invoking_event, "invokingEvent") - if is_oversized_changed_notification(invoking_event["messageType"]): - configuration_item_summary = check_defined( - invoking_event["configurationItemSummary"], "configurationItemSummary" - ) - return get_configuration( - configuration_item_summary["resourceType"], - configuration_item_summary["resourceId"], - configuration_item_summary["configurationItemCaptureTime"], - ) - if is_scheduled_notification(invoking_event["messageType"]): - return None - return check_defined(invoking_event["configurationItem"], "configurationItem") - - -# Check whether the resource has been deleted. If it has, then the evaluation is unnecessary. -def is_applicable(configuration_item, event): - try: - check_defined(configuration_item, "configurationItem") - check_defined(event, "event") - except: - return True - status = configuration_item["configurationItemStatus"] - event_left_scope = event["eventLeftScope"] - if status == "ResourceDeleted": - print("Resource Deleted, setting Compliance Status to NOT_APPLICABLE.") - - return status in ("OK", "ResourceDiscovered") and not event_left_scope - - -def get_assume_role_credentials(role_arn, region=None): - sts_client = boto3.client("sts", region) - try: - assume_role_response = sts_client.assume_role( - RoleArn=role_arn, - RoleSessionName="configLambdaExecution", - DurationSeconds=CONFIG_ROLE_TIMEOUT_SECONDS, - ) - if "liblogging" in sys.modules: - liblogging.logSession(role_arn, assume_role_response) - return assume_role_response["Credentials"] - except botocore.exceptions.ClientError as ex: - # Scrub error message for any internal account info leaks - print(str(ex)) - if "AccessDenied" in ex.response["Error"]["Code"]: - ex.response["Error"][ - "Message" - ] = "AWS Config does not have permission to assume the IAM role." - else: - ex.response["Error"]["Message"] = "InternalError" - ex.response["Error"]["Code"] = "InternalError" - raise ex - - -# This removes older evaluation (usually useful for periodic rule not reporting on AWS::::Account). -def clean_up_old_evaluations(latest_evaluations, event): - - cleaned_evaluations = [] - - old_eval = AWS_CONFIG_CLIENT.get_compliance_details_by_config_rule( - ConfigRuleName=event["configRuleName"], - ComplianceTypes=["COMPLIANT", "NON_COMPLIANT"], - Limit=100, - ) - - old_eval_list = [] - - while True: - for old_result in old_eval["EvaluationResults"]: - old_eval_list.append(old_result) - if "NextToken" in old_eval: - next_token = old_eval["NextToken"] - old_eval = AWS_CONFIG_CLIENT.get_compliance_details_by_config_rule( - ConfigRuleName=event["configRuleName"], - ComplianceTypes=["COMPLIANT", "NON_COMPLIANT"], - Limit=100, - NextToken=next_token, - ) - else: - break - - for old_eval in old_eval_list: - old_resource_id = old_eval["EvaluationResultIdentifier"][ - "EvaluationResultQualifier" - ]["ResourceId"] - newer_founded = False - for latest_eval in latest_evaluations: - if old_resource_id == latest_eval["ComplianceResourceId"]: - newer_founded = True - if not newer_founded: - cleaned_evaluations.append( - build_evaluation(old_resource_id, "NOT_APPLICABLE", event) - ) - - return cleaned_evaluations + latest_evaluations - - -def lambda_handler(event, context): - if "liblogging" in sys.modules: - liblogging.logEvent(event) - - global AWS_CONFIG_CLIENT - - # print(event) - check_defined(event, "event") - invoking_event = json.loads(event["invokingEvent"]) - rule_parameters = {} - if "ruleParameters" in event: - rule_parameters = json.loads(event["ruleParameters"]) - - try: - valid_rule_parameters = evaluate_parameters(rule_parameters) - except ValueError as ex: - return build_parameters_value_error_response(ex) - - try: - AWS_CONFIG_CLIENT = get_client("config", event) - if invoking_event["messageType"] in [ - "ConfigurationItemChangeNotification", - "ScheduledNotification", - "OversizedConfigurationItemChangeNotification", - ]: - configuration_item = get_configuration_item(invoking_event) - if is_applicable(configuration_item, event): - compliance_result = evaluate_compliance( - event, configuration_item, valid_rule_parameters - ) - else: - compliance_result = "NOT_APPLICABLE" - else: - return build_internal_error_response( - "Unexpected message type", str(invoking_event) - ) - except botocore.exceptions.ClientError as ex: - if is_internal_error(ex): - return build_internal_error_response( - "Unexpected error while completing API request", str(ex) - ) - return build_error_response( - "Customer error while making API request", - str(ex), - ex.response["Error"]["Code"], - ex.response["Error"]["Message"], - ) - except ValueError as ex: - return build_internal_error_response(str(ex), str(ex)) - - evaluations = [] - latest_evaluations = [] - - if not compliance_result: - latest_evaluations.append( - build_evaluation( - event["accountId"], - "NOT_APPLICABLE", - event, - resource_type="AWS::::Account", - ) - ) - evaluations = clean_up_old_evaluations(latest_evaluations, event) - elif isinstance(compliance_result, str): - if configuration_item: - evaluations.append( - build_evaluation_from_config_item(configuration_item, compliance_result) - ) - else: - evaluations.append( - build_evaluation( - event["accountId"], - compliance_result, - event, - resource_type=DEFAULT_RESOURCE_TYPE, - ) - ) - elif isinstance(compliance_result, list): - for evaluation in compliance_result: - missing_fields = False - for field in ( - "ComplianceResourceType", - "ComplianceResourceId", - "ComplianceType", - "OrderingTimestamp", - ): - if field not in evaluation: - print("Missing " + field + " from custom evaluation.") - missing_fields = True - - if not missing_fields: - latest_evaluations.append(evaluation) - evaluations = clean_up_old_evaluations(latest_evaluations, event) - elif isinstance(compliance_result, dict): - missing_fields = False - for field in ( - "ComplianceResourceType", - "ComplianceResourceId", - "ComplianceType", - "OrderingTimestamp", - ): - if field not in compliance_result: - print("Missing " + field + " from custom evaluation.") - missing_fields = True - if not missing_fields: - evaluations.append(compliance_result) - else: - evaluations.append( - build_evaluation_from_config_item(configuration_item, "NOT_APPLICABLE") - ) - - # Put together the request that reports the evaluation status - result_token = event["resultToken"] - test_mode = False - if result_token == "TESTMODE": - # Used solely for RDK test to skip actual put_evaluation API call - test_mode = True - - # Invoke the Config API to report the result of the evaluation - evaluation_copy = [] - evaluation_copy = evaluations[:] - while evaluation_copy: - AWS_CONFIG_CLIENT.put_evaluations( - Evaluations=evaluation_copy[:100], - ResultToken=result_token, - TestMode=test_mode, - ) - del evaluation_copy[:100] - - # Used solely for RDK test to be able to test Lambda function - return evaluations - - -def is_internal_error(exception): - return ( - (not isinstance(exception, botocore.exceptions.ClientError)) - or exception.response["Error"]["Code"].startswith("5") - or "InternalError" in exception.response["Error"]["Code"] - or "ServiceError" in exception.response["Error"]["Code"] - ) - - -def build_internal_error_response(internal_error_message, internal_error_details=None): - return build_error_response( - internal_error_message, internal_error_details, "InternalError", "InternalError" - ) - - -def build_error_response( - internal_error_message, - internal_error_details=None, - customer_error_code=None, - customer_error_message=None, -): - error_response = { - "internalErrorMessage": internal_error_message, - "internalErrorDetails": internal_error_details, - "customerErrorMessage": customer_error_message, - "customerErrorCode": customer_error_code, - } - print(error_response) - return error_response diff --git a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF_test.py b/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF_test.py deleted file mode 100644 index c158fee04..000000000 --- a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/EC2_CHECKS_TERMINATION_PROTECTION_ADF_test.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. -# SPDX-License-Identifier: Apache-2.0 - -import sys -import unittest -from unittest.mock import MagicMock -import botocore - -############## -# Parameters # -############## - -# Define the default resource to report to Config Rules -DEFAULT_RESOURCE_TYPE = 'AWS::::Account' - -############# -# Main Code # -############# - -CONFIG_CLIENT_MOCK = MagicMock() -STS_CLIENT_MOCK = MagicMock() - -class Boto3Mock(): - @staticmethod - def client(client_name, *args, **kwargs): - if client_name == 'config': - return CONFIG_CLIENT_MOCK - if client_name == 'sts': - return STS_CLIENT_MOCK - raise Exception("Attempting to create an unknown client") - -sys.modules['boto3'] = Boto3Mock() - -RULE = __import__('EC2_CHECKS_TERMINATION_PROTECTION_ADF') - -class ComplianceTest(unittest.TestCase): - - rule_parameters = '{"SomeParameterKey":"SomeParameterValue","SomeParameterKey2":"SomeParameterValue2"}' - - invoking_event_iam_role_sample = '{"configurationItem":{"relatedEvents":[],"relationships":[],"configuration":{},"tags":{},"configurationItemCaptureTime":"2018-07-02T03:37:52.418Z","awsAccountId":"123456789012","configurationItemStatus":"ResourceDiscovered","resourceType":"AWS::IAM::Role","resourceId":"some-resource-id","resourceName":"some-resource-name","ARN":"some-arn"},"notificationCreationTime":"2018-07-02T23:05:34.445Z","messageType":"ConfigurationItemChangeNotification"}' - - def setUp(self): - pass - - def test_sample(self): - self.assertTrue(True) - -#################### -# Helper Functions # -#################### - -def build_lambda_configurationchange_event(invoking_event, rule_parameters=None): - event_to_return = { - 'configRuleName':'myRule', - 'executionRoleArn':'roleArn', - 'eventLeftScope': False, - 'invokingEvent': invoking_event, - 'accountId': '123456789012', - 'configRuleArn': 'arn:aws:config:us-east-1:123456789012:config-rule/config-rule-abc', - 'resultToken':'token' - } - if rule_parameters: - event_to_return['ruleParameters'] = rule_parameters - return event_to_return - -def build_lambda_scheduled_event(rule_parameters=None): - invoking_event = '{"messageType":"ScheduledNotification","notificationCreationTime":"2017-12-23T22:11:18.158Z"}' - event_to_return = { - 'configRuleName':'myRule', - 'executionRoleArn':'roleArn', - 'eventLeftScope': False, - 'invokingEvent': invoking_event, - 'accountId': '123456789012', - 'configRuleArn': 'arn:aws:config:us-east-1:123456789012:config-rule/config-rule-abc', - 'resultToken':'token' - } - if rule_parameters: - event_to_return['ruleParameters'] = rule_parameters - return event_to_return - -def build_expected_response(compliance_type, compliance_resource_id, compliance_resource_type=DEFAULT_RESOURCE_TYPE, annotation=None): - if not annotation: - return { - 'ComplianceType': compliance_type, - 'ComplianceResourceId': compliance_resource_id, - 'ComplianceResourceType': compliance_resource_type - } - return { - 'ComplianceType': compliance_type, - 'ComplianceResourceId': compliance_resource_id, - 'ComplianceResourceType': compliance_resource_type, - 'Annotation': annotation - } - -def assert_successful_evaluation(test_class, response, resp_expected, evaluations_count=1): - if isinstance(response, dict): - test_class.assertEquals(resp_expected['ComplianceResourceType'], response['ComplianceResourceType']) - test_class.assertEquals(resp_expected['ComplianceResourceId'], response['ComplianceResourceId']) - test_class.assertEquals(resp_expected['ComplianceType'], response['ComplianceType']) - test_class.assertTrue(response['OrderingTimestamp']) - if 'Annotation' in resp_expected or 'Annotation' in response: - test_class.assertEquals(resp_expected['Annotation'], response['Annotation']) - elif isinstance(response, list): - test_class.assertEquals(evaluations_count, len(response)) - for i, response_expected in enumerate(resp_expected): - test_class.assertEquals(response_expected['ComplianceResourceType'], response[i]['ComplianceResourceType']) - test_class.assertEquals(response_expected['ComplianceResourceId'], response[i]['ComplianceResourceId']) - test_class.assertEquals(response_expected['ComplianceType'], response[i]['ComplianceType']) - test_class.assertTrue(response[i]['OrderingTimestamp']) - if 'Annotation' in response_expected or 'Annotation' in response[i]: - test_class.assertEquals(response_expected['Annotation'], response[i]['Annotation']) - -def assert_customer_error_response(test_class, response, customer_error_code=None, customer_error_message=None): - if customer_error_code: - test_class.assertEqual(customer_error_code, response['customerErrorCode']) - if customer_error_message: - test_class.assertEqual(customer_error_message, response['customerErrorMessage']) - test_class.assertTrue(response['customerErrorCode']) - test_class.assertTrue(response['customerErrorMessage']) - if "internalErrorMessage" in response: - test_class.assertTrue(response['internalErrorMessage']) - if "internalErrorDetails" in response: - test_class.assertTrue(response['internalErrorDetails']) - -def sts_mock(): - assume_role_response = { - "Credentials": { - "AccessKeyId": "string", - "SecretAccessKey": "string", - "SessionToken": "string"}} - STS_CLIENT_MOCK.reset_mock(return_value=True) - STS_CLIENT_MOCK.assume_role = MagicMock(return_value=assume_role_response) - -################## -# Common Testing # -################## - -class TestStsErrors(unittest.TestCase): - - def test_sts_unknown_error(self): - RULE.ASSUME_ROLE_MODE = True - RULE.evaluate_parameters = MagicMock(return_value=True) - STS_CLIENT_MOCK.assume_role = MagicMock(side_effect=botocore.exceptions.ClientError( - {'Error': {'Code': 'unknown-code', 'Message': 'unknown-message'}}, 'operation')) - response = RULE.lambda_handler(build_lambda_configurationchange_event('{}'), {}) - assert_customer_error_response( - self, response, 'InternalError', 'InternalError') - - def test_sts_access_denied(self): - RULE.ASSUME_ROLE_MODE = True - RULE.evaluate_parameters = MagicMock(return_value=True) - STS_CLIENT_MOCK.assume_role = MagicMock(side_effect=botocore.exceptions.ClientError( - {'Error': {'Code': 'AccessDenied', 'Message': 'access-denied'}}, 'operation')) - response = RULE.lambda_handler(build_lambda_configurationchange_event('{}'), {}) - assert_customer_error_response( - self, response, 'AccessDenied', 'AWS Config does not have permission to assume the IAM role.') diff --git a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/parameters.json b/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/parameters.json deleted file mode 100644 index 1b8ce5dae..000000000 --- a/samples/sample-rdk-rules/config-rules/EC2_CHECKS_TERMINATION_PROTECTION_ADF/parameters.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Version": "1.0", - "Parameters": { - "RuleName": "EC2_CHECKS_TERMINATION_PROTECTION_ADF", - "Description": "EC2_CHECKS_TERMINATION_PROTECTION_ADF", - "SourceRuntime": "python3.12", - "CodeKey": "EC2_CHECKS_TERMINATION_PROTECTION_ADFeu-central-1.zip", - "InputParameters": "{}", - "OptionalParameters": "{}", - "SourceEvents": "AWS::EC2::Instance", - "SourcePeriodic": "One_Hour" - }, - "Tags": "[]" -} diff --git a/samples/sample-rdk-rules/lambda_helper.py b/samples/sample-rdk-rules/lambda_helper.py deleted file mode 100644 index b2aa42020..000000000 --- a/samples/sample-rdk-rules/lambda_helper.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright Amazon.com Inc. or its affiliates. -# SPDX-License-Identifier: MIT-0 - -import argparse -import json -import os -import shutil -import uuid -import sys -import logging -import boto3 -from s3 import S3 -from pathlib import Path - -deployment_account_region = os.environ.get("AWS_REGION") -project_root = os.path.dirname(__file__) -s3_rdk_assets_prefix = "rdk_assets" -config_rules_dir = "config-rules" -templates_dir = "templates" -config_rules_root = os.path.join(project_root, "config-rules") -templates_root = os.path.join(project_root, templates_dir) - - -def load_json_file(file: str) -> dict: - try: - with open(f"{file}", "r", ecoding="utf-8") as file: - return json.load(file) - except FileNotFoundError: - logging.exception(f"File {file} not found.") - sys.exit(1) - - -def replace_rule_name_and_load(file: str, rule_name:str, rule_name_stripped:str) -> dict: - try: - with open(file, 'r', encoding="utf-8") as f: - content = f.read().replace("RuleNameStripped", rule_name_stripped) - content = content.replace("RuleName", rule_name) - return json.loads(content) - except FileNotFoundError: - logging.exception(f"File {file} not found.") - sys.exit(1) - - -def clean_up_template(file: str): - if os.path.exists(file): - os.remove(file) - - -def get_template_skeleton(shared_modules_bucket: str) -> dict: - #get skeleton - parameters = load_json_file(Path(templates_root).joinpath("parameters.json")) - parameters["SourceBucketFolder"]["Default"] = s3_rdk_assets_prefix - parameters["SourceBucket"]["Default"] = shared_modules_bucket - - #get parameters - skeleton = load_json_file(Path(templates_root).joinpath("skeleton.json")) - - skeleton["Parameters"] = parameters - - return skeleton - - -def add_lambda_to_template_by_rule(template:dict, config_rule_dir: str, rule_name:str, s3_asset_key:str) -> dict: - parameter_file = Path(config_rule_dir).joinpath("parameters.json") - parameter_content = load_json_file(parameter_file) - rule_name_stripped = rule_name.replace("_", "") - runtime = parameter_content.get('Parameters').get('SourceRuntime') - - lambda_role = replace_rule_name_and_load(Path(templates_root).joinpath("lambda-role.json"), rule_name, rule_name_stripped) - template["Resources"][f"{rule_name_stripped}LambdaRole"] = lambda_role - - lambda_function = replace_rule_name_and_load(Path(templates_root).joinpath("lambda-function.json"), rule_name, rule_name_stripped) - lambda_function["Properties"]["Code"]["S3Key"] = s3_asset_key - lambda_function["Properties"]["Runtime"] = runtime - template["Resources"][f"{rule_name_stripped}LambdaFunction"] = lambda_function - - lambda_permission = replace_rule_name_and_load(Path(templates_root).joinpath("lambda-permission.json"), rule_name, rule_name_stripped) - template["Resources"][f"{rule_name_stripped}LambdaPermissions"] = lambda_permission - - return template - - -def write_template(template:dict, file_name:str): - with open(file_name, "a") as file: - json.dump(template, file, indent=4) - - -def main(shared_modules_bucket: str): - s3 = S3(deployment_account_region, shared_modules_bucket) - clean_up_template(template_name) - template = get_template_skeleton(shared_modules_bucket) - - config_rules_dirs = [x for x in Path(config_rules_root).iterdir() if x.is_dir()] - for config_rule_dir in config_rules_dirs: - rule_name = config_rule_dir.name.replace("-", "_") - - logging.info(f'Zipping rule {config_rule_dir.name}') - - file_asset_path = shutil.make_archive( - Path(config_rule_dir).joinpath(config_rule_dir.name), - "zip", - config_rule_dir - ) - unique_id = uuid.uuid4() - if asset_folder: - s3_asset_key =f'{asset_folder}/{rule_name}/{rule_name}-{unique_id}.zip' - - logging.info(f'Uploading rule {config_rule_dir.name}') - uploaded_asset_path = s3.put_object( - s3_asset_key, - file_asset_path, - style="s3-url", - pre_check=True, - ) - print(f"uploaded to {uploaded_asset_path}") - clean_up_template(file_asset_path) - print(f"Creating template for {rule_name}") - template = add_lambda_to_template_by_rule(template, config_rule_dir, rule_name, s3_asset_key) - - write_template(template, template_name) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument('--asset-folder', required=False, help='[optional] Asset folder in the ADF bucket') - parser.add_argument('--template-name', required=True, help='Name for the generated template name') - parser.add_argument( - "-r", - "--region", - ) - args = parser.parse_args() - - target_region = args.region if args.region else deployment_account_region - parameter_store = boto3.client('ssm') - - template_name = args.template_name - - bucket_path_ssm = f"/cross_region/s3_regional_bucket/{target_region}" - res = parameter_store.get_parameter(Name=bucket_path_ssm) - - shared_modules_bucket = res['Parameter']['Value'] - asset_folder = args.asset_folder if args.asset_folder else s3_rdk_assets_prefix - # If remove trailing slash if exists to be - if asset_folder and asset_folder.endswith('/'): - asset_folder = asset_folder[:-1] - - main(shared_modules_bucket) diff --git a/samples/sample-rdk-rules/meta/custom-configs.png b/samples/sample-rdk-rules/meta/custom-configs.png deleted file mode 100644 index c52993c21..000000000 Binary files a/samples/sample-rdk-rules/meta/custom-configs.png and /dev/null differ diff --git a/samples/sample-rdk-rules/meta/lambda-account-id-trusted-entity.png b/samples/sample-rdk-rules/meta/lambda-account-id-trusted-entity.png deleted file mode 100644 index c7ccd341b..000000000 Binary files a/samples/sample-rdk-rules/meta/lambda-account-id-trusted-entity.png and /dev/null differ diff --git a/samples/sample-rdk-rules/params/global.json b/samples/sample-rdk-rules/params/global.json deleted file mode 100644 index b659fa258..000000000 --- a/samples/sample-rdk-rules/params/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "Parameters": { - "LambdaAccountId": "1111111111", - "ConfigRoleArnToAssume": "config-role-arn-here | ex: arn:aws:iam::*:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig" - } -} diff --git a/samples/sample-rdk-rules/requirements.txt b/samples/sample-rdk-rules/requirements.txt deleted file mode 100644 index e34a0b267..000000000 --- a/samples/sample-rdk-rules/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -s3==3.0.0 -boto3==1.34.80 -argparse==1.4.0 diff --git a/samples/sample-rdk-rules/templates/lambda-function.json b/samples/sample-rdk-rules/templates/lambda-function.json deleted file mode 100644 index d8dabb960..000000000 --- a/samples/sample-rdk-rules/templates/lambda-function.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "Type": "AWS::Lambda::Function", - "DependsOn": "RuleNameStrippedLambdaRole", - "Properties": { - "FunctionName": "RDK-Rule-Function-RuleNameStripped", - "Code": { - "S3Bucket": { - "Ref": "SourceBucket" - }, - "S3Key": "RuleName/RuleName.zip" - }, - "Description": "Function for AWS Config Rule RuleName", - "Handler": "RuleName.lambda_handler", - "MemorySize": "256", - "Role": { - "Fn::GetAtt": [ - "RuleNameStrippedLambdaRole", - "Arn" - ] - }, - "Runtime": "RuleRuntime", - "Timeout": "60", - "Tags": [] - } -} diff --git a/samples/sample-rdk-rules/templates/lambda-permission.json b/samples/sample-rdk-rules/templates/lambda-permission.json deleted file mode 100644 index fa151fe3f..000000000 --- a/samples/sample-rdk-rules/templates/lambda-permission.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Type": "AWS::Lambda::Permission", - "DependsOn": "RuleNameStrippedLambdaFunction", - "Properties": { - "FunctionName": { - "Fn::GetAtt": [ - "RuleNameStrippedLambdaFunction", - "Arn" - ] - }, - "Action": "lambda:InvokeFunction", - "Principal": "config.amazonaws.com" - } -} diff --git a/samples/sample-rdk-rules/templates/lambda-role.json b/samples/sample-rdk-rules/templates/lambda-role.json deleted file mode 100644 index ccc249765..000000000 --- a/samples/sample-rdk-rules/templates/lambda-role.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "Type": "AWS::IAM::Role", - "Properties": { - "Path": "/rdk/", - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AllowLambdaAssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] - }, - "Policies": [ - { - "PolicyName": "ConfigRulePolicy", - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "1", - "Action": ["s3:GetObject"], - "Effect": "Allow", - "Resource": { - "Fn::Sub": "arn:${AWS::Partition}:s3:::${SourceBucket}/${SourceBucketFolder}/*" - } - }, - { - "Sid": "2", - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", - "logs:DescribeLogStreams" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Sid": "3", - "Action": ["config:PutEvaluations"], - "Effect": "Allow", - "Resource": "*" - }, - { - "Sid": "4", - "Action": [ - "iam:List*", - "iam:Describe*", - "iam:Get*" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Sid": "5", - "Action": ["sts:AssumeRole"], - "Effect": "Allow", - "Resource": "${ConfigRoleArnToAssume}" - } - ] - } - } - ], - "ManagedPolicyArns": [ - { - "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/ReadOnlyAccess" - } - ] - } -} diff --git a/samples/sample-rdk-rules/templates/parameters.json b/samples/sample-rdk-rules/templates/parameters.json deleted file mode 100644 index 91bb41969..000000000 --- a/samples/sample-rdk-rules/templates/parameters.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "SourceBucket": { - "Description": "Name of the S3 bucket that you have stored the rule zip files in.", - "Type": "String", - "MinLength": "1", - "MaxLength": "255" - }, - "SourceBucketFolder": { - "Description": "Folder in the s3 bucket all the lambda function code stored", - "Type": "String", - "MinLength": "1", - "MaxLength": "255" - }, - "LambdaAccountId": { - "Description": "Account ID that contains Lambda functions for Config Rules.", - "Type": "String", - "MinLength": "12", - "MaxLength": "12" - }, - "ConfigRoleArnToAssume": { - "Description": "Lambda function required to assume this config role in target accounts to put evaluations", - "Type": "String" - } -} diff --git a/samples/sample-rdk-rules/templates/skeleton.json b/samples/sample-rdk-rules/templates/skeleton.json deleted file mode 100644 index 5c8a2f2e9..000000000 --- a/samples/sample-rdk-rules/templates/skeleton.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09", - "Description": "AWS CloudFormation template to create Lambda functions for backing custom AWS Config rules. You will be billed for the AWS resources used if you create a stack from this template.", - "Resources": {} -} diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml index 0665d73ba..6d6220ad1 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/deployment/global.yml @@ -320,6 +320,7 @@ Resources: - "sts:AssumeRole" Resource: - !Sub arn:${AWS::Partition}:iam::*:role/adf-readonly-automation-role + - !Sub arn:${AWS::Partition}:iam::*:role/adf/organizations/adf-organizations-readonly Condition: StringEquals: aws:PrincipalOrgID: !Ref OrganizationId diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/terraform/adf_terraform.sh b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/terraform/adf_terraform.sh index 111731c84..39093b16a 100755 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/terraform/adf_terraform.sh +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/helpers/terraform/adf_terraform.sh @@ -28,15 +28,17 @@ tfinit() { fi terraform init \ -backend-config "bucket=$S3_BUCKET_REGION_NAME" \ + -backend-config "encrypt=true" \ -backend-config "kms_key_id=$KMS_KEY_ARN" \ -backend-config "region=$AWS_REGION" \ -backend-config "key=$ADF_PROJECT_NAME/$ACCOUNT_ID.tfstate" \ -backend-config "dynamodb_table=adf-tflocktable" - echo "Bucket: $S3_BUCKET_REGION_NAME" - echo "KMS Key ARN: $KMS_KEY_ARN" - echo "Region: $AWS_REGION" - echo "Key: $ADF_PROJECT_NAME/$ACCOUNT_ID.tfstate" + echo "Bucket: $S3_BUCKET_REGION_NAME" + echo "Encrypt: true" + echo "KMS Key ARN: $KMS_KEY_ARN" + echo "Region: $AWS_REGION" + echo "Key: $ADF_PROJECT_NAME/$ACCOUNT_ID.tfstate" echo "DynamoDB table: adf-tflocktable" } tfplan() { @@ -50,7 +52,7 @@ tfplan() { aws s3 cp \ "${ADF_PROJECT_NAME}-${TF_VAR_TARGET_ACCOUNT_ID}-${TS}.log" \ "s3://${S3_BUCKET_REGION_NAME}/${ADF_PROJECT_NAME}/tf-plan/${DATE}/${TF_VAR_TARGET_ACCOUNT_ID}/${ADF_PROJECT_NAME}-${TF_VAR_TARGET_ACCOUNT_ID}-${TS}.log" \ - --sse-kms-key-id $KMS_KEY_ARN + --sse-kms-key-id $KMS_KEY_ARN --sse "aws:kms" echo "Path to terraform plan s3://$S3_BUCKET_REGION_NAME/$ADF_PROJECT_NAME/tf-plan/$DATE/$TF_VAR_TARGET_ACCOUNT_ID/$ADF_PROJECT_NAME-$TF_VAR_TARGET_ACCOUNT_ID-$TS.log" } tfapply() {