🐥

異なるAWSアカウントのs3からデータを取得する方法

2024/12/15に公開

この記事はPREVENTアドベントカレンダーの15日目の記事です。

はじめに

株式会社PREVENTの永田です。
社内で実際にあった課題とその解決方法を紹介します。
主に、解決方法として使ったs3のクロスアカウント設定の部分について書きたいと思います。

前提

AシステムとBシステムは、以下のような状況です。

  • AWS Organizationでアカウントが分かれています。
  • ECS Fargate上で動かしています。

課題

「Aシステムでファイルを一度ダウンロードして手動でzip化し、Bシステムにそのファイルをアップロードすることで顧客へ提出する」という作業があり、作業コストとファイルのアップロード間違いというヒューマンエラーリスクが課題となっていました。

解決方法

Aシステムでzip化したファイルをs3に保存し、Aシステムのs3のデータをBシステムから取得することで解決しました。

クロスアカウント設定について

Aシステム

IAMからs3アクセスのポリシーをアタッチしたロールを作成します。

画像ではAmazonS3FullAccessになっていますが、状況に応じて必要なs3アクセスポリシー(取得だけであれば「AmazonS3ReadOnlyAccess」だけで良いです。)をアタッチしてください。

信頼関係に、BシステムのEcsTaskRoleのarnを追加します。

フロントエンドのソースコード

s3から取得したファイルのURLとフロントエンドのoriginが一致しないため、blobに変換してからダウンロードしました。

import toast from 'react-hot-toast'

// s3から取得したファイルのURLとフロントエンドのoriginが一致しないため、blobに変換してからダウンロード
export const downloadS3FileAsBlob = (s3FileUrl: string, fileName: string) => {
  fetch(s3FileUrl)
    .then((response) => {
      if (response.ok) return response.blob()
      throw new Error('Network response was not ok.')
    })
    .then((fileBlob) => {
      const url = window.URL.createObjectURL(fileBlob)
      const a = document.createElement('a')
      a.href = url
      a.download = fileName
      document.body.appendChild(a)
      a.click()
      window.URL.revokeObjectURL(url)
      toast.success('ファイルのダウンロードを開始しました。')
    })
    .catch((error) => {
      console.error(error)
    })
}

Bシステム

Aシステム側で作成したroleのarnをリソースにしたポリシーを作成します。

EcsTaskRoleに上記のポリシーをアタッチします。

以上でAWS上の設定は完了です。

Bシステムのソースコード

ASystemRoleArnに、Aシステムのarnを設定してあげることで、s3からデータ取得が可能となります。
弊社ではGolangを利用しているため、Golangのサンプルコードになります。

func NewS3ASystemRole() *s3.S3 {
	var cfgs []*aws.Config

	cfgs = append(cfgs, &aws.Config{
		Region: aws.String("ap-northeast-1"),
	})

	sess, err := session.NewSession(cfgs...)
	if err != nil {
		log.Fatalf("Failed to create session: %s", err)
	}

	creds := stscreds.NewCredentials(sess, config.Conf.ASystemRoleArn)

	return s3.New(sess, &aws.Config{Credentials: creds})
}

最後に

主にAWSのクロスアカウント設定について書かせていただきました。
誰かの助けになると嬉しいです。また、他に良い解決方法があれば教えていただけるとありがたいです。

Discussion