API Gateway と AWS Lambda を連携させた、標準的な RESTful または HTTP API エンドポイントを瞬時にプロビジョニングする構成です。
AWS CLIを使用してCloudFormationスタックをデプロイする場合は、以下のコマンドを実行します。
aws cloudformation create-stack \ --stack-name serverless-api-stack \ --template-body file://serverless-api.yaml \ --capabilities CAPABILITY_IAM
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Serverless API with Lambda, API Gateway, and DynamoDB - Best Practices'
Resources:
ApiTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
SSESpecification:
SSEEnabled: true
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ApiFunction:
Type: AWS::Lambda::Function
Properties:
Runtime: python3.13
Handler: index.handler
Architectures:
- arm64
Environment:
Variables:
TABLE_NAME: !Ref ApiTable
Code:
ZipFile: |
import json
import os
import boto3
from datetime import datetime
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])
def handler(event, context):
try:
method = event['httpMethod']
if method == 'GET':
response = table.scan()
return {
'statusCode': 200,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps(response['Items'])
}
elif method == 'POST':
body = json.loads(event['body'])
item = {
'id': body['id'],
'data': body.get('data', ''),
'timestamp': datetime.utcnow().isoformat()
}
table.put_item(Item=item)
return {
'statusCode': 201,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps(item)
}
return {
'statusCode': 405,
'body': json.dumps({'error': 'Method not allowed'})
}
except Exception as e:
return {
'statusCode': 500,
'body': json.dumps({'error': str(e)})
}
Role: !GetAtt ApiFunctionRole.Arn
ReservedConcurrentExecutions: 10
LoggingConfig:
LogGroup: !Ref ApiFunctionLogGroup
ApiFunctionRole:
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: DynamoDBAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:Scan
- dynamodb:Query
Resource: !GetAtt ApiTable.Arn
ApiFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: 7
RestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub ${AWS::StackName}-api
EndpointConfiguration:
Types:
- REGIONAL
ApiResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RestApi
ParentId: !GetAtt RestApi.RootResourceId
PathPart: items
ApiMethodGet:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref ApiResource
HttpMethod: GET
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations
ApiMethodPost:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RestApi
ResourceId: !Ref ApiResource
HttpMethod: POST
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiFunction.Arn}/invocations
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- ApiMethodGet
- ApiMethodPost
Properties:
RestApiId: !Ref RestApi
ApiStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref RestApi
DeploymentId: !Ref ApiDeployment
StageName: prod
TracingEnabled: true
MethodSettings:
- ResourcePath: /*
HttpMethod: '*'
LoggingLevel: INFO
DataTraceEnabled: true
MetricsEnabled: true
ApiGatewayAccount:
Type: AWS::ApiGateway::Account
Properties:
CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchRole.Arn
ApiGatewayCloudWatchRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref ApiFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*
Outputs:
ApiUrl:
Value: !Sub https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod/items
Description: API endpoint URL
TableName:
Value: !Ref ApiTable
Description: DynamoDB table name
FunctionName:
Value: !Ref ApiFunction
Description: Lambda function name