open-swe/infra/test/s3-list-prefix.test.ts

72 lines
2.3 KiB
TypeScript
Raw Normal View History

import * as cdk from "aws-cdk-lib";
import { Match, Template } from "aws-cdk-lib/assertions";
import { OpenSweIamStack } from "../lib/open-swe-iam-stack";
import { OpenSweStack } from "../lib/open-swe-stack";
const ENV = { account: "328440206208", region: "us-east-1" };
// F-1 / IAC-04: s3:ListBucket must be constrained to the releases/ prefix so a
// compromised box / leaked CI token cannot enumerate the rest of the bucket.
const RELEASES_PREFIX_CONDITION = { StringLike: { "s3:prefix": ["releases/*"] } };
describe("S3 ListBucket prefix scoping (F-1/IAC-04)", () => {
it("instance role ListBucket is constrained to releases/*", () => {
const app = new cdk.App();
const stack = new OpenSweStack(app, "OpenSweDevStack", {
stackName: "open-swe-dev",
env: ENV,
envName: "dev",
});
Template.fromStack(stack).hasResourceProperties("AWS::IAM::Policy", {
PolicyDocument: Match.objectLike({
Statement: Match.arrayWith([
Match.objectLike({
Sid: "ListArtifactBucket",
Action: "s3:ListBucket",
Condition: RELEASES_PREFIX_CONDITION,
}),
]),
}),
});
});
it("github deploy app role ListBucket is constrained to releases/*", () => {
const app = new cdk.App();
const stack = new OpenSweIamStack(app, "OpenSweIamStack", {
stackName: "open-swe-iam",
env: ENV,
});
Template.fromStack(stack).hasResourceProperties("AWS::IAM::Policy", {
PolicyDocument: Match.objectLike({
Statement: Match.arrayWith([
Match.objectLike({
Sid: "ListArtifactBucket",
Action: "s3:ListBucket",
Condition: RELEASES_PREFIX_CONDITION,
}),
]),
}),
});
});
it("GetBucketLocation stays a separate, unconditioned statement", () => {
const app = new cdk.App();
const stack = new OpenSweStack(app, "OpenSweDevStack", {
stackName: "open-swe-dev",
env: ENV,
envName: "dev",
});
Template.fromStack(stack).hasResourceProperties("AWS::IAM::Policy", {
PolicyDocument: Match.objectLike({
Statement: Match.arrayWith([
Match.objectLike({
Sid: "GetArtifactBucketLocation",
Action: "s3:GetBucketLocation",
Condition: Match.absent(),
}),
]),
}),
});
});
});