はじめに
ECS 上で動かしている Next.js から Timestream のデータを読み出すのに、認証周りでいろいろと苦労したので成果をここに残します。
当初は個人のアクセスキーを使っていたのですが、これだと自分ひとりしか使えないので困っていましたが、コンテナに適切なタスクロールを付与することで解決できました。
Next.js に限らず ECS 上から JavaScript(TypeScript) で Timestream にアクセスする場合には、同じような設定でいけるのではないかと思います。
環境
- Next.js (TypeScript) + AWS SDK for JavaScript v3
- Amazon ECS
- Amazon Timestream
Next.js から Timestream の呼び出し
今回は Route Handlers 内に実装しました。
fromContainerMetadata
が、コンテナ内の特殊な URI から ACCESS_KEY_ID や SECRET_ACCESS_KEY 等を取得しているようで、Client Components では動かせません。
サンプルコードなのでエラーハンドリング等は省略しています。
import { NextResponse } from 'next/server'
import { TimestreamQueryClient, QueryCommand } from '@aws-sdk/client-timestream-query'
import { fromContainerMetadata } from '@aws-sdk/credential-providers'
const query = 'SELECT * from "DB"."Table" LIMIT 10'
export const GET = async () => {
const timestreamClient = new TimestreamQueryClient({
region: 'ap-northeast-1',
credentials: fromContainerMetadata(),
})
const data = await timestreamClient.send(new QueryCommand({ QueryString: query }))
return NextResponse.json({ data })
}
ロール作成
ECS のコンテナが Timestream にアクセスする権限を付けたロールを作成します。
ユースケースで Elastic Container Service Task を選び、次へをクリック。
許可ポリシーで自分に合わせたポリシーを選びます。
私の場合ここではポリシーは選ばず、この後インラインポリシーで厳しい制限を付けたポリシーを作成しました。
インラインポリシー
もっと細かくカスタマイズしたポリシーを作るためにインラインポリシーを作成します。
作成したロールを開き、「許可を追加」から「インラインポリシーを作成」
「アクションをフィルタリング」に Timestream と入力して、Timestream のアクションに絞り込みます。
今回は Select だけを行えればよかったので、DescribeEndpoints
と Select
にチェックを入れます。
またデータベースやテーブルも限定したかったので、リソースは「特定」を選び、データベースとテーブルを指す ARN を入力しました。
タスク定義
ECS のタスク定義で、タスクロールの値に先ほど作成したロールを当てはめます。