Amazon Web Services ブログ
AWS Amplify の新機能: SQL データベース、OIDC/SAML プロバイダー、AWS CDK との統合
AWS Amplify のローンチウィークの「拡張性の日」へようこそ! AWS Amplify の Gen 2 では、ビジネスニーズに合わせてアプリをカスタマイズするための 4 つの新しい機能を提供しています。本日発表する機能は以下の通りです。
- 既存のデータソース (PostgreSQL または MySQL データベースを含む) との統合
- 任意の OpenID Connect (OIDC) または SAML 認証プロバイダーによる認証
- Amplify で生成された AWS サービスのリソース (Amazon Simple Storage Service (S3) バケットや Amazon DynamoDB テーブルなど) のカスタマイズ
- 200 を超える AWS サービスをアプリに追加
既存のデータソースとの統合 (PostgreSQL データベースを含む)
Amplify Gen 2 は、既存の PostgreSQL または MySQL データベースに接続するための、優れた統合機能を提供しています。これにより、PostgreSQL や MySQL データベースに対してリアルタイムのサブスクリプションやきめ細かなアクセス制御ができるようになりました。データベースは AWS 外部 (例: Neon) または AWS 内部 (例: Amazon RDS または Amazon Aurora) のどちらにもデプロイできます。今回のデモでは、PostgreSQL データベースのリアルタイム API を構築し、ユーザーがノートの作成とサブスクリプションができるようにします。
PostgreSQL や MySQL を使用していませんか? 問題ありません。次のサービスと統合する方法のガイドが提供されています: Amazon DynamoDB、Amazon OpenSearch、Amazon EventBridge、Amazon Polly、Amazon Bedrock、Amazon Rekognition、Amazon Translate、または任意の HTTP エンドポイント。使いたいデータソースがリストにない場合でも? AWS Lambda 関数に接続できるものであれば、Functions 機能を使って何でも統合できます。要するに Amplify Gen 2 は、あらゆるものと統合可能なのです。
Neon (AWS ではない外部の PostgreSQL データベースサービス) との統合を見ていきましょう。まず、Amplify Gen 2 で React のスターターアプリケーションをセットアップします。
npm create vite@latest gen2-postgres-test
スターターオプションとして「React + TypeScript」を選択します。次に、新しい Amplify Gen 2 プロジェクトを初期化します。
npm create amplify@latest
さらに、後で使用する認証 UI を素早く設定できるように、React UI ライブラリもインストールしてください。
npm install @aws-amplify/ui-react
次に、Neon のウェブサイトにアクセスし、新しいデータベースを作成します。以下の PostgreSQL スキーマを使用できます。
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS postgis;
-- Create a table to events
CREATE TABLE events (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
geom GEOMETRY(Point, 4326)
);
-- Create a spatial index on the geometry column
CREATE INDEX idx_events_geom ON events USING GIST (geom);
-- Insert some sample data
INSERT INTO events (name, geom)
VALUES
('Event A', ST_SetSRID(ST_MakePoint(-73.985428, 40.748817), 4326)),
('Event B', ST_SetSRID(ST_MakePoint(-73.990673, 40.742051), 4326)),
('Event C', ST_SetSRID(ST_MakePoint(-73.981226, 40.744681), 4326)),
('Event D', ST_SetSRID(ST_MakePoint(-73.987369, 40.739917), 4326)),
('Event E', ST_SetSRID(ST_MakePoint(-73.992743, 40.746035), 4326));
-- Create a notes table where we'll add owner-based authorization
CREATE TABLE notes (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
content TEXT,
owner TEXT
);
次に、データベース接続文字列を取得し、それをシークレットとして Amplify に提供します。
npx ampx sandbox secret set SQL_CONNECTION_STRING
次に、SQL データベーススキーマの TypeScript 表現を生成します。
npx ampx generate schema-from-database --connection-uri-secret SQL_CONNECTION_STRING --out amplify/data/schema.sql.ts
スキーマを amplify/data/resource.ts ファイルにインポートし、Amplify の Data クライアントを利用してテーブルに対して作成、読み取り、更新、削除の操作を許可する認可ルールを設定できます。
次の例では、Data クライアントで notes
テーブルの名前を、より適切に表される名前 Note
に 変更し、オーナーに対する認可を追加しています。
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
import { schema as generatedSqlSchema} from './schema.sql'
const schema = generatedSqlSchema.renameModels(() => [
['notes', 'Note'] // Renames the models from "notes" -> "Note"
]).setAuthorization((models) => [
// Defines owner-based authorization rule and isolates the record
// based on the record owner. The owner is the user identifier
// stored in the column named "owner".
models.Note.authorization(allow => allow.ownerDefinedIn('owner'))
])
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'userPool',
},
});
クラウドサンドボックスを起動して、アプリケーションのデータバックエンドのイテレーションを開始します。
npx ampx sandbox
次に、クライアント側で、型指定された Data クライアントを使用して、バックエンドのデータを取得または更新できます。例えば、React コードでは、Amplify のリアルタイムサブスクリプション機能を利用して、observeQuery
でデータの変更を監視することができます。src/App.tsx ファイルを次のコードで編集してください。
import { useEffect, useState } from 'react'
import { generateClient } from 'aws-amplify/api'
import { type Schema } from '../amplify/data/resource'
import { Amplify } from 'aws-amplify'
import outputs from '../amplify_outputs.json'
import { withAuthenticator } from '@aws-amplify/ui-react'
import '@aws-amplify/ui-react/styles.css'
Amplify.configure(outputs)
const client = generateClient<Schema>();
function App() {
const [notes, setNotes] = useState<Schema["Note"]["type"][]>([])
useEffect(() => {
const sub = client.models.Note.observeQuery().subscribe({
next: (data) => {
setNotes([...data.items])
}
})
return () => sub.unsubscribe()
}, [])
return (
<>
<h1>Note</h1>
<ul>
{notes?.map(note => (
<li key={note.id} onClick={async () => {
await client.models.Note.delete({ id: note.id })
}}>
<div>{note.content}</div>
</li>
))}
</ul>
<button onClick={async () => {
await client.models.Note.create({
content: window.prompt("New note?"),
})
}}>Create Note</button>
</>
)
}
export default withAuthenticator(App)
変更をローカルでテストすると、リアルタイムでメモを作成できるはずです。
npm run dev
以下のデモビデオでは、各ウィンドウで同一のユーザーとしてログインしており、1 つのウィンドウで新しく作成したメモが他のウィンドウに自動的に同期されています。
カスタムクエリやミューテーションを追加して、特定の SQL クエリを実行することもできます。例えば、PostGIS などの PostgreSQL 拡張機能を使用して、地理空間クエリを実行できます。
const schema = generatedSqlSchema.renameModels(() => [
['notes', 'Note']
]).setAuthorization((models) => [
models.Note.authorization(allow => allow.ownerDefinedIn('owner'))
]).addToSchema({
// Adds a new query that uses PostgreSQL's PostGIS extension to
// convert a geom type to lat and long coordinates
listEventWithCoord: a.query()
.returns(a.ref('EventWithCoord').array())
.authorization(allow => allow.authenticated())
.handler(a.handler.inlineSql(`
SELECT id, name, ST_X(geom) AS longitude, ST_Y(geom) AS latitude FROM events;
`)),
// Defines a custom type that matches the response shape of the query
EventWithCoord: a.customType({
id: a.integer(),
name: a.string(),
latitude: a.float(),
longitude: a.float(),
})
})
この新しいクエリを Data クライアントから呼び出すことができます。例えば、ボタンを追加し、結果のポップアップアラートを作成しましょう。
<button onClick={async () => {
const { data } = await client.queries.listEventWithCoord()
window.alert(JSON.stringify(data))
}}>Fetch events</button>
準備ができたら、PostgreSQL データベースに対応した新しい API を Git にコミットして Amplify でホスティングします。ブランチ環境に対して AWS Amplify コンソールで SQL_CONNECTION_STRING シークレットを設定することを忘れないでください。
OpenID Connect または SAML 認証プロバイダーによる認証
Amplify Gen 2 は、任意の OpenID Connect (OIDC) プロバイダーまたは 任意の SAML プロバイダーでユーザー認証を柔軟に行うことができます。つまり、Microsoft EntraID、Auth0、Okta などの一般的な ID プロバイダーや、独自のカスタム OIDC プロバイダーや SAML プロバイダーをアプリと統合できるということです。
OIDC プロバイダーをセットアップするには、amplify/auth/resource.ts ファイルの defineAuth
ハンドラーで構成できます。例えば、Microsoft EntraID プロバイダーをセットアップする場合は、次のように行います。
import { defineAuth, secret } from '@aws-amplify/backend';
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
oidc: [
{
name: 'MicrosoftEntraID',
clientId: secret('MICROSOFT_ENTRA_ID_CLIENT_ID'),
clientSecret: secret('MICROSOFT_ENTRA_ID_CLIENT_SECRET'),
issuerUrl: '<your-issuer-url>',
},
],
logoutUrls: ['http://localhost:3000/', 'https://mywebsite.com'],
callbackUrls: [
'http://localhost:3000/profile',
'https://mywebsite.com/profile',
],
},
},
});
注: プロダクションブランチの場合は AWS コンソール、クラウドサンドボックスの場合は npx ampx sandbox secret set
で、シークレットを必ず設定してください。
フロントエンドでは、signInWithRedirect()
関数を呼び出すだけで、OIDC/SAML 認証ワークフローをトリガーできます。
import { signInWithRedirect } from 'aws-amplify/auth';
await signInWithRedirect({
provider: {
custom: 'MicrosoftEntraID'
}
});
Amplify で生成された AWS サービスリソースのカスタマイズ
お客様から「Amplify を使うのは AWS で裏技を使っているようだ」と言われたことがあります。しかし、時にはその裏技だけでは不十分で、生成されたリソースをカスタマイズして、ユースケースに最適化する必要が出てくることもあるでしょう。私たちはこれを 謎めいたものではなく、魔法のように直感的なもの と考えています。
「バケットに保存したファイルを 30 日後に削除する必要がある場合はどうすればよいでしょうか?」
Amplify を使わない場合、30 日ごとに関数をトリガーし、すべてのファイルを辿ってから削除する、複雑な cron ジョブを構築する必要があります。これは維持管理が必要で、さらにはコストもかかる機能です。
Amplify を使う場合、基盤となるサービスの機能を十分に活用することができます。Amplify Storage は Amazon S3 で構築されており、オブジェクトのライフサイクルルールを設定できます。バケットにオプションを設定するだけで済みます。amplify/backend.ts ファイルにて、生成された S3 バケットに対してオブジェクトのライフサイクルルールを設定するだけです。
const backend = defineBackend({
auth,
data,
storage,
});
// Override generated resources
backend.storage.resources.cfnResources.cfnBucket.lifecycleConfiguration = {
rules: [{
expirationInDays: 30,
prefix: 'room/',
status: 'Enabled'
}]
}
Amplify の Data, Auth, Storage, Functions など、すべての機能をオーバーライドできるようにサポートしています。
200 を超える AWS サービスをアプリに追加
アプリが成長するにつれ、Amplify の組み込み機能を超えた機能を必要とするようになるのは避けられません。それでも問題ありません。すべてのアプリはその目的を達成するために最適なサービスを利用すべきです。そのため、Amplify アプリに 200 以上の AWS サービスを追加できるようにしました。
Amplify Gen 2 は、AWS Cloud Development Kit (CDK) の上に構築されています。これにより、TypeScript の高い表現力を活かして、クラウド上で信頼性が高く、スケーラブルで、コストパフォーマンスに優れたアプリケーションを開発できます。
「アプリケーションに生成 AI のユースケースのための Amazon Bedrock や、通知のファンアウト機能を追加する必要がある場合はどうすればいいのでしょうか?」
Amplify を使わない場合、アプリケーションのフロントエンドとは別に、バックエンドインフラストラクチャのコードベースを管理する必要があります。つまり、フロントエンドとバックエンドのデプロイを同期するために数週間の DevOps オーバーヘッドがかかり、開発、テスト、本番の各ワークフローをカスタムで構築しなければなりません。
Amplify を使う場合、Amplify アプリにバックエンドインフラストラクチャを簡単に追加できます。Amplify の CI/CD 機能が組み込まれているため、DevOps が手間なく実現できます。新しい環境が必要ですか? Git ブランチを作成するだけです。ローカルでフロントエンドのコードをテストするためのサンドボックス環境が必要ですか? Amplify のクラウドサンドボックスを使用します。
200 以上の AWS サービスからリソースを追加するには、それぞれの CDK コンストラクトをインポートし、amplify/backend.ts ファイルのスタックに追加します。もちろん、Amplify は AWS によって構築され、AWS 上で動作するため、これらのカスタムリソースを Amplify で生成されたリソースと接続することができます。
import { defineBackend } from '@aws-amplify/backend';
import { auth } from './auth/resource';
import { data } from './data/resource';
import { generateHaiku } from './functions/generateHaiku/resource';
import { handleSubscription } from './functions/handleSubscription/resource';
// Import CDK constructs directly into an Amplify Project
import * as iam from 'aws-cdk-lib/aws-iam';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';
const backend = defineBackend({
auth,
data,
generateHaiku,
handleSubscription
});
// Grant function access to Amazon Bedrock
backend.generateHaiku.resources.lambda.addToRolePolicy(
new iam.PolicyStatement({
effect: Effect.ALLOW,
actions: ["bedrock:InvokeModel"],
resources: [
`arn:aws:bedrock:${Stack.of(backend.data).region}::foundation-model/anthropic.claude-3-haiku-20240307-v1:0`,
],
})
)
// Define a new stack for the SNS topic
const snsStack = backend.createStack("SnsStack");
// Create the SNS topic
const topic = new sns.Topic(snsStack, "Topic");
// Use an Amplify Function (defineFunction) as a subscription handler
topic.addSubscription(new subscriptions.LambdaSubscription(
backend.handleSubscription.resources.lambda
));
まとめ
これは AWS Amplifiy プロジェクトを拡張する方法の一例にすぎません。私たちは、DevOps ワークフローやデータソースの接続のために、差別化につながらない手作業によるコーディングで時間を浪費することをなくしたいと考えています。インフラストラクチャの設定に悩むのではなく、アプリケーションのユースケースに集中していただきたいのです。まずは、Amplify のクイックスタートチュートリアルをお試しください!
本記事は New in AWS Amplify: Integrate with SQL databases, OIDC/SAML providers, and the AWS CDK を翻訳したものです。翻訳は Solutions Architect の都築が担当しました。