102 lines
3.4 KiB
TypeScript
102 lines
3.4 KiB
TypeScript
import * as cdk from "aws-cdk-lib";
|
|
import * as amplify from "@aws-cdk/aws-amplify-alpha";
|
|
import * as s3 from "aws-cdk-lib/aws-s3";
|
|
import * as iam from "aws-cdk-lib/aws-iam";
|
|
import { Construct } from "constructs";
|
|
import { AppConfig } from "./utils/config-manager";
|
|
|
|
export interface AmplifyStackProps extends cdk.NestedStackProps {
|
|
config: AppConfig;
|
|
}
|
|
|
|
export class AmplifyHostingStack extends cdk.NestedStack {
|
|
public readonly amplifyApp: amplify.App;
|
|
public readonly amplifyUrl: string;
|
|
public readonly stagingBucket: s3.Bucket;
|
|
|
|
constructor(scope: Construct, id: string, props: AmplifyStackProps) {
|
|
const description =
|
|
"Fullstack AgentCore Solution Template - Amplify Hosting Stack";
|
|
super(scope, id, { ...props, description });
|
|
|
|
// Create access logs bucket for staging bucket
|
|
const accessLogsBucket = new s3.Bucket(this, "StagingBucketAccessLogs", {
|
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
autoDeleteObjects: true,
|
|
publicReadAccess: false,
|
|
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
lifecycleRules: [
|
|
{
|
|
id: "DeleteOldAccessLogs",
|
|
enabled: true,
|
|
expiration: cdk.Duration.days(90), // Keep access logs for 90 days
|
|
},
|
|
],
|
|
});
|
|
|
|
// Create staging bucket for Amplify deployments with dynamic name
|
|
this.stagingBucket = new s3.Bucket(this, "StagingBucket", {
|
|
removalPolicy: cdk.RemovalPolicy.DESTROY,
|
|
autoDeleteObjects: true,
|
|
versioned: true, // Enable versioning as required by Amplify
|
|
publicReadAccess: false,
|
|
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
|
|
serverAccessLogsBucket: accessLogsBucket,
|
|
serverAccessLogsPrefix: "staging-bucket-access-logs/",
|
|
lifecycleRules: [
|
|
{
|
|
id: "DeleteOldDeployments",
|
|
enabled: true,
|
|
expiration: cdk.Duration.days(30), // Clean up old deployment artifacts after 30 days
|
|
},
|
|
],
|
|
});
|
|
|
|
// Add bucket policy to allow Amplify service access
|
|
this.stagingBucket.addToResourcePolicy(
|
|
new iam.PolicyStatement({
|
|
sid: "AmplifyAccess",
|
|
effect: iam.Effect.ALLOW,
|
|
principals: [new iam.ServicePrincipal("amplify.amazonaws.com")],
|
|
actions: ["s3:GetObject", "s3:GetObjectVersion"],
|
|
resources: [this.stagingBucket.arnForObjects("*")],
|
|
}),
|
|
);
|
|
|
|
// Enforce SSL/TLS for all requests to the bucket
|
|
this.stagingBucket.addToResourcePolicy(
|
|
new iam.PolicyStatement({
|
|
sid: "DenyInsecureConnections",
|
|
effect: iam.Effect.DENY,
|
|
principals: [new iam.AnyPrincipal()],
|
|
actions: ["s3:*"],
|
|
resources: [
|
|
this.stagingBucket.bucketArn,
|
|
this.stagingBucket.arnForObjects("*"),
|
|
],
|
|
conditions: {
|
|
Bool: {
|
|
"aws:SecureTransport": "false",
|
|
},
|
|
},
|
|
}),
|
|
);
|
|
|
|
// Create the Amplify app
|
|
this.amplifyApp = new amplify.App(this, "AmplifyApp", {
|
|
appName: `${props.config.stack_name_base}-frontend`,
|
|
description: `${props.config.stack_name_base} - React Frontend`,
|
|
platform: amplify.Platform.WEB,
|
|
});
|
|
|
|
// Create main branch for the Amplify app
|
|
this.amplifyApp.addBranch("main", {
|
|
stage: "PRODUCTION",
|
|
branchName: "main",
|
|
});
|
|
|
|
// The predictable domain format: https://main.{appId}.amplifyapp.com
|
|
this.amplifyUrl = `https://main.${this.amplifyApp.appId}.amplifyapp.com`;
|
|
}
|
|
}
|