サンドボックスシード
Sandbox Seed 機能を使用すると、Amplify サンドボックス環境に初期データを設定でき、現実的なデータを使用してアプリケーションをより簡単にテストおよび開発できます。
シードスクリプトのセットアップ
まず、@aws-amplify/seed パッケージをインストールします。
npm install @aws-amplify/seed --save-dev次に、シードスクリプトを作成する必要があります。このスクリプトはサンドボックス環境をデプロイするときと ampx sandbox seed コマンドを実行するときに実行されます。
amplifyディレクトリの下にseedという名前のフォルダを作成しますseedフォルダ内にseed.tsというファイルを作成します
amplify/ └── seed/ └── seed.ts必要な権限のセットアップ
サンドボックス環境をシードするには、AWS プロファイルユーザーまたは実行ロールに必要な権限を追加する必要があります。Amplify は必要な権限を生成します。これを AmplifyBackendDeployFullAccess を含む権限セットまたはロールに付与できます。
- アクティブなサンドボックス環境がデプロイされていること。
npx ampx sandboxを使用してサンドボックス環境をデプロイできます。 - 必要な権限ポリシーテンプレートを生成します
npx ampx sandbox seed generate-policy > seed-policy.json- このポリシーをロールに付与します (AWS CLI を使用した例):
aws iam put-role-policy --role-name <your-role-name> --policy-name <policy-name> --policy-document file://seed-policy.jsonシードスクリプトの作成
権限のセットアップが完了したら、シードスクリプトを作成できます。@aws-amplify/seed パッケージは、サンドボックス環境をシードするのに役立つ API のセットを提供します。
認証
例えば、認証をユーザーでシードして、ユーザーを admin グループに追加したい場合は、まず認証リソースを作成することから始めましょう:
import { defineAuth } from "@aws-amplify/backend";
export const auth = defineAuth({ loginWith: { email: true, }, userAttributes: { locale: { required: false, mutable: true, }, }, groups: ["admin"],});npx ampx sandbox secret set を使用して 2 つのシークレットを作成します
npx ampx sandbox secret set usernamenpx ampx sandbox secret set password次に、ユーザーを作成して admin グループに追加するために、以下のスクリプトを作成できます:
import { readFile } from "node:fs/promises";import { addToUserGroup, createAndSignUpUser, getSecret,} from "@aws-amplify/seed";import { Amplify } from "aws-amplify";
// this is used to get the amplify_outputs.json file as the file will not exist until sandbox is createdconst url = new URL("../../amplify_outputs.json", import.meta.url);const outputs = JSON.parse(await readFile(url, { encoding: "utf8" }));Amplify.configure(outputs);
const username = await getSecret("username");const password = await getSecret("password");
const user = await createAndSignUpUser({ username: username, password: password, signInAfterCreation: false, signInFlow: "Password", userAttributes: { locale: "en", },});
await addToUserGroup(user, "admin");シードスクリプトを実行します
npx ampx sandbox seedこれにより、提供されたユーザー名とパスワードを使用してユーザーが作成され、admin グループに追加されます。
getSecret 関数は npx ampx sandbox secret set を使用して作成したシークレットを取得します。これにより、認証情報をコードにハードコードすることを回避できます。または、ユーザー名とパスワードを createAndSignUpUser 関数の string として直接設定することもできますが、リポジトリで機密情報を公開することを避けるために、getSecret を使用することを強くお勧めします。
多要素認証 (MFA)
Amplify シードは、TOTP (時間ベースのワンタイムパスワード)、メール、SMS など、複数のタイプの MFA をサポートします。以下は、シードスクリプトで MFA を実装する方法の例です。
TOTP MFA を使用した認証
例えば、TOTP MFA が有効になっているユーザーで認証をシードしたい場合は、まず認証リソースを構成することから始めましょう:
import { defineAuth } from "@aws-amplify/backend";
export const auth = defineAuth({ loginWith: { email: true, },
multifactor: { mode: "REQUIRED", totp: true, },});TOTP MFA が有効になっているユーザーを作成してサインインするには、以下のスクリプトを作成できます:
この例では、otpauth ライブラリを使用して TOTP コードを生成します。
npm install otpauthimport type { ChallengeResponse } from "@aws-amplify/seed";import { readFile } from "node:fs/promises";import { createAndSignUpUser, getSecret,} from "@aws-amplify/seed";import { Amplify } from "aws-amplify";import * as auth from "aws-amplify/auth";import * as otpauth from "otpauth";
// this is used to get the amplify_outputs.json file as the file will not exist until sandbox is createdconst url = new URL("../../amplify_outputs.json", import.meta.url);const outputs = JSON.parse(await readFile(url, { encoding: "utf8" }));Amplify.configure(outputs);
const username = await getSecret("username");const password = await getSecret("password");let totpSecret: string;
const createTOTP = (secret: string) => { return new otpauth.TOTP({ secret, algorithm: "SHA1", digits: 6, period: 30, });};
const generateTOTPCode = (secret: string): string => { const totp = createTOTP(secret); return totp.generate();};
const challengeWithTOTP = async ( totpSetup: auth.SetUpTOTPOutput): Promise<ChallengeResponse> => { totpSecret = totpSetup.sharedSecret; const answer = generateTOTPCode(totpSetup.sharedSecret); return { challengeResponse: answer };};
const user = await createAndSignUpUser({ username, password, signInAfterCreation: false, signInFlow: "MFA", mfaPreference: "TOTP", totpSignUpChallenge: async (totpSetup) => { return await challengeWithTOTP(totpSetup); },});
console.log(`User ${user.username} was created`);
// Wait for a moment to get a fresh TOTP codeawait new Promise((resolve) => setTimeout(resolve, 35000));
const signIn = await signInUser({ username, password, signInFlow: "MFA", signInChallenge: async () => { const answer = generateTOTPCode(totpSecret); return { challengeResponse: answer }; },});
console.log(`User was signed in: ${signIn}`);
auth.signOut();これにより、TOTP MFA が有効になっているユーザー名とパスワードを使用してユーザーが作成されます。TOTP コードは otpauth ライブラリを使用して生成されます。その後、ユーザーがサインインし、TOTP コードが生成されます。
タイムアウトにより、ユーザーの作成と認証の両方に同じ TOTP コードが使用される場合に発生する可能性のある競合を防ぐために、前の TOTP コードが有効期限切れになってからサインイン用の新しいコードを生成します。
シードスクリプトを実行します
npx ampx sandbox seedメール MFA を使用した認証
例えば、メール MFA が有効になっているユーザーで認証をシードしたい場合:
import { readFile } from "node:fs/promises";import { createAndSignUpUser, getSecret, signInUser} from "@aws-amplify/seed";import { Amplify } from "aws-amplify";import * as auth from "aws-amplify/auth";
// this is used to get the amplify_outputs.json file as the file will not exist until sandbox is createdconst url = new URL("../../amplify_outputs.json", import.meta.url);const outputs = JSON.parse(await readFile(url, { encoding: "utf8" }));Amplify.configure(outputs);
const username = await getSecret("username");const password = await getSecret("password");
// Set mfaPreference to EMAIL when using email-only MFAconst user = await createAndSignUpUser({ username: username, password: password, signInAfterCreation: false, signInFlow: "MFA", mfaPreference: "EMAIL",});
// Sign in will prompt for MFA code in command lineawait signInUser({ username: username, password: password, signInFlow: "MFA",});
auth.signOut();これにより、メール MFA が有効になっているユーザー名とパスワードを使用してユーザーが作成されます。その後、ユーザーがサインインし、コマンドラインで MFA コードを入力するよう求められます。
シードスクリプトを実行します
npx ampx sandbox seedSMS MFA はメール MFA と同じパターンに従い、検証にはコマンドラインプロンプトを使用します。設定で mfaPreference: "EMAIL" を mfaPreference: "SMS" に置き換えるだけです。コマンドラインの操作は同じで、メールコードの代わりに SMS コードを入力するよう求められます。
データ
例えば、Data API をシードしたい場合は、まず認可モードが userPool に設定された Todo モデルを使用して GraphQL API を作成することから始めましょう:
import { a, defineData, type ClientSchema } from "@aws-amplify/backend";
const schema = a.schema({ Todo: a .model({ content: a.string(), isDone: a.boolean(), }) .authorization((allow) => [allow.authenticated()]),});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({ name: "TodoApi", schema, authorizationModes: { defaultAuthorizationMode: "userPool", },});次に、todo テーブルを todo でシードするために、以下のスクリプトを作成できます:
import type { Schema } from "../data/resource";import { readFile } from "node:fs/promises";import { getSecret, signInUser } from "@aws-amplify/seed";import { Amplify } from "aws-amplify";import * as auth from "aws-amplify/auth";import { generateClient } from "aws-amplify/api";
// this is used to get the amplify_outputs.json file as the file will not exist until sandbox is createdconst url = new URL("../../amplify_outputs.json", import.meta.url);const outputs = JSON.parse(await readFile(url, { encoding: 'utf8' }));
Amplify.configure(outputs);
const dataClient = generateClient<Schema>();
const username = await getSecret("username");const password = await getSecret("password");
await signInUser({ username: username, password: password, signInFlow: "Password",});
const response = await dataClient.models.Todo.create( { content: `My first todo`, isDone: false, }, { authMode: "userPool", });if (response.errors && response.errors.length > 0) { throw response.errors;}
auth.signOut();スクリプトは Amplify Data API クライアントを使用して API テーブルと対話し、signInUser 関数を使用して認証されたユーザーにサインインします。
シードスクリプトを実行します
npx ampx sandbox seedこれにより、認証されたユーザーを使用して My first todo というコンテンツを含む todo が作成され、isDone フィールドが false に設定されます。
ストレージ
import { defineStorage } from "@aws-amplify/backend";
export const storage = defineStorage({ name: "myStorage", isDefault: true, access: (allow) => ({ "pictures/*": [allow.authenticated.to(["write", "list"])], }),});次に、ストレージに画像をシードするために、以下のスクリプトを作成できます:
import { getSecret, signInUser } from "@aws-amplify/seed";import { Amplify } from "aws-amplify";import * as auth from "aws-amplify/auth";import * as storage from "aws-amplify/storage";import { readFile } from 'node:fs/promises';
// this is used to get the amplify_outputs.json file as the file will not exist until sandbox is createdconst url = new URL("../../amplify_outputs.json", import.meta.url);const outputs = JSON.parse(await readFile(url, { encoding: 'utf8' }));Amplify.configure(outputs);
const username = await getSecret("username");const password = await getSecret("password");
await signInUser({ username: username, password: password, signInFlow: "Password",});
const uploadTask = storage.uploadData({ data: `My first content created by ${username}`, path: `pictures/${Math.random().toString()}`,});
await uploadTask.result;
const s3Items = await storage.list({ path: "pictures/", options: { pageSize: 1000, },});
console.log(s3Items.items);
auth.signOut();シードスクリプトを実行します
npx ampx sandbox seedこれにより、My first content created by ${username} というコンテンツを含む画像が作成され、ストレージの pictures フォルダに保存されます。
ベストプラクティス
安全な認証情報
シードスクリプトでユーザー名とパスワードを使用する場合、Amplify サンドボックスシークレットを使用して認証情報を安全に保存します:
- CLI を使用してシークレットを設定します:
npx ampx sandbox secret set usernamenpx ampx sandbox secret set password- シードスクリプトでシークレットを取得します:
import { getSecret } from '@aws-amplify/seed'; const username = await getSecret('username');const password = await getSecret('password');ユーザーセッション管理
操作が終わったら、常にユーザーをサインアウトします。これにより、ユーザーセッションに関する潜在的な問題を回避できます:
import * as auth from "aws-amplify/auth";
auth.signOut();createAndSignUpUser でユーザーを作成する場合、signInAfterCreation パラメータは、ユーザーが作成された後に自動的にサインインするかどうかを制御します。このパラメータはユーザーセッション管理に重要な影響を与えます:
// Create and sign in first userconst user1 = await createAndSignUpUser({ username: 'user1@example.com', password: 'Password123!', signInAfterCreation: true});// At this point, user1 is signed in
// Create second userconst user2 = await createAndSignUpUser({ username: 'user2@example.com', password: 'Password123!', signInAfterCreation: true});// Now user2 is signed in, and user1 has been signed out
// Create third user without auto sign-inconst user3 = await createAndSignUpUser({ username: 'user3@example.com', password: 'Password123!', signInAfterCreation: false});// No user is signed in, as user2 was signed out during user3's creation// and user3 wasn't automatically signed in注意する重要な動作:
signInAfterCreation: trueを設定すると、新しく作成されたユーザーが自動的にサインインし、以前にサインインしたユーザーがサインアウトされます。signInAfterCreation: falseの場合、ユーザーは作成後にサインインされません- 同時にサインインできるユーザーは 1 人のみです
この動作は、複数のユーザーをアプリケーションにシードする場合に特に重要です。シードプロセスの最後でどのユーザーをサインアウトすべきかを慎重に管理する必要があります。
複数回のシード実行間でのユーザー管理
シードは、実行するたびに createAndSignUpUser の各インスタンスに対して新しいユーザーを作成しようとします。
複数回のシード実行で同じユーザーを使用したい場合は、createAndSignUpUser が重複したユーザーを作成しようとすることによって生じる可能性のあるエラーを回避するため、以下を使用します:
const username = await getSecret('username');const password = await getSecret('password');
try { const user = await createAndSignUpUser({ username: username, password: password, signInFlow: 'Password', signInAfterCreation: true });} catch (err) { const error = err as Error; if (error.name === 'UsernameExistsError') { await signInUser({ username: username, password: password, signInFlow: 'Password' }); } else { throw err; }}MFA チャレンジ処理
-
サインアップチャレンジの場合、各 MFA タイプは独自の特定のチャレンジコールバックを持っています:
- TOTP:
totpSignUpChallenge - メール:
emailSignUpChallenge - SMS:
smsSignUpChallenge
- TOTP:
-
サインインの場合、すべての MFA タイプ (TOTP、メール、または SMS) で機能する単一の普遍的な
signInChallengeコールバックがあります
重要な動作:
- コマンドラインプロンプトは、サインイン中のすべての MFA タイプで機能します
- サインアップ中、コマンドラインはメール MFA と SMS MFA でプロンプトを表示しますが、TOTP MFA では表示しません
- MFA がユーザープールで「オプション」に設定されている場合、ユーザーはパスワードフローを通じて送信されます
TOTP に関する考慮事項
TOTP MFA を使用する場合、これらの動作に注意してください:
- 異なる TOTP インスタンスに同じ TOTP セットアップシークレットを複数回使用すると、エラーが発生します
- サインアップとサインイン (有効期限切れ前) に同じ 6 桁のパスコードを使用すると、エラーが発生します
- TOTP を使用して複数のユーザーを作成したり複数のサインインを実行したりする場合:
- 前のパスコードが有効期限切れになるまで待機してから、新しいパスコードを生成します
- 例にはこれを処理するためのタイムアウトが含まれています:
await new Promise((resolve) => setTimeout(resolve, 35000));
シード API
@aws-amplify/seed パッケージは、サンドボックス環境をシードするのに役立つ Amplify JS Auth API と互換性のある一連の API を提供します。
シークレット API
シークレット API は AWS Parameter Store を使用し、ampx sandbox secret コマンドと互換性があります。
-
getSecret - シークレットの名前を取得して、そのシークレットの値を返します
const secretValue = await getSecret('secretName'); -
setSecret - シークレットの名前とその値を取得して、シークレットの名前を返します
const secretName = await setSecret('secretName', 'secretValue');
認証 API
認証 API を使用すると、サンドボックス環境でユーザーを作成および管理でき、Amplify JS Auth API と互換性があります。
-
createAndSignUpUser - 渡されたプロパティに基づいてユーザーを作成します
const user = await createAndSignUpUser({username: 'username',password: 'password',signInAfterCreation: true,signInFlow: 'Password',userAttributes?: StandardUserAttributes // Optional user attributes}); -
signInUser - ユーザー名、パスワード、サインインフローを使用してユーザーにサインインします
await signInUser({username: 'username',password: 'password',signInFlow: 'Password' | 'MFA',signInChallenge?: () => Promise<ChallengeResponse> // Optional for MFA}); -
addToUserGroup - 既存のユーザーグループにユーザーを追加します
await addToUserGroup({username: 'username' // User to add to group}, 'GroupName');
その他の型
@aws-amplify/seed パッケージは、これらの重要な型を提供します:
AuthSignUp- ユーザーサインアップ構成の型AuthUser- ユーザーサインインの型ChallengeResponse- MFA チャレンジレスポンスの型StandardUserAttributes- サインアップ中のユーザー属性管理の型AuthOutputs- ユーザーサインアップ出力の型
MFA チャレンジコールバック型:
emailSignUpChallenge- サインアップ中のメール MFA を処理しますsmsSignUpChallenge- サインアップ中の SMS MFA を処理しますtotpSignUpChallenge- サインアップ中の TOTP MFA を処理しますsignInChallenge- サインイン中のすべての MFA タイプの普遍的なハンドラー
これらの API の使用方法の詳細については、Amplify JS Auth API ドキュメントを参照してください。