アクセスキー無しでIAMロールだけでMATLABからAWSのS3ストレージにアクセスする方法

# MATLAB本体でできるクラウドストレージへのファイル読み込み・書き込み
**MATLAB** では本体機能(Toolbox 無し)で、Amazon の**S3** (Simple Storage Service)やAzure の**BLOB** ストレージといったクラウドのストレージサービスにアクセスできます。
近年のバージョンアップでクラウドストレージへの対応関数も強化されています。

全てではないですが、まとめると以下のとおりです。

* 読み込み
 * **datastore**、**imageDatastore**、**fileDatastore**、**tabluarTextDatastore** (R2017a～)
 * **readtable**、**imfinfo**、**imread** (R2018b～)
 * **readtimetable**、**readmatrix**、**readcell**、**parquetinfo**、**parquetread**、**parquetDatastore** (R2019a～) 
 * **audioread**、**audioinfo**、**h5disp**、**h5read** (R2020b～) 
 * **fopen**、**fread**、**load** (R2021a～)


* 書き込み
 * **write** (R2018b～)
 * **writetable**、**writetimetable**、**writematrix**、**writecell** 、**parquetwrite**、**imwrite** (R2019a～)
 * **audiowrite**、**h5write** (R2020b～)
 * **fwrite**、**save** (R2021a～)

* ファイル管理
 * **delete**、**dir**、**isfile**、**what** (R2019b～)

【参考】[MATLAB のリリースノート](https://jp.mathworks.com/help/matlab/release-notes.html)



# アクセスキーを設定するのがドキュメントの方法
現在の下記の公式ドキュメントだと、S3 にMATLAB からアクセスするためには、AWS で事前にIAM (Identity and Access Management) ユーザーを作成し、アクセスキーやシークレットアクセスキーを発行するのが手順となっています。

【MATLAB ドキュメント】[リモート データの操作](https://jp.mathworks.com/help/matlab/import_export/work-with-remote-data.html)

![s3_matlab_access_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/1a090ea9-273a-c501-4ce1-7656c82874c0.png)

この手順の後、MATLAB で環境変数として設定します。

    setenv('AWS_ACCESS_KEY_ID', 'XXXXXX');
    setenv('AWS_SECRET_ACCESS_KEY','YYYYYY'); 
    setenv('AWS_REGION', 'ap-northeast-1');

すると、

    t = readtable('s3://bucketname/filename.xlsx');

などでファイルを読み取ることができます。

ただ、組織によってはアクセスキーを使う方法よりも、IAM ロールをEC2 (Elastic Compute Cloud)に割り当てて運用したいという要望があると思います。

* クラウド外からアクセスさせずに、EC2 からだけのアクセスに絞りたい。
* バケット全てではなく特定のフォルダだけのアクセスに制約したい。
* 読み取り専用にしてストレージのオリジナルのファイルには影響しないで使いたい。
 
などの理由のためです。

そこでIAM ロールを使った方法でEC2 にインストールされたMATLAB からS3 にアクセスする方法をまとめてみました。
![s3_matlab_access_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/a3b996bf-5c15-929d-f8d6-0dec81fe63c4.png)


# IAMロールの設定
まず、EC2 のコンソール画面から、「IAM」をクリックし、「ロールを作成」をおこない、S3 にアクセスするためのロールを作成します。既存のロールを使う場合はここはスキップして大丈夫です。

# 必要なIAM ポリシー
次にIAM ロールにポリシーを割り当てます。読み取り専用か書き込みも可能にするかで必要な権限が変わります。以下の2 セクションでそれぞれに必要なポリシーを記載します。

## 読み取り専用のIAM ポリシー
まずは読み取りのみの権限の場合。ここではバケット「bucketname」のフォルダ「folder1」のファイル全てを読み取りできるポリシーとします。
MATLAB でS3 からのファイル読み取り必要な権限は、「s3:GetObject」が対象のフォルダ、「s3:ListBucket」と「s3:GetBucketLocation」が対象のバケットに必要となります。

ポリシーのJSON の例は以下のとおりです。bucketname とfolder1 は適宜置き換えてください。

    {
      "Version": "2012-10-17",
      "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/folder1/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::bucketname"
        }
      ]
    }

## 書き込みも可能なIAM ポリシー
次に書き込み(アップロード)も可能にするためのポリシーについて。ここではバケット「bucketname」のフォルダ「folder1」のファイル全てを読み取りでき、フォルダ「folder2」にファイルを書き込みもできるポリシーとします。

ポリシーのJSON の例は以下のとおりです。bucketname とfolder1、folder2 は適宜置き換えてください。

    {
      "Version": "2012-10-17",
      "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/folder1/*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::bucketname"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::bucketname/folder2/*"
        }
      ]
     }

# EC2にIAMロールを割り当て
続いて、設定したIAM ロールをEC2 に割り当てます。
対象のEC2 インスタンスを選択した状態で、「アクション」ボタンを押し下げ、「セキュリティ」→「IAM ロールを変更」をクリックし、設定したIAM ロールを指定します。

![ec2_change_iam_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/6430ea97-a85b-8923-25b5-fb5451692ba1.png)



EC2 インスタンスの情報に割り当てたIAM ロールが表示されます。
![ec2_assign_iam_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/65b7e87e-3101-5dd6-7344-3bee921294d8.png)

# EC2 のMATLAB からS3 のファイルを読み取り
そしてEC2 でMATLAB を起動します。もし既にMATLAB が起動した状態だったら、IAM ロールの割り当てを反映させるために一旦MATLAB を再起動します。

上記の「読み取り専用のIAM ポリシー」を割り当てたEC2 のマシンのMATLAB からS3 からのファイルアクセスを確認します。MATLAB のバージョンはR2021b で確認しています。
![after_iam_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/adc79866-efe7-2c9f-ce7d-8017a7b5154b.png)

無事にfolder1 に置いてあるCSV ファイルの中身が読めていますね。

# EC2 のMATLAB からS3 へファイル書き込み
続いてS3 へ書き込みをする場合について確認します。単にputObject を入れれば行けると思ったのですが、意外とハマりました。試行錯誤してもMATLAB からwritetable などでS3 にファイルをアップロードしようとすると、「<font color="red">Location 's3://bucketname/foldername/filename.csv' reequires credential. You must setup an AWS credentials file, or set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.</font>」というエラーが出てしまいます。

     dbstop if error

を掛けてからwritetable を実行してデバッグしてみると、**validateCloudEnvVariables.m** (＜MATLAB インストールフォルダ＞\toolbox\shared\virtualfileio\+matlab\+io\+internal\+vfs\+validators\validateCloudEnvVariables.m)
の中でAWS のクレデンシャルファイルがあるか、あるいは環境変数(AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEY)が設定されているかのチェックをしているのですが、ここでエラーが出ていました。

R2021b 時点では、IAM ロールだけで書き込もうとするとどうしてもエラーが出てしまうので、下記のスクリーンショットのように、error 文をコメントアウト(冒頭に%を付ける)ことで回避できます。あくまでもワークアラウンドになりますので、試される際は自己責任でお願いいたします。

![setting_iam_role_to_ec2_write.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/77f91511-1372-57af-0901-883b952acf20.png)

error 文をコメントアウトしてからwritetable でS3 にアップロードするとエラーが解消されました。
![setting_iam_role_to_ec2_write2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/19a559bc-7c98-0ff3-9438-550390d86073.png)


S3 側の画面でもアップロードされたCSV を確認できました。
![setting_iam_role_to_ec2_write3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/f080dcc0-8a7f-cd0e-67a8-dbd6b94d45ad.png)

続いて、アップロードされたCSV をMATLAB で読み取ったり、delete で削除したりしてみます。
![setting_iam_role_to_ec2_write4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254990/2a354d87-7775-1a1f-8e30-def7bee34fde.png)

全て問題なくできていますね。

# まとめ
アクセスキーを使わずにIAM ロールだけを使ってMATLAB からS3 にファイルを読み取り・書き込みする方法についてまとめました。読み取りの場合は上記「読み取り専用のIAM ポリシー」で設定したIAM ロールをEC2に付与すればできますし、書き込みもしたい場合は上記「書き込みも可能なIAM ポリシー」で設定したIAM ロールをEC2に付与し、さらにワークアラウンドでvalidateCloudEnvVariables.mを1行コメントアウトすれば実現できます。