From 037aa749e5f8b5ff1e95afe4e72be291ecb1ae2e Mon Sep 17 00:00:00 2001 From: Ian Hou <45278651+iankhou@users.noreply.github.com> Date: Wed, 22 Jan 2025 10:55:35 -0500 Subject: [PATCH] POC for IAM tracking in Integ test snapshots --- .../cli-integ/arn-operation-map.json | 4 +++ .../@aws-cdk-testing/cli-integ/lib/aws.ts | 33 +++++++++++++++++++ .../cli-integ/lib/iam-tracking-middleware.ts | 25 ++++++++++++++ .../cli-integ/lib/with-cdk-app.ts | 5 +++ .../@aws-cdk-testing/cli-integ/package.json | 8 ++--- .../tests/cli-integ-tests/cli.integtest.ts | 6 ++++ 6 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk-testing/cli-integ/arn-operation-map.json create mode 100644 packages/@aws-cdk-testing/cli-integ/lib/iam-tracking-middleware.ts diff --git a/packages/@aws-cdk-testing/cli-integ/arn-operation-map.json b/packages/@aws-cdk-testing/cli-integ/arn-operation-map.json new file mode 100644 index 0000000000000..4514f4931778e --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/arn-operation-map.json @@ -0,0 +1,4 @@ +{ + "CloudFormation:CreateStack": "arn:aws:iam::597088032010:user/cdk-workshop", + "CloudFormation:DescribeStacks": "arn:aws:iam::597088032010:user/cdk-workshop" +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/cli-integ/lib/aws.ts b/packages/@aws-cdk-testing/cli-integ/lib/aws.ts index aee6512bdedcb..15cf1da43a12d 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/aws.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/aws.ts @@ -1,3 +1,4 @@ +import { writeFile } from 'fs/promises'; import { CloudFormationClient, DeleteStackCommand, @@ -22,6 +23,7 @@ import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; import { fromIni } from '@aws-sdk/credential-providers'; import type { AwsCredentialIdentityProvider } from '@smithy/types'; import { ConfiguredRetryStrategy } from '@smithy/util-retry'; +import { iamLoggingMiddleware } from './iam-tracking-middleware'; interface ClientConfig { readonly credentials?: AwsCredentialIdentityProvider; readonly region: string; @@ -49,6 +51,7 @@ export class AwsClients { public readonly iam: IAMClient; public readonly lambda: LambdaClient; public readonly sts: STSClient; + public readonly arnOperationMap: Map; constructor(public readonly region: string, private readonly output: NodeJS.WritableStream) { this.config = { @@ -56,15 +59,45 @@ export class AwsClients { region: this.region, retryStrategy: new ConfiguredRetryStrategy(9, (attempt: number) => attempt ** 500), }; + + this.arnOperationMap = new Map(); + this.cloudFormation = new CloudFormationClient(this.config); + this.cloudFormation.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.s3 = new S3Client(this.config); + this.cloudFormation.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.ecr = new ECRClient(this.config); + this.ecr.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.ecs = new ECSClient(this.config); + this.ecs.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.sso = new SSOClient(this.config); + this.sso.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.sns = new SNSClient(this.config); + this.sns.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.iam = new IAMClient(this.config); + this.iam.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.lambda = new LambdaClient(this.config); + this.lambda.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + this.sts = new STSClient(this.config); + this.sts.middlewareStack.use(iamLoggingMiddleware(this.arnOperationMap, this.config.region)); + } + + public async outputFile() { + // console.log(this.arnOperationMap); + const mapObject = Object.fromEntries(this.arnOperationMap); + + await writeFile( + 'arn-operation-map.json', + JSON.stringify(mapObject, null, 2), + ); } public async account(): Promise { diff --git a/packages/@aws-cdk-testing/cli-integ/lib/iam-tracking-middleware.ts b/packages/@aws-cdk-testing/cli-integ/lib/iam-tracking-middleware.ts new file mode 100644 index 0000000000000..dfce792fbdcef --- /dev/null +++ b/packages/@aws-cdk-testing/cli-integ/lib/iam-tracking-middleware.ts @@ -0,0 +1,25 @@ +import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'; +import { MiddlewareStack, SMITHY_CONTEXT_KEY } from '@smithy/types'; + +export const iamLoggingMiddleware = (arnOperationMap: Map, region: string) => { + return { + applyToStack: (stack: MiddlewareStack) => { + stack.add( + (next, context) => async (args: any): Promise => { + // Get identity information using STS + const stsClient = new STSClient({ region }); + const identity = await stsClient.send(new GetCallerIdentityCommand({})); + + arnOperationMap.set(`${context[SMITHY_CONTEXT_KEY]?.service}:${context[SMITHY_CONTEXT_KEY]?.operation}`, identity.Arn as string); + + return next(args); + }, + { + name: 'IAMLoggingMiddleware', + step: 'build', + override: true, + }, + ); + }, + }; +}; diff --git a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts index 7bdfff1154ba2..33bc98c0597d0 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts @@ -375,6 +375,11 @@ export class TestFixture extends ShellHelper { this.packages = packageSourceInSubprocess(); } + public async outputFile() { + await this.aws.outputFile(); + console.log('with cdk app file written!'); + } + public log(s: string) { this.output.write(`${s}\n`); } diff --git a/packages/@aws-cdk-testing/cli-integ/package.json b/packages/@aws-cdk-testing/cli-integ/package.json index a1df0347c43ad..885e725837280 100644 --- a/packages/@aws-cdk-testing/cli-integ/package.json +++ b/packages/@aws-cdk-testing/cli-integ/package.json @@ -1,7 +1,7 @@ { "name": "@aws-cdk-testing/cli-integ", "description": "Integration tests for the AWS CDK CLI", - "version": "0.0.0", + "version": "2.176.0", "bin": { "run-suite": "bin/run-suite", "download-and-run-old-tests": "bin/download-and-run-old-tests", @@ -29,13 +29,13 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-build-tools": "2.176.0-alpha.0", "@types/semver": "^7.5.8", "@types/yargs": "^15.0.19", "@types/fs-extra": "^9.0.13", "@types/glob": "^7.2.0", "@types/npm": "^7.19.3", - "@aws-cdk/pkglint": "0.0.0" + "@aws-cdk/pkglint": "2.176.0-alpha.0" }, "dependencies": { "@octokit/rest": "^18.12.0", @@ -86,4 +86,4 @@ "publishConfig": { "tag": "latest" } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts index f4736584a065f..9bc49f3a25cee 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts @@ -1143,6 +1143,9 @@ integTest( expect(response.Stacks?.[0].StackStatus).toEqual('UPDATE_COMPLETE'); } finally { await fixture.cdkDestroy('migrate-stack'); + await fixture.outputFile(); + // eslint-disable-next-line no-console + console.log('file written! from cli.integ.test'); } }), ); @@ -1159,6 +1162,9 @@ integTest( // We can make it fail by passing --fail await expect(fixture.cdk(['diff', '--fail', fixture.fullStackName('test-1')])).rejects.toThrow('exited with error'); + await fixture.outputFile(); + // eslint-disable-next-line no-console + console.log('file written!'); }), );