Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
CDKアプリとしてのAmplify Gen2 - @aws-amplify/backendの...
Search
MURAKAMI Masahiko
July 06, 2024
Technology
3.7k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
CDKアプリとしてのAmplify Gen2 - @aws-amplify/backendのアーキテクチャにみるCDKベストプラクティス -
MURAKAMI Masahiko
July 06, 2024
More Decks by MURAKAMI Masahiko
See All by MURAKAMI Masahiko
AWS Amplifyをもっと便利に使うための取り組み/amplify-tools-and-contributions
fossamagna
1
150
Amazon Verified Permissions実践入門 〜Cedar活用とAppSync導入事例/Practical Introduction to Amazon Verified Permissions
fossamagna
2
370
Amplify Gen2から知るAWS CDK Toolkit Libraryの使い方/How to use the AWS CDK Toolkit Library as known from Amplify Gen2
fossamagna
1
900
AWS Amplify Gen2向けのVSCode拡張を作って公開してみた話/lts-techday-2024
fossamagna
0
49
Amplify Gen2の 新機能と実践的な使用例 AWS Amplify Gen 2 Festival in Japan/New features and practical use cases in Amplify Gen2
fossamagna
0
850
Amplify Gen2を 拡張してみよう JAWS-UG北陸新幹線 ( 福井開催 ) 2024-04-06/Let's extend Amplify Gen2
fossamagna
0
1k
みんな本当に AWS Amplify を知っている?/do-you-really-know-aws-amplify
fossamagna
0
200
Amplify OSSにコントリビュートしてAmplify Badgeを手に入れよう!/contribute-to-amplify-oss-and-get-an-amplify-badge
fossamagna
0
630
Using custom function template with AWS Amplify
fossamagna
1
580
Other Decks in Technology
See All in Technology
EventBridge Connection
_kensh
5
710
チームで進めるAI駆動アジャイル×ウォーターフォール
kumaiu
0
160
AIエージェントが名古屋の猛暑からあなたを守る
happysamurai294
0
110
AIっぽい文章を採点して人間らしく直すアプリを作ってみた
yama3133
2
150
GitHub Copilot 最新アップデート – 「一歩先」の実践活用術
moulongzhang
1
280
Chainlitで作るお手軽チャットUI
ynt0485
0
230
中期計画、2回作ってみた ~業務委託と正社員、両方の視点から~
demaecan
1
740
RSA暗号を手計算したくなること、ありますよね?? (20260615_orestudy6_rsa)
thousanda
0
380
非定型業務をAI slackbotで自動化する ~ 社内要望を自動壁打ちするbotを作った ~/automating-ad-hoc-work-with-ai-slackbot
shibayu36
0
650
「エンジニア進化論」2028年の開発完全自動化、エンジニアはどう進化するか
cyberagentdevelopers
PRO
6
5.1k
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
4
2.9k
MUSUBI 田中裕一『AIと共に行う「しごとのリデザイン」- スモールバックオフィス編』AI Ops Lab #4
musubi
0
140
Featured
See All Featured
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
390
Building the Perfect Custom Keyboard
takai
2
790
Typedesign – Prime Four
hannesfritz
42
3.1k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
22k
sira's awesome portfolio website redesign presentation
elsirapls
0
280
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Deep Space Network (abreviated)
tonyrice
0
170
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Transcript
CDKアプリとしての Amplify Gen2 - @aws-amplify/backendのアーキテク チャにみる CDKベストプラクティス - AWS CDK
Conference Japan 2024 presented by JAWS-UG 2024-07-06 株式会社永和システムマネジメント 村上雅彦 (a.k.a @fossamagna)
村上 雅彦 株式会社永和システムマネジメント Amplify Japan User Group 運営メンバー AWS Community
Builder (Front-End Web & Mobile since 2022) GitHub: https://github.com/fossamagna X(旧Twitter): https://x.com/fossamagna 自己紹介
• AWS CDKをベースとする次世代のAmplifyのバックエン ド構築ツール • TypeScriptによるバックエンド定義を提供 • CoC(設定より規約を優先する) • GitのブランチとAWS環境を1:1でマッピング
• 開発者毎の独立したsandbox環境を提供 Amplify Gen2
• AWS CDKをベースとする次世代のAmplifyのバックエン ド構築ツール • TypeScriptによるバックエンド定義を提供 • ファイルベース規約(設定より規約を優先する) • GitのブランチとAWS環境を1:1でマッピング
• 開発者毎の独立したsandbox環境を提供 Amplify Gen2の新機能
ファイルベース規約 amplify ├── auth // 認証のカテゴリ │ └── resource.ts ├──
data // GraphQL APIのカテゴリ │ └── resource.ts ├── backend.ts // バックエンド全体 ├── package.json └── tsconfig.json • Amplifyが提供する機能 毎のディレクトリ内の resource.tsに定義する • backend.tsにバックエン ド全体を定義する • どの機能のリソース定義 がどこにあるのか予測で きる
TypeScriptによる 定義 // amplify/data/resource.ts const schema = a.schema({ Todo: a
.model({ content: a.string(), }) .authorization((allow) => [allow.publicApiKey()]), }); export type Schema = ClientSchema<typeof schema>; export const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: "apiKey", // API Key is used for a.allow.public() rules apiKeyAuthorizationMode: { expiresInDays: 30, }, }, }); • defineData関数でリ ソースを宣言的に定義 • TypeScriptで GraphQLのSchemaと APIの認証設定を記述 するのみ • この例ではAppSync, DynamoDBによる GraphQL APIが構築さ れる
TypeScriptによる 定義 // amplify/backend.ts import { defineBackend } from '@aws-amplify/backend'
; import { auth } from './auth/resource'; import { data } from './data/resource'; defineBackend({ auth, data, }); • defineBackendでバッ クエンド全体を定義 • 機能毎の定義をimport してアプリのバックエド ン全体を構成する
• prodcutionやstagingといった環境がGitのブランチと 1 : 1 で対応 • Gitのブランチへpushすることで自動でデプロイされる https://docs.amplify.aws/react/how-amplify-works/concepts/#faster-local-development Gitベースのフルスタック環境
• 開発者毎の独立した sandbox環境を提供 • npx ampx sandboxコマン ド一発で環境構築完了 • hot
swapデプロイ対応で 迅速にデプロイ可能 https://docs.amplify.aws/react/how-amplify-works/concepts/#faster-local-development sandbox環境
Amplify Gen2バックエンドの内側
• Gitブランチに対応するフルスタック環境 ◦ npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
• sandbox環境 ◦ npx ampx sandbox Amplify Gen2バックエンドのデプロイ
• CDKアプリとして見ると Amplify Gen2 CLIプロセスは aws-cdkプロセスを呼び出す ラッパー • 赤枠部分はAWS CDKそのも
の Amplify Gen2 バックエンドのプロセス構成 https://github.com/aws-amplify/amplify-backend/blob/main/PROJECT_ARCHITECTURE.md から引用
• Best practices for developing and deploying cloud infrastructure with
the AWS CDK (AWS CDKを使用したクラウドイン フラストラクチャの開発とデプロイのベストプラ クティス) • Best practices for using the AWS CDK in TypeScript to create IaC projects - AWS Prescriptive Guidance (AWS 規範ガ イダンス AWS CDK で TypeScript を使用し て IaC プロジェクトを作成するためのベストプ ラクティス) AWS CDKのベストプラクティスの参考資料
L3 Constructの作成
• dataとauthの2つのL3 Construct ◦ @aws-amplify/data-construct ◦ @aws-amplify/auth-construct • @aws-amplify/<feature>-construct という規則のパッケージ名
• 素早く簡単にAmplifyライクなリソースを 構築できる • Amplifyから独立しても使える L3 Constructsの作成 パッケージ構造の依存関係図: https://github.com/aws-amplify/amplify-backend/blob/main/PROJECT_ARCHITECTURE.md から引用
@aws-amplify/ data-construct // Cognito ユーザープールベースの認証を使用したシンプルな Todo リスト import { App,
Stack } from 'aws-cdk-lib'; import { UserPool } from 'aws-cdk-lib/aws-cognito'; import { AmplifyData, AmplifyDataDefinition } from '@aws-amplify/data-construct'; const app = new App(); const stack = new Stack(app, 'TodoStack'); new AmplifyData(stack, 'TodoApp', { definition: AmplifyDataDefinition.fromString(/* GraphQL */ ` type Todo @model @auth(rules: [{ allow: owner }]) { description: String! completed: Boolean } `), authorizationModes: { userPoolConfig: { userPool: UserPool.fromUserPoolId(stack, 'ImportedUserPool', '<YOUR_USER_POOL_ID>'), }, }, }); • GraphQLのスキーマ定 義がTypeScriptではな いこと以外はほぼ Amplify Gen2と同じ • AppSync+DynamoDB というパターンに対して特 化した効果的なインタ フェース
@aws-amplify/ auth-construct // SMSを使ったMFA設定を使用したEメールログイン import { App, Stack } from
"aws-cdk-lib"; import { AmplifyAuth } from "@aws-amplify/auth-construct"; const app = new App(); const stack = new Stack(app, "AuthStack"); new AmplifyAuth(stack, "Auth", { loginWith: { email: true, }, multifactor: { mode: "OPTIONAL", sms: { smsMessage: (code: string) => `Your verification code is ${code}`, }, totp: false, }, }); • 設定オブジェクトによる宣 言的な設定 • Amplify の auth が提 供するWebアプリ、モバ イル向けのAmplify ライ クな認証設定を簡単に設 定可能
Abstract Factoryパターン を利用する *万人向けではありません
ConstructFactory // amplify-backend/packages/plugin-types/src/construct_factory.ts /** * Functional interface for construct factories.
All objects in the backend-engine definition must implement this interface. */ export type ConstructFactory<T extends ResourceProvider = ResourceProvider> = { readonly provides?: string; getInstance: (props: ConstructFactoryGetInstanceProps) => T; }; // amplify-backend/packages/plugin-types/src/resource_provider.ts /** * Provides reference to underlying CDK resources. */ export type ResourceProvider<T extends object = object> = { resources: T; }; • @aws-amplify/backen dでのCDKコンストラクトの 構築を担うクラス • synthプロセス内で呼び出 される • 機能間で依存するコンスト ラクトの解決(DIコンテナ) に利用される • 依存するコンストラクトの具 体的な構築方法を知らなく てよい
https://github.com/aws-amplify/amplify-backend/blob/main/PROJECT_ARCHITECTURE.md から引用 ConstructFactoryの実装 Amplify Gen2 バックエンドのプロセス構成の詳細
Aspectsを使ってセキュリティプ ロパティに関する アサーションを行う
Cognito IdPの 信頼ポリシー { "Version": "2012-10-17", "Statement": [ { "Effect":
"Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-west-2:abcdefg-1234-5678-910a-0e8443553f95" }, "ForAnyValue:StringLike": { "cognito-identity.amazonaws.com:amr": "authenticated" } } } ] } • sts:AssumeRoleWithWebIden tity を許可する信頼ポリシーには 適切な条件が設定されている必要 がある ◦ モバイルやWebアプリなどWebベースのIDプロ バイダーを使用して認証されたユーザーに、 IAM Roleの一時的なセキュリティ認証情報を 発行するAPIリクエスト ◦ cognito-identity.amazonaws.com:aud で 特定のCognito IdentityPoolからのオペレー ションに制限する ◦ cognito-identity.amazonaws.com:amr で ロールの付与を認証済みもしくはゲストユー ザーに制限する
Aspectsによるポリ シーの条件チェック // packages/backend/src/engine/amplify_stack.ts から一部抜粋 class CognitoRoleTrustPolicyValidator implements IAspect {
visit = (node: IConstruct ) => { ... const assumeRolePolicyDocument = node.assumeRolePolicy ?.toJSON(); assumeRolePolicyDocument .Statement .forEach( this.cognitoTrustPolicyStatementValidator ); }; private cognitoTrustPolicyStatementValidator = ({ Action: action, Condition: condition , Effect: effect, Principal: principal , }: { // These property names come from the IAM policy document which we do not control Action: string; Condition ?: Record<string, Record<string, string>>; Effect: 'Allow' | 'Deny'; Principal ?: { Federated ?: string }; }) => { ... const audCondition = condition ?.StringEquals ?.['cognito-identity.amazonaws.com:aud' ]; if (typeof audCondition !== 'string' || audCondition .length === 0) { throw new AmplifyFault ('InvalidTrustPolicyFault' , { message: 'Cannot create a Role trust policy with Cognito that does not have a StringEquals condition for cognito-identity.amazonaws.com:aud' , }); } ... }; } • Aspectsを使ってセキュリティに関する チェックを実施している • CognitoRoleTrustPolicyValidatorと いうAspectでCognito Idpの sts:AssumeRoleWithWebIdentity のActionを付与するロールに条件が 含まれているのかを検証している • 特定のCognito IdentityPoolからの オペレーションに制限する指定がある か、ロールの付与を認証済みもしくは ゲストユーザーに制限する指定がある をチェック。
カスタムリソース
secrets import { defineAuth, secret } from '@aws-amplify/backend' ; export
const auth = defineAuth({ loginWith: { email: true, externalProviders: { facebook: { // fooという名前のシークレットを利用 clientId: secret('foo'), clientSecret: secret('bar') } } } }); • Amplify Gen2でのシーク レット値を管理する機能 • secret関数にシークレット の名前を指定するだけで参 照可能。 • シークレット値はアプリ全 体、ブランチ毎にシークレッ ト値を設定できる • SSM Parameter Storeに 登録される
secrets export const handler = async ( event: CloudFormationCustomResourceEvent ):
Promise<CloudFormationCustomResourceSuccessResponse > => { console.info(`Received ' ${event.RequestType }' event` ); const physicalId = event.RequestType === 'Create' ? randomUUID () : event.PhysicalResourceId ; let data: { secretValue : string } | undefined = undefined ; if (event.RequestType === 'Update' || event.RequestType === 'Create' ) { // SSM からシークレットを取得する const val = await handleCreateUpdateEvent (secretClient , event); data = { secretValue: val, }; } return { RequestId: event.RequestId , LogicalResourceId: event.LogicalResourceId , PhysicalResourceId: physicalId , Data: data, StackId: event.StackId, NoEcho: true, Status: 'SUCCESS' , } as CloudFormationCustomResourceSuccessResponse ; }; • SSMから対象ブランチまたは アプリ全体のシークレット値 を取得する CustomResourceProvide rとして実装されている • シークレットを参照する側が Lambdaの場合、シークレッ ト値を取得して環境変数に設 定するランタイムコードが ユーザーコードの先頭に挿 入されデプロイされる
• AWS::DynamoDB::Tableを置き換えるAmplify用DynamoDBTableカ スタムリソース • 一度で複数のGSIの更新をサポート ◦ isCompleteはDynamoDBへの変更処理行う。 WaiterStateMachineはisCompleteがエラーを返さなくまで(複数 のDynamoDBへの更新処理が完了するまで)retryする Custom::AmplifyDynamoDBTable
• Amplify Gen2 で使われているベストプラクティス、L3 ConstructやAbstract Factoryパターンにより利用する 側はより宣言的にリソースを定義できる。 • AWS CDK
をベースにしたプラットフォームを提供する場 合の参考になる。 まとめ
ご清聴ありがとうございました!