Snowflake S3データロード：①ストレージ統合

[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)
　
### ■本記事の目的
Snowflakeのデータロードを理解する。
ユーザー管理のAmazonS3からSnowflakeにデータロードを行います。
S3バケットとフォルダおよび取込用のテストデータ（CSV形式）は、事前に作成済みとします。

### ■概要
ストレージ統合を作成していきます。
ストレージ統合とは、SnowflakeとS3の間のセキュアアクセスを行うための
認証情報とストレージの所在の定義とご理解いただけると良いと思います。
また、Snowflake,ユーザー管理のAWSの双方で、セキュリティに関する設定を行っていきます。

### ■AmazonS3のARNとURIを取得する。
ユーザー管理のAWSでの作業です。
　
Snowflakeからデータロードに使用するAmazonS3のARNとURIを取得します。
　
ARNを取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/bf392772-5520-d82e-8512-b629faa4e08a.png)

```
arn:aws:s3:::<バケット>/<フォルダ>/
```
　
URIを取得する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/aa5dacae-fd06-e22f-cb2b-0a050bcb5f24.png)
```
s3://<バケット>/<フォルダ>/
```

### ■AWS IAMポリシーを作成する。
ユーザー管理のAWSでの作業です。
　
任意の名前で、IAMロールに割り当てる用のIAMポリシーを作成します。
バケット名およびフォルダ名は、任意のS3の所在で埋めてください。
　
読み取り専用の場合は、以下のJSONでIAMポリシーを作成します。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
              "s3:GetObject",
              "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::<バケット>/<フォルダ>/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::<バケット>",
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "<フォルダ>/*"
                    ]
                }
            }
        }
    ]
}
```
　
ロード/アンロードの両方で利用する場合は、以下のJSONでIAMポリシーを作成します。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
              "s3:PutObject",
              "s3:GetObject",
              "s3:GetObjectVersion",
              "s3:DeleteObject",
              "s3:DeleteObjectVersion"
            ],
            "Resource": "arn:aws:s3:::<バケット>/<フォルダ>/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::<バケット>",
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "<フォルダ>/*"
                    ]
                }
            }
        }
    ]
}
```

### ■AWS IAMロールを作成する。
ユーザー管理のAWSでの作業です。
　
Snowflakeのストレージ統合で、利用するためのIAMロールを作成します。
　
IAMからロールを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/80f77909-8aff-6cd1-4316-eb16c7d57762.png)

信頼されたエンティティタイプ＞AWSアカウントを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/17922d11-f2a0-d685-bb42-dc68450b9c46.png)

AWSアカウント＞仮置で、このアカウントを選択
オプション＞外部IDにチェック＞仮置で、4桁の0を入れる。
※後ほど、いずれの値も信頼関係で書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/3fc30022-098c-62b8-e9ee-47a469af257a.png)
　
許可ポリシーは、前段で作成したIAMポリシーを割り当ててください。
　
管理しやすい任意の名前で、IAMポリシーを作成してください。
　
作成後、ロールARNを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/7238dcde-17f6-491a-97b4-81081a960106.png)
```
arn:aws:iam::<アカウントID>:role/<ロール>
```


### ■ストレージ統合を作成する。
Snowflakeアカウントに戻ります。
　
S3の場合は、以下の構文でストレージ統合を作成します。
デフォルトでは、アカウント管理者が作成できます。
別のロールに作成させる場合は、ストレージ統合作成権を、別途割り当ててください。
```
use role ACCOUNTADMIN;

create storage integration <ストレージ統合>
type=EXTERNAL_STAGE --外部ステージ
storage_provider='S3' --ストレージのクラウドプロバイダ名
enabled=TRUE --有効化
storage_aws_role_arn='arn:aws:iam::<アカウントID>:role/<ロール>' --IAMロールのARN
storage_allowed_locations=('s3://<バケット>/<フォルダ>/') --許可するS3のバケットおよびフォルダのURI
;

例）
use role ACCOUNTADMIN;
create storage integration TEST_INTEG
type=EXTERNAL_STAGE
storage_provider='S3'
enabled=TRUE
storage_aws_role_arn='arn:aws:iam::123456789098:role/ROLE_SF_S3'
storage_allowed_locations=('s3://backet_name/folder/')
;
```
　
### ■ストレージ統合使用権を、外部ステージ作成者のロールに付与する。
後ほど、外部ステージを作成する際、ストレージ統合使用権がないと
外部ステージを作成できないため権限を付与します。
```
use role ACCOUNTADMIN;
grant usage on integration <ストレージ統合> to role <ロール>;
```



### ■ストレージ統合の情報を取得する。
作成後、以下の構文でストレージ統合の情報を照会します。
```
describe integration <ストレージ統合>;
```

照会後の出力から赤枠内のSnowflakeアカウントの
STORAGE_AWS_IAM_USER_ARNおよびSTORAGE_AWS_EXTERNAL_IDの値を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/54260905-701d-c10c-b9c2-8315ee3c61c6.png)
STORAGE_AWS_IAM_USER_ARN：SnowflakeアカウントのIAMユーザー
STORAGE_AWS_EXTERNAL_ID：上記IAMユーザーが利用する外部ID

### ■ストレージ統合の情報をAWS IAMロールの信頼関係に連携する。
ユーザー管理のAWSに戻ります。

前段で作成したロールを参照し、信頼関係を展開＞信頼ポリシーの編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/216048b3-3674-4fd7-7b4e-8920f28749fc.png)
　 ↓↓↓↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/4b3dabdc-fee9-84c5-29a5-2e06402a2f40.png)

　
ストレージ統合の照会から取得した2点を使用し、以下<>を書き換えてください
```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": "<STORAGE_AWS_IAM_USER_ARN>"
			},
			"Action": "sts:AssumeRole",
			"Condition": {
				"StringEquals": {
					"sts:ExternalId": "<STORAGE_AWS_EXTERNAL_ID>"
				}
			}
		}
	]
}
```
　
書き換えたら、ポリシーを更新します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731433/0668bff7-4cd6-7a4a-3669-b938cba408fc.png)

### ■ストレージ統合の変更の注意点
ストレージ統合のステータス変更を行う場合は、ALTER STORAGE INTEGRATIONを使用しましょう。
CREATE OR REPLACE STORAGE INTEGRATIONを行うと、実行毎に外部IDが切り替わるため、再度IAMロールの信頼ポリシーを更新する必要があります。

### ■あとがき
一貫して、認証情報の動作確認まで行いたかったのですが、
外部ステージを作成する必要があるため、今回はここまでとします。

### ■次の記事
[Snowflake S3データロード：②ファイル形式](https://qiita.com/taku_tachibana/items/6ca0f9a49158260c1e39)
　
[目次に戻る](https://qiita.com/taku_tachibana/items/408686a031b9624e981e)