trypost/cdk/trypostmedia-stack.ts
vickytechkey c899d7db13
All checks were successful
Setup EC2 Tools / setup-server (push) Successful in 2m40s
chore: add missing AWS CDK and project dependencies to node_modules
2026-09-10 22:50:11 +05:30

112 lines
4 KiB
TypeScript

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
export interface TrypostMediaStackProps extends cdk.StackProps {
/**
* Name of the S3 bucket.
* @default 'trypostmedia'
*/
readonly bucketName?: string;
/**
* Removal policy for S3 bucket when stack is deleted.
* @default cdk.RemovalPolicy.RETAIN
*/
readonly removalPolicy?: cdk.RemovalPolicy;
/**
* Whether to auto delete objects when the bucket is removed.
* Only applicable if removalPolicy is DESTROY.
* @default false
*/
readonly autoDeleteObjects?: boolean;
}
export class TrypostMediaStack extends cdk.Stack {
public readonly mediaBucket: s3.Bucket;
public readonly distribution: cloudfront.Distribution;
constructor(scope: Construct, id: string, props?: TrypostMediaStackProps) {
super(scope, id, props);
const bucketName = props?.bucketName ?? 'trypostmedia';
const removalPolicy = props?.removalPolicy ?? cdk.RemovalPolicy.RETAIN;
const autoDeleteObjects = props?.autoDeleteObjects ?? false;
// 1. S3 Bucket for Media Storage
this.mediaBucket = new s3.Bucket(this, 'TrypostMediaBucket', {
bucketName,
removalPolicy,
autoDeleteObjects,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, // Direct public access to S3 is blocked
encryption: s3.BucketEncryption.S3_MANAGED,
enforceSSL: true,
cors: [
{
allowedMethods: [
s3.HttpMethods.GET,
s3.HttpMethods.HEAD,
s3.HttpMethods.PUT,
s3.HttpMethods.POST,
s3.HttpMethods.DELETE,
],
allowedOrigins: ['*'],
allowedHeaders: ['*'],
exposedHeaders: ['ETag'],
maxAge: 3000,
},
],
});
// 2. CloudFront Distribution with Origin Access Control (OAC)
// S3BucketOrigin.withOriginAccessControl automatically configures OAC
// and attaches the required IAM policy to the S3 bucket allowing CloudFront read access.
this.distribution = new cloudfront.Distribution(this, 'TrypostMediaDistribution', {
comment: 'CloudFront distribution for trypostmedia S3 bucket',
defaultBehavior: {
origin: origins.S3BucketOrigin.withOriginAccessControl(this.mediaBucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
responseHeadersPolicy: cloudfront.ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS_AND_SECURITY_HEADERS,
compress: true,
},
priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
});
// 3. CloudFormation Outputs
new cdk.CfnOutput(this, 'BucketName', {
value: this.mediaBucket.bucketName,
description: 'The name of the media S3 bucket',
exportName: `${this.stackName}-BucketName`,
});
new cdk.CfnOutput(this, 'BucketArn', {
value: this.mediaBucket.bucketArn,
description: 'The ARN of the media S3 bucket',
exportName: `${this.stackName}-BucketArn`,
});
new cdk.CfnOutput(this, 'DistributionId', {
value: this.distribution.distributionId,
description: 'The ID of the CloudFront distribution',
exportName: `${this.stackName}-DistributionId`,
});
new cdk.CfnOutput(this, 'DistributionDomainName', {
value: this.distribution.distributionDomainName,
description: 'The domain name of the CloudFront distribution',
exportName: `${this.stackName}-DistributionDomainName`,
});
new cdk.CfnOutput(this, 'DistributionUrl', {
value: `https://${this.distribution.distributionDomainName}`,
description: 'The URL of the CloudFront distribution (use for AWS_URL in Laravel .env)',
exportName: `${this.stackName}-DistributionUrl`,
});
}
}