この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
福岡オフィスの梶原です。
AWSのドキュメントで公開されているJavascriptによるサンプル
ブラウザから Amazon S3 への写真のアップロード
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/s3-example-photo-album.html
を参考に、作成対象のAWSのリソースをCloudFormation化したので公開します。
※注意
Cognitoの未認可で割り当てられるRoleについては、アクセス元のIPアドレスだけで制限をかけていますがテンプレートのデフォルトのパラメータ0.0.0.0/0
では
世界中のすべてのユーザーに、バケット、およびバケット内のすべてのオブジェクトへの書き込みアクセス許可が付与されますので、制限がかからない状態になりますので、アクセス元のIPアドレスを設定するか、
実際に使用する場合はCognitoの認証を用いて、認証されているユーザに対しては書込み、認証されていないユーザは読み込みのみなどの権限を適切に割り当ててください。
構成図
環境構築
CloudFormationの実行
- 作成するバケット(Website用)
- アップロード先のバケット名
- IP制限用のIPアドレス
を入力して、CloudFormationのテンプレートを実行してください。
IAMロールを作成するため
□AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。
にチェックを入れて実行します。
S3バケット(Webサイト)、S3バケット(アップロード)、Cognito ID プール, IAMRoleが作成されます。
HTML, Javascriptの配置
index.hmtl, javascriptを取得します。 (githubに上げてますのでご参照ください)
git clone https://github.com/ambasad/javascript-s3-upload-cfn.git
cd javascript-s3-upload-cfn/website/
Javascriptの編集
app.jsの
- アップロード先のバケット名
- Cognito ID プールを変更します。
IdentityPoolIdは、CloudFormationの出力またCognitoのコンソールから確認できます。
https://ap-northeast-1.console.aws.amazon.com/cognito/federated?region=ap-northeast-1
var albumBucketName = 'js-album-upload-bucket'; <== バケット名
var IdentityPoolId = 'ap-northeast-1:XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX';
HTML, Javascriptの配置
S3BucketWebsite=js-album-website <== (CloudFormationのパラメータで指定したWebsite用のバケット名)
# S3 へHTMLとjavascriptを配置します(--dryrun)
aws s3 sync . s3://$S3BucketWebsite --acl public-read --dryrun
(dryrun) upload: ./app.js to s3://js-album-website/app.js
(dryrun) upload: ./index.html to s3://js-album-website/index.html
# S3 へHTMLとjavascriptを配置します
aws s3 sync . s3://$S3BucketWebsite --acl public-read
upload: ./index.html to s3://js-album-website/index.html
upload: ./app.js to s3://js-album-website/app.js
配置後
http://バケット名.s3-website-ap-northeast-1.amazonaws.com
にアクセスしてみてください。特にエラーが表示されず
の画面が正常に表示されていれば、javasciptは正常に動作しており 各ボタンを押下することにより、
Create New Album
(S3バケットへフォルダ作成)Add Photo
(S3バケットへファイルを保存)X
(フォルダ or ファイルを削除)
等が実施されます。 可能であれば、アクセス元のIPアドレスを変更して同じ動作をしてみてください。SDKの実行時にAccess Deniedになるかと思います。 (読み取りはpublicReadにより可能ですのでアップロードする画像についてはご注意ください) プログラムの内容については、参考元に詳細は記載されていますので、割愛させて頂きます。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/s3-example-photo-album.html
まとめ
コンソールでCognitoの認証周りの動作確認をするために、いくつか作っていたのですが 何度も環境を作るのが面倒だったのでCloudFormation化しました。次回はCognitoと連携させてみたいと思います。
参考
CloudFormation で Cognito
https://qiita.com/y13i/items/1923b47079bdf7c44eec
CloudFormation Template
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
S3BucketNameUpload:
Type: String
Default: js-album-upload-bucket
Description: S3 BucketName for Upload
S3BucketNameWebsite:
Type: String
Default: js-album-website
Description: S3 BucketName for Website
SourceIp:
Type: String
Default: 0.0.0.0/0
Description: Allow S3 Bucket IpAddress ex. 10.0.48.0/32
Resources:
# S3 Bucket (Upload)
S3BucketUpload:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref S3BucketNameUpload
AccessControl: PublicRead
CorsConfiguration:
CorsRules:
- AllowedOrigins: ['*']
AllowedMethods: [POST, GET, PUT, DELETE, HEAD]
AllowedHeaders: ['*']
# S3 Bucket (Website)
S3BucketWebsite:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref S3BucketNameWebsite
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: "index.html"
# IAM Role
UnauthenticatedRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: cognito-identity.amazonaws.com
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: !Ref CognitoIdentityPool
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: unauthenticated
Policies:
- PolicyName: "Allow-S3-Policy"
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:*
Resource:
- !Sub arn:aws:s3:::${S3BucketUpload}/*
Condition:
IpAddress:
aws:SourceIp:
- !Ref SourceIp
- PolicyName: "CognitoRole"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- mobileanalytics:PutEvents
- cognito-sync:*
Resource: '*'
# Cognite ID pool
CognitoIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
AllowUnauthenticatedIdentities: true
CognitoIdentityPoolRoleAttachment:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId: !Ref CognitoIdentityPool
Roles:
unauthenticated: !GetAtt [UnauthenticatedRole, Arn]
Outputs:
WebsiteURL:
Value: !GetAtt [S3BucketWebsite, WebsiteURL]
Description: URL for website hosted on S3
CognitoIdentityPool:
Value: !Ref CognitoIdentityPool
Description: Cognito IdentityPool Id
UploadBucketName:
Value: !Ref S3BucketUpload
Description: Upload BucketName
WebsiteBucketName:
Value: !Ref S3BucketWebsite
Description: Website BucketName