aws について
aws はアプリケーションのテスト向けに、AWS API をインメモリで模擬します。S3、SQS、Cognito、IAM、STS を扱い、AWS SDK クライアント向けのリクエスト形式に対応します。
主な機能
- 01S3、SQS、Cognito、IAM、STS の模擬
- 02AWS SDK のリクエスト形式に対応
- 03サービス状態をメモリ内に保持
- 04シード設定からデータを初期化
- 05状態インスペクターを提供
活用シーン
- 01S3 のアップロードとダウンロードのテスト
- 02SQS メッセージ処理の検証
- 03Cognito の登録と認証のテスト
- 04IAM と STS API 連携の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vercel-labs/ emulate --skill awsインストール後、Claude Code で/awsを入力して読み込まれたか確認します。
詳細
AWS Emulator
S3、SQS、Cognito、IAM、STS のエミュレーションを提供し、AWS SDK と互換性のある S3 パスを使用します。S3 のアップロードとダウンロードでは、生のバイト長や ETag を含む任意のバイナリペイロードが保持されます。SQS は AWS JSON 1.0 プロトコルと XML Query プロトコルに対応し、IAM と STS は XML Query を使用します。すべての状態はメモリ内に保持されます。
起動
ローカルリスナーは、デフォルトで 127.0.0.1 にバインドします。コンテナーやほかのマシンからアクセスするには、CLI に --host 0.0.0.0 を渡すか、createEmulator に hostname: '0.0.0.0' を渡してください。クライアントから到達可能な URL を通知するには、--base-url または baseUrl を設定してください。
# AWS only
npx emulate --service aws
# Default port (when run alone)
# http://localhost:4000
または、プログラムから起動します。
import { createEmulator } from 'emulate'
const aws = await createEmulator({ service: 'aws', port: 4006 })
// aws.url === 'http://localhost:4006'
認証
トークンは Authorization: Bearer <token> として渡します。スコープ付き権限では、s3:*、sqs:*、iam:*、sts:* のパターンを使用します。
curl http://localhost:4006/ \
-H "Authorization: Bearer test_token_admin"
アプリをエミュレーターに接続する
環境変数
AWS_EMULATOR_URL=http://localhost:4006
AWS SDK v3
import { S3Client } from '@aws-sdk/client-s3'
const s3 = new S3Client({
endpoint: process.env.AWS_EMULATOR_URL,
region: 'us-east-1',
credentials: {
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
},
forcePathStyle: true,
})
import { SQSClient } from '@aws-sdk/client-sqs'
const sqs = new SQSClient({
endpoint: `${process.env.AWS_EMULATOR_URL}/sqs`,
region: 'us-east-1',
credentials: {
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
},
})
import { IAMClient } from '@aws-sdk/client-iam'
const iam = new IAMClient({
endpoint: `${process.env.AWS_EMULATOR_URL}/iam`,
region: 'us-east-1',
credentials: {
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
},
})
シード設定
aws:
region: us-east-1
s3:
buckets:
- name: my-app-bucket
- name: my-app-uploads
region: eu-west-1
sqs:
queues:
- name: my-app-events
- name: my-app-dlq
visibility_timeout: 60
- name: my-app-orders.fifo
fifo: true
iam:
users:
- user_name: developer
create_access_key: true
- user_name: readonly-user
roles:
- role_name: lambda-execution-role
description: Role for Lambda function execution
assume_role_policy: '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
デフォルトのシード(常に作成されます):S3 バケット emulate-default、SQS キュー emulate-default-queue、アクセスキーのペア(AKIAIOSFODNN7EXAMPLE / wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY)を持つ IAM ユーザー admin。
API エンドポイント
S3
S3 のルートでは、実際の AWS S3 ワイヤーフォーマットに一致するルートパスを使用します。従来の /s3/ 付きパスにも対応しています。
# List all buckets
curl http://localhost:4006/ \
-H "Authorization: Bearer $TOKEN"
# Create bucket
curl -X PUT http://localhost:4006/my-bucket \
-H "Authorization: Bearer $TOKEN"
# Delete bucket (must be empty)
curl -X DELETE http://localhost:4006/my-bucket \
-H "Authorization: Bearer $TOKEN"
# Head bucket (check existence, get region)
curl -I http://localhost:4006/my-bucket \
-H "Authorization: Bearer $TOKEN"
# List objects (with prefix, delimiter, pagination)
curl "http://localhost:4006/my-bucket?prefix=uploads/&delimiter=/&max-keys=100" \
-H "Authorization: Bearer $TOKEN"
# Put object
curl -X PUT http://localhost:4006/my-bucket/path/to/file.txt \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: text/plain" \
-H "x-amz-meta-author: test" \
--data-binary "file contents"
# Get object
curl http://localhost:4006/my-bucket/path/to/file.txt \
-H "Authorization: Bearer $TOKEN"
# Head object (metadata only)
curl -I http://localhost:4006/my-bucket/path/to/file.txt \
-H "Authorization: Bearer $TOKEN"
# Delete object
curl -X DELETE http://localhost:4006/my-bucket/path/to/file.txt \
-H "Authorization: Bearer $TOKEN"
# Copy object
curl -X PUT http://localhost:4006/dest-bucket/copy.txt \
-H "Authorization: Bearer $TOKEN" \
-H "x-amz-copy-source: /source-bucket/original.txt"
SQS
現在の AWS SDK クライアントでは、上記に示す /sqs エンドポイントを使用します。SQS は、Content-Type: application/x-amz-json-1.0 と X-Amz-Target: AmazonSQS.<Action> を指定した POST /sqs/ への AWS JSON 1.0 リクエストを受け付け、JSON 形式の結果とエラーを返します。Action フォームパラメーターを含む XML Query リクエストにも引き続き対応しています。キュー操作では、返された QueueUrl をエンドポイントとして使用することもできます。
# List queues using AWS JSON 1.0
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-amz-json-1.0" \
-H "X-Amz-Target: AmazonSQS.ListQueues" \
-d '{}'
# Create queue
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "Action=CreateQueue&QueueName=my-queue"
# Create queue with attributes
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "Action=CreateQueue&QueueName=my-queue&Attribute.1.Name=VisibilityTimeout&Attribute.1.Value=30"
# List queues
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ListQueues"
# List queues with prefix filter
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ListQueues&QueueNamePrefix=my-"
# Get queue URL
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetQueueUrl&QueueName=my-queue"
# Get queue attributes
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetQueueAttributes&QueueUrl=<queue_url>"
# Send message
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=SendMessage&QueueUrl=<queue_url>&MessageBody=Hello+World"
# Send message with attributes
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=SendMessage&QueueUrl=<queue_url>&MessageBody=Hello&MessageAttribute.1.Name=type&MessageAttribute.1.Value.DataType=String&MessageAttribute.1.Value.StringValue=greeting"
# Receive messages
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ReceiveMessage&QueueUrl=<queue_url>&MaxNumberOfMessages=5"
# Delete message
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=DeleteMessage&QueueUrl=<queue_url>&ReceiptHandle=<receipt_handle>"
# Purge queue
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=PurgeQueue&QueueUrl=<queue_url>"
# Delete queue
curl -X POST http://localhost:4006/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=DeleteQueue&QueueUrl=<queue_url>"
IAM
IAM のすべての操作では、Action を form-urlencoded パラメーターとして指定して POST /iam/ を使用します。
# Create user
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=CreateUser&UserName=new-user"
# Get user
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetUser&UserName=new-user"
# List users
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ListUsers"
# Delete user
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=DeleteUser&UserName=new-user"
# Create access key
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=CreateAccessKey&UserName=developer"
# List access keys
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ListAccessKeys&UserName=developer"
# Delete access key
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=DeleteAccessKey&UserName=developer&AccessKeyId=AKIA..."
# Create role
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=CreateRole&RoleName=my-role&AssumeRolePolicyDocument={}"
# Get role
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetRole&RoleName=my-role"
# List roles
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ListRoles"
# Delete role
curl -X POST http://localhost:4006/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=DeleteRole&RoleName=my-role"
Cognito
エンドポイント /cognito-idp では CognitoIdentityProviderClient を、/cognito-identity では CognitoIdentityClient を使用します。どちらも AWS JSON 1.1 を受け付け、公式 AWS SDK v3 で動作します。
import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";
const cognito = new CognitoIdentityProviderClient({
endpoint: "http://localhost:4007/cognito-idp",
region: "us-east-1",
credentials: { accessKeyId: "local-access-key", secretAccessKey: "local-secret" },
});
const result = await cognito.send(new InitiateAuthCommand({
ClientId: "emulateclient",
AuthFlow: "USER_PASSWORD_AUTH",
AuthParameters: { USERNAME: "developer", PASSWORD: "LocalPass123!" },
}));
デフォルトのユーザープール us-east-1_emulate、パブリックアプリクライアント emulateclient、アイデンティティプール us-east-1:00000000-0000-4000-8000-000000000001 が、ユーザーなしで作成されます。上記の例で使う、確認済みアカウントをシードします。
aws:
cognito:
user_pools:
- id: us-east-1_emulate
confirmation_code: "123456"
users:
- username: developer
password: LocalPass123!
attributes:
email: [email protected]
email_verified: "true"
name: Developer
ユーザープールでは、name と、client_id、省略可能な client_secret、完全一致する redirect_uris、許可する scopes を含む clients も指定できます。ユーザーでは、status(CONFIRMED、UNCONFIRMED、FORCE_CHANGE_PASSWORD のいずれか)と enabled を指定できます。パスワードは8文字以上である必要があり、ソルト付きハッシュとして保存されます。機密クライアントでは、SDK フローで Cognito の HMAC SecretHash または SECRET_HASH が必要です。
SignUp、ConfirmSignUp、ResendConfirmationCode、ForgotPassword、ConfirmForgotPasswordは、アカウントの確認と復旧をシミュレートします。コードの有効期限は10分で、プールのconfirmation_codeフィクスチャを使用します。デフォルトは123456です。メールや SMS は送信されません。有効なコードは/_inspector?tab=cognitoで確認できます。シードされた未確認ユーザーは、ResendConfirmationCodeでコードを要求できます。InitiateAuthはUSER_PASSWORD_AUTH、REFRESH_TOKEN_AUTH、REFRESH_TOKENをサポートします。AdminInitiateAuthはADMIN_USER_PASSWORD_AUTHもサポートします。管理者が作成した一時パスワードではNEW_PASSWORD_REQUIREDが返され、RespondToAuthChallengeまたはAdminRespondToAuthChallengeで完了します。チャレンジセッションの有効期限は3分で、ユーザーとクライアントに紐付けられます。GetUser、ChangePassword、GlobalSignOut、RevokeTokenは発行済みトークンを使用します。AdminCreateUser(TemporaryPasswordを指定)、AdminGetUser、AdminConfirmSignUp、AdminSetUserPassword、AdminEnableUser、AdminDisableUser、AdminDeleteUser、ページネーション付きのListUsersは、テストのセットアップと管理に対応しています。
トークンは Cognito の token_use クレームを含む RS256 JWT です。ID トークンではアプリクライアントを aud で識別し、アクセストークンでは client_id を使用します。ID トークンとアクセストークンの有効期限は1時間、リフレッシュトークンの有効期限は30日です。サインアウト、失効、無効化、削除、パスワードのリセットを行うと、影響を受けるセッションは無効になります。ユーザー、セッション、アイデンティティ、署名鍵はスナップショット、復元、リセットの対象です。
ローカルの発行者は http://localhost:4007/cognito-idp/USER_POOL_ID です。ディスカバリー情報と公開鍵は ISSUER/.well-known/openid-configuration および ISSUER/.well-known/jwks.json で提供されます。トークン検証器には、このローカルの発行者と JWKS を設定してください。ISSUER/oauth2/authorize ではローカルユーザー選択画面が表示され、ISSUER/oauth2/token では認可コードまたはリフレッシュトークンを交換し、ISSUER/oauth2/userInfo ではスコープで指定されたプロフィールクレームを返します。認可コードの有効期限は5分で、1回のみ使用でき、クライアント、完全一致するリダイレクト URI、省略可能な S256 PKCE チャレンジに紐付けられます。クライアント認証では client_secret_basic または client_secret_post を使用できます。デフォルトのクライアントでは http://localhost:3000/callback が許可されています。
Identity Pool は GetId と GetCredentialsForIdentity をサポートします。Logins に、cognito-idp.REGION.amazonaws.com/USER_POOL_ID をキーとして ID トークンを指定します。デフォルトの Identity Pool は、デフォルトの User Pool とアプリクライアントを受け付けます。カスタム aws.cognito.identity_pools エントリでは、id、省略可能な name、providers: [{ user_pool_id, client_id }]、allow_unauthenticated_identities(デフォルトは false)を指定します。同じ認証済みサブジェクトには、常に同じアイデンティティが割り当てられます。認証情報の有効期限は1時間です。ログイン署名、有効期限、オーディエンス、アイデンティティの所有権が検証されます。
SRP、MFA、外部アイデンティティプロバイダー、Lambda トリガー、プール/クライアント管理 API、ListUsers のフィルター、Identity Pool のロール選択はシミュレートされません。管理者リクエストでは、AWS エミュレーターの寛容な認証情報の動作が適用されます。SigV4 署名と IAM ポリシーは評価されません。Identity Pool の認証情報はテスト用に生成され、ロールやポリシーの評価は行われません。
STS
STS のすべての操作では、Action を form-urlencoded パラメーターとして指定し、POST /sts/ を使用します。
# Get caller identity
curl -X POST http://localhost:4006/sts/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetCallerIdentity"
# Assume role
curl -X POST http://localhost:4006/sts/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=AssumeRole&RoleArn=arn:aws:iam::123456789012:role/my-role&RoleSessionName=my-session"
Inspector
# HTML dashboard (shows S3, SQS, IAM state)
curl http://localhost:4006/_inspector?tab=s3
curl http://localhost:4006/_inspector?tab=sqs
curl http://localhost:4006/_inspector?tab=iam
共通パターン
オブジェクトのアップロードと取得
TOKEN="test_token_admin"
BASE="http://localhost:4006"
# Create bucket
curl -X PUT $BASE/my-data \
-H "Authorization: Bearer $TOKEN"
# Upload file
curl -X PUT $BASE/my-data/config.json \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data-binary '{"key": "value"}'
# Download file
curl $BASE/my-data/config.json \
-H "Authorization: Bearer $TOKEN"
SQS メッセージの送受信
TOKEN="test_token_admin"
BASE="http://localhost:4006"
# Get queue URL
QUEUE_URL=$(curl -s -X POST $BASE/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=GetQueueUrl&QueueName=emulate-default-queue" | grep -oP '<QueueUrl>\K[^<]+')
# Send message
curl -X POST $BASE/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=SendMessage&QueueUrl=$QUEUE_URL&MessageBody=Hello+from+emulate"
# Receive messages
curl -X POST $BASE/sqs/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=ReceiveMessage&QueueUrl=$QUEUE_URL&MaxNumberOfMessages=1"
アクセスキー付き IAM ユーザーの作成
TOKEN="test_token_admin"
BASE="http://localhost:4006"
# Create user
curl -X POST $BASE/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=CreateUser&UserName=ci-user"
# Generate access key
curl -X POST $BASE/iam/ \
-H "Authorization: Bearer $TOKEN" \
-d "Action=CreateAccessKey&UserName=ci-user"
組み込みエミュレーターと並行して使用するカスタムエミュレーター
npx emulate init --custom inventory を使用して、サードパーティ API エミュレーターをスキャフォールドし、テストします。emulate の defineConfig を使って、{ emulator: "aws" } などの組み込みエントリと並べて、emulate.config.ts に登録します。npx emulate start --watch を実行すると、インポートが再読み込みされ、表示された /_emulate URL でカスタム状態を確認できます。再読み込みが成功すると、実行状態はシードにリセットされます。既存のフラットなシード設定も引き続き使用できます。--config で明示的なファイルを指定します。サードパーティ API エミュレーターの作成とテストについては、https://emulate.dev/docs/custom-emulators をご覧ください。