블로그 릴레이 - CDK 에서 다른 리전에서 만들어진 리소스를 참조하는 방법
안녕하세요 생산지원 그룹 리테일 어플리케이션부의 김승연입니다.
본 블로그는 당사의 한국어 블로그 릴레이의 2025년 스물세 번째 블로그입니다.
이번 블로그의 주제는 「CDK 에서 다른 리전에서 만들어진 리소스를 참조하는방법」 입니다.
결론
결론부터 말하면 CDK에서는 다른 리전에서 만들어진 리소스를 참조할 수 있는 옵션을 제공하고 있습니다.
You can enable the Stack property crossRegionReferences in order to access resources in a different stack and region. With this feature flag enabled it is possible to do something like creating a CloudFront distribution in us-east-2 and an ACM certificate in us-east-1.
예시
아래 예시는 Amazon CloudFront + Amazon S3 + AWS WAF 구성으로 리소스를 작성할 때의 예입니다.
두 개의 서로 다른 Region에서 만들어진 Stack이 있다면, 아래와 같이 WebSecurityStack에서 만들어진 AWS WAF의 Web ACL 의 ARN 값을 WebStack에 Props으로 전달 할 수 있습니다.
bin/iac.ts
...
const webSecurityStackResult = new WebSecurityStack(app,'WebSecurityStack',{
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: 'us-east-1', // 버지니아
},
}
);
new WebStack(app, 'WebStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: 'ap-northeast-2' //서울
},
webAclArn: webSecurityStackResult.webAcl.attrArn,
crossRegionReferences: true,
});
AWS WAF
lib/stacks/web-security-stack.ts
...
export class WebSecurityStack extends cdk.Stack {
public readonly webAcl: wafv2.CfnWebACL;
constructor(scope: Construct, id: string, props: WebSecurityStackProps) {
super(scope, id, props);
// Whitelist IP Set
const allowedIpSet = new wafv2.CfnIPSet(this, 'AllowedIPSet', {
name: 'allowed-ips',
scope: 'CLOUDFRONT',
ipAddressVersion: 'IPV4',
addresses: [],
});
this.webAcl = new wafv2.CfnWebACL(this, 'WebACL', {
name: 'web-acl',
scope: 'CLOUDFRONT',
defaultAction: { block: {} },
visibilityConfig: {
metricName: 'web-acl-metric',
sampledRequestsEnabled: true,
cloudWatchMetricsEnabled: true,
},
rules: [
{
name: 'allow-whitelisted-ips',
priority: 1,
statement: {
ipSetReferenceStatement: {
arn: allowedIpSet.attrArn,
},
},
action: { allow: {} },
visibilityConfig: {
metricName: 'allow-whitelisted-ips-metric',
sampledRequestsEnabled: true
cloudWatchMetricsEnabled: true
},
},
],
});
}
}
Amazon CloudFront + Amazon S3
lib/stacks/web-stack.ts
...
export class WebStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: WebStackProps) {
super(scope, id, props);
const hostingBucket = new s3.Bucket(this, 'HostingBucket', {
bucketName: '...',
publicReadAccess: false,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
const distribution = new cloudfront.Distribution(this, 'Distribution', {
defaultRootObject: 'index.html',
webAclId: props.webAclArn, // NOTE: WAF ACL ARN 지정
errorResponses: [
{
ttl: cdk.Duration.seconds(300),
httpStatus: 404,
responseHttpStatus: 200,
responsePagePath: '/index.html',
},
],
defaultBehavior: {
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD,
cachedMethods: cloudfront.CachedMethods.CACHE_GET_HEAD,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
origin: cloudfrontOrigins.S3BucketOrigin.withOriginAccessControl(hostingBucket),
responseHeadersPolicy: new cloudfront.ResponseHeadersPolicy(this, 'ResponseHeaderPolicy', {
securityHeadersBehavior: {
contentTypeOptions: { override: true },
referrerPolicy: {
referrerPolicy: cloudfront.HeadersReferrerPolicy.SAME_ORIGIN,
override: true,
},
frameOptions: {
frameOption: cloudfront.HeadersFrameOption.DENY,
override: true,
},
strictTransportSecurity: {
accessControlMaxAge: cdk.Duration.seconds(63072000),
includeSubdomains: true,
preload: true,
override: true,
},
xssProtection: {
protection: true,
modeBlock: true,
override: true,
},
},
}),
},
});
new s3Deployment.BucketDeployment(this, 'Deployment', {
sources: [],
destinationBucket: hostingBucket,
distribution: distribution,
distributionPaths: ['/*'],
});
}
}
보충
이번에 소개한 옵션은 상당히 편리한 기능이지만, 아래의 설명을 볼 때 이후 업데이트 등이 활발할 것으로 보이기 때문에 향후 업데이트에 주의를 기울어야 할 것 같습니다.
This feature is currently experimental
참고자료
문의 사항은 클래스메소드 코리아로!
클래스메소드 코리아에서는 다양한 세미나 및 이벤트를 진행하고 있습니다.
진행중인 이벤트는 아래 페이지를 참고해주세요.
AWS에 대한 상담 및 클래스 메소드 멤버스에 관한 문의사항은 아래 메일로 연락주시면 감사드립니다!
Info@classmethod.kr