cdk-serverless-agentic-api
Version:
CDK construct for serverless web applications with CloudFront, S3, Cognito, API Gateway, and Lambda
223 lines • 10 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCloudFrontDistribution = createCloudFrontDistribution;
exports.createResponseHeadersPolicy = createResponseHeadersPolicy;
exports.createApiResponseHeadersPolicy = createApiResponseHeadersPolicy;
const cloudfront = __importStar(require("aws-cdk-lib/aws-cloudfront"));
const origins = __importStar(require("aws-cdk-lib/aws-cloudfront-origins"));
const acm = __importStar(require("aws-cdk-lib/aws-certificatemanager"));
const aws_cdk_lib_1 = require("aws-cdk-lib");
const error_handling_1 = require("./error-handling");
/**
* Creates the CloudFront distribution with S3 and API Gateway origins
*
* @param scope The construct scope
* @param id The construct ID
* @param bucket The S3 bucket for static content
* @param originAccessIdentity The CloudFront Origin Access Identity
* @param api The API Gateway REST API
* @param props Configuration properties
* @param loggingBucket The S3 bucket for CloudFront access logs
* @returns The created CloudFront distribution
*/
function createCloudFrontDistribution(scope, id, bucket, originAccessIdentity, api, props, loggingBucket) {
// Create S3 origin for static content
const s3Origin = origins.S3BucketOrigin.withOriginAccessIdentity(bucket, {
originAccessIdentity: originAccessIdentity,
originPath: '',
});
// Create API Gateway origin for /api/* paths
const apiOrigin = new origins.HttpOrigin(`${api.restApiId}.execute-api.${process.env.AWS_REGION || 'us-east-1'}.amazonaws.com`, {
originPath: '',
});
// Configure SSL certificate if custom domain is provided
const certificate = props?.certificateArn
? acm.Certificate.fromCertificateArn(scope, 'Certificate', props.certificateArn)
: undefined;
// Create CloudFront distribution
const distribution = new cloudfront.Distribution(scope, 'Distribution', {
comment: `CloudFront distribution for ${id} serverless web application`,
// Configure default behavior for static content (S3)
defaultBehavior: {
origin: s3Origin,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD_OPTIONS,
compress: true,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
originRequestPolicy: cloudfront.OriginRequestPolicy.CORS_S3_ORIGIN,
responseHeadersPolicy: createResponseHeadersPolicy(scope, id),
},
// Configure additional behaviors for API Gateway
additionalBehaviors: {
'/api/*': {
origin: apiOrigin,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD,
compress: true,
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
responseHeadersPolicy: createApiResponseHeadersPolicy(scope, id),
},
},
// Configure custom domain if provided
...(props?.domainName && certificate && {
domainNames: [props.domainName],
certificate: certificate,
}),
// Configure default root object
defaultRootObject: 'index.html',
// Configure custom error responses using error handling utilities
errorResponses: (0, error_handling_1.createErrorPages)(scope, bucket, id),
// No geographic restrictions by default
// Configure price class for cost optimization
priceClass: cloudfront.PriceClass.PRICE_CLASS_100,
// Enable IPv6
enableIpv6: true,
// Configure logging if enabled
...(props?.enableLogging !== false && loggingBucket && {
enableLogging: true,
logBucket: loggingBucket,
logFilePrefix: 'cloudfront-logs/',
logIncludesCookies: false,
}),
// Configure HTTP version
httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,
// Configure minimum TLS version
minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,
// Configure web ACL if needed (placeholder for future enhancement)
webAclId: undefined,
});
return distribution;
}
/**
* Creates a response headers policy for static content with security headers
*
* @param scope The construct scope
* @param id The construct ID
* @returns The created response headers policy
*/
function createResponseHeadersPolicy(scope, id) {
return new cloudfront.ResponseHeadersPolicy(scope, 'StaticContentResponseHeadersPolicy', {
responseHeadersPolicyName: `${id}-static-headers`,
comment: 'Security headers for static content',
// Configure security headers
securityHeadersBehavior: {
contentTypeOptions: {
override: true,
},
frameOptions: {
frameOption: cloudfront.HeadersFrameOption.DENY,
override: true,
},
referrerPolicy: {
referrerPolicy: cloudfront.HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
override: true,
},
strictTransportSecurity: {
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(31536000), // 1 year
includeSubdomains: true,
preload: true,
override: true,
},
contentSecurityPolicy: {
contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https:; media-src 'self'; object-src 'none'; child-src 'none'; worker-src 'none'; frame-ancestors 'none'; form-action 'self'; base-uri 'self';",
override: true,
},
},
// Configure CORS headers for static content
corsBehavior: {
accessControlAllowCredentials: false,
accessControlAllowHeaders: [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Api-Key',
'X-Amz-Security-Token',
'X-Amz-User-Agent',
'X-Requested-With',
],
accessControlAllowMethods: ['GET', 'HEAD', 'OPTIONS'],
accessControlAllowOrigins: ['*'],
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(86400), // 24 hours
originOverride: true,
},
});
}
/**
* Creates a response headers policy for API Gateway with appropriate CORS settings
*
* @param scope The construct scope
* @param id The construct ID
* @returns The created response headers policy
*/
function createApiResponseHeadersPolicy(scope, id) {
return new cloudfront.ResponseHeadersPolicy(scope, 'ApiResponseHeadersPolicy', {
responseHeadersPolicyName: `${id}-api-headers`,
comment: 'Headers for API Gateway responses',
// Configure minimal security headers for API responses
securityHeadersBehavior: {
contentTypeOptions: {
override: false, // Let API Gateway control this
},
strictTransportSecurity: {
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(31536000), // 1 year
includeSubdomains: true,
preload: true,
override: false, // Let API Gateway control this
},
},
// Configure CORS headers for API responses
corsBehavior: {
accessControlAllowCredentials: true,
accessControlAllowHeaders: [
'Content-Type',
'X-Amz-Date',
'Authorization',
'X-Api-Key',
'X-Amz-Security-Token',
'X-Amz-User-Agent',
'X-Requested-With',
],
accessControlAllowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
accessControlAllowOrigins: ['*'], // Will be restricted when custom domain is configured
accessControlMaxAge: aws_cdk_lib_1.Duration.seconds(3600), // 1 hour
originOverride: false, // Let API Gateway control CORS
},
});
}
//# sourceMappingURL=cloudfront.js.map