🐧

StorageBrowser for AWS S3をAmplifyでカスタム認証+既存S3バケットで使う手順

に公開

はじめに

Cursorで作業した内容を記事にまとめるのにもう人間の手は入らないでもいいんだな、、、という気持ちでいっぱいですが、こういう知見を共有するのはいいことだし記事を書くのに時間かけてると本末転倒(楽しいけど)なので、良いことだな、、と文章の枕元にを妙に書いてしまう今日この頃ですがいかがお過ごしですか?

というわけで、タイトルの用にAmplify Gen1を使ってWEBアプリケーションの運用・保守を行なっているのですが、管理者画面からS3の特定のディレクトリにファイルをアップロードしたい、という要望がありました。要件を簡単にまとめると

  • webアプリでログインしてるユーザーの認証を使ってファイル操作をしたい(今回は特定のグループに所属してれば利用できる、という条件で実装しました)
  • バケットはamplify add storageしたものではなく、別途任意で作られたバケットを指定したい

という感じです。はじめの時点では「Amplify.configureに設定を追加してあげれば良いかな」と軽く考えてたんですが、configがそもそもamplifyconfiguration.jsonにない(add storageしてないんだからそれはそう。でもadd storageはしたくない)のでどうにもうまくいかなったです。で、考えてみたらStorageBrowser for AWS S3って独立したサービスページがあるくらいなので、別にAmplifyにこだわらずとも使えるのでは?という当たり前のことに気がつきました。
https://aws.amazon.com/jp/s3/features/storage-browser/

で、ドキュメントを読んでみるとカスタム認証やバケットの指定がそもそもできるのでAmplifyと切り離して設定を行うことができるわけです。
https://ui.docs.amplify.aws/react/connected-components/storage/storage-browser

ならそれで進めようとCursorとああでもないこうでもないと進めたところ下記の内容になりました。
アクセスできるようになってみるとStorageBrowser自体は大変便利ですね。

では以下にやったことをまとめてもらったのでそちらをご覧ください。

ーーーーここからーーーー

AWS AmplifyのStorageBrowserは、S3バケットのファイルをWeb UIで管理できる便利なコンポーネントです。Amplify CLIで管理されたバケット以外にも、既存のS3バケットカスタム認証と組み合わせて利用することができます。本記事では、Next.js(App Router)環境を例に、カスタム認証で既存バケットをStorageBrowserで操作する手順を解説します。


必要なパッケージのインストール

npm install aws-amplify @aws-amplify/ui-react-storage

Amplifyの基本設定

Amplify.configure()でCognitoなどの認証情報を設定します。
(この部分は通常のAmplify Authのセットアップと同じです)


StorageBrowser用のカスタム認証設定

Amplify StorageBrowserのcreateStorageBrowserに、カスタム認証用のconfigを渡します。

import { fetchAuthSession } from 'aws-amplify/auth'
import { createStorageBrowser } from '@aws-amplify/ui-react-storage/browser'

export function StorageBrowserComponent() {
  const { StorageBrowser } = createStorageBrowser({
    config: {
      listLocations: getS3Locations,
      getLocationCredentials: getLocationCredentials,
      registerAuthListener: () => () => {},
      region: 'ap-northeast-1', // 利用するリージョン
    },
  })

  return <StorageBrowser />
}

S3ロケーション情報の提供

listLocations関数で、ユーザーに見せたいS3バケットやプレフィックス(フォルダ)を返します。
各ロケーションにはidbucketprefixtypedisplayNamepermissionsを指定します。

async function getS3Locations() {
  return {
    items: [
      {
        id: 'example-folder',
        bucket: 'your-bucket-name',
        prefix: 'your-prefix/',
        type: 'PREFIX' as const,
        displayName: '表示名',
        permissions: ['delete', 'get', 'list', 'write'] as Array<'delete' | 'get' | 'list' | 'write'>,
      },
      // 必要な分だけ追加
    ],
    nextToken: undefined,
  }
}

S3アクセス用の一時認証情報の提供

getLocationCredentials関数で、Amplify Auth経由で取得した一時クレデンシャルを返します。

const getLocationCredentials = async (input: any) => {
  const session = await fetchAuthSession()
  if (!session.credentials) throw new Error('No credentials')
  return {
    credentials: {
      accessKeyId: session.credentials.accessKeyId,
      secretAccessKey: session.credentials.secretAccessKey,
      sessionToken: session.credentials.sessionToken || '',
      expiration: session.credentials.expiration || new Date(Date.now() + 3600000),
    },
    expiration: session.credentials.expiration || new Date(Date.now() + 3600000),
  }
}

S3バケットのCORS設定

S3バケットに以下のようなCORS設定を適用します。
AllowedOriginsは自分のアプリのURLに合わせて調整)

{
  "CORSRules": [
    {
      "AllowedHeaders": ["*"],
      "AllowedMethods": ["GET", "HEAD", "PUT", "POST", "DELETE"],
      "AllowedOrigins": [
        "http://localhost:3000",
        "https://your-app-domain.com"
      ],
      "ExposeHeaders": [
        "last-modified",
        "content-type",
        "content-length",
        "etag",
        "x-amz-version-id",
        "x-amz-request-id",
        "x-amz-id-2",
        "x-amz-cf-id",
        "x-amz-storage-class",
        "date",
        "access-control-expose-headers"
      ],
      "MaxAgeSeconds": 3000
    }
  ]
}

適用コマンド例:

aws s3api put-bucket-cors --bucket your-bucket-name --cors-configuration file://cors-policy.json

動作確認

  • アプリを起動し、StorageBrowser画面を開く
  • フォルダをクリックしてファイル一覧を表示
  • ファイルを選択し、アクションメニューから「Download」等の操作ができることを確認

まとめ

Amplify StorageBrowserは、カスタム認証と既存S3バケットの組み合わせでも柔軟に利用できます。
ポイントは「listLocations」「getLocationCredentials」のカスタマイズと、S3バケットのCORS設定です。


参考:

ーーーーここまでーーーー

実際にやってみたらそれほど大きな手間がかからずにUIを備えたファイル管理の仕組みが出来たのでこれは便利ですね。UI自体のカスタムも出来るみたいです。

というわけで、Amplifyで100万超えたユーザー数のウェブサービスを運用保守してるんですが、比較的Amplifyの箱庭の中でやれることは多いので、何かご依頼があれば気軽に こちらまで にご連絡ください。その際はこの記事を読んだよ、と教えてくれると話が早いと思います。

Discussion