🗂
SAMを利用してPrivate ApiGatewayに対して、Privateのカスタムドメインを作成する
はじめに
SAMでPrivate ApiGatewayを作成していて、カスタムドメインを作成したいケースがありました。
2024年11月のアップデートで、Privateのカスタムドメインを作成できるようになりました。
SAMで作成する方法の情報が少なかったので、実際に作成してみました。
こちらを参考にしていきました。
template
リソースに対する補足はコメントで記載しています。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
private-works
Globals:
Function:
LoggingConfig:
LogFormat: JSON
Api:
OpenApiVersion: 3.0.3
Resources:
# api gateway private 設定
PrivateWorksApi:
Type: AWS::Serverless::Api
Properties:
Name: PrivateWorksApi
StageName: Prod
EndpointConfiguration:
Type: PRIVATE
# 特定の VPC エンドポイントのみからのアクセスを許可
VpcEndpointIds: !Ref VpcEndpointIds
Auth:
# リソースポリシーは必須
ResourcePolicy:
CustomStatements:
- Effect: Allow
Principal: "*"
Action: execute-api:Invoke
Resource: "arn:aws:execute-api:*:*:*/*/*/*"
Condition:
StringEquals:
aws:SourceVpce: !Ref VpceId
# 実行用のlambda
StartFunctionLambda:
Type: AWS::Serverless::Function
Properties:
Handler: app.lambda_handler
Runtime: python3.9
CodeUri: sample_workflows/function_start_execution
Timeout: 5
MemorySize: 128
Role: !GetAtt PrivateWorksStartExecutionLambdaRole.Arn
Events:
CatchAll:
Type: Api
Properties:
Path: /private_works
Method: POST
RestApiId:
Ref: PrivateWorksApi
PrivateWorksStartExecutionLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: AllowCloudWatchLogs
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/*"
# private custom domain 設定
PrivateDomainName:
DependsOn: PrivateWorksApi
Type: AWS::ApiGateway::DomainNameV2
Properties:
CertificateArn: !Ref CertificateArn
DomainName: !Ref CustomDomainName
EndpointConfiguration:
Types:
- PRIVATE
SecurityPolicy: TLS_1_2
Policy: !Sub |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*",
"Condition": {
"StringEquals": {
"aws:SourceVpce": ["${VpceId}"]
}
}
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": ["${VpceId}"]
}
}
}
]
}
# custom domain と api gateway の紐付け
Mapping:
DependsOn: PrivateDomainName
Type: AWS::ApiGateway::BasePathMappingV2
Properties:
DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
RestApiId: !Ref PrivateWorksApi
Stage: Prod
Association:
Type: AWS::ApiGateway::DomainNameAccessAssociation
Properties:
AccessAssociationSource: !Ref VpceId
AccessAssociationSourceType: VPCE
DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
# ホストゾーンにcustom domainのCNAMEを設定
ApiCustomDomainRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZoneId
Name: !Ref CustomDomainName
Type: CNAME
TTL: "60"
ResourceRecords: !Ref VpcEndpointDns
Parameters:
Env:
Type: String
Description: "Environment name (e.g., local, stg, prod)"
VpcEndpointIds:
Type: List<String>
Description: "VPC Endpoint IDs for the API Gateway"
VpceId:
Type: String
Description: ID of the VPC Endpoint to allow
CustomDomainName:
Type: String
Description: "Custom Domain Name (e.g., api.example.com)"
CertificateArn:
Type: String
Description: "ARN of the SSL/TLS Certificate in ACM"
HostedZoneId:
Type: String
Description: "Route 53 Hosted Zone ID for the custom domain"
VpcEndpointDns:
Type: List<String>
Description: "DNS name of the VPC Endpoint"
samconfig.toml
# More information about the configuration file can be found here:
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
version = 0.1
[stg]
[stg.global.parameters]
stack_name = "stg-private"
[stg.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
s3_prefix = "stg-private"
parameter_overrides = [
"Env=stg",
"VpcId=<vpcId>",
"VpcEndpointIds=<vpcエンドポイントId>",
"VpceId=<vpcエンドポイントId>",
"VpcEndpointDns=<vpcエンドポイントDns名>",
"SubnetIds=<sunetId>,<sunetId>,<sunetId>",
"CustomDomainName=private.stg.com",
"CertificateArn=<acm arn>",
"HostedZoneId=<private host zone id>",
]
[stg.package.parameters]
resolve_s3 = true
Discussion