in tools/ci-cdk/lib/aws-sdk-rust/canary-stack.ts [27:140]
constructor(scope: Construct, id: string, props: Properties) {
super(scope, id, props);
// Tag the resources created by this stack to make identifying resources easier
Tags.of(this).add("stack", id);
this.awsSdkRustOidcRole = new GitHubOidcRole(this, "aws-sdk-rust", {
name: "aws-sdk-rust-canary",
githubOrg: "awslabs",
githubRepo: "aws-sdk-rust",
oidcProvider: props.githubActionsOidcProvider,
});
// Grant permission to create/invoke/delete a canary Lambda
this.awsSdkRustOidcRole.oidcRole.addToPolicy(
new PolicyStatement({
actions: [
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:InvokeFunction",
"lambda:GetFunctionConfiguration",
],
effect: Effect.ALLOW,
// Only allow this for functions starting with prefix `canary-`
resources: ["arn:aws:lambda:*:*:function:canary-*"],
}),
);
// Grant permission to put metric data to CloudWatch
this.awsSdkRustOidcRole.oidcRole.addToPolicy(
new PolicyStatement({
actions: ["cloudwatch:PutMetricData"],
effect: Effect.ALLOW,
resources: ["*"],
}),
);
// Create S3 bucket to upload canary Lambda code into
this.canaryCodeBucket = new Bucket(this, "canary-code-bucket", {
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
encryption: BucketEncryption.S3_MANAGED,
lifecycleRules: [
{
id: "delete-old-code-files",
enabled: true,
expiration: Duration.days(7),
},
],
versioned: false,
removalPolicy: RemovalPolicy.DESTROY,
});
// Allow the OIDC role to GetObject and PutObject to the code bucket
this.canaryCodeBucket.grantRead(this.awsSdkRustOidcRole.oidcRole);
this.canaryCodeBucket.grantWrite(this.awsSdkRustOidcRole.oidcRole);
// Create S3 bucket for the canaries to talk to
this.canaryTestBucket = new Bucket(this, "canary-test-bucket", {
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
encryption: BucketEncryption.S3_MANAGED,
lifecycleRules: [
{
id: "delete-old-test-files",
enabled: true,
expiration: Duration.days(7),
},
],
versioned: false,
removalPolicy: RemovalPolicy.DESTROY,
});
// Create a role for the canary Lambdas to assume
this.lambdaExecutionRole = new Role(this, "lambda-execution-role", {
roleName: "aws-sdk-rust-canary-lambda-exec-role",
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
});
// Allow canaries to write logs to CloudWatch
this.lambdaExecutionRole.addToPolicy(
new PolicyStatement({
actions: ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
effect: Effect.ALLOW,
resources: ["arn:aws:logs:*:*:/aws/lambda/canary-lambda-*:*"],
}),
);
// Allow canaries to talk to their test bucket
this.canaryTestBucket.grantReadWrite(this.lambdaExecutionRole);
// Allow canaries to call Transcribe's StartStreamTranscription
this.lambdaExecutionRole.addToPolicy(
new PolicyStatement({
actions: ["transcribe:StartStreamTranscription"],
effect: Effect.ALLOW,
resources: ["*"],
}),
);
// Allow the OIDC role to pass the Lambda execution role to Lambda
this.awsSdkRustOidcRole.oidcRole.addToPolicy(
new PolicyStatement({
actions: ["iam:PassRole"],
effect: Effect.ALLOW,
// Security: only allow the Lambda execution role to be passed
resources: [this.lambdaExecutionRole.roleArn],
// Security: only allow the role to be passed to Lambda
conditions: {
StringEquals: {
"iam:PassedToService": "lambda.amazonaws.com",
},
},
}),
);
}