- 公開日
- 最終更新日
【API Gateway】awscurl + IAM 認可を使用し、API Gateway にリクエストを送信する
この記事を共有する

目次
はじめに
こんにちは!パーソル&サーバーワークスの遠藤です。
Amazon API Gateway (以下、API Gateway) を構築する機会があり、改めて API Gateway について整理したいと思いましたので本記事を作成いたしました!
また、今回認可機能として IAM を、動作確認では awscurl ツールを使用したため、こちらについても併せてまとめました。
前提知識
API Gateway とは
まずは API Gatewayについてです!API Gateway は、REST API や HTTP API、 WebSocket API を簡単に構築、公開、管理できる、AWS が提供するサービスです。
バックエンドとして AWS Lambda や HTTP エンドポイントと連携し、認証、アクセス制御、スロットリング、モニタリングなどの機能も標準で備えています。
API Gateway がサポートする API タイプには、ステートレスである REST および HTTP と、ステートフルである WebSocket があります。
次の項では、今回設定する HTTP API の機能概要をまとめたいと思います。
HTTP API とは
HTTP API は、 REST ベースの API をより簡素かつ高速に提供する軽量な API タイプです。
REST API より機能は限定されますが、コストが抑えられます。利用可能な機能については、REST API と HTTP API のどちらかを選択するをご参照ください。
認可機能については、IAM 、Amazon Cognito(※)、Lambda 、JSON ウェブトークン(JWT)が利用可能です。
※ JWT の ID プロバイダーとして、Amazon Cognito を利用することが可能です。
IAM 認可とは
今回構築する API Gateway では、HTTP API タイプ + IAM 認可の組合わせを利用しました。
IAM 認可は、前項でご紹介したとおり HTTP API で利用可能なアクセス制御手法の一つです。
標準の AWS IAM ロールとポリシーをして、どのユーザーが API を呼び出せるか、また作成および管理ができるかをコントロールできます。
IAM 認可が有効である場合、API に接続する際には以下の条件を満たす必要があります。
- Signature Version 4 (以下、SigV4) (※) を使用し、AWS 認証情報でリクエストに署名する
- 接続に使用する IAM ロールやユーザーに execute-api アクションが許可されている
※ SigV4は、AWSサービスへのリクエスト認証プロトコルです。
awscurl とは
署名付き AWS API リクエストを作成することで、署名を作成することも可能ですが、左記の公式リファレンス内記載のとおり少々手間がかかります。
しかし、awscurl を使用することで、署名のプロセスが自動化され、従来の curl と同じようにリクエストができます。
これにより、煩雑な署名手順を意識せずに、API Gateway や他 AWS サービスへ署名付きリクエストを簡単に送信することが可能となります。
今回はこの awscurl を EC2 インスタンスにインストールし、動作確認していきたいと思います。
APIの実装
CloudFormation で API 処理用の API Gateway と Lambda および動作確認用の EC2 インスタンスを構築しました。
awscurl は EC2 の UserData にインストールコマンドを入力し、事前にインストールしておきます。
※VPCなどのネットワークリソースは事前に作成しているものを使用します。
テンプレートは以下を展開し、ご確認ください。
ここを押すと展開します
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: python3.11
Timeout: 10
MemorySize: 128
# Amazon Linux 2023 の最新AMIを参照
Parameters:
AmiId:
Type: AWS::SSM::Parameter::Value
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
AllowedSSHCidr1:
Type: String
Default: XX.XX.XX.XX/32
Description: SSH Allow CIDR Block
Resources:
# Lambda
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: HelloWorld-Function
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
InlineCode: |
def handler(event, context):
return {
'statusCode': 200,
'headers': {'Content-Type': 'text/plain'},
'body': 'Hello, World'
}
Events:
HelloApiEvent:
Type: HttpApi
Properties:
Path: /
Method: GET
ApiId: !Ref HelloHttpApi
Auth:
Authorizer: AWS_IAM
# APIGateway
HelloHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Name: HelloWorld-HttpApi
FailOnWarnings: true
Auth:
EnableIamAuthorizer: true
DefaultAuthorizer: AWS_IAM
CorsConfiguration:
AllowMethods: ['GET', 'OPTIONS']
AllowOrigins: ['*']
# Lambda 権限付与
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref HelloWorldFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${HelloHttpApi}/$default/*/*'
# Lambda 用 IAM ロール
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: HelloWorld-ambdaRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Path: '/'
Policies:
- PolicyName: AllowLambdaLogs
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
# EC2 用 IAM ロール
Ec2IamRole:
Type: AWS::IAM::Role
Properties:
RoleName: Test-EC2Role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
Path: '/'
Policies:
- PolicyName: AllowInvokeApi
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- execute-api:Invoke
Resource: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:*'
Ec2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles:
- !Ref Ec2IamRole
Path: '/'
# KeyPair
MyKeyPair:
Type: AWS::EC2::KeyPair
Properties:
KeyName: Test-KeyPair
KeyType: ed25519
KeyFormat: pem
Tags:
- Key: Name
Value: Test-KeyPair
# EC2
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.small
ImageId: !Ref AmiId
IamInstanceProfile: !Ref Ec2InstanceProfile
KeyName: !Ref MyKeyPair
SecurityGroupIds:
- !Ref InstanceSecurityGroup
SubnetId: !ImportValue TestPublicSubnetIdExport
Tags:
- Key: Name
Value: Test-EC2
UserData:
Fn::Base64: !Sub |
#!/bin/bash
# システムアップデート
dnf update -y
# Python3-pip インストール
dnf install -y python3-pip
# awscurl pip3 インストール
pip3 install awscurl
echo 'export PATH=$PATH:~/.local/bin' >> /home/ec2-user/.bash_profile
chown -R ec2-user:ec2-user /home/ec2-user/.local
# 確認用
sudo -u ec2-user bash -lc 'awscurl --version'
Ec2EIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Ec2EIPAssociation:
Type: AWS::EC2::EIPAssociation
Properties:
AllocationId: !GetAtt Ec2EIP.AllocationId
InstanceId: !Ref Ec2Instance
# インスタンス用セキュリティグループ
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: SSH only from specific CIDR
VpcId: !ImportValue TestVpcIdExport
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref AllowedSSHCidr
Tags:
- Key: Name
Value: Test-EC2-SG
Outputs:
ApiEndpoint:
Description: 'HTTP API Endpint URL'
Value: !Sub 'https://${HelloHttpApi}.execute-api.${AWS::Region}.amazonaws.com/'
KeyPairParameterName:
Description: 'KeyPiar ParameterName'
Value: !Sub '/ec2/keypair/${MyKeyPair}'
動作確認
動作確認用の EC2 インスタンスに接続し、awscurl ツールでレスポンスを確認します。
- SigV4 署名ありの場合
[ec2-user@ip-XX-XX-XX-XX ~]$ awscurl --service execute-api \
--region ap-northeast-1 \
https://XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/
Hello, World
レスポンスとして、Lambda 関数に登録した Hello, World が返ってきていれば、正常に認可されている状態となります。
- SigV4 署名なしの場合
curl -v https://XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/
* ...
* Trying XXX.XXX.XXX.XXX:443...
* Connected to XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com (XXX.XXX.XXX.XXX) port 443 (#0)
* ALPN: curl offers h2,http/1.1
* ...
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 403
< date: Tue, 03 Jun 2025 12:10:32 GMT
< content-type: application/json
< content-length: 23
< apigw-requestid: XXXXXXXXXXXX
<
* Connection #0 to host XXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com left intact
{"message":"Forbidden"}
curl -v コマンドで レスポンスの詳細を確認すると、以下が返却されました。
- ステータスコード:403
- エラーメッセージ:{"message":"Forbidden"}
正常に認可されていない状態となり、想定どおりの動作となっています!
おわりに
今回は API Gateway ( HTTP API )での IAM 認可 に関して記事を作成いたしました。
本記事が何かのご参考になりましたら幸いです。
参考情報
この記事は私が書きました
S.Endo
記事一覧コーヒーを飲みながら仕事をしています
