はじめに
こんにちは、インフラ担当の清水です。
AWS Amplify を用いた構成を実際に試してみたかったため、公式のハンズオン『サーバーレスのウェブアプリケーションを構築する』に取り組んでみました。
この記事では、AWS Amplifyのハンズオンで私が実際に遭遇し、解決に苦労した点とその解決策を共有します。
同じように困っている方の助けになれば幸いです。
構成
AWS Lambda、Amazon API Gateway、AWS Amplify、Amazon DynamoDB、および Amazon Cognito を使用した構成となっております。

ハンズオンのモジュール 1でハマったポイント
CodeCommit を macOS で利用した際の問題
macOS 環境で CodeCommit の HTTPS を利用した際に、しばらく時間が経過すると何をしてもステータスコードが 403 になる現象が発生するケースがあります。
原因
AWS CLI 認証情報ヘルパーを使用した、Linux、macOS、または UNIX での AWS CodeCommit リポジトリへの HTTPS 接続のセットアップ手順
macOS を使用している場合は、HTTPS を使用して CodeCommit リポジトリに接続します。HTTPS を使用して CodeCommit リポジトリに初めて接続すると、約 15 分後に後続のアクセスが失敗します。macOS のデフォルトの Git バージョンは、Keychain Access ユーティリティを使用して認証情報を保存します。セキュリティ対策のために、CodeCommit リポジトリへのアクセス用に生成されるパスワードは一時的なものであり、約 15 分後にキーチェーンに保存されている認証情報は機能しなくなります。
解決策
CodeCommit への接続方法として、HTTPS (GRC) を選択してください。
ちなみにGRC とは?
正式な名称『Git-Remote-Codecommit』の頭文字のGRCからきています。
”AWS CLI”に設定されている認証情報(アクセスキー、シークレットキー、など)を用いて、CodeCommitのリポジトリにプッシュやプルなどを簡単にできるGitの拡張になります。 GRCを使用する場合も、AWS CLIで認証情報の設定が必要です。また、IAMユーザーにはCodeCommitへのアクセス権限が付与されている必要があります。
インストール手順と詳しい内容については、下記のドキュメントをご参照ください。
AWSのハンズオンで提供されているウェブサイトの静的ファイルがコピーできない問題
ハンズオンの手順に従い、S3 から静的ファイルをコピーするために下記のコマンドを実行しました。
aws s3 cp s3://wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website ./ --recursive
実行した結果、下記のエラーメッセージが表示されました。
fatal error: An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
原因
このエラーは、S3 バケット s3://wildrydes-us-east-1/WebApplication/1_StaticWebHosting/website 内のオブジェクトをリスト表示する権限がないために発生しました。
原因としては、S3 バケットの公開設定が変更された可能性があります。
解決策
ハンズオンで必要な静的ファイルは、AWS 公式リポジトリ(AWS Samples)でも公開されています。
解決策として、以下の GitHub リポジトリをクローンして、静的ファイルをローカル環境にダウンロードしてください。
ハンズオンのモジュール 3でハマったポイント
Lambda 関数を作成する際の問題点
このハンズオンは Node.js 16.x 環境で作成されたため、Lambda 関数のコードは AWS SDK for JavaScript v2 で記述されています。
しかし、現在の推奨環境は Node.js 20.x 以降であり、AWS SDK for JavaScript v3 への移行が必要です。
そこで、AWS SDK for JavaScript v3 に書き換えたコードをご用意しました。
以下のコードに置き換えてください!
const { randomBytes } = require('crypto');
const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
const { marshall } = require('@aws-sdk/util-dynamodb');
const ddbClient = new DynamoDBClient({ region: 'us-west-2' }); // 利用しているリージョン
const fleet = [
{
Name: 'Angel',
Color: 'White',
Gender: 'Female',
},
{
Name: 'Gil',
Color: 'White',
Gender: 'Male',
},
{
Name: 'Rocinante',
Color: 'Yellow',
Gender: 'Female',
},
];
exports.handler = async (event) => {
if (!event.requestContext.authorizer) {
return errorResponse('Authorization not configured', event.requestContext.requestId);
}
const rideId = toUrlString(randomBytes(16));
console.log('Received event (', rideId, '): ', event);
const username = event.requestContext.authorizer.claims['cognito:username'];
const requestBody = JSON.parse(event.body);
const pickupLocation = requestBody.PickupLocation;
const unicorn = findUnicorn(pickupLocation);
try {
await recordRide(rideId, username, unicorn);
return {
statusCode: 201,
body: JSON.stringify({
RideId: rideId,
Unicorn: unicorn,
UnicornName: unicorn.Name,
Eta: '30 seconds',
Rider: username,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
} catch (err) {
console.error(err);
return errorResponse(err.message, event.requestContext.requestId);
}
};
function findUnicorn(pickupLocation) {
console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude);
return fleet[Math.floor(Math.random() * fleet.length)];
}
async function recordRide(rideId, username, unicorn) {
const params = {
TableName: 'Rides',
Item: marshall({
RideId: rideId,
User: username,
Unicorn: unicorn,
UnicornName: unicorn.Name,
RequestTime: new Date().toISOString(),
}),
};
await ddbClient.send(new PutItemCommand(params));
}
function toUrlString(buffer) {
return buffer
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
function errorResponse(errorMessage, awsRequestId) {
return {
statusCode: 500,
body: JSON.stringify({
Error: errorMessage,
Reference: awsRequestId,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
};
}
まとめ
マネジメントコンソールのデザイン変更に戸惑ったり、つまずきポイントで苦労したりする場面もありましたが、無事にハンズオンを完了できてとても満足しています。
Amplify を利用したウェブアプリケーションの構築は今回が初めてでしたが、マネジメントコンソールから直感的に操作できたため、サーバーレスの知識が少ない初心者でも比較的容易にウェブアプリケーションを構築できると感じました。
非常におすすめのハンズオンです!ご参考になれば幸いです!