Azure Synapse Analytics SQLプールの外部テーブルにおける認証方式について

## 1.概要
Azure Synapse AnalyticsのSQLプールは、外部テーブルでAzure Storage Blob（以下、ストレージ）に格納されているデータファイルを参照することができます。この記事は外部テーブルを作成する際に指定する認証方式（CREDENTIAL）を説明します。

※本記事の内容はストレージ側のネットワーク設定において、「すべてのネットワークから有効」に設定していることが前提です。
※本記事の内容は専用SQLプールと、サーバレスSQLプールの両方を対象としていますが、区別する場合はその旨を明記します。


**まずは結論:**
・ストレージのコンテナはアクセスレベルが**パブリックアクセス**になっている場合、資格情報が必要なく、データファイルをアクセスすることが可能です。そのため、外部テーブルの定義に認証方式を指定しなくても問題ありません。

:::note warn
この時は、データファイルのパスを知っていれば誰でもアクセスができてしまう点にご注意ください。
:::

・ストレージのコンテナはアクセスレベルが**プライベート**になっている場合、資格情報が必要になります。外部テーブルの定義では、利用したい認証方式（User Identity/SAS/Service principal/Managed Identity)を指定する必要があります。

:::note warn
・User Identity/Service principal/Managed Identityを利用する時は、ストレージにおけるRBAC権限を持つ必要があります。
・User Identity方式は現時点、サーバレスSQLプールのみに対応しており、専用SQLプールは対応していません。
:::



## 2.Azure Synapse Analytics SQLプールの外部テーブルとは

外部テーブルについての説明は、詳細は次の公式ドキュメントにて記述しています。
[Synapse SQL で外部テーブルを使用する](https://learn.microsoft.com/ja-jp/azure/synapse-analytics/sql/develop-tables-external-tables?tabs=hadoop#external-tables-in-dedicated-sql-pool-and-serverless-sql-pool)

>外部テーブルは、Hadoop、Azure Storage BLOB、または Azure Data Lake Storage にあるデータを参照します。 Azure Storage 内のファイルからデータを読み取ったり、ファイルにデータを書き込んだりするために、外部テーブルを使用できます。

イメージとしては、ストレージに格納しているデータを参照したり、SQLプールにインポートしたりすることができます。

## 3.テストデータ
使用するテストデータは以下のような、４列のデータからから構成するcsvファイルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/ae4df750-0366-3ae6-2324-2f1abd333b3a.png)


## 4.外部テーブルを作成するサンプルコード
マスタキーを作成
```
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<Password>' ;
```

ファイルフォーマットを作成

```
CREATE EXTERNAL FILE FORMAT [SynapseDelimitedTextFormat] 
WITH ( FORMAT_TYPE = DELIMITEDTEXT ,
	       FORMAT_OPTIONS (
			 FIELD_TERMINATOR = ',',
			 USE_TYPE_DEFAULT = FALSE
));
```

外部データソースを作成
```
CREATE EXTERNAL DATA SOURCE ＜external data source name>
WITH
  ( LOCATION = 'wasbs://<container name>@<storage account name>.blob.core.windows.net/' ,
    CREDENTIAL = <Authorization type>,※省略可能
    TYPE = HADOOP
  ) ;
```

外部テーブルを作成
```
  --create external table
CREATE EXTERNAL TABLE <external table name> (
	[C1] nvarchar(4000),
	[C2] nvarchar(4000),
	[C3] nvarchar(4000),
	[C4] nvarchar(4000)
	)
	WITH (
	LOCATION = '/<file name>.csv',
	DATA_SOURCE = ＜external data source name>,
	FILE_FORMAT = [SynapseDelimitedTextFormat]
);
```

## 4.認証方式の種類と設定方法

###### 4.1 コンテナはパブリックアクセスの場合

アクセスレベルを「コンテナ」にすると、パブリックアクセスになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/895bb3e8-91b3-e7d2-27e1-d03d0e507b39.png)

この場合は冒頭で述べた通り、資格情報が必要なく、ファイルパスを知っていれば誰でもアクセスができてしまいます。
ここで試として、コンテナ内にあるファイルのフルパス（https://xxx.blob.core.windows.net/container/xxx.csv）
をブラウザのURL欄に入力すると、対象ファイルがダウンロードされることが確認できます。

コンテナは資格情報無しでアクセスができるようになったため、
外部データソースの定義において、CREDENTIALの指定は省略しても問題ありません。


```
CREATE EXTERNAL DATA SOURCE ＜external data source name>
WITH
  ( LOCATION = 'wasbs://<container name>@<storage account name>.blob.core.windows.net/' ,
    --CREDENTIAL = <Authorization type>, ←省略します
    TYPE = HADOOP
  ) ;
```

###### 4.2 コンテナはプライベートアクセスの場合
アクセスレベルを「プライベート」にすると、プライベートアクセスになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/3e60918f-5b4c-a44e-4aff-05aa4bdec757.png)

この場合は、コンテナ内のデータを参照するために資格情報が必要になります。
外部データソースの定義にて、利用したい認証方式（User Identity/SAS/Service principal/Managed Identity)を指定する必要があります。


* **User Identity方式**


操作ユーザにはストレージアカウントのRBACロール、「ストレージ BLOB データ所有者」、「ストレージ BLOB データ共同作成者」、または「ストレージ BLOB データ閲覧者」ロールを付与している必要があります。


利用方法：外部データソースの定義でCREDENTIALを省略することで、User Identity方式になります。操作ユーザのMicrosoft Entra IDは認証に使われます。

:::note warn
User Identity方式は現時点、サーバレスSQLプールのみに対応しており、専用SQLプールは対応していません。
:::

ユーザにストレージアカウントのRBACロールを付与していない場合は、
作成した外部テーブルに対してクエリをすると、下記のエラーメッセージが表示されます。

>External table 'dbo.extablewithoutCR' is not accessible because location does not exist or it is used by another process.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/b289c637-e642-d293-512a-9d80f2e1f8e9.png)


RBACロールを付与している場合は成功します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/91de54a5-f5c4-0d10-1200-06bdbb5d3954.png)


* **SAS方式**
SASを利用する場合は、操作ユーザにストレージアカウントのRBACロールを付与する必要がありません。

利用方法：
```
--クレデンシャルにSASを指定する
--SAS
CREATE DATABASE SCOPED CREDENTIAL [ADLS_credential_SAS]
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = '<SAS Token>';

-- Create an external data source [with] CREDENTIAL_SAS option.
CREATE EXTERNAL DATA SOURCE exdatawithCR_SAS
WITH
  ( LOCATION = '<location path>',
    CREDENTIAL = [ADLS_credential_SAS]
	);


--create external table
CREATE EXTERNAL TABLE dbo.extablewithCR_SAS (
	[C1] nvarchar(4000),
	[C2] nvarchar(4000),
	[C3] nvarchar(4000),
	[C4] nvarchar(4000)
	)
	WITH (
	LOCATION = '/<filename>.csv',
	DATA_SOURCE = exdatawithCR_SAS,
	FILE_FORMAT = [SynapseDelimitedTextFormat]
);
```


* **Managed Identity方式**

Managed Identity方式は、操作ユーザにストレージアカウントのRBACを付与する必要がありませんが、
外部テーブルを作成する時点で、Synapse WorkspaceのManaged IdentityにストレージアカウントのRBACロールを付与している必要があります。
必要なロールは上述同様。（「ストレージ BLOB データ所有者」、「ストレージ BLOB データ共同作成者」、または「ストレージ BLOB データ閲覧者」）

利用方法：

```
--クレデンシャルにmanaged Identityを指定する
--Managed Identity
CREATE DATABASE SCOPED CREDENTIAL [ADLS_credential_managedID]
WITH IDENTITY = 'Managed Identity';

-- Create an external data source [with] CREDENTIAL_managedID option.
CREATE EXTERNAL DATA SOURCE exdatawithCR_managedID
WITH
  ( LOCATION = 'abfss://<container name>@<storage account name>.dfs.core.windows.net',
    CREDENTIAL = [ADLS_credential_managedID],
    TYPE = HADOOP
  ) ;

--create external table
CREATE EXTERNAL TABLE dbo.extablewithCR_managedID (
	[C1] nvarchar(4000),
	[C2] nvarchar(4000),
	[C3] nvarchar(4000),
	[C4] nvarchar(4000)
	)
	WITH (
	LOCATION = '/<file name>.csv',
	DATA_SOURCE = exdatawithCR_managedID,
	FILE_FORMAT = [SynapseDelimitedTextFormat]
);
```

Synapse WorkspaceのManaged IdentityにストレージアカウントのRBACロールを付与していない状態で、外部テーブル作成のクエリを実行すると、下記のエラーメッセージが表示されます。
>External file access failed due to internal error: 'Error occurred while accessing HDFS: Java exception raised on call to HdfsBridge_IsDirExist. Java exception message:
HdfsBridge::isDirExist - Unexpected error encountered checking whether directory exists or not: AbfsRestOperationException: Operation failed: "This request is not authorized to perform this operation using this permission.", 403, HEAD, https://jessestorage1220.dfs.core.windows.net/container/productpart1220.csv?upn=false&action=getStatus&timeout=90'
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367780/6183a514-ad11-8338-b5ba-9e4cf67b0ad4.png)

RBACロールを付与している場合は成功します。



## 5.最後
今回は、Azure Synapse Analytics SQLプールの外部テーブルにおける認証方式を紹介しました。
以下、おさらいします。
コンテナがパブリックアクセスの場合は、
資格情報が必要ありません。外部データソースのクレデンシャルを指定しなくとも、アクセスできます。

コンテナがプライベートアクセスの場合は、
資格情報が必要です。外部データソースのクレデンシャルに、利用したい認証方式を指定します。

* User Identity方式：　操作ユーザにストレージアカウントのRBACロールを付与する必要あります。
* Managed Identity方式：　Synapse WOrkspaceのmanaged IdentityにストレージアカウントのRBACロールを付与する必要があります。
* SAS方式：　ストレージアカウントのRBACロールは特に必要がありません。

サービスプリンシパル方式については次回紹介します。


参考資料：
- [CREATE EXTERNAL DATA SOURCE (Transact-SQL)](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-external-data-source-transact-sql?view=azure-sqldw-latest&preserve-view=true&tabs=dedicated)

- [Control storage account access for serverless SQL pool in Azure Synapse Analytics](https://learn.microsoft.com/en-us/azure/synapse-analytics/sql/develop-storage-files-storage-access-control?tabs=user-identity#supported-authorization-types-for-databases-users)