【Snowflake】外部ステージを使うためになぜ統合ストレージを使用するのか

# 前置き
こんにちは。データエンジニアの山口歩夢です！



Snowflakeには外部ステージという機能があります。
こちらの機能を使うことで、S3やGCSなどのクラウドストレージに格納されているデータを、まるでSnowflakeのテーブルのようにクエリすることができます。

外部ステージ使用するときに、**統合ストレージ**というものも必要になるのですが、どうして必要なのか理解が浅かったので、こちらの記事でまとめてみることにしました。

#### 参考リンク

https://docs.snowflake.com/ja/user-guide/tables-external-intro

https://docs.snowflake.com/ja/user-guide/data-load-s3-config-storage-integration




# 本題
統合ストレージをどのように使用するのか、どうして必要になるのかなどを順番にまとめていきます！

## 統合ストレージの概要
統合ストレージがどういうものか簡潔に言うと、
Snowflakeからクラウドストレージ(S3など)のデータにアクセスするための権限を管理・保管するためのものです。

例えば、S3を操作できるようにするには、まず以下のようなS3の操作権限を持ったRoleを作成し、そちらをSnowflakeに与える必要があります。

#### Snowflakeに渡すS3操作権限の例
```S3の操作権限の例.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ListObjectsInBucket",
            "Effect": "Allow",
            "Action": ["s3:ListBucket"],
            "Resource": ["arn:aws:s3:::bucket-name"]
        },
        {
            "Sid": "AllObjectActions",
            "Effect": "Allow",
            "Action": "s3:*Object",
            "Resource": ["arn:aws:s3:::bucket-name/*"]
        }
    ]
}
```

このIAMロールを統合ストレージに保管し、
外部ステージにこの統合ストレージを指定することで、Snowflakeに対してSnowflakeからS3バケットにアクセス可能な権限を渡すことができるんだなと解釈しました。


以下のクエリで統合ストレージを作成することができます。
```create_storage_integration.sql
CREATE STORAGE INTEGRATION [統合ストレージ名]
  TYPE = EXTERNAL_STAGE
  STORAGE_PROVIDER = S3
  ENABLED = TRUE
  STORAGE_AWS_ROLE_ARN = 'S3にアクセスするための権限を付与したIAMのARN'
  STORAGE_ALLOWED_LOCATIONS = ('s3://<データレイクとなるS3バケット>');
```

https://docs.snowflake.com/en/sql-reference/sql/create-storage-integration

## Snowflakeに権限を渡すための前準備
Snowflakeに権限を渡す方法は、AWSのS3を使用する場合だとAssumeRoleでAWSからSnowflakeに対してS3の操作権限を受け渡すかたちになります。

まずは、以下のコマンドを実行することで、統合ストレージの設定内容を確認することができます。
```bash
$ desc integration
```

SnowflakeにS3(外部ステージ)へのアクセス権限を渡すために、
上記のクエリを実行して出力される`STORAGE_AWS_IAM_USER_ARN`と`STORAGE_AWS_EXTERNAL_ID`を使用します。

`STORAGE_AWS_IAM_USER_ARN`と`STORAGE_AWS_EXTERNAL_ID`を使って、
S3操作権限を所持しているIAMロールの**信頼されたエンティティ**を以下のように書き換えます。

```信頼されたエンティティ.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "[STORAGE_AWS_IAM_USER_ARN]"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "[STORAGE_AWS_EXTERNAL_ID]"
        }
      }
    }
  ]
}
```
Snowflake側のIAMユーザー（`STORAGE_AWS_IAM_USER_ARN`)が、AssumeRoleで外部ステージとして使用するS3の操作権限を受け取れるように設定していることが分かります。

`STORAGE_AWS_EXTERNAL_ID`はAWSのExternal Idのことで、セキュリティの向上のために使用しています。
ユーザーの一意のIDで、IAMロールのARNが外部に漏れてしまった場合になど不正アクセスされないように設定しておくものです。

https://dev.classmethod.jp/articles/iam-role-externalid/




## 統合ストレージと外部ステージを紐付ける
そして最後に統合ストレージを指定して、外部ステージを作成すれば統合ストレージと外部ステージの紐付けが完了します。
先ほどS3の操作権限を入れておいた統合ストレージを外部ステージに指定することで、SnowflakeにS3の操作権限の付与が完了し、SnowflakeがS3を外部ステージとして使用できるようになります。

```create_external_stage.sql
create stage [ステージの名称]
  url='統合ストレージ作成時に指定したS3バケット'
  storage_integration = [作成した統合ストレージ];
```

# まとめ
S3などの外部のクラウドストレージを操作するための権限を管理し、Snowflakeに対してその権限を受け渡しするために、統合ストレージを使用するんだなと言うことが理解できました！






# 最後に宣伝
この度、5/25~の技術書典16に向けて、Streamlitの入門書を執筆しました！

Streamlitについて、基本的な内容から実践的な内容、自分が開発する上で躓いたポイントやTipsなどを書かせていただきました。

また最新のアップデートで追加された機能なども一部紹介してあります。
是非、チェックいただけると幸いです。


https://techbookfest.org/product/t5GBwbFm4kUhXrTPkGpAnY?utm_source=twitter&utm_medium=social&utm_campaign=share