diff --git a/.editorconfig b/.editorconfig index 402505f..9f09849 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ root = true [*] end_of_line = lf insert_final_newline = true +charset = utf-8 +indent_style = space +tab_width = 2 diff --git a/.gitignore b/.gitignore index a566ebf..a5835b9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,40 @@ !jest.config.js !.eslintrc.js !.prettierrc.js + +!lib/**/*.ts +!test/**/*.ts *.d.ts -node_modules + dist +node_modules + +# yarn asset +yarn-install.log +.yarn/* +!.yarn/releases/ +!.yarn/plugins/ +!.yarn/versions/ +!.yarn/sdks/ +.pnp.* + +# yarn asset +yarn-install.log +.yarn/* +!.yarn/releases/ +!.yarn/plugins/ +!.yarn/versions/ +!.yarn/sdks/ +.pnp.* + +# yarn asset +yarn-install.log +.yarn/* +!.yarn/releases/ +!.yarn/plugins/ +!.yarn/versions/ +!.yarn/sdks/ +.pnp.* # yarn asset yarn-install.log @@ -28,3 +59,4 @@ cdk.context.json assets source-zip +aws4embeddedlinux-cdk-lib-*.tgz diff --git a/.npmignore b/.npmignore index c1d6d45..c42d5b9 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,18 @@ -*.ts -!*.d.ts +.yarn +.github +.vscode +test -# CDK asset staging directory -.cdk.staging -cdk.out +.editorconfig +.gitattributes +.pre-commit-config.yaml +eslint.config.mjs +jest.config.js +typedoc.json +tsconfig.*.json +package-lock.json +yarn.lock + +CODE_OF_CONDUCT.md +CONTRIBUTING.md +SECURITY.md diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0afa7b4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "eslint.alwaysShowStatus": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "explorer.autoReveal": false +} diff --git a/README.md b/README.md index 657fbfd..e6ff5a5 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,7 @@ npm install aws4embeddedlinux/aws4embeddedlinux-ci of `yarn': ```bash -yarn add github:aws4embeddedlinux/aws4embeddedlinux-ci +yarn add aws4embeddedlinux-cdk-lib@aws4embeddedlinux/aws4embeddedlinux-ci yarn install ``` @@ -254,7 +254,7 @@ const projectPipeline = new EmbeddedLinuxCodePipelineStack(app, "demo-project", }); ``` -Refer to the [API Documentation](https://aws4embeddedlinux.github.io/aws4embeddedlinux-ci) and the [sample](github.com/aws4embeddedlinux/aws4embeddedlinux-ci-examples) for more details. +Refer to the [API Documentation](https://aws4embeddedlinux.github.io/aws4embeddedlinux-ci) and the [sample](https://github.com/aws4embeddedlinux/aws4embeddedlinux-ci-examples) for more details. Once you have completed the code of your application, you can deploy the CDK stack using: @@ -275,7 +275,7 @@ This will create an Ubuntu based container for building the Yocto images. > [!NOTE] > -> We recommend you to deploy first the 'Base Image' pipeline and once the pipeline completes successfully, then you can deploy the other pipelines in you application as described in the [sample](github.com/aws4embeddedlinux/aws4embeddedlinux-ci-examples). +> We recommend you to deploy first the 'Base Image' pipeline and once the pipeline completes successfully, then you can deploy the other pipelines in you application as described in the [sample](https://github.com/aws4embeddedlinux/aws4embeddedlinux-ci-examples). > Once your pipelines completes successfully, the Yocto deploy directory generated content will be pushed into a S3 bucket. diff --git a/eslint.config.mjs b/eslint.config.mjs index a9f6154..c266dc2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,11 +1,12 @@ import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin"; +import simpleImportSort from "eslint-plugin-simple-import-sort"; import tsdoc from "eslint-plugin-tsdoc"; import globals from "globals"; import tsParser from "@typescript-eslint/parser"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import eslint from "@eslint/js"; -import tseslint from "typescript-eslint"; +import eslintjs from "@eslint/js"; +import eslintts from "typescript-eslint"; import { FlatCompat } from "@eslint/eslintrc"; const __filename = fileURLToPath(import.meta.url); @@ -16,14 +17,22 @@ const gitignorePath = path.resolve(__dirname, ".gitignore"); const compat = new FlatCompat({ baseDirectory: __dirname, - recommendedConfig: eslint.configs.recommended, - allConfig: eslint.configs.all, + recommendedConfig: eslintjs.configs.recommended, + allConfig: eslintjs.configs.all, }); export default [ + ...compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + ), + ...eslintts.configs.recommended, { + ...eslintjs.configs.recommended, plugins: { "@typescript-eslint": typescriptEslintEslintPlugin, + "simple-import-sort": simpleImportSort, tsdoc, }, @@ -39,7 +48,7 @@ export default [ parserOptions: { sourceType: "module", - project: "./tsconfig.json", + project: "./tsconfig.eslint.json", }, }, @@ -61,8 +70,21 @@ export default [ "prettier/prettier": [ "error", { - singleQuote: true, - trailingComma: "es5", + singleQuote: false, + trailingComma: "all", + }, + ], + + "@typescript-eslint/no-unused-vars": [ + "error", + { + args: "all", + argsIgnorePattern: "^_", + caughtErrors: "all", + caughtErrorsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + varsIgnorePattern: "^_", + ignoreRestSiblings: true, }, ], }, @@ -77,13 +99,6 @@ export default [ "/test/**", "/tmp/**", ], - ...eslint.configs.recommended, }, includeIgnoreFile(gitignorePath), - ...compat.extends( - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended", - ), - ...tseslint.configs.recommended, ]; diff --git a/jest.config.js b/jest.config.js index 000683e..2f696c9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,13 +1,4 @@ /* eslint-env node */ -// module.exports = { -// testEnvironment: "node", -// roots: ["/test"], -// testMatch: ["**/*.test.ts"], -// transform: { -// "^.+\\.tsx?$": "ts-jest", -// }, -// }; - export const testEnvironment = "node"; export const roots = ["/test"]; export const testMatch = ["**/*.test.ts"]; diff --git a/lib/codepipeline-embedded-linux.ts b/lib/codepipeline-embedded-linux.ts index b27fdcb..c3bdbc2 100644 --- a/lib/codepipeline-embedded-linux.ts +++ b/lib/codepipeline-embedded-linux.ts @@ -49,7 +49,7 @@ export interface EmbeddedLinuxCodePipelineProps extends cdk.StackProps { readonly buildPolicyAdditions?: iam.PolicyStatement[]; /** Additional build environment variables to the build project. */ readonly environmentVariables?: { - string: codebuild.BuildEnvironmentVariable; + [key: string]: codebuild.BuildEnvironmentVariable; }; /** The encryption key use across*/ readonly encryptionKey: kms.Key; @@ -272,12 +272,12 @@ export class EmbeddedLinuxCodePipelineStack extends cdk.Stack { project, }); - const artifactAction: codepipeline_actions.S3DeployAction = + const outputAction: codepipeline_actions.S3DeployAction = new codepipeline_actions.S3DeployAction({ - actionName: "Artifact", + actionName: "Output", input: buildActionOutputArtifact, - bucket: props.pipelineArtifactBucket, - objectKey: `${props.pipelineArtifactPrefix}/${sourceRepoAsset.s3ObjectKey}`, + bucket: props.pipelineOutputBucket, + objectKey: `${props.pipelineOutputPrefix}`, }); /** Here we create the logic to check for presence of ECR image on the CodeCodePipeline automatic triggering upon resource creation, @@ -352,8 +352,8 @@ export class EmbeddedLinuxCodePipelineStack extends cdk.Stack { actions: [buildAction], }, { - stageName: "Artifact", - actions: [artifactAction], + stageName: "Output", + actions: [outputAction], }, ], }, diff --git a/lib/index.ts b/lib/index.ts index e897a4a..2707f01 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,23 +1,8 @@ -import * as s3 from "aws-cdk-lib/aws-s3"; - export * from "./codebuild-embedded-linux"; export * from "./codepipeline-embedded-linux-base-image"; export * from "./codepipeline-embedded-linux"; export * from "./codepipeline-resources"; -export function isBucketVersioned(bucket: s3.Bucket | s3.IBucket) { - const bucketCfn: s3.CfnBucket = bucket.node.defaultChild as s3.CfnBucket; - if ( - bucketCfn.versioningConfiguration && - ( - bucketCfn.versioningConfiguration as s3.CfnBucket.VersioningConfigurationProperty - ).status != "Enabled" - ) { - return true; - } - return false; -} - /** * The type of project built. */ diff --git a/package-lock.json b/package-lock.json index f52d61d..3f3f560 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "eslint": "^9.16.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-tsdoc": "^0.4.0", "globals": "^15.13.0", "jest": "^29.7.0", @@ -2405,6 +2406,16 @@ } } }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", + "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, "node_modules/eslint-plugin-tsdoc": { "version": "0.4.0", "dev": true, diff --git a/package.json b/package.json index bf40894..9bc5113 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "aws4embeddedlinux-cdk-lib", "version": "0.2.0", - "main": "dist/lib/index.js", - "types": "dist/lib/index.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "license": "MIT", "scripts": { "build": "tsc", @@ -11,17 +11,12 @@ "doc": "typedoc --sort source-order --readme README.md", "format": "eslint '**/*.{js,ts,json}' --quiet --fix", "postinstall": "npm run build > /dev/null || echo 'prepapre command completed successfully with errors'", - "prepare": "npm run build > /dev/null || echo 'prepapre command completed successfully with errors'", "prepare-commit": "pre-commit run --all-files --color=always --show-diff-on-failure", "test": "jest", "update-snapshot": "jest -u", "watch": "tsc -w", - "postclean": "rm -rf ./dist", - "prebuild": "./utils/build-assets.sh", "precheck": "yarn clean", - "preformat": "yarn clean", - "pretest": "yarn prebuild", - "preupdate-snapshot": "yarn prebuild" + "preformat": "yarn clean" }, "dependencies": { "aws-cdk-lib": "2.176.0", @@ -40,6 +35,7 @@ "eslint": "^9.16.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-tsdoc": "^0.4.0", "globals": "^15.13.0", "jest": "^29.7.0", diff --git a/test/__snapshots__/codebuild-embedded-linux.test.ts.snap b/test/__snapshots__/codebuild-embedded-linux.test.ts.snap new file mode 100644 index 0000000..8d811aa --- /dev/null +++ b/test/__snapshots__/codebuild-embedded-linux.test.ts.snap @@ -0,0 +1,1656 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EmbeddedLinuxCodeBuildProjectStack Custom Snapshot 1`] = ` +{ + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "EmbeddedLinuxCodeBuildProject2101BD97": { + "DependsOn": [ + "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5", + ], + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS", + }, + "Cache": { + "Type": "NO_CACHE", + }, + "EncryptionKey": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_XLARGE", + "Image": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 4, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + ], + }, + ], + }, + ".dkr.ecr.", + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + ], + }, + ], + }, + ".", + { + "Ref": "AWS::URLSuffix", + }, + "/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", + }, + ":latest", + ], + ], + }, + "ImagePullCredentialsType": "SERVICE_ROLE", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER", + }, + "FileSystemLocations": [ + { + "Identifier": "nfs", + "Location": { + "Fn::Join": [ + "", + [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + ".efs.eu-central-1.amazonaws.com:/", + ], + ], + }, + "MountPoint": "/nfs", + "Type": "EFS", + }, + ], + "LogsConfig": { + "CloudWatchLogs": { + "GroupName": { + "Ref": "EmbeddedLinuxCodeBuildProjectLogs790B1140", + }, + "Status": "ENABLED", + }, + }, + "Name": "test-stack", + "ServiceRole": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + "Arn", + ], + }, + "Source": { + "BuildSpec": "{ + "version": "0.2", + "phases": { + "build": { + "commands": [ + "echo \\"DUMMY BUILDSPEC - can not be empty\\"" + ] + } + }, + "artifacts": { + "files": [ + "**/*" + ], + "base-directory": "." + } +}", + "Type": "NO_SOURCE", + }, + "TimeoutInMinutes": 240, + "VpcConfig": { + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B", + "GroupId", + ], + }, + ], + "Subnets": [ + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + }, + "Type": "AWS::CodeBuild::Project", + }, + "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F": { + "DeletionPolicy": "Delete", + "Properties": { + "Encrypted": true, + "FileSystemTags": [ + { + "Key": "Name", + "Value": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem", + }, + ], + }, + "Type": "AWS::EFS::FileSystem", + "UpdateReplacePolicy": "Delete", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsMountTarget1BB9724D2": { + "Properties": { + "FileSystemId": { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + ], + "SubnetId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + }, + "Type": "AWS::EFS::MountTarget", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsMountTarget270BB2C65": { + "Properties": { + "FileSystemId": { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + ], + "SubnetId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + }, + "Type": "AWS::EFS::MountTarget", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65": { + "Properties": { + "GroupDescription": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem/EfsSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "Tags": [ + { + "Key": "Name", + "Value": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem", + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroupfromteststackEmbeddedLinuxCodeBuildProjectSecurityGroup58F8D73B20499408861B": { + "Properties": { + "Description": "from teststackEmbeddedLinuxCodeBuildProjectSecurityGroup58F8D73B:2049", + "FromPort": 2049, + "GroupId": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + "IpProtocol": "tcp", + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B", + "GroupId", + ], + }, + "ToPort": 2049, + }, + "Type": "AWS::EC2::SecurityGroupIngress", + }, + "EmbeddedLinuxCodeBuildProjectLogs790B1140": { + "DeletionPolicy": "Delete", + "Properties": { + "LogGroupName": "test-stack-EmbeddedLinuxCodeBuildProjectLogs", + "RetentionInDays": 365, + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Delete", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49": { + "DependsOn": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC", + ], + "Properties": { + "Code": { + "ZipFile": { + "Fn::Join": [ + "", + [ + " +import boto3 +import json + +ecr_client = boto3.client('ecr') +codepipeline_client = boto3.client('codepipeline') + +def handler(event, context): + print("Received event: " + json.dumps(event, indent=2)) + response = ecr_client.describe_images(repositoryName='", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", + }, + "', filter={'tagStatus': 'TAGGED'}) + for i in response['imageDetails']: + if 'latest' in i['imageTags']: + break + else: + print('OS image not found. Stopping execution.') + response = codepipeline_client.stop_pipeline_execution( + pipelineName=event['detail']['pipeline'], + pipelineExecutionId=event['detail']['execution-id'], + abandon=True, + reason='OS image not found in ECR repository. Stopping pipeline until image is present.') + ", + ], + ], + }, + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC", + "Arn", + ], + }, + "Runtime": "python3.10", + }, + "Type": "AWS::Lambda::Function", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartLogRetentionC530B5EE": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + }, + ], + ], + }, + "RetentionInDays": 365, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleA197C004": { + "Properties": { + "EventPattern": { + "detail": { + "execution-trigger": { + "trigger-type": [ + "CreatePipeline", + ], + }, + "state": [ + "STARTED", + ], + }, + "detail-type": [ + "CodePipeline Pipeline Execution State Change", + ], + "source": [ + "aws.codepipeline", + ], + }, + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + "Arn", + ], + }, + "Id": "Target0", + }, + ], + }, + "Type": "AWS::Events::Rule", + }, + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleAllowEventRuleteststackEmbeddedLinuxCodeBuildProjectOSImageCheckOnStartDE4F09A20DAF4342": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + "Arn", + ], + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleA197C004", + "Arn", + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", + "ec2:DescribeDhcpOptions", + "ec2:DescribeVpcs", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5", + "Roles": [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "EmbeddedLinuxCodeBuildProjectRole692E9BCD": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AWSCodeBuildAdminAccess", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "EmbeddedLinuxCodeBuildProjectRoleDefaultPolicyFE7F690E": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + ], + "Effect": "Allow", + "Resource": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectLogs790B1140", + "Arn", + ], + }, + }, + { + "Action": "ec2:CreateNetworkInterfacePermission", + "Condition": { + "StringEquals": { + "ec2:AuthorizedService": "codebuild.amazonaws.com", + "ec2:Subnet": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":subnet/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":subnet/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + ], + ], + }, + ], + }, + }, + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":network-interface/*", + ], + ], + }, + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":logs:eu-central-1:111111111111:log-group:/aws/codebuild/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":logs:eu-central-1:111111111111:log-group:/aws/codebuild/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":codebuild:eu-central-1:111111111111:report-group/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + "-*", + ], + ], + }, + }, + { + "Action": [ + "kms:Decrypt", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + ], + "Effect": "Allow", + "Resource": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", + }, + }, + { + "Action": "s3:GetObject", + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "ec2:DescribeSecurityGroups", + "codestar-connections:GetConnection", + "codestar-connections:GetConnectionToken", + "codeconnections:GetConnectionToken", + "codeconnections:GetConnection", + "codeconnections:ListConnection", + "codeconnections:UseConnection", + "codebuild:ListConnectedOAuthAccounts", + "codebuild:ListRepositories", + "codebuild:PersistOAuthToken", + "codebuild:ImportSourceCredentials", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "EmbeddedLinuxCodeBuildProjectRoleDefaultPolicyFE7F690E", + "Roles": [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B": { + "Properties": { + "GroupDescription": "Security Group to allow attaching EFS", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestvpc8985080ECidrBlockEB7C13CD", + }, + "Description": "NFS Mount Port", + "FromPort": 2049, + "IpProtocol": "tcp", + "ToPort": 2049, + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + ], + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-111111111111-eu-central-1", + "S3Key": "arbitrary-file.ext", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn", + ], + }, + "Runtime": "nodejs20.x", + "Timeout": 900, + }, + "Type": "AWS::Lambda::Function", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:PutRetentionPolicy", + "logs:DeleteRetentionPolicy", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; + +exports[`EmbeddedLinuxCodeBuildProjectStack Snapshot 1`] = ` +{ + "Parameters": { + "BootstrapVersion": { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": { + "EmbeddedLinuxCodeBuildProject2101BD97": { + "DependsOn": [ + "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5", + ], + "Properties": { + "Artifacts": { + "Type": "NO_ARTIFACTS", + }, + "Cache": { + "Type": "NO_CACHE", + }, + "EncryptionKey": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", + }, + "Environment": { + "ComputeType": "BUILD_GENERAL1_XLARGE", + "Image": { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 4, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + ], + }, + ], + }, + ".dkr.ecr.", + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + ], + }, + ], + }, + ".", + { + "Ref": "AWS::URLSuffix", + }, + "/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", + }, + ":latest", + ], + ], + }, + "ImagePullCredentialsType": "SERVICE_ROLE", + "PrivilegedMode": true, + "Type": "LINUX_CONTAINER", + }, + "FileSystemLocations": [ + { + "Identifier": "nfs", + "Location": { + "Fn::Join": [ + "", + [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + ".efs.eu-central-1.amazonaws.com:/", + ], + ], + }, + "MountPoint": "/nfs", + "Type": "EFS", + }, + ], + "LogsConfig": { + "CloudWatchLogs": { + "GroupName": { + "Ref": "EmbeddedLinuxCodeBuildProjectLogs790B1140", + }, + "Status": "ENABLED", + }, + }, + "Name": "test-stack", + "ServiceRole": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + "Arn", + ], + }, + "Source": { + "BuildSpec": "{ + "version": "0.2", + "phases": { + "build": { + "commands": [ + "echo \\"DUMMY BUILDSPEC - can not be empty\\"" + ] + } + }, + "artifacts": { + "files": [ + "**/*" + ], + "base-directory": "." + } +}", + "Type": "NO_SOURCE", + }, + "TimeoutInMinutes": 240, + "VpcConfig": { + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B", + "GroupId", + ], + }, + ], + "Subnets": [ + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + }, + "Type": "AWS::CodeBuild::Project", + }, + "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F": { + "DeletionPolicy": "Delete", + "Properties": { + "Encrypted": true, + "FileSystemTags": [ + { + "Key": "Name", + "Value": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem", + }, + ], + }, + "Type": "AWS::EFS::FileSystem", + "UpdateReplacePolicy": "Delete", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsMountTarget1BB9724D2": { + "Properties": { + "FileSystemId": { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + ], + "SubnetId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + }, + "Type": "AWS::EFS::MountTarget", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsMountTarget270BB2C65": { + "Properties": { + "FileSystemId": { + "Ref": "EmbeddedLinuxCodeBuildProjectFilesystem54E4C11F", + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + ], + "SubnetId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + }, + "Type": "AWS::EFS::MountTarget", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65": { + "Properties": { + "GroupDescription": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem/EfsSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "Tags": [ + { + "Key": "Name", + "Value": "test-stack/EmbeddedLinuxCodeBuildProjectFilesystem", + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroupfromteststackEmbeddedLinuxCodeBuildProjectSecurityGroup58F8D73B20499408861B": { + "Properties": { + "Description": "from teststackEmbeddedLinuxCodeBuildProjectSecurityGroup58F8D73B:2049", + "FromPort": 2049, + "GroupId": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectFilesystemEfsSecurityGroup64B52E65", + "GroupId", + ], + }, + "IpProtocol": "tcp", + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B", + "GroupId", + ], + }, + "ToPort": 2049, + }, + "Type": "AWS::EC2::SecurityGroupIngress", + }, + "EmbeddedLinuxCodeBuildProjectLogs790B1140": { + "DeletionPolicy": "Delete", + "Properties": { + "LogGroupName": "test-stack-EmbeddedLinuxCodeBuildProjectLogs", + "RetentionInDays": 365, + }, + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Delete", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49": { + "DependsOn": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC", + ], + "Properties": { + "Code": { + "ZipFile": { + "Fn::Join": [ + "", + [ + " +import boto3 +import json + +ecr_client = boto3.client('ecr') +codepipeline_client = boto3.client('codepipeline') + +def handler(event, context): + print("Received event: " + json.dumps(event, indent=2)) + response = ecr_client.describe_images(repositoryName='", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", + }, + "', filter={'tagStatus': 'TAGGED'}) + for i in response['imageDetails']: + if 'latest' in i['imageTags']: + break + else: + print('OS image not found. Stopping execution.') + response = codepipeline_client.stop_pipeline_execution( + pipelineName=event['detail']['pipeline'], + pipelineExecutionId=event['detail']['execution-id'], + abandon=True, + reason='OS image not found in ECR repository. Stopping pipeline until image is present.') + ", + ], + ], + }, + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC", + "Arn", + ], + }, + "Runtime": "python3.10", + }, + "Type": "AWS::Lambda::Function", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartLogRetentionC530B5EE": { + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + }, + ], + ], + }, + "RetentionInDays": 365, + "ServiceToken": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A", + "Arn", + ], + }, + }, + "Type": "Custom::LogRetention", + }, + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartServiceRole886C2BCC": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleA197C004": { + "Properties": { + "EventPattern": { + "detail": { + "execution-trigger": { + "trigger-type": [ + "CreatePipeline", + ], + }, + "state": [ + "STARTED", + ], + }, + "detail-type": [ + "CodePipeline Pipeline Execution State Change", + ], + "source": [ + "aws.codepipeline", + ], + }, + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + "Arn", + ], + }, + "Id": "Target0", + }, + ], + }, + "Type": "AWS::Events::Rule", + }, + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleAllowEventRuleteststackEmbeddedLinuxCodeBuildProjectOSImageCheckOnStartDE4F09A20DAF4342": { + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOSImageCheckOnStartA4649D49", + "Arn", + ], + }, + "Principal": "events.amazonaws.com", + "SourceArn": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectOnPipelineStartRuleA197C004", + "Arn", + ], + }, + }, + "Type": "AWS::Lambda::Permission", + }, + "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", + "ec2:DescribeDhcpOptions", + "ec2:DescribeVpcs", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "EmbeddedLinuxCodeBuildProjectPolicyDocumentCDFD1ED5", + "Roles": [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "EmbeddedLinuxCodeBuildProjectRole692E9BCD": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/AWSCodeBuildAdminAccess", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "EmbeddedLinuxCodeBuildProjectRoleDefaultPolicyFE7F690E": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + ], + "Effect": "Allow", + "Resource": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", + }, + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*", + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodeBuildProjectLogs790B1140", + "Arn", + ], + }, + }, + { + "Action": "ec2:CreateNetworkInterfacePermission", + "Condition": { + "StringEquals": { + "ec2:AuthorizedService": "codebuild.amazonaws.com", + "ec2:Subnet": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":subnet/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", + }, + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":subnet/", + { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", + }, + ], + ], + }, + ], + }, + }, + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":ec2:", + { + "Ref": "AWS::Region", + }, + ":", + { + "Ref": "AWS::AccountId", + }, + ":network-interface/*", + ], + ], + }, + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":logs:eu-central-1:111111111111:log-group:/aws/codebuild/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + ], + ], + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":logs:eu-central-1:111111111111:log-group:/aws/codebuild/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + ":*", + ], + ], + }, + ], + }, + { + "Action": [ + "codebuild:CreateReportGroup", + "codebuild:CreateReport", + "codebuild:UpdateReport", + "codebuild:BatchPutTestCases", + "codebuild:BatchPutCodeCoverages", + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":codebuild:eu-central-1:111111111111:report-group/", + { + "Ref": "EmbeddedLinuxCodeBuildProject2101BD97", + }, + "-*", + ], + ], + }, + }, + { + "Action": [ + "kms:Decrypt", + "kms:Encrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + ], + "Effect": "Allow", + "Resource": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", + }, + }, + { + "Action": [ + "ec2:DescribeSecurityGroups", + "codestar-connections:GetConnection", + "codestar-connections:GetConnectionToken", + "codeconnections:GetConnectionToken", + "codeconnections:GetConnection", + "codeconnections:ListConnection", + "codeconnections:UseConnection", + "codebuild:ListConnectedOAuthAccounts", + "codebuild:ListRepositories", + "codebuild:PersistOAuthToken", + "codebuild:ImportSourceCredentials", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "EmbeddedLinuxCodeBuildProjectRoleDefaultPolicyFE7F690E", + "Roles": [ + { + "Ref": "EmbeddedLinuxCodeBuildProjectRole692E9BCD", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + "EmbeddedLinuxCodeBuildProjectSecurityGroupB289294B": { + "Properties": { + "GroupDescription": "Security Group to allow attaching EFS", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1", + }, + ], + "SecurityGroupIngress": [ + { + "CidrIp": { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestvpc8985080ECidrBlockEB7C13CD", + }, + "Description": "NFS Mount Port", + "FromPort": 2049, + "IpProtocol": "tcp", + "ToPort": 2049, + }, + ], + "VpcId": { + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", + }, + }, + "Type": "AWS::EC2::SecurityGroup", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { + "DependsOn": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + ], + "Properties": { + "Code": { + "S3Bucket": "cdk-hnb659fds-assets-111111111111-eu-central-1", + "S3Key": "arbitrary-file.ext", + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + "Arn", + ], + }, + "Runtime": "nodejs20.x", + "Timeout": 900, + }, + "Type": "AWS::Lambda::Function", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB": { + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com", + }, + }, + ], + "Version": "2012-10-17", + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + ], + ], + }, + ], + }, + "Type": "AWS::IAM::Role", + }, + "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB": { + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:PutRetentionPolicy", + "logs:DeleteRetentionPolicy", + ], + "Effect": "Allow", + "Resource": "*", + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", + "Roles": [ + { + "Ref": "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRole9741ECFB", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5", + ], + { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; diff --git a/test/__snapshots__/codepipeline-embedded-linux-base-image.test.ts.snap b/test/__snapshots__/codepipeline-embedded-linux-base-image.test.ts.snap index 4c808c7..e4acead 100644 --- a/test/__snapshots__/codepipeline-embedded-linux-base-image.test.ts.snap +++ b/test/__snapshots__/codepipeline-embedded-linux-base-image.test.ts.snap @@ -11,21 +11,21 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` [ "aws ecr list-images --repository-name "", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesECRRepositoryA0DB7EB625EEF25E", + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", }, - "" --query "imageIds[?imageTag=='MyTestStack']"", + "" --query "imageIds[?imageTag=='test-stack']"", ], ], }, }, "ECRBaseImageTag": { "Description": "The ECR Image Tag where the base image will be pushed", - "Value": "MyTestStack", + "Value": "test-stack", }, "ECRRepositoryName": { "Description": "The ECR Repository name where the base image will be pushed", "Value": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesECRRepositoryA0DB7EB625EEF25E", + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", }, }, "SourceURI": { @@ -36,7 +36,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` [ "s3://", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, "/base-image/arbitrary-file.ext", ], @@ -67,7 +67,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Properties": { "DestinationBucketKeyPrefix": "base-image", "DestinationBucketName": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, "Extract": false, "OutputObjectKeys": true, @@ -178,14 +178,14 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, "/*", ], @@ -193,19 +193,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, ], "Version": "2012-10-17", }, @@ -221,7 +208,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "CodePipelineBuildBaseImageBuildLogs48BFE4D7": { "DeletionPolicy": "Delete", "Properties": { - "LogGroupName": "MyTestStack-CodePipelineBuildBaseImageBuildLogs", + "LogGroupName": "test-stack-CodePipelineBuildBaseImageBuildLogs", "RetentionInDays": 365, }, "Type": "AWS::Logs::LogGroup", @@ -237,18 +224,12 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` ], "Properties": { "ArtifactStore": { - "EncryptionKey": { - "Id": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - "Type": "KMS", - }, "Location": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesArtifactBucketFF61EB98FA6EAAC1", + "Fn::ImportValue": "test-common:ExportsOutputReftestartF0FFB4BEEC699EE6", }, "Type": "S3", }, - "Name": "MyTestStack", + "Name": "test-stack", "PipelineType": "V1", "RestartExecutionOnUpdate": true, "RoleArn": { @@ -270,7 +251,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Configuration": { "PollForSourceChanges": false, "S3Bucket": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, "S3ObjectKey": "base-image/arbitrary-file.ext", }, @@ -456,83 +437,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, "Type": "AWS::IAM::Policy", }, - "CodePipelineBuildBaseImageCodePipelineMyTestStackCodePipelineBuildBaseImageCodePipelineFF25ACC6SourceEventRulebaseimage1ccdf1583059080a3911192a20ae50cc6b3bfa57d56d0b5b4d3866f920b3ad20zip04E1981E": { - "DependsOn": [ - "CodePipelineBuildBaseImageProject69590E59", - "CodePipelineBuildBaseImageProjectRoleDefaultPolicy6F99FFCC", - "CodePipelineBuildBaseImageProjectRole12B97AA7", - ], - "Properties": { - "EventPattern": { - "detail": { - "eventName": [ - "CompleteMultipartUpload", - "CopyObject", - "PutObject", - ], - "requestParameters": { - "bucketName": [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", - }, - ], - "key": [ - "base-image/arbitrary-file.ext", - ], - }, - "resources": { - "ARN": [ - { - "Fn::Join": [ - "", - [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", - }, - "/base-image/arbitrary-file.ext", - ], - ], - }, - ], - }, - }, - "detail-type": [ - "AWS API Call via CloudTrail", - ], - "source": [ - "aws.s3", - ], - }, - "State": "ENABLED", - "Targets": [ - { - "Arn": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":codepipeline:eu-central-1:111111111111:", - { - "Ref": "CodePipelineBuildBaseImageCodePipeline7907AE86", - }, - ], - ], - }, - "Id": "Target0", - "RoleArn": { - "Fn::GetAtt": [ - "CodePipelineBuildBaseImageCodePipelineEventsRoleD9A83D03", - "Arn", - ], - }, - }, - ], - }, - "Type": "AWS::Events::Rule", - }, "CodePipelineBuildBaseImageCodePipelineRole73E36B25": { "DependsOn": [ "CodePipelineBuildBaseImageProject69590E59", @@ -580,14 +484,14 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -595,19 +499,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, { "Action": "sts:AssumeRole", "Effect": "Allow", @@ -691,14 +582,14 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, "/base-image/arbitrary-file.ext", ], @@ -706,16 +597,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, { "Action": [ "s3:DeleteObject*", @@ -729,14 +610,14 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -744,18 +625,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:Decrypt", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, ], "Version": "2012-10-17", }, @@ -768,6 +637,83 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, "Type": "AWS::IAM::Policy", }, + "CodePipelineBuildBaseImageCodePipelineteststackCodePipelineBuildBaseImageCodePipelineBEEAC58ESourceEventRulebaseimage1ccdf1583059080a3911192a20ae50cc6b3bfa57d56d0b5b4d3866f920b3ad20zipE860D013": { + "DependsOn": [ + "CodePipelineBuildBaseImageProject69590E59", + "CodePipelineBuildBaseImageProjectRoleDefaultPolicy6F99FFCC", + "CodePipelineBuildBaseImageProjectRole12B97AA7", + ], + "Properties": { + "EventPattern": { + "detail": { + "eventName": [ + "CompleteMultipartUpload", + "CopyObject", + "PutObject", + ], + "requestParameters": { + "bucketName": [ + { + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", + }, + ], + "key": [ + "base-image/arbitrary-file.ext", + ], + }, + "resources": { + "ARN": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", + }, + "/base-image/arbitrary-file.ext", + ], + ], + }, + ], + }, + }, + "detail-type": [ + "AWS API Call via CloudTrail", + ], + "source": [ + "aws.s3", + ], + }, + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":codepipeline:eu-central-1:111111111111:", + { + "Ref": "CodePipelineBuildBaseImageCodePipeline7907AE86", + }, + ], + ], + }, + "Id": "Target0", + "RoleArn": { + "Fn::GetAtt": [ + "CodePipelineBuildBaseImageCodePipelineEventsRoleD9A83D03", + "Arn", + ], + }, + }, + ], + }, + "Type": "AWS::Events::Rule", + }, "CodePipelineBuildBaseImageProject69590E59": { "DependsOn": [ "CodePipelineBuildBaseImageBucketDeploymentAwsCliLayerF8B77510", @@ -781,7 +727,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Type": "NO_CACHE", }, "EncryptionKey": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", }, "Environment": { "ComputeType": "BUILD_GENERAL1_MEDIUM", @@ -800,7 +746,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Fn::Split": [ ":", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, ], }, @@ -814,7 +760,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Fn::Split": [ ":", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, ], }, @@ -826,7 +772,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, "/", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesECRRepositoryA0DB7EB625EEF25E", + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", }, ], ], @@ -845,7 +791,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` { "Name": "IMAGE_TAG", "Type": "PLAINTEXT", - "Value": "MyTestStack", + "Value": "test-stack", }, ], "Image": "aws/codebuild/standard:7.0", @@ -861,7 +807,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Status": "ENABLED", }, }, - "Name": "MyTestStack", + "Name": "test-stack", "ServiceRole": { "Fn::GetAtt": [ "CodePipelineBuildBaseImageProjectRole12B97AA7", @@ -993,7 +939,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` ], "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", }, }, { @@ -1008,7 +954,7 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` ], "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, }, { @@ -1025,14 +971,14 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -1040,16 +986,6 @@ exports[`EmbeddedLinuxCodePipelineBaseImageStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, ], "Version": "2012-10-17", }, diff --git a/test/__snapshots__/codepipeline-embedded-linux.test.ts.snap b/test/__snapshots__/codepipeline-embedded-linux.test.ts.snap index 22deb32..376c99d 100644 --- a/test/__snapshots__/codepipeline-embedded-linux.test.ts.snap +++ b/test/__snapshots__/codepipeline-embedded-linux.test.ts.snap @@ -11,9 +11,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` [ "s3://", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesArtifactBucketFF61EB98FA6EAAC1", + "Fn::ImportValue": "test-common:ExportsOutputReftestartF0FFB4BEEC699EE6", }, - "/poky/arbitrary-file.ext", + "/custom/arbitrary-file.ext", ], ], }, @@ -26,9 +26,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` [ "s3://", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesOutputBucketA2144F25070A0F1C", + "Fn::ImportValue": "test-common:ExportsOutputReftestoutA50725182A5BCA18", }, - "/poky", + "/custom", ], ], }, @@ -41,9 +41,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` [ "s3://", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, - "/poky/arbitrary-file.ext", + "/custom/arbitrary-file.ext", ], ], }, @@ -100,18 +100,12 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` ], "Properties": { "ArtifactStore": { - "EncryptionKey": { - "Id": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - "Type": "KMS", - }, "Location": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesArtifactBucketFF61EB98FA6EAAC1", + "Fn::ImportValue": "test-common:ExportsOutputReftestartF0FFB4BEEC699EE6", }, "Type": "S3", }, - "Name": "MyTestStack", + "Name": "test-stack", "PipelineType": "V1", "RestartExecutionOnUpdate": true, "RoleArn": { @@ -133,9 +127,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Configuration": { "PollForSourceChanges": false, "S3Bucket": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, - "S3ObjectKey": "poky/arbitrary-file.ext", + "S3ObjectKey": "custom/arbitrary-file.ext", }, "Name": "Source", "OutputArtifacts": [ @@ -201,162 +195,32 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "Configuration": { "BucketName": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesArtifactBucketFF61EB98FA6EAAC1", + "Fn::ImportValue": "test-common:ExportsOutputReftestoutA50725182A5BCA18", }, "Extract": "true", - "ObjectKey": "poky/arbitrary-file.ext", + "ObjectKey": "custom", }, "InputArtifacts": [ { "Name": "Artifact_Build_Build", }, ], - "Name": "Artifact", + "Name": "Output", "RoleArn": { "Fn::GetAtt": [ - "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRole97F56214", + "EmbeddedLinuxCodePipelineOutputCodePipelineActionRole999D254E", "Arn", ], }, "RunOrder": 1, }, ], - "Name": "Artifact", + "Name": "Output", }, ], }, "Type": "AWS::CodePipeline::Pipeline", }, - "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRole97F56214": { - "DependsOn": [ - "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", - "EmbeddedLinuxCodePipelineProjectF55E3B36", - "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", - "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", - ], - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":iam::111111111111:root", - ], - ], - }, - }, - }, - ], - "Version": "2012-10-17", - }, - }, - "Type": "AWS::IAM::Role", - }, - "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRoleDefaultPolicyF6D7AEC0": { - "DependsOn": [ - "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", - "EmbeddedLinuxCodePipelineProjectF55E3B36", - "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", - "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", - ], - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "s3:DeleteObject*", - "s3:PutObject", - "s3:PutObjectLegalHold", - "s3:PutObjectRetention", - "s3:PutObjectTagging", - "s3:PutObjectVersionTagging", - "s3:Abort*", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", - }, - "/*", - ], - ], - }, - ], - }, - { - "Action": [ - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:Decrypt", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*", - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", - }, - { - "Fn::Join": [ - "", - [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", - }, - "/*", - ], - ], - }, - ], - }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRoleDefaultPolicyF6D7AEC0", - "Roles": [ - { - "Ref": "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRole97F56214", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, "EmbeddedLinuxCodePipelineBucketDeploymentAwsCliLayerAA1BBC13": { "Properties": { "Content": { @@ -370,9 +234,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "EmbeddedLinuxCodePipelineBucketDeploymentCustomResourceBA39990C": { "DeletionPolicy": "Delete", "Properties": { - "DestinationBucketKeyPrefix": "poky", + "DestinationBucketKeyPrefix": "custom", "DestinationBucketName": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", }, "Extract": false, "OutputObjectKeys": true, @@ -483,14 +347,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, "/*", ], @@ -498,19 +362,6 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, ], "Version": "2012-10-17", }, @@ -606,7 +457,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "SecurityGroupIngress": [ { "CidrIp": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesVpc54FB4A02CidrBlock1B329233", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestvpc8985080ECidrBlockEB7C13CD", }, "Description": "NFS Mount Port", "FromPort": 2049, @@ -615,7 +466,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], "VpcId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpc54FB4A0241E4C5E5", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", }, }, "Type": "AWS::EC2::SecurityGroup", @@ -647,7 +498,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Action": "ecr:DescribeImages", "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, }, ], @@ -733,7 +584,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "FileSystemTags": [ { "Key": "Name", - "Value": "MyTestStack/EmbeddedLinuxCodePipelineFileSystem", + "Value": "test-stack/EmbeddedLinuxCodePipelineFileSystem", }, ], }, @@ -754,7 +605,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], "SubnetId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet1Subnet8DD627A684935C4B", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", }, }, "Type": "AWS::EFS::MountTarget", @@ -773,33 +624,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], "SubnetId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet2SubnetC1071C9093652F10", - }, - }, - "Type": "AWS::EFS::MountTarget", - }, - "EmbeddedLinuxCodePipelineFileSystemEfsMountTarget3FAD334C7": { - "Properties": { - "FileSystemId": { - "Ref": "EmbeddedLinuxCodePipelineFileSystemB969CAF1", - }, - "SecurityGroups": [ - { - "Fn::GetAtt": [ - "EmbeddedLinuxCodePipelineFileSystemEfsSecurityGroup35971CF1", - "GroupId", - ], - }, - ], - "SubnetId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet3SubnetCA196C90FDAFF9BF", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", }, }, "Type": "AWS::EFS::MountTarget", }, "EmbeddedLinuxCodePipelineFileSystemEfsSecurityGroup35971CF1": { "Properties": { - "GroupDescription": "MyTestStack/EmbeddedLinuxCodePipelineFileSystem/EfsSecurityGroup", + "GroupDescription": "test-stack/EmbeddedLinuxCodePipelineFileSystem/EfsSecurityGroup", "SecurityGroupEgress": [ { "CidrIp": "0.0.0.0/0", @@ -810,18 +642,18 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/EmbeddedLinuxCodePipelineFileSystem", + "Value": "test-stack/EmbeddedLinuxCodePipelineFileSystem", }, ], "VpcId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpc54FB4A0241E4C5E5", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", }, }, "Type": "AWS::EC2::SecurityGroup", }, - "EmbeddedLinuxCodePipelineFileSystemEfsSecurityGroupfromMyTestStackEmbeddedLinuxCodePipelineBuildProjectSecurityGroupEA21757F2049FC93D5D2": { + "EmbeddedLinuxCodePipelineFileSystemEfsSecurityGroupfromteststackEmbeddedLinuxCodePipelineBuildProjectSecurityGroup418A122320491D06894E": { "Properties": { - "Description": "from MyTestStackEmbeddedLinuxCodePipelineBuildProjectSecurityGroupEA21757F:2049", + "Description": "from teststackEmbeddedLinuxCodePipelineBuildProjectSecurityGroup418A1223:2049", "FromPort": 2049, "GroupId": { "Fn::GetAtt": [ @@ -840,84 +672,6 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "Type": "AWS::EC2::SecurityGroupIngress", }, - "EmbeddedLinuxCodePipelineMyTestStackEmbeddedLinuxCodePipelineE5C7D172SourceEventRulepokyf48cd2a94def24552abdd5b6ef9ffe6137be08fbc49a17964c6f7cae81245d5dzipEC68B3DA": { - "DependsOn": [ - "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", - "EmbeddedLinuxCodePipelineProjectF55E3B36", - "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", - "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", - ], - "Properties": { - "EventPattern": { - "detail": { - "eventName": [ - "CompleteMultipartUpload", - "CopyObject", - "PutObject", - ], - "requestParameters": { - "bucketName": [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesSourceBucket1FA488F54AA73B60", - }, - ], - "key": [ - "poky/arbitrary-file.ext", - ], - }, - "resources": { - "ARN": [ - { - "Fn::Join": [ - "", - [ - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", - }, - "/poky/arbitrary-file.ext", - ], - ], - }, - ], - }, - }, - "detail-type": [ - "AWS API Call via CloudTrail", - ], - "source": [ - "aws.s3", - ], - }, - "State": "ENABLED", - "Targets": [ - { - "Arn": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":codepipeline:eu-central-1:111111111111:", - { - "Ref": "EmbeddedLinuxCodePipeline4B3C7651", - }, - ], - ], - }, - "Id": "Target0", - "RoleArn": { - "Fn::GetAtt": [ - "EmbeddedLinuxCodePipelineEventsRole8EBF7C1D", - "Arn", - ], - }, - }, - ], - }, - "Type": "AWS::Events::Rule", - }, "EmbeddedLinuxCodePipelineOSImageCheckOnStart9461FE82": { "DependsOn": [ "EmbeddedLinuxCodePipelineOSImageCheckOnStartServiceRoleEBA0BE6A", @@ -939,11 +693,11 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` print("Received event: " + json.dumps(event, indent=2)) response = ecr_client.describe_images(repositoryName='", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesECRRepositoryA0DB7EB625EEF25E", + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", }, "', filter={'tagStatus': 'TAGGED'}) for i in response['imageDetails']: - if 'MyBaseImageStack' in i['ecrRepositoryImageTags']: + if 'latest' in i['ecrRepositoryImageTags']: break else: print('OS image not found. Stopping execution.') @@ -1057,7 +811,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "Type": "AWS::Events::Rule", }, - "EmbeddedLinuxCodePipelineOnCodePipelineStartRuleAllowEventRuleMyTestStackEmbeddedLinuxCodePipelineOSImageCheckOnStartADCB57EA531B1926": { + "EmbeddedLinuxCodePipelineOnCodePipelineStartRuleAllowEventRuleteststackEmbeddedLinuxCodePipelineOSImageCheckOnStart43D18F0A7FAE588F": { "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { @@ -1076,6 +830,114 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "Type": "AWS::Lambda::Permission", }, + "EmbeddedLinuxCodePipelineOutputCodePipelineActionRole999D254E": { + "DependsOn": [ + "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", + "EmbeddedLinuxCodePipelineProjectF55E3B36", + "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", + "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", + ], + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":iam::111111111111:root", + ], + ], + }, + }, + }, + ], + "Version": "2012-10-17", + }, + }, + "Type": "AWS::IAM::Role", + }, + "EmbeddedLinuxCodePipelineOutputCodePipelineActionRoleDefaultPolicy75D08DD8": { + "DependsOn": [ + "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", + "EmbeddedLinuxCodePipelineProjectF55E3B36", + "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", + "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", + ], + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:DeleteObject*", + "s3:PutObject", + "s3:PutObjectLegalHold", + "s3:PutObjectRetention", + "s3:PutObjectTagging", + "s3:PutObjectVersionTagging", + "s3:Abort*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", + }, + "/*", + ], + ], + }, + ], + }, + { + "Action": [ + "s3:GetObject*", + "s3:GetBucket*", + "s3:List*", + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", + }, + "/*", + ], + ], + }, + ], + }, + ], + "Version": "2012-10-17", + }, + "PolicyName": "EmbeddedLinuxCodePipelineOutputCodePipelineActionRoleDefaultPolicy75D08DD8", + "Roles": [ + { + "Ref": "EmbeddedLinuxCodePipelineOutputCodePipelineActionRole999D254E", + }, + ], + }, + "Type": "AWS::IAM::Policy", + }, "EmbeddedLinuxCodePipelineProjectF55E3B36": { "DependsOn": [ "EmbeddedLinuxCodePipelineBucketDeploymentAwsCliLayerAA1BBC13", @@ -1090,7 +952,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Type": "NO_CACHE", }, "EncryptionKey": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", }, "Environment": { "ComputeType": "BUILD_GENERAL1_XLARGE", @@ -1108,19 +970,19 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` { "Name": "PIPELINE_PROJECT_NAME", "Type": "PLAINTEXT", - "Value": "MyTestStack", + "Value": "test-stack", }, { "Name": "PIPELINE_OUTPUT_BUCKET", "Type": "PLAINTEXT", "Value": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesOutputBucketA2144F25070A0F1C", + "Fn::ImportValue": "test-common:ExportsOutputReftestoutA50725182A5BCA18", }, }, { "Name": "PIPELINE_OUTPUT_BUCKET_PREFIX", "Type": "PLAINTEXT", - "Value": "poky", + "Value": "custom", }, { "Name": "VM_IMPORT_ROLE", @@ -1141,7 +1003,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Fn::Split": [ ":", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, ], }, @@ -1155,7 +1017,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Fn::Split": [ ":", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, ], }, @@ -1167,9 +1029,9 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "/", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesECRRepositoryA0DB7EB625EEF25E", + "Fn::ImportValue": "test-common:ExportsOutputReftestecr18D9BBA8F49E3A2C", }, - ":MyBaseImageStack", + ":latest", ], ], }, @@ -1203,7 +1065,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Status": "ENABLED", }, }, - "Name": "MyTestStack", + "Name": "test-stack", "ServiceRole": { "Fn::GetAtt": [ "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", @@ -1226,17 +1088,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` ], "Subnets": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet1Subnet8DD627A684935C4B", - }, - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet2SubnetC1071C9093652F10", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", }, { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet3SubnetCA196C90FDAFF9BF", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", }, ], "VpcId": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpc54FB4A0241E4C5E5", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpc8985080E5120E245", }, }, }, @@ -1245,7 +1104,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "EmbeddedLinuxCodePipelineProjectLogsBA5DB55C": { "DeletionPolicy": "Delete", "Properties": { - "LogGroupName": "MyTestStack-EmbeddedLinuxCodePipelineProjectLogs", + "LogGroupName": "test-stack-EmbeddedLinuxCodePipelineProjectLogs", "RetentionInDays": 365, }, "Type": "AWS::Logs::LogGroup", @@ -1300,7 +1159,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` ], "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesECRRepositoryA0DB7EB6Arn5EC8487E", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestecr18D9BBA8Arn6B304346", }, }, { @@ -1345,30 +1204,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ":subnet/", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet1Subnet8DD627A684935C4B", - }, - ], - ], - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition", - }, - ":ec2:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":subnet/", - { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet2SubnetC1071C9093652F10", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet1Subnet865FB50A19DF49CF", }, ], ], @@ -1391,7 +1227,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ":subnet/", { - "Fn::ImportValue": "MyResourceStack:ExportsOutputRefPipelineResourcesVpcPrivateSubnet3SubnetCA196C90FDAFF9BF", + "Fn::ImportValue": "test-common:ExportsOutputReftestvpcPrivateSubnet2Subnet23D3396F45FDAD97", }, ], ], @@ -1497,7 +1333,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` ], "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", }, }, { @@ -1516,14 +1352,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, "/*", ], @@ -1531,19 +1367,6 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, { "Action": [ "ec2:CreateImage", @@ -1576,14 +1399,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, "/*", ], @@ -1638,14 +1461,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -1735,14 +1558,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -1750,19 +1573,6 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, { "Action": "sts:AssumeRole", "Effect": "Allow", @@ -1788,7 +1598,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": { "Fn::GetAtt": [ - "EmbeddedLinuxCodePipelineArtifactCodePipelineActionRole97F56214", + "EmbeddedLinuxCodePipelineOutputCodePipelineActionRole999D254E", "Arn", ], }, @@ -1858,31 +1668,21 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesSourceBucket1FA488F5Arn3CF62A69", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", }, - "/poky/arbitrary-file.ext", + "/custom/arbitrary-file.ext", ], ], }, ], }, - { - "Action": [ - "kms:Decrypt", - "kms:DescribeKey", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, { "Action": [ "s3:DeleteObject*", @@ -1896,14 +1696,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactBucketFF61EB98Arn7A6F2306", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestartF0FFB4BEArnE74A2E94", }, "/*", ], @@ -1911,18 +1711,6 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, ], }, - { - "Action": [ - "kms:Encrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:Decrypt", - ], - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", - }, - }, ], "Version": "2012-10-17", }, @@ -1967,14 +1755,14 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Effect": "Allow", "Resource": [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, { "Fn::Join": [ "", [ { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesOutputBucketA2144F25ArnBAEF4928", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377", }, "/*", ], @@ -1990,7 +1778,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "Condition": { "StringEquals": { "ec2:ResourceTag/CreatedBy": [ - "MyTestStack", + "test-stack", ], }, }, @@ -2016,7 +1804,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` ], "Effect": "Allow", "Resource": { - "Fn::ImportValue": "MyResourceStack:ExportsOutputFnGetAttPipelineResourcesArtifactKey368D3018Arn0E784876", + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestkey784D0285Arn58FA9A21", }, }, ], @@ -2025,7 +1813,7 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` "PolicyName": "vmImportPolicy", }, ], - "RoleName": "MyTestStack-vm-mport", + "RoleName": "test-stack-vm-mport", }, "Type": "AWS::IAM::Role", }, @@ -2062,6 +1850,84 @@ exports[`EmbeddedLinuxCodePipelineStack Snapshot 1`] = ` }, "Type": "AWS::Events::Rule", }, + "EmbeddedLinuxCodePipelineteststackEmbeddedLinuxCodePipelineE603BC4FSourceEventRulecustom23834a673736e04b0b5d6b7ff0d2481039b6661f0b52b80c5ef1f4296a0f0fbezip38762D1B": { + "DependsOn": [ + "EmbeddedLinuxCodePipelineProjectPolicyDocument1FA633EB", + "EmbeddedLinuxCodePipelineProjectF55E3B36", + "EmbeddedLinuxCodePipelineProjectRoleDefaultPolicyC205FC16", + "EmbeddedLinuxCodePipelineProjectRoleFD913DB7", + ], + "Properties": { + "EventPattern": { + "detail": { + "eventName": [ + "CompleteMultipartUpload", + "CopyObject", + "PutObject", + ], + "requestParameters": { + "bucketName": [ + { + "Fn::ImportValue": "test-common:ExportsOutputReftestsrc6C860343FD6A5870", + }, + ], + "key": [ + "custom/arbitrary-file.ext", + ], + }, + "resources": { + "ARN": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::ImportValue": "test-common:ExportsOutputFnGetAtttestsrc6C860343Arn869D5331", + }, + "/custom/arbitrary-file.ext", + ], + ], + }, + ], + }, + }, + "detail-type": [ + "AWS API Call via CloudTrail", + ], + "source": [ + "aws.s3", + ], + }, + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition", + }, + ":codepipeline:eu-central-1:111111111111:", + { + "Ref": "EmbeddedLinuxCodePipeline4B3C7651", + }, + ], + ], + }, + "Id": "Target0", + "RoleArn": { + "Fn::GetAtt": [ + "EmbeddedLinuxCodePipelineEventsRole8EBF7C1D", + "Arn", + ], + }, + }, + ], + }, + "Type": "AWS::Events::Rule", + }, "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A": { "DependsOn": [ "LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aServiceRoleDefaultPolicyADDA7DEB", diff --git a/test/__snapshots__/codepipeline-resources.test.ts.snap b/test/__snapshots__/codepipeline-resources.test.ts.snap index 78df388..c531c39 100644 --- a/test/__snapshots__/codepipeline-resources.test.ts.snap +++ b/test/__snapshots__/codepipeline-resources.test.ts.snap @@ -723,7 +723,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "PipelineResourcesVPCFlowLogGroupCCF3042F": { "DeletionPolicy": "Delete", "Properties": { - "LogGroupName": "MyTestStack-PipelineResourcesVPCFlowLogGroup", + "LogGroupName": "test-stack-PipelineResourcesVPCFlowLogGroup", "RetentionInDays": 365, }, "Type": "AWS::Logs::LogGroup", @@ -748,7 +748,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVPCFlowLogs", + "Value": "test-stack/PipelineResourcesVPCFlowLogs", }, ], "TrafficType": "ALL", @@ -772,7 +772,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVPCFlowLogs", + "Value": "test-stack/PipelineResourcesVPCFlowLogs", }, ], }, @@ -827,7 +827,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc", + "Value": "test-stack/PipelineResourcesVpc", }, ], }, @@ -838,7 +838,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc", + "Value": "test-stack/PipelineResourcesVpc", }, ], }, @@ -861,7 +861,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet1", }, ], "VpcId": { @@ -897,7 +897,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet1", }, ], "VpcId": { @@ -934,7 +934,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet2", }, ], "VpcId": { @@ -959,7 +959,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet2", }, ], "VpcId": { @@ -985,7 +985,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet3", }, ], "VpcId": { @@ -1021,7 +1021,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PrivateSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PrivateSubnet3", }, ], "VpcId": { @@ -1051,7 +1051,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet1", }, ], }, @@ -1075,7 +1075,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet1", }, ], }, @@ -1086,7 +1086,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet1", }, ], "VpcId": { @@ -1122,7 +1122,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet1", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet1", }, ], "VpcId": { @@ -1152,7 +1152,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet2", }, ], }, @@ -1176,7 +1176,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet2", }, ], }, @@ -1187,7 +1187,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet2", }, ], "VpcId": { @@ -1223,7 +1223,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet2", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet2", }, ], "VpcId": { @@ -1253,7 +1253,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet3", }, ], }, @@ -1277,7 +1277,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet3", }, ], }, @@ -1299,7 +1299,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` "Tags": [ { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet3", }, ], "VpcId": { @@ -1324,7 +1324,7 @@ exports[`PipelineResourcesStack Snapshot 1`] = ` }, { "Key": "Name", - "Value": "MyTestStack/PipelineResourcesVpc/PublicSubnet3", + "Value": "test-stack/PipelineResourcesVpc/PublicSubnet3", }, ], "VpcId": { diff --git a/test/buildspec/build.buildspec.yml b/test/buildspec/build.buildspec.yml new file mode 100644 index 0000000..25ef8e1 --- /dev/null +++ b/test/buildspec/build.buildspec.yml @@ -0,0 +1,29 @@ +version: 0.2 +run-as: yoctouser + +env: + shell: bash + # HOME is set to /root even when running as a non-root user. + variables: + HOME: "/home/yoctouser" + +phases: + pre_build: + run-as: root + commands: + - echo "Pre build started - [$(date '+%F %H:%M:%S')]" + - echo "Pre build completed - [$(date '+%F %H:%M:%S')]" + build: + commands: + - echo "Build started - [$(date '+%F %H:%M:%S')]" + - echo "Build completed - [$(date '+%F %H:%M:%S')]" + post_build: + commands: + - echo "Post build statred - [$(date '+%F %H:%M:%S')]" + - echo "" > /tmp/out.log + - echo "Post build completed - [$(date '+%F %H:%M:%S')]" + +artifacts: + discard-paths: true + files: + - /tmp/out.log diff --git a/test/codebuild-embedded-linux-nag.test.ts b/test/codebuild-embedded-linux-nag.test.ts new file mode 100644 index 0000000..9966a2c --- /dev/null +++ b/test/codebuild-embedded-linux-nag.test.ts @@ -0,0 +1,162 @@ +import { describe, expect, test, beforeAll } from "@jest/globals"; +import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag"; +import { Annotations, Match } from "aws-cdk-lib/assertions"; + +import * as cdk from "aws-cdk-lib"; +import * as ecr from "aws-cdk-lib/aws-ecr"; +import * as kms from "aws-cdk-lib/aws-kms"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import { + EmbeddedLinuxCodeBuildProjectProps, + EmbeddedLinuxCodeBuildProjectStack, +} from "../lib"; +import { DEFAULT_ENV } from "./util"; + +const base_path = `EmbeddedLinuxCodeBuild`; + +function addNagSuppressions( + _stack: EmbeddedLinuxCodeBuildProjectStack, + _props: EmbeddedLinuxCodeBuildProjectProps, +) { + NagSuppressions.addStackSuppressions(_stack, [ + { id: "CdkNagValidationFailure", reason: "Multiple Validation Failures." }, + { + id: "AwsSolutions-CB3", + reason: "CodeBuild Privilege mode is required for this pipeline.", + }, + { + id: "AwsSolutions-IAM4", + reason: "TODO: Re-evaluate managed policies per resources.", + }, + ]); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}ProjectSecurityGroup/Resource`, + [ + { + id: "AwsSolutions-EC23", + reason: "CidrBlock parameter referencing an intrinsic function", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}Project/Resource`, + [ + { + id: "AwsSolutions-CB5", + reason: "PipelineImage parameter referencing an intrinsic function", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}Project/Role/DefaultPolicy/Resource`, + [ + { + id: "AwsSolutions-IAM5", + reason: + "Because these are the default permissions assigned to a CDK default created role.", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource`, + [ + { + id: "AwsSolutions-IAM5", + reason: + "Because these are the default permissions assigned to a CDK default created role.", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}ProjectOSImageCheckOnStart/Resource`, + [ + { + id: "AwsSolutions-L1", + reason: "There is no latest PYTHON version to set.", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}Project/PolicyDocument/Resource`, + [ + { + id: "AwsSolutions-IAM5", + reason: + "Because these are the default permissions assigned to a CDK default created role.", + }, + ], + ); +} + +describe("EmbeddedLinuxCodeBuildProjectStack cdk-nag AwsSolutions Pack", () => { + const resource_prefix = "test"; + + let app: cdk.App; + let stack: EmbeddedLinuxCodeBuildProjectStack; + let props: EmbeddedLinuxCodeBuildProjectProps; + let common: cdk.Stack; + + beforeAll(() => { + // GIVEN + app = new cdk.App(); + + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, + }); + + // Create required resources for testing + const vpc = new ec2.Vpc(common, `${resource_prefix}-vpc`, { + maxAzs: 2, + }); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + + // Create the pipeline stack & props + props = { + env: DEFAULT_ENV, + ecrRepository: ecrRepository, + encryptionKey: encryptionKey, + ecrRepositoryImageTag: "PipelineImage", + vpc: vpc, + }; + + stack = new EmbeddedLinuxCodeBuildProjectStack( + app, + `${resource_prefix}-stack`, + props, + ); + + addNagSuppressions(stack, props); + + // WHEN + cdk.Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true })); + }); + + // THEN + test("No unsuppressed Warnings", () => { + const results = Annotations.fromStack(stack).findWarning( + "*", + Match.stringLikeRegexp("AwsSolutions-.*"), + ); + for (const result of results) { + console.log(JSON.stringify(result, null, 4)); + } + expect(results).toHaveLength(0); + }); + test("No unsuppressed Errors", () => { + const results = Annotations.fromStack(stack).findError( + "*", + Match.stringLikeRegexp("AwsSolutions-.*"), + ); + for (const result of results) { + console.log(JSON.stringify(result, null, 4)); + } + expect(results).toHaveLength(0); + }); +}); diff --git a/test/codebuild-embedded-linux.test.ts b/test/codebuild-embedded-linux.test.ts new file mode 100644 index 0000000..24b0c3a --- /dev/null +++ b/test/codebuild-embedded-linux.test.ts @@ -0,0 +1,413 @@ +import { beforeEach, describe, expect, test } from "@jest/globals"; +import { Match, Template } from "aws-cdk-lib/assertions"; + +import * as cdk from "aws-cdk-lib"; +import * as ecr from "aws-cdk-lib/aws-ecr"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as kms from "aws-cdk-lib/aws-kms"; +import * as iam from "aws-cdk-lib/aws-iam"; +import { + EmbeddedLinuxCodeBuildProjectStack, + EmbeddedLinuxCodeBuildProjectProps, +} from "../lib"; +import { DEFAULT_ENV, normalizedTemplateFromStack } from "./util"; + +describe("EmbeddedLinuxCodeBuildProjectStack", () => { + const resource_prefix = "test"; + + let app: cdk.App; + let stack: EmbeddedLinuxCodeBuildProjectStack; + let props: EmbeddedLinuxCodeBuildProjectProps; + let template: Template; + let common: cdk.Stack; + + beforeEach(() => { + app = new cdk.App(); + + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, + }); + + // Create required props + const vpc = new ec2.Vpc(common, `${resource_prefix}-vpc`, { + maxAzs: 2, + }); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + + // Create the pipeline stack & props + props = { + env: DEFAULT_ENV, + ecrRepository: ecrRepository, + ecrRepositoryImageTag: "latest", + vpc: vpc, + encryptionKey: encryptionKey, + }; + + stack = new EmbeddedLinuxCodeBuildProjectStack( + app, + `${resource_prefix}-stack`, + props, + ); + + template = Template.fromStack(stack); + }); + + test("Creates EFS filesystem with security group", () => { + template.hasResourceProperties("AWS::EFS::FileSystem", { + FileSystemTags: [ + { + Key: "Name", + Value: `${stack.stackName}/EmbeddedLinuxCodeBuildProjectFilesystem`, + }, + ], + Encrypted: true, + }); + + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + SecurityGroupIngress: Match.arrayWith([ + Match.objectLike({ + CidrIp: { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.vpc.node.id.replace(/-/g, "")}*`, + ), + }, + FromPort: 2049, + IpProtocol: "tcp", + ToPort: 2049, + }), + ]), + }); + }); + + test("creates CodeBuild project", () => { + template.hasResourceProperties("AWS::CodeBuild::Project", { + Environment: { + ComputeType: "BUILD_GENERAL1_XLARGE", + Image: { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 4, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ], + }, + ], + }, + ".dkr.ecr.", + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ], + }, + ], + }, + ".", + { + Ref: "AWS::URLSuffix", + }, + "/", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputRef${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ":latest", + ], + ], + }, + PrivilegedMode: true, + Type: "LINUX_CONTAINER", + }, + TimeoutInMinutes: 240, + }); + }); + + test("creates Lambda function for pipeline check", () => { + template.hasResourceProperties("AWS::Lambda::Function", { + Handler: "index.handler", + Runtime: "python3.10", + }); + }); + + test("creates EventBridge rule", () => { + template.hasResourceProperties("AWS::Events::Rule", { + EventPattern: { + "detail-type": ["CodePipeline Pipeline Execution State Change"], + source: ["aws.codepipeline"], + detail: { + state: ["STARTED"], + "execution-trigger": { + "trigger-type": ["CreatePipeline"], + }, + }, + }, + }); + }); + + test("adds required policies to CodeBuild role", () => { + template.hasResourceProperties("AWS::IAM::Policy", { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: [ + "ec2:DescribeSecurityGroups", + "codestar-connections:GetConnection", + "codestar-connections:GetConnectionToken", + "codeconnections:GetConnectionToken", + "codeconnections:GetConnection", + "codeconnections:ListConnection", + "codeconnections:UseConnection", + "codebuild:ListConnectedOAuthAccounts", + "codebuild:ListRepositories", + "codebuild:PersistOAuthToken", + "codebuild:ImportSourceCredentials", + ], + Effect: "Allow", + Resource: "*", + }), + ]), + }, + }); + }); + + test("creates CloudWatch log group", () => { + template.hasResourceProperties("AWS::Logs::LogGroup", { + RetentionInDays: 365, + }); + }); + + test("Snapshot", () => { + /* We must change some randomly generated file names used in the S3 asset construct. */ + const templateWithConstKeys = normalizedTemplateFromStack(stack); + expect(templateWithConstKeys).toMatchSnapshot(); + }); +}); + +describe("EmbeddedLinuxCodeBuildProjectStack Custom", () => { + const resource_prefix = "test"; + + let app: cdk.App; + let stack: EmbeddedLinuxCodeBuildProjectStack; + let props: EmbeddedLinuxCodeBuildProjectProps; + let template: Template; + let common: cdk.Stack; + + beforeEach(() => { + app = new cdk.App(); + + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, + }); + + // Create required props + const vpc = new ec2.Vpc(common, `${resource_prefix}-vpc`, { + maxAzs: 2, + }); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + const customPolicy = new iam.PolicyStatement({ + actions: ["s3:GetObject"], + resources: ["*"], + }); + + // Create the pipeline stack & props + props = { + env: DEFAULT_ENV, + ecrRepository: ecrRepository, + ecrRepositoryImageTag: "latest", + vpc: vpc, + encryptionKey: encryptionKey, + buildPolicyAdditions: [customPolicy], + }; + + stack = new EmbeddedLinuxCodeBuildProjectStack( + app, + `${resource_prefix}-stack`, + props, + ); + + template = Template.fromStack(stack); + }); + + test("Creates EFS filesystem with security group", () => { + template.hasResourceProperties("AWS::EFS::FileSystem", { + FileSystemTags: [ + { + Key: "Name", + Value: `${stack.stackName}/EmbeddedLinuxCodeBuildProjectFilesystem`, + }, + ], + Encrypted: true, + }); + + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + SecurityGroupIngress: Match.arrayWith([ + Match.objectLike({ + CidrIp: { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.vpc.node.id.replace(/-/g, "")}*`, + ), + }, + FromPort: 2049, + IpProtocol: "tcp", + ToPort: 2049, + }), + ]), + }); + }); + + test("creates CodeBuild project", () => { + template.hasResourceProperties("AWS::CodeBuild::Project", { + Environment: { + ComputeType: "BUILD_GENERAL1_XLARGE", + Image: { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 4, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ], + }, + ], + }, + ".dkr.ecr.", + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ], + }, + ], + }, + ".", + { + Ref: "AWS::URLSuffix", + }, + "/", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputRef${props.ecrRepository.node.id.replace(/-/g, "")}`, + ), + }, + ":latest", + ], + ], + }, + PrivilegedMode: true, + Type: "LINUX_CONTAINER", + }, + TimeoutInMinutes: 240, + }); + }); + + test("creates Lambda function for pipeline check", () => { + template.hasResourceProperties("AWS::Lambda::Function", { + Handler: "index.handler", + Runtime: "python3.10", + }); + }); + + test("creates EventBridge rule", () => { + template.hasResourceProperties("AWS::Events::Rule", { + EventPattern: { + "detail-type": ["CodePipeline Pipeline Execution State Change"], + source: ["aws.codepipeline"], + detail: { + state: ["STARTED"], + "execution-trigger": { + "trigger-type": ["CreatePipeline"], + }, + }, + }, + }); + }); + + test("adds required policies to CodeBuild role", () => { + template.hasResourceProperties("AWS::IAM::Policy", { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: [ + "ec2:DescribeSecurityGroups", + "codestar-connections:GetConnection", + "codestar-connections:GetConnectionToken", + "codeconnections:GetConnectionToken", + "codeconnections:GetConnection", + "codeconnections:ListConnection", + "codeconnections:UseConnection", + "codebuild:ListConnectedOAuthAccounts", + "codebuild:ListRepositories", + "codebuild:PersistOAuthToken", + "codebuild:ImportSourceCredentials", + ], + Effect: "Allow", + Resource: "*", + }), + ]), + }, + }); + }); + + test("creates CloudWatch log group", () => { + template.hasResourceProperties("AWS::Logs::LogGroup", { + RetentionInDays: 365, + }); + }); + + test("adds custom policy statements when provided", () => { + template.hasResourceProperties("AWS::IAM::Policy", { + PolicyName: Match.stringLikeRegexp( + `EmbeddedLinuxCodeBuildProjectRoleDefaultPolicy*`, + ), + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: "s3:GetObject", + Effect: "Allow", + Resource: "*", + }), + ]), + }, + }); + }); + + test("Snapshot", () => { + /* We must change some randomly generated file names used in the S3 asset construct. */ + const templateWithConstKeys = normalizedTemplateFromStack(stack); + expect(templateWithConstKeys).toMatchSnapshot(); + }); +}); diff --git a/test/codepipeline-embedded-linux-base-image-nag.test.ts b/test/codepipeline-embedded-linux-base-image-nag.test.ts index a2b2e66..7181ccb 100644 --- a/test/codepipeline-embedded-linux-base-image-nag.test.ts +++ b/test/codepipeline-embedded-linux-base-image-nag.test.ts @@ -1,19 +1,26 @@ -import * as cdk from "aws-cdk-lib"; -import { Annotations, Match } from "aws-cdk-lib/assertions"; +import { describe, expect, test, beforeAll } from "@jest/globals"; import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag"; +import { Annotations, Match } from "aws-cdk-lib/assertions"; + +import * as cdk from "aws-cdk-lib"; import * as ecr from "aws-cdk-lib/aws-ecr"; import * as kms from "aws-cdk-lib/aws-kms"; import * as s3 from "aws-cdk-lib/aws-s3"; import { EmbeddedLinuxCodePipelineBaseImageProps, EmbeddedLinuxCodePipelineBaseImageStack, -} from "../lib/codepipeline-embedded-linux-base-image"; +} from "../lib"; import { DEFAULT_ENV } from "./util"; -function addNagSuppressions(stack: cdk.Stack) { +const base_path = `CodePipelineBuildBaseImage`; + +function addNagSuppressions( + _stack: EmbeddedLinuxCodePipelineBaseImageStack, + _props: EmbeddedLinuxCodePipelineBaseImageProps, +) { NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource`, + _stack, + `/${_stack.stackName}/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource`, [ { id: "AwsSolutions-L1", @@ -22,19 +29,18 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/CodePipelineBuildBaseImageBucketDeploymentRole/Resource`, + _stack, + `/${_stack.stackName}/${base_path}BucketDeploymentRole/Resource`, [ { id: "AwsSolutions-IAM5", - reason: - "Because CodePipelineBuildBaseImageBucketDeploymentRole/Resource is needed here.", + reason: `Because ${base_path}BucketDeploymentRole/Resource is needed here.`, }, ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/CodePipelineBuildBaseImageBucketDeploymentRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}BucketDeploymentRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -44,8 +50,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/CodePipelineBuildBaseImageProject/Role/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}Project/Role/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -55,8 +61,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/CodePipelineBuildBaseImageCodePipeline/Role/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}CodePipeline/Role/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -66,8 +72,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/CodePipelineBuildBaseImageCodePipeline/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}CodePipeline/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -79,46 +85,49 @@ function addNagSuppressions(stack: cdk.Stack) { } describe("EmbeddedLinuxCodePipelineBaseImageStack cdk-nag AwsSolutions Pack", () => { - const app: cdk.App = new cdk.App(); - let stack: cdk.Stack; + const resource_prefix = "test"; + + let app: cdk.App; + let stack: EmbeddedLinuxCodePipelineBaseImageStack; + let props: EmbeddedLinuxCodePipelineBaseImageProps; + let common: cdk.Stack; beforeAll(() => { // GIVEN - const baseStack = new cdk.Stack(app, "BaseStack", { env: DEFAULT_ENV }); + app = new cdk.App(); - const encryptionKey = new kms.Key(baseStack, "EncryptionKey", { - removalPolicy: cdk.RemovalPolicy.DESTROY, - enableKeyRotation: true, + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, }); + + // Create required resources for testing const pipelineSourceBucket = new s3.Bucket( - baseStack, - "PipelineSourceBucket", - { - versioned: true, - }, + common, + `${resource_prefix}-src`, + { versioned: true }, ); const pipelineArtifactBucket = new s3.Bucket( - baseStack, - "PipelineArtifactBucket", + common, + `${resource_prefix}-art`, {}, ); - const ecrRepository = new ecr.Repository(baseStack, "EcrRepository", {}); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); - const props: EmbeddedLinuxCodePipelineBaseImageProps = { + props = { env: DEFAULT_ENV, pipelineSourceBucket: pipelineSourceBucket, pipelineArtifactBucket: pipelineArtifactBucket, ecrRepository: ecrRepository, encryptionKey: encryptionKey, }; - stack = new EmbeddedLinuxCodePipelineBaseImageStack( app, - "MyTestStack", + `${resource_prefix}-stack`, props, ); - addNagSuppressions(stack); + addNagSuppressions(stack, props); // WHEN cdk.Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true })); diff --git a/test/codepipeline-embedded-linux-base-image.test.ts b/test/codepipeline-embedded-linux-base-image.test.ts index 9679efa..93da6fb 100644 --- a/test/codepipeline-embedded-linux-base-image.test.ts +++ b/test/codepipeline-embedded-linux-base-image.test.ts @@ -1,62 +1,159 @@ +import { beforeEach, describe, expect, test } from "@jest/globals"; +import { Match, Template } from "aws-cdk-lib/assertions"; + import * as cdk from "aws-cdk-lib"; -import * as assertions from "aws-cdk-lib/assertions"; -import { PipelineResourcesProps, PipelineResourcesStack } from "../lib"; +import * as s3 from "aws-cdk-lib/aws-s3"; +import * as ecr from "aws-cdk-lib/aws-ecr"; +import * as kms from "aws-cdk-lib/aws-kms"; import { EmbeddedLinuxCodePipelineBaseImageProps, EmbeddedLinuxCodePipelineBaseImageStack, } from "../lib"; import { DEFAULT_ENV, normalizedTemplateFromStack } from "./util"; -// TODO -// - add test with PipelineResourcesProps values for various buckets -// - add test for other outouts - describe("EmbeddedLinuxCodePipelineBaseImageStack", () => { - let app: cdk.App; - let stack: cdk.Stack; - let template: assertions.Template; - let pipelineResourcesStack: PipelineResourcesStack; + const resource_prefix = "test"; - const pipelineResourcesProps: PipelineResourcesProps = { - resource_prefix: "test", - env: DEFAULT_ENV, - }; + let app: cdk.App; + let stack: EmbeddedLinuxCodePipelineBaseImageStack; + let props: EmbeddedLinuxCodePipelineBaseImageProps; + let template: Template; + let common: cdk.Stack; - beforeAll(() => { - // GIVEN + beforeEach(() => { app = new cdk.App(); - pipelineResourcesStack = new PipelineResourcesStack( - app, - "MyResourceStack", - pipelineResourcesProps, - ); - const embeddedLinuxCodePipelineBaseImageProps: EmbeddedLinuxCodePipelineBaseImageProps = - { - env: DEFAULT_ENV, - pipelineSourceBucket: pipelineResourcesStack.pipelineSourceBucket, - pipelineArtifactBucket: pipelineResourcesStack.pipelineArtifactBucket, - ecrRepository: pipelineResourcesStack.ecrRepository, - encryptionKey: pipelineResourcesStack.encryptionKey, - }; + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, + }); + + // Create required resources for testing + const sourceBucket = new s3.Bucket(common, `${resource_prefix}-src`); + const artifactBucket = new s3.Bucket(common, `${resource_prefix}-art`); + const ecrRepo = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + + // Create the pipeline stack & props + props = { + env: DEFAULT_ENV, + pipelineSourceBucket: sourceBucket, + pipelineArtifactBucket: artifactBucket, + ecrRepository: ecrRepo, + encryptionKey: encryptionKey, + }; stack = new EmbeddedLinuxCodePipelineBaseImageStack( app, - "MyTestStack", - embeddedLinuxCodePipelineBaseImageProps, + `${resource_prefix}-stack`, + props, ); - template = assertions.Template.fromStack(stack); + + // Create template from stack + template = Template.fromStack(stack); + }); + + test("Pipeline is created with correct stages", () => { + template.hasResourceProperties("AWS::CodePipeline::Pipeline", { + Stages: [ + { + Name: "Source", + Actions: [ + { + Name: "Source", + ActionTypeId: { + Category: "Source", + Owner: "AWS", + Provider: "S3", + Version: "1", + }, + }, + ], + }, + { + Name: "Build", + Actions: [ + { + Name: "Build", + ActionTypeId: { + Category: "Build", + Owner: "AWS", + Provider: "CodeBuild", + Version: "1", + }, + }, + ], + }, + ], + }); + }); + + test("CodeBuild project is created with correct configuration", () => { + template.hasResourceProperties("AWS::CodeBuild::Project", { + Environment: { + ComputeType: "BUILD_GENERAL1_MEDIUM", + Image: "aws/codebuild/standard:7.0", + PrivilegedMode: true, + Type: "LINUX_CONTAINER", + }, + }); + }); + + test("EventBridge rule is created for weekly pipeline execution", () => { + template.hasResourceProperties("AWS::Events::Rule", { + ScheduleExpression: "cron(0 6 ? * Monday *)", + State: "ENABLED", + Targets: [ + { + Arn: { + "Fn::Join": [ + "", + [ + "arn:", + { + Ref: "AWS::Partition", + }, + `:codepipeline:${props.env?.region}:${props.env?.account}:`, + { + Ref: Match.stringLikeRegexp( + "CodePipelineBuildBaseImageCodePipeline*", + ), + }, + ], + ], + }, + }, + ], + }); }); - test("Has Resources", () => { - template.resourceCountIs("AWS::CodePipeline::Pipeline", 1); - template.resourceCountIs("AWS::CodeBuild::Project", 1); - template.resourceCountIs("AWS::Events::Rule", 2); // one for the S3 trigger and one for the weekly refresh - template.resourceCountIs("AWS::Logs::LogGroup", 1); - template.allResourcesProperties("AWS::Logs::LogGroup", { + test("CloudWatch log group is created with correct retention", () => { + template.hasResourceProperties("AWS::Logs::LogGroup", { RetentionInDays: 365, }); }); + test("Required outputs are created", () => { + template.hasOutput("ECRRepositoryName", {}); + template.hasOutput("ECRBaseImageTag", {}); + template.hasOutput("ECRBaseImageCheckCommand", {}); + template.hasOutput("SourceURI", {}); + }); + + test("IAM role for bucket deployment has correct permissions", () => { + template.hasResourceProperties("AWS::IAM::Role", { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { + Service: "lambda.amazonaws.com", + }, + }, + ], + }, + }); + }); + test("Snapshot", () => { /* We must change some randomly generated file names used in the S3 asset construct. */ const templateWithConstKeys = normalizedTemplateFromStack(stack); diff --git a/test/codepipeline-embedded-linux-nag.test.ts b/test/codepipeline-embedded-linux-nag.test.ts index 065e74c..9680660 100644 --- a/test/codepipeline-embedded-linux-nag.test.ts +++ b/test/codepipeline-embedded-linux-nag.test.ts @@ -1,17 +1,26 @@ +import { describe, expect, test, beforeAll } from "@jest/globals"; +import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag"; +import { Annotations, Match } from "aws-cdk-lib/assertions"; + import * as cdk from "aws-cdk-lib"; import * as ecr from "aws-cdk-lib/aws-ecr"; import * as s3 from "aws-cdk-lib/aws-s3"; import * as ec2 from "aws-cdk-lib/aws-ec2"; import * as kms from "aws-cdk-lib/aws-kms"; - -import { Annotations, Match } from "aws-cdk-lib/assertions"; -import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag"; -import { EmbeddedLinuxCodePipelineStack } from "../lib/codepipeline-embedded-linux"; -import { ProjectType } from "../lib"; +import { + ProjectType, + EmbeddedLinuxCodePipelineStack, + EmbeddedLinuxCodePipelineProps, +} from "../lib"; import { DEFAULT_ENV } from "./util"; -function addNagSuppressions(stack: cdk.Stack) { - NagSuppressions.addStackSuppressions(stack, [ +const base_path = `EmbeddedLinuxCodePipeline`; + +function addNagSuppressions( + _stack: EmbeddedLinuxCodePipelineStack, + _props: EmbeddedLinuxCodePipelineProps, +) { + NagSuppressions.addStackSuppressions(_stack, [ { id: "CdkNagValidationFailure", reason: "Multiple Validation Failures." }, { id: "AwsSolutions-CB3", @@ -23,19 +32,19 @@ function addNagSuppressions(stack: cdk.Stack) { }, ]); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineBucketDeploymentRole/Resource`, + _stack, + `/${_stack.stackName}/${base_path}BucketDeploymentRole/Resource`, [ { id: "AwsSolutions-IAM5", reason: - "/aws/lambda/EmbeddedLinuxCodePipeline-CustomCDKBucketDeployment* is needed here.", + "/aws/lambda/${base_path}-CustomCDKBucketDeployment* is needed here.", }, ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource`, + _stack, + `/${_stack.stackName}/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource`, [ { id: "AwsSolutions-L1", @@ -44,8 +53,19 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineProject/PolicyDocument/Resource`, + _stack, + `/${_stack.stackName}/${base_path}Project/PolicyDocument/Resource`, + [ + { + id: "AwsSolutions-IAM5", + reason: + "Because these are the default permissions assigned to a CDK default created role.", + }, + ], + ); + NagSuppressions.addResourceSuppressionsByPath( + _stack, + `/${_stack.stackName}/${base_path}Project/Role/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -55,8 +75,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineProject/Role/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}BucketDeploymentRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -66,8 +86,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineBucketDeploymentRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}/Role/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -77,8 +97,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipeline/Role/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -88,8 +108,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipeline/Artifact/Artifact/CodePipelineActionRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}/Build/Build/CodePipelineActionRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -99,8 +119,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipeline/Source/Source/CodePipelineActionRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/${base_path}/Output/Output/CodePipelineActionRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -110,8 +130,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource`, + _stack, + `/${_stack.stackName}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource`, [ { id: "AwsSolutions-IAM5", @@ -121,8 +141,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineOSImageCheckOnStart/Resource`, + _stack, + `/${_stack.stackName}/${base_path}OSImageCheckOnStart/Resource`, [ { id: "AwsSolutions-L1", @@ -131,8 +151,8 @@ function addNagSuppressions(stack: cdk.Stack) { ], ); NagSuppressions.addResourceSuppressionsByPath( - stack, - `/${stack.stackName}/EmbeddedLinuxCodePipelineVMImportRole/Resource`, + _stack, + `/${_stack.stackName}/${base_path}VMImportRole/Resource`, [ { id: "AwsSolutions-IAM5", @@ -142,10 +162,13 @@ function addNagSuppressions(stack: cdk.Stack) { regex: `/Resource::arn:aws:ec2:${DEFAULT_ENV.region}::snapshot/\\*$/g`, }, { - regex: `/Resource::/\\*$/g`, + regex: `/Resource::<${_props.pipelineOutputBucket.node.id.replace(/-/g, "")}A5072518.Arn>/\\*$/g`, }, { - regex: `/Resource::BaseStack:ExportsOutputFnGetAttOutputBucket7114EB27Arn67D5716D/\\*$/g`, + regex: `/Resource::${_stack.stackName}:ExportsOutputFnGetAtt${_props.pipelineOutputBucket.node.id.replace(/-/g, "").toLowerCase()}A5072518ArnD3542377/\\*$/g`, + }, + { + regex: `/Resource::test-common:ExportsOutputFnGetAtttestoutA5072518ArnD3542377/\\*$/g`, }, { regex: `/Resource::\\*$/g`, @@ -157,37 +180,46 @@ function addNagSuppressions(stack: cdk.Stack) { } describe("EmbeddedLinuxCodePipelineStack cdk-nag AwsSolutions Pack", () => { - const app: cdk.App = new cdk.App(); - let stack: cdk.Stack; + const resource_prefix = "test"; + + let app: cdk.App; + let stack: EmbeddedLinuxCodePipelineStack; + let props: EmbeddedLinuxCodePipelineProps; + let common: cdk.Stack; beforeAll(() => { // GIVEN - const baseStack = new cdk.Stack(app, "BaseStack", { env: DEFAULT_ENV }); + app = new cdk.App(); - // GIVEN - const encryptionKey = new kms.Key(baseStack, "EncryptionKey", { - removalPolicy: cdk.RemovalPolicy.DESTROY, - enableKeyRotation: true, + common = new cdk.Stack(app, `${resource_prefix}-common`, { + env: DEFAULT_ENV, }); + + // GIVEN + + // Create required resources for testing const pipelineSourceBucket = new s3.Bucket( - baseStack, - "pipelineSourceBucket", - { - versioned: true, - }, + common, + `${resource_prefix}-src`, + { versioned: true }, ); const pipelineArtifactBucket = new s3.Bucket( - baseStack, - "ArtifactBucket", + common, + `${resource_prefix}-art`, {}, ); - const pipelineOutputBucket = new s3.Bucket(baseStack, "OutputBucket", { - encryptionKey: encryptionKey, + const pipelineOutputBucket = new s3.Bucket( + common, + `${resource_prefix}-out`, + {}, + ); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + const vpc = new ec2.Vpc(common, `${resource_prefix}-vpc`, { + maxAzs: 2, }); - const ecrRepository = new ecr.Repository(baseStack, "EcrRepository", {}); - const vpc = new ec2.Vpc(baseStack, "Vpc", {}); - stack = new EmbeddedLinuxCodePipelineStack(app, "MyTestStack", { + props = { env: DEFAULT_ENV, pipelineSourceBucket: pipelineSourceBucket, pipelineArtifactBucket: pipelineArtifactBucket, @@ -198,9 +230,14 @@ describe("EmbeddedLinuxCodePipelineStack cdk-nag AwsSolutions Pack", () => { vpc: vpc, pipelineArtifactPrefix: `${ProjectType.PokyAmi}`, encryptionKey: encryptionKey, - }); + }; + stack = new EmbeddedLinuxCodePipelineStack( + app, + `${resource_prefix}-stack`, + props, + ); - addNagSuppressions(stack); + addNagSuppressions(stack, props); // WHEN cdk.Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true })); diff --git a/test/codepipeline-embedded-linux.test.ts b/test/codepipeline-embedded-linux.test.ts index 0497075..22eaf8c 100644 --- a/test/codepipeline-embedded-linux.test.ts +++ b/test/codepipeline-embedded-linux.test.ts @@ -1,84 +1,70 @@ +import * as path from "path"; + +import { beforeEach, describe, expect, test } from "@jest/globals"; +import { Match, Template } from "aws-cdk-lib/assertions"; + import * as cdk from "aws-cdk-lib"; -import * as assertions from "aws-cdk-lib/assertions"; -import { - PipelineResourcesProps, - PipelineResourcesStack, - ProjectType, -} from "../lib"; -import { - EmbeddedLinuxCodePipelineBaseImageProps, - EmbeddedLinuxCodePipelineBaseImageStack, -} from "../lib"; +import * as s3 from "aws-cdk-lib/aws-s3"; +import * as ecr from "aws-cdk-lib/aws-ecr"; +import * as ec2 from "aws-cdk-lib/aws-ec2"; +import * as kms from "aws-cdk-lib/aws-kms"; import { EmbeddedLinuxCodePipelineProps, EmbeddedLinuxCodePipelineStack, + ProjectType, } from "../lib"; import { DEFAULT_ENV, normalizedTemplateFromStack } from "./util"; -// TODO -// - add test with PipelineResourcesProps values for various buckets -// - add test for other outouts - describe("EmbeddedLinuxCodePipelineStack", () => { + const resource_prefix = "test"; + let app: cdk.App; - let stack: cdk.Stack; - let template: assertions.Template; - let pipelineResourcesStack: PipelineResourcesStack; - let embeddedLinuxCodePipelineBaseImageStack: EmbeddedLinuxCodePipelineBaseImageStack; - - const pipelineResourcesProps: PipelineResourcesProps = { - resource_prefix: "test", - env: DEFAULT_ENV, - }; - - beforeAll(() => { - // GIVEN + let stack: EmbeddedLinuxCodePipelineStack; + let props: EmbeddedLinuxCodePipelineProps; + let template: Template; + let common: cdk.Stack; + + beforeEach(() => { app = new cdk.App(); - pipelineResourcesStack = new PipelineResourcesStack( - app, - "MyResourceStack", - pipelineResourcesProps, - ); - const embeddedLinuxCodePipelineBaseImageProps: EmbeddedLinuxCodePipelineBaseImageProps = - { - env: DEFAULT_ENV, - pipelineSourceBucket: pipelineResourcesStack.pipelineSourceBucket, - pipelineArtifactBucket: pipelineResourcesStack.pipelineArtifactBucket, - ecrRepository: pipelineResourcesStack.ecrRepository, - encryptionKey: pipelineResourcesStack.encryptionKey, - }; - - embeddedLinuxCodePipelineBaseImageStack = - new EmbeddedLinuxCodePipelineBaseImageStack( - app, - "MyBaseImageStack", - embeddedLinuxCodePipelineBaseImageProps, - ); - - const embeddedLinuxCodePipelineProps: EmbeddedLinuxCodePipelineProps = { + common = new cdk.Stack(app, `${resource_prefix}-common`, { env: DEFAULT_ENV, - ecrRepository: embeddedLinuxCodePipelineBaseImageStack.ecrRepository, - ecrRepositoryImageTag: - embeddedLinuxCodePipelineBaseImageStack.ecrRepositoryImageTag, - pipelineSourceBucket: pipelineResourcesStack.pipelineSourceBucket, - pipelineArtifactBucket: pipelineResourcesStack.pipelineArtifactBucket, - pipelineOutputBucket: pipelineResourcesStack.pipelineOutputBucket, - projectType: ProjectType.Poky, - vpc: pipelineResourcesStack.vpc, - pipelineArtifactPrefix: `${ProjectType.Poky}`, - encryptionKey: pipelineResourcesStack.encryptionKey, - }; + }); + + // Create required resources for testing + const vpc = new ec2.Vpc(common, `${resource_prefix}-vpc`, { + maxAzs: 2, + }); + const sourceBucket = new s3.Bucket(common, `${resource_prefix}-src`); + const artifactBucket = new s3.Bucket(common, `${resource_prefix}-art`); + const outputBucket = new s3.Bucket(common, `${resource_prefix}-out`); + const ecrRepository = new ecr.Repository(common, `${resource_prefix}-ecr`); + const encryptionKey = new kms.Key(common, `${resource_prefix}-key`); + // Create the pipeline stack & props + props = { + env: DEFAULT_ENV, + pipelineSourceBucket: sourceBucket, + pipelineArtifactBucket: artifactBucket, + pipelineOutputBucket: outputBucket, + ecrRepository: ecrRepository, + ecrRepositoryImageTag: "latest", + projectType: ProjectType.Custom, + vpc: vpc, + encryptionKey: encryptionKey, + sourceCustomPath: path.join(__dirname, "buildspec"), + }; stack = new EmbeddedLinuxCodePipelineStack( app, - "MyTestStack", - embeddedLinuxCodePipelineProps, + `${resource_prefix}-stack`, + props, ); - template = assertions.Template.fromStack(stack); + + // Create template from stack + template = Template.fromStack(stack); }); - test("Has Resources", () => { + test("Has Correct Resources Count", () => { template.resourceCountIs("AWS::CodePipeline::Pipeline", 1); template.resourceCountIs("AWS::CodeBuild::Project", 1); // AWS::Events::Rule: @@ -87,6 +73,217 @@ describe("EmbeddedLinuxCodePipelineStack", () => { // - the weekly refresh template.resourceCountIs("AWS::Events::Rule", 3); template.resourceCountIs("AWS::Logs::LogGroup", 1); + }); + + test("Creates CodePipeline with correct stages", () => { + template.hasResourceProperties("AWS::CodePipeline::Pipeline", { + Stages: [ + { + Name: "Source", + Actions: [ + { + Name: "Source", + ActionTypeId: { + Category: "Source", + Owner: "AWS", + Provider: "S3", + Version: "1", + }, + }, + ], + }, + { + Name: "Build", + Actions: [ + { + Name: "Build", + ActionTypeId: { + Category: "Build", + Owner: "AWS", + Provider: "CodeBuild", + Version: "1", + }, + }, + ], + }, + { + Name: "Output", + Actions: [ + { + Name: "Output", + ActionTypeId: { + Category: "Deploy", + Owner: "AWS", + Provider: "S3", + Version: "1", + }, + }, + ], + }, + ], + }); + }); + + test("Creates CodeBuild project with correct configuration", () => { + template.hasResourceProperties("AWS::CodeBuild::Project", { + Environment: { + ComputeType: "BUILD_GENERAL1_XLARGE", + Image: { + "Fn::Join": [ + "", + [ + { + "Fn::Select": [ + 4, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}*`, + ), + }, + ], + }, + ], + }, + ".dkr.ecr.", + { + "Fn::Select": [ + 3, + { + "Fn::Split": [ + ":", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.ecrRepository.node.id.replace(/-/g, "")}*`, + ), + }, + ], + }, + ], + }, + ".", + { + Ref: "AWS::URLSuffix", + }, + "/", + { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputRef${props.ecrRepository.node.id.replace(/-/g, "")}*`, + ), + }, + ":latest", + ], + ], + }, + PrivilegedMode: true, + Type: "LINUX_CONTAINER", + }, + }); + }); + + test("Creates EventBridge rule for weekly pipeline execution", () => { + template.hasResourceProperties("AWS::Events::Rule", { + ScheduleExpression: "cron(0 6 ? * Tuesday *)", + State: "ENABLED", + Targets: [ + { + Arn: { + "Fn::Join": [ + "", + [ + "arn:", + { + Ref: "AWS::Partition", + }, + `:codepipeline:${props.env?.region}:${props.env?.account}:`, + { + Ref: Match.stringLikeRegexp("EmbeddedLinuxCodePipeline*"), + }, + ], + ], + }, + Id: "Target0", + RoleArn: { + "Fn::GetAtt": [ + Match.stringLikeRegexp("EmbeddedLinuxCodePipelineEventsRole*"), + "Arn", + ], + }, + }, + ], + }); + }); + + test("Creates EFS filesystem with security group", () => { + template.hasResourceProperties("AWS::EFS::FileSystem", { + FileSystemTags: [ + { + Key: "Name", + Value: `${stack.stackName}/EmbeddedLinuxCodePipelineFileSystem`, + }, + ], + Encrypted: true, + }); + + template.hasResourceProperties("AWS::EC2::SecurityGroup", { + SecurityGroupIngress: Match.arrayWith([ + Match.objectLike({ + CidrIp: { + "Fn::ImportValue": Match.stringLikeRegexp( + `${common.stackName}:ExportsOutputFnGetAtt${props.vpc.node.id.replace(/-/g, "")}*`, + ), + }, + FromPort: 2049, + IpProtocol: "tcp", + ToPort: 2049, + }), + ]), + }); + }); + + test("Creates required IAM roles and policies", () => { + // Test VM import role + template.hasResourceProperties("AWS::IAM::Role", { + RoleName: `${stack.stackName}-vm-mport`, + AssumeRolePolicyDocument: { + Statement: [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { + Service: "vmie.amazonaws.com", + }, + }, + ], + }, + }); + + // Test CodeBuild service role policies + template.hasResourceProperties("AWS::IAM::Policy", { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: [ + "ec2:CreateImage", + "ec2:CreateTags", + "ec2:DescribeImages", + "ec2:DescribeSnapshots", + "ec2:DescribeImportSnapshotTasks", + "ec2:DescribeTags", + "ec2:CancelImportTask", + ], + Effect: "Allow", + Resource: "*", + }), + ]), + }, + }); + }); + + test("Logs Have Minimum Retention Period", () => { + template.resourceCountIs("AWS::Logs::LogGroup", 1); template.allResourcesProperties("AWS::Logs::LogGroup", { RetentionInDays: 365, }); diff --git a/test/codepipeline-resources-nag.test.ts b/test/codepipeline-resources-nag.test.ts index 310bee9..15cee0b 100644 --- a/test/codepipeline-resources-nag.test.ts +++ b/test/codepipeline-resources-nag.test.ts @@ -1,22 +1,28 @@ -import * as cdk from "aws-cdk-lib"; - -import { Annotations, Match } from "aws-cdk-lib/assertions"; +import { describe, expect, test, beforeAll } from "@jest/globals"; import { AwsSolutionsChecks } from "cdk-nag"; +import { Annotations, Match } from "aws-cdk-lib/assertions"; + +import * as cdk from "aws-cdk-lib"; +import { PipelineResourcesProps, PipelineResourcesStack } from "../lib"; import { DEFAULT_ENV } from "./util"; -import { PipelineResourcesStack } from "../lib"; describe("PipelineResourcesStack cdk-nag AwsSolutions Pack", () => { - const app: cdk.App = new cdk.App(); - let stack: cdk.Stack; + const resource_prefix = "test"; + + let app: cdk.App; + let stack: PipelineResourcesStack; + let props: PipelineResourcesProps; beforeAll(() => { // GIVEN - const props = { + app = new cdk.App(); + + props = { env: DEFAULT_ENV, resource_prefix: `${DEFAULT_ENV.account}-${DEFAULT_ENV.region}`, }; - stack = new PipelineResourcesStack(app, "MyTestStack", props); + stack = new PipelineResourcesStack(app, `${resource_prefix}-stack`, props); // WHEN cdk.Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true })); diff --git a/test/codepipeline-resources.test.ts b/test/codepipeline-resources.test.ts index 391e12c..954542a 100644 --- a/test/codepipeline-resources.test.ts +++ b/test/codepipeline-resources.test.ts @@ -1,56 +1,146 @@ +import { beforeEach, describe, expect, it, test } from "@jest/globals"; +import { Match, Template } from "aws-cdk-lib/assertions"; + import * as cdk from "aws-cdk-lib"; -import * as assertions from "aws-cdk-lib/assertions"; import { PipelineResourcesProps, PipelineResourcesStack } from "../lib"; import { DEFAULT_ENV, normalizedTemplateFromStack } from "./util"; -// TODO -// - add test with PipelineResourcesProps values for various buckets -// - add test for other outouts +Object.prototype.toString = function () { + return JSON.stringify(this); +}; describe("PipelineResourcesStack", () => { - let stack: cdk.Stack, app: cdk.App, template: assertions.Template; - const props: PipelineResourcesProps = { - resource_prefix: "test", - env: DEFAULT_ENV, - }; - beforeAll(() => { - // GIVEN + const resource_prefix = "test"; + + let app: cdk.App; + let stack: PipelineResourcesStack; + let props: PipelineResourcesProps; + let template: Template; + + beforeEach(() => { app = new cdk.App(); - stack = new PipelineResourcesStack(app, "MyTestStack", props); - template = assertions.Template.fromStack(stack); + + props = { + resource_prefix: resource_prefix, + env: DEFAULT_ENV, + }; + + stack = new PipelineResourcesStack(app, `${resource_prefix}-stack`, props); + template = Template.fromStack(stack); + }); + + test("creates VPC with correct CIDR", () => { + template.hasResourceProperties("AWS::EC2::VPC", { + CidrBlock: "10.0.0.0/16", + }); + }); + + test("creates ECR repository", () => { + template.hasResourceProperties("AWS::ECR::Repository", { + RepositoryName: `${resource_prefix}-${DEFAULT_ENV.account}-${DEFAULT_ENV.region}-repo`, + }); + }); + + test("creates KMS key with rotation enabled", () => { + template.hasResourceProperties("AWS::KMS::Key", { + EnableKeyRotation: true, + }); }); const bucketSuffixes = [`artifact`, `source`, `output`, `logs`]; - it.each(bucketSuffixes)(`Has S3 Bucket`, (bucketSuffix) => { - const bucketName = - `${props.resource_prefix}-${props.env?.account}-${props.env?.region}-${bucketSuffix}`.toLowerCase(); - template.hasResourceProperties("AWS::S3::Bucket", { - BucketName: bucketName, - }); - }); - - test("Has Versionned S3 Bucket - Source", () => { - expect( - Object.keys(template.findResources("AWS::S3::Bucket")).find((key) => - key.match(/^PipelineResourcesSourceBucket[A-F0-9]{8}$/), - ), - ).toBeDefined(); - expect( - Object.entries(template.findResources("AWS::S3::Bucket")).filter( - ([key, value]) => - key.match(/^PipelineResourcesSourceBucket[A-F0-9]{8}$/) && - value.Properties.VersioningConfiguration.Status == "Enabled", - ), - ).toHaveLength(1); - }); - - test("Logs Have Retention Period", () => { + it.each(bucketSuffixes)( + `Has S3 Bucket with versioning enabled`, + (bucketSuffix) => { + const bucketName = `${resource_prefix}-${DEFAULT_ENV.account}-${DEFAULT_ENV.region}-${bucketSuffix}`; + template.hasResourceProperties("AWS::S3::Bucket", { + BucketName: bucketName, + VersioningConfiguration: { + Status: "Enabled", + }, + }); + }, + ); + + test("creates VPC flow logs", () => { + template.hasResourceProperties("AWS::EC2::FlowLog", { + ResourceType: "VPC", + TrafficType: "ALL", + }); + + template.hasResourceProperties("AWS::Logs::LogGroup", { + RetentionInDays: 365, + }); + }); + + test("creates buckets and ECR repo with custom names when provided", () => { + const customName: string = `${resource_prefix}-${DEFAULT_ENV.account}-${DEFAULT_ENV.region}-custom-xxxxxxxxxxxxxx`; + const appWithCustomNames = new cdk.App(); + const stackWithCustomNames = new PipelineResourcesStack( + appWithCustomNames, + `${resource_prefix}-stack-custom`, + { + resource_prefix: resource_prefix, + ecrRepositoryName: customName, + pipelineArtifactBucketName: customName, + pipelineSourceBucketName: customName, + pipelineOutputBucketName: customName, + loggingBucketName: customName, + }, + ); + const templateWithCustomNames = Template.fromStack(stackWithCustomNames); + + templateWithCustomNames.hasResourceProperties("AWS::ECR::Repository", { + RepositoryName: customName, + }); + + templateWithCustomNames.hasResourceProperties("AWS::S3::Bucket", { + BucketName: customName, + }); + + templateWithCustomNames.resourceCountIs("AWS::S3::Bucket", 4); + }); + + test("Logs Have Minimum Retention Period", () => { template.resourceCountIs("AWS::Logs::LogGroup", 1); template.allResourcesProperties("AWS::Logs::LogGroup", { RetentionInDays: 365, }); }); + test("creates required outputs", () => { + template.hasOutput("LoggingBucket", {}); + template.hasOutput("SourceBucket", {}); + template.hasOutput("ArtifactBucket", {}); + template.hasOutput("OutputBucket", {}); + }); + + test("enforces SSL on all buckets", () => { + const buckets = template.findResources("AWS::S3::Bucket"); + template.resourceCountIs( + "AWS::S3::BucketPolicy", + Object.keys(buckets).length, + ); + + template.hasResourceProperties("AWS::S3::BucketPolicy", { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: "s3:*", + Condition: { + Bool: { + "aws:SecureTransport": "false", + }, + }, + Effect: "Deny", + Principal: { + AWS: "*", + }, + }), + ]), + }, + }); + }); + test("Snapshot", () => { /* We must change some randomly generated file names used in the S3 asset construct. */ const templateWithConstKeys = normalizedTemplateFromStack(stack); diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 0000000..09a9b02 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "rootDir": "." + }, + "include": ["./lib/**/*", "./test/**/*"] +} diff --git a/tsconfig.json b/tsconfig.json index b8ce2fc..f433262 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2020", + "target": "es2020", "module": "commonjs", "lib": ["es2020", "dom"], "declaration": true, @@ -18,8 +18,10 @@ "experimentalDecorators": true, "strictPropertyInitialization": false, "typeRoots": ["./node_modules/@types"], - "outDir": "./dist", - "resolveJsonModule": true + "resolveJsonModule": true, + "rootDir": "./lib", + "outDir": "./dist" }, + "include": ["./lib/**/*", "../test/**/*"], "exclude": ["node_modules", "cdk.out", "dist"] } diff --git a/utils/build-assets.sh b/utils/build-assets.sh deleted file mode 100755 index 425cd67..0000000 --- a/utils/build-assets.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" - -WD="$SCRIPTPATH/.." - -# copy the folders into th dist folder -if [ -d $WD/dist/source-repo ]; then rm -rf $WD/dist/source-repo; fi -mkdir -p $WD/dist/source-repo -cp -r $WD/source-repo $WD/dist diff --git a/yarn.lock b/yarn.lock index 542ddf3..894692b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,9 +16,9 @@ __metadata: linkType: hard "@aws-cdk/asset-awscli-v1@npm:^2.2.208": - version: 2.2.224 - resolution: "@aws-cdk/asset-awscli-v1@npm:2.2.224" - checksum: 10c0/9199f2fc67faf0a7606e76241ad94ba25e81e361125933b648186869223a3e1b10698469f84216e14ef2fc04487302c4a9431463cf564c53919302a8ef5552df + version: 2.2.229 + resolution: "@aws-cdk/asset-awscli-v1@npm:2.2.229" + checksum: 10c0/24a7ef8c49318bb6b177db90b63d407c0e5954fa785ffaa64a0055290361cc61610d9ad2df18d41fe13977be0f70222435ca0fcc2d75339e2f89453a7b37c545 languageName: node linkType: hard @@ -57,7 +57,7 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.26.5": +"@babel/compat-data@npm:^7.26.8": version: 7.26.8 resolution: "@babel/compat-data@npm:7.26.8" checksum: 10c0/66408a0388c3457fff1c2f6c3a061278dd7b3d2f0455ea29bb7b187fa52c60ae8b4054b3c0a184e21e45f0eaac63cf390737bc7504d1f4a088a6e7f652c068ca @@ -65,51 +65,51 @@ __metadata: linkType: hard "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9": - version: 7.26.9 - resolution: "@babel/core@npm:7.26.9" + version: 7.26.10 + resolution: "@babel/core@npm:7.26.10" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.26.2" - "@babel/generator": "npm:^7.26.9" + "@babel/generator": "npm:^7.26.10" "@babel/helper-compilation-targets": "npm:^7.26.5" "@babel/helper-module-transforms": "npm:^7.26.0" - "@babel/helpers": "npm:^7.26.9" - "@babel/parser": "npm:^7.26.9" + "@babel/helpers": "npm:^7.26.10" + "@babel/parser": "npm:^7.26.10" "@babel/template": "npm:^7.26.9" - "@babel/traverse": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" + "@babel/traverse": "npm:^7.26.10" + "@babel/types": "npm:^7.26.10" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/ed7212ff42a9453765787019b7d191b167afcacd4bd8fec10b055344ef53fa0cc648c9a80159ae4ecf870016a6318731e087042dcb68d1a2a9d34eb290dc014b + checksum: 10c0/e046e0e988ab53841b512ee9d263ca409f6c46e2a999fe53024688b92db394346fa3aeae5ea0866331f62133982eee05a675d22922a4603c3f603aa09a581d62 languageName: node linkType: hard -"@babel/generator@npm:^7.26.9, @babel/generator@npm:^7.7.2": - version: 7.26.9 - resolution: "@babel/generator@npm:7.26.9" +"@babel/generator@npm:^7.26.10, @babel/generator@npm:^7.27.0, @babel/generator@npm:^7.7.2": + version: 7.27.0 + resolution: "@babel/generator@npm:7.27.0" dependencies: - "@babel/parser": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" + "@babel/parser": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^3.0.2" - checksum: 10c0/6b78872128205224a9a9761b9ea7543a9a7902a04b82fc2f6801ead4de8f59056bab3fd17b1f834ca7b049555fc4c79234b9a6230dd9531a06525306050becad + checksum: 10c0/7cb10693d2b365c278f109a745dc08856cae139d262748b77b70ce1d97da84627f79648cab6940d847392c0e5d180441669ed958b3aee98d9c7d274b37c553bd languageName: node linkType: hard "@babel/helper-compilation-targets@npm:^7.26.5": - version: 7.26.5 - resolution: "@babel/helper-compilation-targets@npm:7.26.5" + version: 7.27.0 + resolution: "@babel/helper-compilation-targets@npm:7.27.0" dependencies: - "@babel/compat-data": "npm:^7.26.5" + "@babel/compat-data": "npm:^7.26.8" "@babel/helper-validator-option": "npm:^7.25.9" browserslist: "npm:^4.24.0" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/9da5c77e5722f1a2fcb3e893049a01d414124522bbf51323bb1a0c9dcd326f15279836450fc36f83c9e8a846f3c40e88be032ed939c5a9840922bed6073edfb4 + checksum: 10c0/375c9f80e6540118f41bd53dd54d670b8bf91235d631bdead44c8b313b26e9cd89aed5c6df770ad13a87a464497b5346bb72b9462ba690473da422f5402618b6 languageName: node linkType: hard @@ -164,24 +164,24 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.26.9": - version: 7.26.9 - resolution: "@babel/helpers@npm:7.26.9" +"@babel/helpers@npm:^7.26.10": + version: 7.27.0 + resolution: "@babel/helpers@npm:7.27.0" dependencies: - "@babel/template": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" - checksum: 10c0/3d4dbc4a33fe4181ed810cac52318b578294745ceaec07e2f6ecccf6cda55d25e4bfcea8f085f333bf911c9e1fc13320248dd1d5315ab47ad82ce1077410df05 + "@babel/template": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" + checksum: 10c0/a3c64fd2d8b164c041808826cc00769d814074ea447daaacaf2e3714b66d3f4237ef6e420f61d08f463d6608f3468c2ac5124ab7c68f704e20384def5ade95f4 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.26.9": - version: 7.26.9 - resolution: "@babel/parser@npm:7.26.9" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.26.10, @babel/parser@npm:^7.27.0": + version: 7.27.0 + resolution: "@babel/parser@npm:7.27.0" dependencies: - "@babel/types": "npm:^7.26.9" + "@babel/types": "npm:^7.27.0" bin: parser: ./bin/babel-parser.js - checksum: 10c0/4b9ef3c9a0d4c328e5e5544f50fe8932c36f8a2c851e7f14a85401487cd3da75cad72c2e1bcec1eac55599a6bbb2fdc091f274c4fcafa6bdd112d4915ff087fc + checksum: 10c0/ba2ed3f41735826546a3ef2a7634a8d10351df221891906e59b29b0a0cd748f9b0e7a6f07576858a9de8e77785aad925c8389ddef146de04ea2842047c9d2859 languageName: node linkType: hard @@ -372,39 +372,39 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.26.9, @babel/template@npm:^7.3.3": - version: 7.26.9 - resolution: "@babel/template@npm:7.26.9" +"@babel/template@npm:^7.26.9, @babel/template@npm:^7.27.0, @babel/template@npm:^7.3.3": + version: 7.27.0 + resolution: "@babel/template@npm:7.27.0" dependencies: "@babel/code-frame": "npm:^7.26.2" - "@babel/parser": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" - checksum: 10c0/019b1c4129cc01ad63e17529089c2c559c74709d225f595eee017af227fee11ae8a97a6ab19ae6768b8aa22d8d75dcb60a00b28f52e9fa78140672d928bc1ae9 + "@babel/parser": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" + checksum: 10c0/13af543756127edb5f62bf121f9b093c09a2b6fe108373887ccffc701465cfbcb17e07cf48aa7f440415b263f6ec006e9415c79dfc2e8e6010b069435f81f340 languageName: node linkType: hard -"@babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.9": - version: 7.26.9 - resolution: "@babel/traverse@npm:7.26.9" +"@babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.26.10": + version: 7.27.0 + resolution: "@babel/traverse@npm:7.27.0" dependencies: "@babel/code-frame": "npm:^7.26.2" - "@babel/generator": "npm:^7.26.9" - "@babel/parser": "npm:^7.26.9" - "@babel/template": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" + "@babel/generator": "npm:^7.27.0" + "@babel/parser": "npm:^7.27.0" + "@babel/template": "npm:^7.27.0" + "@babel/types": "npm:^7.27.0" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/51dd57fa39ea34d04816806bfead04c74f37301269d24c192d1406dc6e244fea99713b3b9c5f3e926d9ef6aa9cd5c062ad4f2fc1caa9cf843d5e864484ac955e + checksum: 10c0/c7af29781960dacaae51762e8bc6c4b13d6ab4b17312990fbca9fc38e19c4ad7fecaae24b1cf52fb844e8e6cdc76c70ad597f90e496bcb3cc0a1d66b41a0aa5b languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.9, @babel/types@npm:^7.3.3": - version: 7.26.9 - resolution: "@babel/types@npm:7.26.9" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.10, @babel/types@npm:^7.27.0, @babel/types@npm:^7.3.3": + version: 7.27.0 + resolution: "@babel/types@npm:7.27.0" dependencies: "@babel/helper-string-parser": "npm:^7.25.9" "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10c0/999c56269ba00e5c57aa711fbe7ff071cd6990bafd1b978341ea7572cc78919986e2aa6ee51dacf4b6a7a6fa63ba4eb3f1a03cf55eee31b896a56d068b895964 + checksum: 10c0/6f1592eabe243c89a608717b07b72969be9d9d2fce1dee21426238757ea1fa60fdfc09b29de9e48d8104311afc6e6fb1702565a9cc1e09bc1e76f2b2ddb0f6e1 languageName: node linkType: hard @@ -432,13 +432,13 @@ __metadata: linkType: hard "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.1 - resolution: "@eslint-community/eslint-utils@npm:4.4.1" + version: 4.5.1 + resolution: "@eslint-community/eslint-utils@npm:4.5.1" dependencies: eslint-visitor-keys: "npm:^3.4.3" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/2aa0ac2fc50ff3f234408b10900ed4f1a0b19352f21346ad4cc3d83a1271481bdda11097baa45d484dd564c895e0762a27a8240be7a256b3ad47129e96528252 + checksum: 10c0/b520ae1b7bd04531a5c5da2021071815df4717a9f7d13720e3a5ddccf5c9c619532039830811fcbae1c2f1c9d133e63af2435ee69e0fc0fabbd6d928c6800fb2 languageName: node linkType: hard @@ -450,18 +450,18 @@ __metadata: linkType: hard "@eslint/compat@npm:^1.2.4": - version: 1.2.6 - resolution: "@eslint/compat@npm:1.2.6" + version: 1.2.7 + resolution: "@eslint/compat@npm:1.2.7" peerDependencies: eslint: ^9.10.0 peerDependenciesMeta: eslint: optional: true - checksum: 10c0/e767b62f1e43a1b4e3f9f1ac64546f8bcdf4f3fb84c504d8f1b0ea31a71f1607bcd11288c86c77b8ddd3d0bba9a9513d7203d4e6d15b1b3a1cff7718dea61b40 + checksum: 10c0/df89a0396750748c3748eb5fc582bd6cb89be6599d88ed1c5cc60ae0d13f77d4bf5fb30fabdb6c9ce16dda35745ef2e6417fa82548cde7d2b3fa5a896da02c8e languageName: node linkType: hard -"@eslint/config-array@npm:^0.19.0": +"@eslint/config-array@npm:^0.19.2": version: 0.19.2 resolution: "@eslint/config-array@npm:0.19.2" dependencies: @@ -472,18 +472,25 @@ __metadata: languageName: node linkType: hard -"@eslint/core@npm:^0.11.0": - version: 0.11.0 - resolution: "@eslint/core@npm:0.11.0" +"@eslint/config-helpers@npm:^0.2.0": + version: 0.2.0 + resolution: "@eslint/config-helpers@npm:0.2.0" + checksum: 10c0/743a64653e13177029108f57ab47460ded08e3412c86216a14b7e8ab2dc79c2b64be45bf55c5ef29f83692a707dc34cf1e9217e4b8b4b272a0d9b691fdaf6a2a + languageName: node + linkType: hard + +"@eslint/core@npm:^0.12.0": + version: 0.12.0 + resolution: "@eslint/core@npm:0.12.0" dependencies: "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/1e0671d035c908175f445864a7864cf6c6a8b67a5dfba8c47b2ac91e2d3ed36e8c1f2fd81d98a73264f8677055559699d4adb0f97d86588e616fc0dc9a4b86c9 + checksum: 10c0/d032af81195bb28dd800c2b9617548c6c2a09b9490da3c5537fd2a1201501666d06492278bb92cfccac1f7ac249e58601dd87f813ec0d6a423ef0880434fa0c3 languageName: node linkType: hard -"@eslint/eslintrc@npm:^3.2.0": - version: 3.2.0 - resolution: "@eslint/eslintrc@npm:3.2.0" +"@eslint/eslintrc@npm:^3.2.0, @eslint/eslintrc@npm:^3.3.1": + version: 3.3.1 + resolution: "@eslint/eslintrc@npm:3.3.1" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -494,14 +501,14 @@ __metadata: js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: 10c0/43867a07ff9884d895d9855edba41acf325ef7664a8df41d957135a81a477ff4df4196f5f74dc3382627e5cc8b7ad6b815c2cea1b58f04a75aced7c43414ab8b + checksum: 10c0/b0e63f3bc5cce4555f791a4e487bf999173fcf27c65e1ab6e7d63634d8a43b33c3693e79f192cbff486d7df1be8ebb2bd2edc6e70ddd486cbfa84a359a3e3b41 languageName: node linkType: hard -"@eslint/js@npm:9.20.0, @eslint/js@npm:^9.16.0": - version: 9.20.0 - resolution: "@eslint/js@npm:9.20.0" - checksum: 10c0/10e7b5b9e628b5192e8fc6b0ecd27cf48322947e83e999ff60f9f9e44ac8d499138bcb9383cbfa6e51e780d53b4e76ccc2d1753b108b7173b8404fd484d37328 +"@eslint/js@npm:9.23.0, @eslint/js@npm:^9.16.0": + version: 9.23.0 + resolution: "@eslint/js@npm:9.23.0" + checksum: 10c0/4e70869372b6325389e0ab51cac6d3062689807d1cef2c3434857571422ce11dde3c62777af85c382b9f94d937127598d605d2086787f08611351bf99faded81 languageName: node linkType: hard @@ -512,13 +519,13 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.2.5": - version: 0.2.6 - resolution: "@eslint/plugin-kit@npm:0.2.6" +"@eslint/plugin-kit@npm:^0.2.7": + version: 0.2.7 + resolution: "@eslint/plugin-kit@npm:0.2.7" dependencies: - "@eslint/core": "npm:^0.11.0" + "@eslint/core": "npm:^0.12.0" levn: "npm:^0.4.1" - checksum: 10c0/2d4cc4497c62e2a6437039fdd778911d768b0706c6256568c4ff1ad8724f663b2fa04a5873db6a20a812be11166e78e0346acfde4b7149e10e92f7b0075a976e + checksum: 10c0/0a1aff1ad63e72aca923217e556c6dfd67d7cd121870eb7686355d7d1475d569773528a8b2111b9176f3d91d2ea81f7413c34600e8e5b73d59e005d70780b633 languageName: node linkType: hard @@ -564,10 +571,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/retry@npm:^0.4.1": - version: 0.4.1 - resolution: "@humanwhocodes/retry@npm:0.4.1" - checksum: 10c0/be7bb6841c4c01d0b767d9bb1ec1c9359ee61421ce8ba66c249d035c5acdfd080f32d55a5c9e859cdd7868788b8935774f65b2caf24ec0b7bd7bf333791f063b +"@humanwhocodes/retry@npm:^0.4.2": + version: 0.4.2 + resolution: "@humanwhocodes/retry@npm:0.4.2" + checksum: 10c0/0235525d38f243bee3bf8b25ed395fbf957fb51c08adae52787e1325673071abe856c7e18e530922ed2dd3ce12ed82ba01b8cee0279ac52a3315fcdc3a69ef0c languageName: node linkType: hard @@ -950,10 +957,10 @@ __metadata: languageName: node linkType: hard -"@pkgr/core@npm:^0.1.0": - version: 0.1.1 - resolution: "@pkgr/core@npm:0.1.1" - checksum: 10c0/3f7536bc7f57320ab2cf96f8973664bef624710c403357429fbf680a5c3b4843c1dbd389bb43daa6b1f6f1f007bb082f5abcb76bb2b5dc9f421647743b71d3d8 +"@pkgr/core@npm:^0.2.0": + version: 0.2.0 + resolution: "@pkgr/core@npm:0.2.0" + checksum: 10c0/29cb9c15f4788096b8b8b786b19c75b6398b6afe814a97189922c3046d8acb5d24f1217fd2537c3f8e42c04e48d572295e7ee56d77964ddc932c44eb5a615931 languageName: node linkType: hard @@ -1070,18 +1077,18 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.6 - resolution: "@types/babel__traverse@npm:7.20.6" + version: 7.20.7 + resolution: "@types/babel__traverse@npm:7.20.7" dependencies: "@babel/types": "npm:^7.20.7" - checksum: 10c0/7ba7db61a53e28cac955aa99af280d2600f15a8c056619c05b6fc911cbe02c61aa4f2823299221b23ce0cce00b294c0e5f618ec772aa3f247523c2e48cf7b888 + checksum: 10c0/5386f0af44f8746b063b87418f06129a814e16bb2686965a575e9d7376b360b088b89177778d8c426012abc43dd1a2d8ec3218bfc382280c898682746ce2ffbd languageName: node linkType: hard "@types/estree@npm:^1.0.6": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a + version: 1.0.7 + resolution: "@types/estree@npm:1.0.7" + checksum: 10c0/be815254316882f7c40847336cd484c3bc1c3e34f710d197160d455dc9d6d050ffbf4c3bc76585dba86f737f020ab20bdb137ebe0e9116b0c86c7c0342221b8c languageName: node linkType: hard @@ -1146,11 +1153,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 22.13.4 - resolution: "@types/node@npm:22.13.4" + version: 22.13.14 + resolution: "@types/node@npm:22.13.14" dependencies: undici-types: "npm:~6.20.0" - checksum: 10c0/3a234fa7766a3efc382cf81f66f474c26cdab2f54f43f757634c81c0444eb2160c2dabbde9741e4983078a318a88515b65416b5f1ab5478548579d7b3ead1d95 + checksum: 10c0/fa2ab5b8277bfbcc86c42e46a3ea9871b0d559894cc9d955685d17178c9499f0b1bf03d1d1ea8d92ef2dda818988f4035acb8abf9dc15423a998fa56173ab804 languageName: node linkType: hard @@ -1193,15 +1200,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.24.1, @typescript-eslint/eslint-plugin@npm:^8.18.0": - version: 8.24.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.24.1" +"@typescript-eslint/eslint-plugin@npm:8.28.0, @typescript-eslint/eslint-plugin@npm:^8.18.0": + version: 8.28.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.28.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.24.1" - "@typescript-eslint/type-utils": "npm:8.24.1" - "@typescript-eslint/utils": "npm:8.24.1" - "@typescript-eslint/visitor-keys": "npm:8.24.1" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/type-utils": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -1209,65 +1216,65 @@ __metadata: peerDependencies: "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/fe5f56f248370f40322a7cb2d96fbab724a7a8892895e3d41027c9a1df309916433633e04df84a1d3f9535d282953738b1ad627d8af37ab288a39a6e411afd76 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/f01b7d231b01ec2c1cc7c40599ddceb329532f2876664a39dec9d25c0aed4cfdbef3ec07f26bac357df000d798f652af6fdb6a2481b6120e43bfa38f7c7a7c48 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.24.1, @typescript-eslint/parser@npm:^8.18.0": - version: 8.24.1 - resolution: "@typescript-eslint/parser@npm:8.24.1" +"@typescript-eslint/parser@npm:8.28.0, @typescript-eslint/parser@npm:^8.18.0": + version: 8.28.0 + resolution: "@typescript-eslint/parser@npm:8.28.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.24.1" - "@typescript-eslint/types": "npm:8.24.1" - "@typescript-eslint/typescript-estree": "npm:8.24.1" - "@typescript-eslint/visitor-keys": "npm:8.24.1" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/typescript-estree": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/9de557698c8debf3de06b6adf6aa06a8345e0e38600e5ccbeda62270d1a4a757dfa191db89d4e86cf373103a11bef1965c9d9889f622c51f4f26d1bf12394ae3 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/4bde6887bbf3fe031c01e46db90f9f384a8cac2e67c2972b113a62d607db75e01db943601279aac847b9187960a038981814042cb02fd5aa27ea4613028f9313 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/scope-manager@npm:8.24.1" +"@typescript-eslint/scope-manager@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/scope-manager@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.24.1" - "@typescript-eslint/visitor-keys": "npm:8.24.1" - checksum: 10c0/779880743ed7ab67fe477f1ad5648bbd77ad69b4663b5a42024112004c8f231049b1e4eeb67e260005769c3bb005049e00a80b885e19d593ffb080bd39f4fa94 + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" + checksum: 10c0/f3bd76b3f54e60f1efe108b233b2d818e44ecf0dc6422cc296542f784826caf3c66d51b8acc83d8c354980bd201e1d9aa1ea01011de96e0613d320c00e40ccfd languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/type-utils@npm:8.24.1" +"@typescript-eslint/type-utils@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/type-utils@npm:8.28.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.24.1" - "@typescript-eslint/utils": "npm:8.24.1" + "@typescript-eslint/typescript-estree": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^2.0.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/ba248bc12068383374d9d077f9cca1815f347ea008d04d08ad7a54dbef70189a0da7872246f8369e6d30938fa7e408dadcda0ae71041be68fc836c886dd9c3ab + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/b8936edc2153bf794efba39bfb06393a228217830051767360f4b691fed7c82f3831c4fc6deac6d78b90a58596e61f866c17eaee9dd793c3efda3ebdcf5a71d8 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/types@npm:8.24.1" - checksum: 10c0/ebb40ce16c746ef236dbcc25cb2e6950753ca6fb34d04ed7d477016370de1fdaf7402ed4569673c6ff14bf60af7124ff45c6ddd9328d2f8c94dc04178368e2a3 +"@typescript-eslint/types@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/types@npm:8.28.0" + checksum: 10c0/1f95895e20dac1cf063dc93c99142fd1871e53be816bcbbee93f22a05e6b2a82ca83c20ce3a551f65555910aa0956443a23268edbb004369d0d5cb282d13c377 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.24.1" +"@typescript-eslint/typescript-estree@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.24.1" - "@typescript-eslint/visitor-keys": "npm:8.24.1" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/visitor-keys": "npm:8.28.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -1275,33 +1282,33 @@ __metadata: semver: "npm:^7.6.0" ts-api-utils: "npm:^2.0.1" peerDependencies: - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/8eeeae6e8de1cd83f2eddd52293e9c31a655e0974cc2d410f00ba2b6fd6bb9aec1c346192d5784d64d0d1b15a55e56e35550788c04dda87e0f1a99b21a3eb709 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/97a91c95b1295926098c12e2d2c2abaa68994dc879da132dcce1e75ec9d7dee8187695eaa5241d09cbc42b5e633917b6d35c624e78e3d3ee9bda42d1318080b6 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/utils@npm:8.24.1" +"@typescript-eslint/utils@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/utils@npm:8.28.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.24.1" - "@typescript-eslint/types": "npm:8.24.1" - "@typescript-eslint/typescript-estree": "npm:8.24.1" + "@typescript-eslint/scope-manager": "npm:8.28.0" + "@typescript-eslint/types": "npm:8.28.0" + "@typescript-eslint/typescript-estree": "npm:8.28.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/b3300d5c7e18ec524a46bf683052539f24df0d8c709e39e3bde9dfc6c65180610c46b875f1f4eaad5e311193a56acdfd7111a73f1e8aec4108e9cd19561bf8b8 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/d3425be7f86c1245a11f0ea39136af681027797417348d8e666d38c76646945eaed7b35eb8db66372b067dee8b02a855caf2c24c040ec9c31e59681ab223b59d languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.24.1": - version: 8.24.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.24.1" +"@typescript-eslint/visitor-keys@npm:8.28.0": + version: 8.28.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.28.0" dependencies: - "@typescript-eslint/types": "npm:8.24.1" + "@typescript-eslint/types": "npm:8.28.0" eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/ba09412fb4b1605aa73c890909c9a8dba2aa72e00ccd7d69baad17c564eedd77f489a06b1686985c7f0c49724787b82d76dcf4c146c4de44ef2c8776a9b6ad2b + checksum: 10c0/245a78ed983fe95fbd1b0f2d4cb9e9d1d964bddc0aa3e3d6ab10c19c4273855bfb27d840bb1fd55deb7ae3078b52f26592472baf6fd2c7019a5aa3b1da974f35 languageName: node linkType: hard @@ -1331,11 +1338,11 @@ __metadata: linkType: hard "acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.4.1": - version: 8.14.0 - resolution: "acorn@npm:8.14.0" + version: 8.14.1 + resolution: "acorn@npm:8.14.1" bin: acorn: bin/acorn - checksum: 10c0/6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7 + checksum: 10c0/dbd36c1ed1d2fa3550140000371fcf721578095b18777b85a79df231ca093b08edc6858d75d6e48c73e431c174dcf9214edbd7e6fa5911b93bd8abfa54e47123 languageName: node linkType: hard @@ -1518,6 +1525,7 @@ __metadata: eslint: "npm:^9.16.0" eslint-config-prettier: "npm:^9.1.0" eslint-plugin-prettier: "npm:^5.2.1" + eslint-plugin-simple-import-sort: "npm:^12.1.1" eslint-plugin-tsdoc: "npm:^0.4.0" globals: "npm:^15.13.0" jest: "npm:^29.7.0" @@ -1725,9 +1733,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001700 - resolution: "caniuse-lite@npm:1.0.30001700" - checksum: 10c0/3d391bcdd193208166d3ad759de240b9c18ac3759dbd57195770f0fcd2eedcd47d5e853609aba1eee5a2def44b0a14eee457796bdb3451a27de0c8b27355017c + version: 1.0.30001707 + resolution: "caniuse-lite@npm:1.0.30001707" + checksum: 10c0/a1beaf84bad4f6617bbc5616d6bc0c9cab73e73f7e9e09b6466af5195b1bc393e0f6f19643d7a1c88bd3f4bfa122d7bea81cf6225ec3ade57d5b1dd3478c1a1b languageName: node linkType: hard @@ -1739,12 +1747,12 @@ __metadata: linkType: hard "cdk-nag@npm:^2.35.0": - version: 2.35.24 - resolution: "cdk-nag@npm:2.35.24" + version: 2.35.56 + resolution: "cdk-nag@npm:2.35.56" peerDependencies: aws-cdk-lib: ^2.156.0 constructs: ^10.0.5 - checksum: 10c0/12783afc8f2cef18e5fb70a988864a548250383e0a4e4430853458fc49f3241697f035b9c9516fe68f07d8f76dcbb6b85bdf6c8522639392aac78db05577e68f + checksum: 10c0/7707908e3ebfde42af327f9f84bdf21b068d55db440d13010dd73d1ebce831f500f8084a488cff9319dd9169128a61113aeab4e2bb33ac8374e4cbf40883b549 languageName: node linkType: hard @@ -1954,9 +1962,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.5.73": - version: 1.5.102 - resolution: "electron-to-chromium@npm:1.5.102" - checksum: 10c0/db07dab3ee3b7fbc39ad26203925669ade86b12a62d09fa14ae48a354a0f34d162ac9a2ca9d6f70ceb1b16821b01b155e56467702bcc915da1e1dd147dd034b4 + version: 1.5.126 + resolution: "electron-to-chromium@npm:1.5.126" + checksum: 10c0/0e481d2467ac603f2fbb365d1cddd1e2d43f5f8c11aa281395cf450cfefa7b5cbdde1b952201fdf04730aa14adaff53e4087f88c3ff671b08f0baee2c1179954 languageName: node linkType: hard @@ -2046,22 +2054,31 @@ __metadata: linkType: hard "eslint-plugin-prettier@npm:^5.2.1": - version: 5.2.3 - resolution: "eslint-plugin-prettier@npm:5.2.3" + version: 5.2.5 + resolution: "eslint-plugin-prettier@npm:5.2.5" dependencies: prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.9.1" + synckit: "npm:^0.10.2" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" - eslint-config-prettier: "*" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 10c0/60d9c03491ec6080ac1d71d0bee1361539ff6beb9b91ac98cfa7176c9ed52b7dbe7119ebee5b441b479d447d17d802a4a492ee06095ef2f22c460e3dd6459302 + checksum: 10c0/b88d4ecfccfdea786aa8c2df8c6b52754070fec48ef5df0dcd325daf7cbe01730a96fb6a8c5ae0ddd173472b43704d6452169b058284e842dfee5894172f310b + languageName: node + linkType: hard + +"eslint-plugin-simple-import-sort@npm:^12.1.1": + version: 12.1.1 + resolution: "eslint-plugin-simple-import-sort@npm:12.1.1" + peerDependencies: + eslint: ">=5.0.0" + checksum: 10c0/0ad1907ad9ddbadd1db655db0a9d0b77076e274b793a77b982c8525d808d868e6ecfce24f3a411e8a1fa551077387f9ebb38c00956073970ebd7ee6a029ce2b3 languageName: node linkType: hard @@ -2075,13 +2092,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^8.2.0": - version: 8.2.0 - resolution: "eslint-scope@npm:8.2.0" +"eslint-scope@npm:^8.3.0": + version: 8.3.0 + resolution: "eslint-scope@npm:8.3.0" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10c0/8d2d58e2136d548ac7e0099b1a90d9fab56f990d86eb518de1247a7066d38c908be2f3df477a79cf60d70b30ba18735d6c6e70e9914dca2ee515a729975d70d6 + checksum: 10c0/23bf54345573201fdf06d29efa345ab508b355492f6c6cc9e2b9f6d02b896f369b6dd5315205be94b8853809776c4d13353b85c6b531997b164ff6c3328ecf5b languageName: node linkType: hard @@ -2100,19 +2117,20 @@ __metadata: linkType: hard "eslint@npm:^9.16.0": - version: 9.20.1 - resolution: "eslint@npm:9.20.1" + version: 9.23.0 + resolution: "eslint@npm:9.23.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" - "@eslint/config-array": "npm:^0.19.0" - "@eslint/core": "npm:^0.11.0" - "@eslint/eslintrc": "npm:^3.2.0" - "@eslint/js": "npm:9.20.0" - "@eslint/plugin-kit": "npm:^0.2.5" + "@eslint/config-array": "npm:^0.19.2" + "@eslint/config-helpers": "npm:^0.2.0" + "@eslint/core": "npm:^0.12.0" + "@eslint/eslintrc": "npm:^3.3.1" + "@eslint/js": "npm:9.23.0" + "@eslint/plugin-kit": "npm:^0.2.7" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" - "@humanwhocodes/retry": "npm:^0.4.1" + "@humanwhocodes/retry": "npm:^0.4.2" "@types/estree": "npm:^1.0.6" "@types/json-schema": "npm:^7.0.15" ajv: "npm:^6.12.4" @@ -2120,7 +2138,7 @@ __metadata: cross-spawn: "npm:^7.0.6" debug: "npm:^4.3.2" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^8.2.0" + eslint-scope: "npm:^8.3.0" eslint-visitor-keys: "npm:^4.2.0" espree: "npm:^10.3.0" esquery: "npm:^1.5.0" @@ -2144,7 +2162,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/056789dd5a00897730376f8c0a191e22840e97b7276916068ec096341cb2ec3a918c8bd474bf94ccd7b457ad9fbc16e5c521a993c7cc6ebcf241933e2fd378b0 + checksum: 10c0/9616c308dfa8d09db8ae51019c87d5d05933742214531b077bd6ab618baab3bec7938256c14dcad4dc47f5ba93feb0bc5e089f68799f076374ddea21b6a9be45 languageName: node linkType: hard @@ -2294,11 +2312,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.19.0 - resolution: "fastq@npm:1.19.0" + version: 1.19.1 + resolution: "fastq@npm:1.19.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10c0/d6a001638f1574a696660fcbba5300d017760432372c801632c325ca7c16819604841c92fd3ccadcdacec0966ca336363a5ff57bc5f0be335d8ea7ac6087b98f + checksum: 10c0/ebc6e50ac7048daaeb8e64522a1ea7a26e92b3cee5cd1c7f2316cdca81ba543aa40a136b53891446ea5c3a67ec215fbaca87ad405f102dd97012f62916905630 languageName: node linkType: hard @@ -3639,8 +3657,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^4.0.0": - version: 4.0.0 - resolution: "minipass-fetch@npm:4.0.0" + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" @@ -3649,7 +3667,7 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 10c0/7fa30ce7c373fb6f94c086b374fff1589fd7e78451855d2d06c2e2d9df936d131e73e952163063016592ed3081444bd8d1ea608533313b0149156ce23311da4b + checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c languageName: node linkType: hard @@ -3976,11 +3994,11 @@ __metadata: linkType: hard "prettier@npm:^3.4.2": - version: 3.5.1 - resolution: "prettier@npm:3.5.1" + version: 3.5.3 + resolution: "prettier@npm:3.5.3" bin: prettier: bin/prettier.cjs - checksum: 10c0/9f6f810eae455d6e4213845151a484a2338f2e0d6a8b84ee8e13a83af8a2421ef6c1e31e61e4b135671fb57b9541f6624648880cc2061ac803e243ac898c0123 + checksum: 10c0/3880cb90b9dc0635819ab52ff571518c35bd7f15a6e80a2054c05dbc8a3aa6e74f135519e91197de63705bcb38388ded7e7230e2178432a1468005406238b877 languageName: node linkType: hard @@ -4135,9 +4153,9 @@ __metadata: linkType: hard "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10c0/c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10c0/4eff0d4a5f9383566c7d7ec437b671cc51b25963bd61bf127c3f3d3f68e44a026d99b8d2f1ad344afff8d278a8fe70a8ea092650a716d22287e8bef7126bb2fa languageName: node linkType: hard @@ -4387,13 +4405,13 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.9.1": - version: 0.9.2 - resolution: "synckit@npm:0.9.2" +"synckit@npm:^0.10.2": + version: 0.10.3 + resolution: "synckit@npm:0.10.3" dependencies: - "@pkgr/core": "npm:^0.1.0" - tslib: "npm:^2.6.2" - checksum: 10c0/e0c262817444e5b872708adb6f5ad37951ba33f6b2d1d4477d45db1f57573a784618ceed5e6614e0225db330632b1f6b95bb74d21e4d013e45ad4bde03d0cb59 + "@pkgr/core": "npm:^0.2.0" + tslib: "npm:^2.8.1" + checksum: 10c0/9855d10231ae9b69c3aa08d46c96bd4befdcac33da44e29fb80e5c1430e453b5a33b8c073cdd25cfe9578f1d625c7d60c394ece1e202237116c1484def614041 languageName: node linkType: hard @@ -4452,17 +4470,17 @@ __metadata: linkType: hard "ts-api-utils@npm:^2.0.1": - version: 2.0.1 - resolution: "ts-api-utils@npm:2.0.1" + version: 2.1.0 + resolution: "ts-api-utils@npm:2.1.0" peerDependencies: typescript: ">=4.8.4" - checksum: 10c0/23fd56a958b332cac00150a652e4c84730df30571bd2faa1ba6d7b511356d1a61656621492bb6c7f15dd6e18847a1408357a0e406671d358115369a17f5bfedd + checksum: 10c0/9806a38adea2db0f6aa217ccc6bc9c391ddba338a9fe3080676d0d50ed806d305bb90e8cef0276e793d28c8a929f400abb184ddd7ff83a416959c0f4d2ce754f languageName: node linkType: hard "ts-jest@npm:^29.2.5": - version: 29.2.5 - resolution: "ts-jest@npm:29.2.5" + version: 29.3.0 + resolution: "ts-jest@npm:29.3.0" dependencies: bs-logger: "npm:^0.2.6" ejs: "npm:^3.1.10" @@ -4471,7 +4489,8 @@ __metadata: json5: "npm:^2.2.3" lodash.memoize: "npm:^4.1.2" make-error: "npm:^1.3.6" - semver: "npm:^7.6.3" + semver: "npm:^7.7.1" + type-fest: "npm:^4.37.0" yargs-parser: "npm:^21.1.1" peerDependencies: "@babel/core": ">=7.0.0-beta.0 <8" @@ -4493,7 +4512,7 @@ __metadata: optional: true bin: ts-jest: cli.js - checksum: 10c0/acb62d168faec073e64b20873b583974ba8acecdb94681164eb346cef82ade8fb481c5b979363e01a97ce4dd1e793baf64d9efd90720bc941ad7fc1c3d6f3f68 + checksum: 10c0/c6a6b80e056a6d78679307fc859ebaafa9809bd707e5679b4f3e75b774137d840e607401698059e98497dac299c8c90305eae7ae8464cb1c6f161edfa8de0903 languageName: node linkType: hard @@ -4535,7 +4554,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.6.2": +"tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 @@ -4565,9 +4584,16 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.37.0": + version: 4.38.0 + resolution: "type-fest@npm:4.38.0" + checksum: 10c0/db9990d682a08697cf8ae67ac3cdbca734c742c96615e8888401d7d54e376b390e6a5d3be25fe3b4b439e1bb88a7da461da678a614ece8caccd9c0a07dd2e5f4 + languageName: node + linkType: hard + "typedoc@npm:^0.27.4": - version: 0.27.7 - resolution: "typedoc@npm:0.27.7" + version: 0.27.9 + resolution: "typedoc@npm:0.27.9" dependencies: "@gerrit0/mini-shiki": "npm:^1.24.0" lunr: "npm:^2.3.9" @@ -4575,24 +4601,24 @@ __metadata: minimatch: "npm:^9.0.5" yaml: "npm:^2.6.1" peerDependencies: - typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x + typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x bin: typedoc: bin/typedoc - checksum: 10c0/727f7da5255f66d949a524582b5ec9ecfa43caade1ea48efe9305117bd18d5a26c423c788767ee992662eff7bec7ac993673cafe14d6fd206881c604cad2f6ba + checksum: 10c0/999668d9d23e1824b762e2c411e2c0860d0ce4a2e61f23a2c31d36a1d6337a763553bc75205aee25ce34659e9315315c720694e9eccd7e7e4755873fdfec1192 languageName: node linkType: hard "typescript-eslint@npm:^8.18.0": - version: 8.24.1 - resolution: "typescript-eslint@npm:8.24.1" + version: 8.28.0 + resolution: "typescript-eslint@npm:8.28.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.24.1" - "@typescript-eslint/parser": "npm:8.24.1" - "@typescript-eslint/utils": "npm:8.24.1" + "@typescript-eslint/eslint-plugin": "npm:8.28.0" + "@typescript-eslint/parser": "npm:8.28.0" + "@typescript-eslint/utils": "npm:8.28.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/5bcb6af12d04777ca04ca9300552e1c7410d640950945d854be41c264fdfe965ce40c0203336e073eb0697567d59043b3096dfed825e76fd7347081e9abf3b16 + typescript: ">=4.8.4 <5.9.0" + checksum: 10c0/bf1c1e4b2f21a95930758d5b285c39a394a50e3b6983f373413b93b80a6cb5aabc1d741780e60c63cb42ad5d645ea9c1e6d441d98174c5a2884ab88f4ac46df6 languageName: node linkType: hard @@ -4663,8 +4689,8 @@ __metadata: linkType: hard "update-browserslist-db@npm:^1.1.1": - version: 1.1.2 - resolution: "update-browserslist-db@npm:1.1.2" + version: 1.1.3 + resolution: "update-browserslist-db@npm:1.1.3" dependencies: escalade: "npm:^3.2.0" picocolors: "npm:^1.1.1" @@ -4672,7 +4698,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10c0/9cb353998d6d7d6ba1e46b8fa3db888822dd972212da4eda609d185eb5c3557a93fd59780ceb757afd4d84240518df08542736969e6a5d6d6ce2d58e9363aac6 + checksum: 10c0/682e8ecbf9de474a626f6462aa85927936cdd256fe584c6df2508b0df9f7362c44c957e9970df55dfe44d3623807d26316ea2c7d26b80bb76a16c56c37233c32 languageName: node linkType: hard