Skip to content

Commit

Permalink
POC for IAM tracking in Integ test snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
iankhou committed Jan 22, 2025
1 parent 61e876b commit 037aa74
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 4 deletions.
4 changes: 4 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/arn-operation-map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"CloudFormation:CreateStack": "arn:aws:iam::597088032010:user/cdk-workshop",
"CloudFormation:DescribeStacks": "arn:aws:iam::597088032010:user/cdk-workshop"
}
33 changes: 33 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/lib/aws.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { writeFile } from 'fs/promises';
import {
CloudFormationClient,
DeleteStackCommand,
Expand All @@ -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;
Expand Down Expand Up @@ -49,22 +51,53 @@ export class AwsClients {
public readonly iam: IAMClient;
public readonly lambda: LambdaClient;
public readonly sts: STSClient;
public readonly arnOperationMap: Map<string, string>;

constructor(public readonly region: string, private readonly output: NodeJS.WritableStream) {
this.config = {
credentials: chainableCredentials(this.region),
region: this.region,
retryStrategy: new ConfiguredRetryStrategy(9, (attempt: number) => attempt ** 500),
};

this.arnOperationMap = new Map<string, string>();

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<string> {
Expand Down
25 changes: 25 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/lib/iam-tracking-middleware.ts
Original file line number Diff line number Diff line change
@@ -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<string, string>, region: string) => {
return {
applyToStack: (stack: MiddlewareStack<any, any>) => {
stack.add(
(next, context) => async (args: any): Promise<any> => {
// 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,
},
);
},
};
};
5 changes: 5 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
}
Expand Down
8 changes: 4 additions & 4 deletions packages/@aws-cdk-testing/cli-integ/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -86,4 +86,4 @@
"publishConfig": {
"tag": "latest"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
}),
);
Expand All @@ -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!');
}),
);

Expand Down

0 comments on commit 037aa74

Please sign in to comment.