Azure Data Factory(ADF)でADLS Gen2からAzure SQL Databaseへデータを移動するパイプラインは、Linked Serviceの認証設計で「セキュリティ」「運用コスト」「障害時の切り分け」が大きく変わります。スケジュールトリガーが誰の権限で動くのか、長期運用で推奨されるマネージドID中心の設計と、具体的な権限付与までまとめます。
まず押さえる:ADFパイプラインの「実行主体」と「接続主体」は別物
ADLS Gen2→Azure SQLのコピーで混乱が起きやすいのは、ADFには大きく2種類の権限が関わるからです。
| 観点 | 何を決める? | 関係する場所 | よくある誤解 |
|---|---|---|---|
| オーケストレーション(起動・スケジュール) | いつ誰がパイプラインを起動できるか | ADF(トリガー、パイプライン、Integration Runtime) | 「開発者のRBACがないとスケジュール実行できない」 |
| データアクセス(読み書き) | ADLS/SQLに“誰として”接続するか | Linked Service(認証方式) | 「トリガー用のサービスプリンシパルが必要」 |
ADFのパイプラインは、手動実行だけでなくトリガー(スケジュール等)でも実行できます。トリガーで起動された実行は“ADFサービスとして”動作するため、開発者PCとは独立して走ります。したがって、日々の安定稼働を左右するのは「誰がトリガーを作れるか」よりも、Linked Serviceが使う認証主体に必要な権限が付いているかです。
質問1:トリガー実行のためにサービスプリンシパルは必須?
結論:必須ではありません。 スケジュールトリガーでの実行そのものに「専用のサービスプリンシパルがないと動かない」という前提はありません。
ただし、次のようなケースでは“ADFを操作するためのID”としてサービスプリンシパル(または別のマネージドID)が登場します。
- Azure DevOps / GitHub Actions などのCI/CDから、ARM/BicepやREST APIでADFへデプロイする
- 外部アプリ(Function Apps等)からADFのパイプラインを起動する(管理APIを呼ぶ)
- 別テナントのリソースへアクセスする必要がある
これは「デプロイや起動の自動化のため」のIDであり、「スケジュールトリガーのため」の必須要件ではありません。なお、ADFでトリガーやLinked Serviceを作成・公開(Publish)するには、一般にリソースグループ以上の権限でData Factory Contributor(またはContributor相当)が必要です。
質問2:Account Key+SQL認証のまま、個人RBACなしでもトリガーで動く?
結論:技術的には動きます。 いま設定している「ADLS Gen2=アカウントキー」「Azure SQL=SQL認証(ユーザー名+パスワード)」は、Linked Serviceに保存された資格情報で接続するため、開発者の個人RBACがなくても、資格情報が有効でネットワーク的に到達できる限りスケジュールトリガーは実行されます。
ただし、運用していると次の条件で“ある日突然失敗する”ことがあります。
| チェック項目 | OKの条件 | 失敗パターン例 | 対策の方向性 |
|---|---|---|---|
| 資格情報の有効性 | アカウントキー/SQLパスワードが期限切れ・無効化されない | セキュリティ対応でキー再生成→ADF未更新で失敗 | Key Vault参照+ローテ運用、またはマネージドID化 |
| ネットワーク到達性 | ストレージ/SQLのFirewallやPrivate Link設定がADF実行経路を許可 | Firewall厳格化→トリガー時だけ到達できず失敗 | マネージドVNet/Managed private endpointの検討 |
| DebugとTriggerの差 | 公開済み(Publish済み)の定義で実行できる | Debugでは動くがTriggerでは失敗(未Publish/パラメータ差) | Monitorで差分確認、Publish徹底、パラメータ管理 |
特に「Debugでは成功するのに、スケジュールトリガーだと失敗する」は現場で頻出です。多くの場合は、Publish漏れ、トリガー実行時のパラメータの解決差、実行時権限(Linked Service/マネージドID)不足、実行タイミングでファイルが存在しないなどが原因になります。
質問3:長期運用でセキュアに動かすなら、どの認証方式が良い?
選定の軸はシンプルで、「秘密情報(キー/パスワード/シークレット)を持ち続ける運用を避けられるか」です。可能なら、ADFのマネージドID(Managed Identity)を中心に設計するのが推奨です。
| 方式 | セキュリティ | 運用負荷 | 向いているケース | 注意点 |
|---|---|---|---|---|
| Account Key(ADLS)+SQL認証 | 低〜中(漏洩時の影響が大きい) | 高(ローテ・更新・監査が必要) | 短期検証、既存都合でEntra認証が使えない | キー/パスワードは“強い権限”になりがち |
| サービスプリンシパル(SPN) | 中(シークレット/証明書を管理) | 中(期限管理・更新が必要) | 別テナント、外部連携、マネージドID未対応先 | 秘密情報ゼロにはできない |
| マネージドID(SAMI/UAMI) | 高(秘密情報を保持しない) | 低(ローテ不要、失効管理が少ない) | 同一テナント内のAzureリソース連携、長期運用 | 権限設計(RBAC/ACL/DBロール)が重要 |
今回の前提(ADF→ADLS Gen2→Azure SQL、同一テナント内、スケジュールで長期運用)なら、マネージドID+最小権限が最も“長持ちする”選択になります。
マネージドIDを選ぶと何が嬉しいのか
マネージドIDは、Azureサービスに「Microsoft Entra ID(旧Azure AD)上のID」を割り当て、下流サービスに対してトークンで認証する仕組みです。シークレットやパスワードをADFの設定に保存しないため、次のメリットが出ます。
- 資格情報の漏洩リスクを下げられる(秘密情報が残らない)
- キー/パスワードのローテーション作業が不要
- スケジュールトリガーの実行時も同じIDで安定して動く
- Key Vaultを使う場合も、Key VaultへのアクセスにマネージドIDを使える
さらに、ADFのマネージドIDは大きく2種類あります(システム割り当てとユーザー割り当て)。
| 種類 | 特徴 | おすすめ用途 | 注意点 |
|---|---|---|---|
| システム割り当て(System-assigned) | ADFリソースに紐づく。ADF削除でIDも削除。 | 単一ADFで完結する運用、まず最初の導入 | ADFを作り直すとIDが変わり、権限付け直しになる |
| ユーザー割り当て(User-assigned) | IDが独立リソース。複数リソースで共有可能。 | IaCで作り直す環境、複数ADFで同じIDを使いたい | IDをADFに割り当てる運用と権限管理が別になる |
質問4:マネージドIDを使う場合、ADLSとAzure SQLにどう権限を割り当てる?
ここからが実務の肝です。ADLS Gen2はRBACとACLの組み合わせ、Azure SQLはEntra管理者設定+DBユーザー作成がポイントです。
ADLS Gen2:RBAC(IAM)とACLをセットで設計する
ADLS Gen2(階層型名前空間有効)では、データへのアクセス制御にAzure RBACとPOSIXライクなACLの両方を使えます。認可は両者を評価して決まるため、「IAMでStorage Blob Data Contributorを付けたのに、フォルダ配下で権限不足になる」という事象が起きます。
手順:ストレージアカウントにRBACロールを付与
- Azure Portalで対象のストレージアカウントを開く
- 「アクセス制御 (IAM)」→「ロールの割り当ての追加」
- 目的に応じてロールを選択して割り当て
| 目的 | 推奨ロール例 | 典型ユースケース |
|---|---|---|
| 読み取りのみ | Storage Blob Data Reader | ADLSをソースとして読み込む |
| 読み書き | Storage Blob Data Contributor | ADLSに書き込み/削除も行う |
「メンバーの選択」からADFのマネージドID(SAMIまたはUAMI)を選び、保存します。
手順:ファイルシステム/フォルダにACLを付与
次に、実際に読み書きするファイルシステム(コンテナー)やフォルダにACLを付与します。最低限、ADFがアクセスするパスに対して「実行(x)」と「読み(r)/書き(w)」を適切に付けます。
- ソース読み取り:対象フォルダに
r-x(読み取り+実行) - シンク書き込み:対象フォルダに
rwx(読み取り+書き込み+実行)
ACLは「親フォルダのx(実行)」が欠けていると子階層へ辿れず失敗します。運用では“パイプラインが触るディレクトリを限定し、その範囲だけACLを通す”設計にすると、権限事故と切り分けコストが大幅に下がります。
権限設計の具体例(ディレクトリを分けて最小権限にする)
「とりあえずストレージ全体にContributor」は後から必ず苦しくなります。以下のようにディレクトリ(ゾーン)を分け、ADFが触る範囲だけ権限を通すのがおすすめです。
| 例:パス | 目的 | ADFに必要な権限(例) | 狙い |
|---|---|---|---|
| /landing | 到着した生データの置き場 | RBAC: Storage Blob Data Reader+ACL: r-x | 読み取り専用にして誤消去を防ぐ |
| /staging | 加工途中・一時退避 | RBAC: Storage Blob Data Contributor+ACL: rwx | 書き込みを許可する範囲を限定 |
| /curated | 利用部門向けの確定データ | 原則:ADFは書き込みのみ(運用ポリシー次第) | データ提供とETLの責任分界を作る |
なお、ストレージのFirewallで「Allow trusted Microsoft services」を使う設計(グローバルAzure IRで接続する等)では、認証方式としてマネージドIDが必要になるケースがあります。ネットワークを締めたい環境ほど、最初からマネージドID前提で考えるのが安全です。
Azure SQL Database:Entra管理者を設定し、DBユーザーとして権限付与
Azure SQLにマネージドIDで接続するには、SQL Server側でMicrosoft Entra認証を使える状態にし、DB内に外部ユーザー(FROM EXTERNAL PROVIDER)を作ります。接続側は「Active Directory Managed Identity」相当の方式でトークン認証を行い、DBはその主体をユーザーとして認識します。
前提:Azure SQL ServerでMicrosoft Entra管理者を設定
Azure PortalでSQL Server(論理サーバー)を開き、Microsoft Entra管理者(旧Azure AD管理者)を設定します。ここが未設定だと、外部プロバイダーからユーザー作成ができず詰まりやすいポイントです。
T-SQL例:ADFマネージドIDのユーザー作成とロール付与
-- ADF のマネージドID(表示名)でDBユーザーを作成
CREATE USER [<ADFのマネージドID名>] FROM EXTERNAL PROVIDER;
-- 読み取りのみ(ソース参照がある場合)
ALTER ROLE db_datareader ADD MEMBER [];
-- 書き込み(コピー先としてINSERT/UPDATEが必要な場合)
ALTER ROLE db_datawriter ADD MEMBER [];
-- 追加で必要な権限がある場合は個別にGRANTする(例)
-- GRANT EXECUTE ON OBJECT::dbo. TO [];
より絞る:スキーマ単位で権限を付ける例
本番では、db_datawriterのような広めのロール付与より、スキーマ単位・テーブル単位のGRANTの方が安全です。たとえばステージング用スキーマ(例:stg)にだけ書き込むなら、次のように権限範囲を限定できます。
-- stgスキーマ配下に対して必要な権限だけ付与する例
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::stg TO [<ADFのマネージドID名>];
| やりたいこと | 付与するロール/権限の例 | 最小権限での考え方 |
|---|---|---|
| SELECTのみ | db_datareader または GRANT SELECT | 参照対象テーブルだけに絞る |
| INSERT/UPDATE/DELETE | db_datawriter または スキーマ単位GRANT | ステージング領域だけに限定し、業務テーブルに直接書かない |
| DDL(テーブル作成など) | db_ddladmin(慎重に) | DDLは別のデプロイ工程に寄せ、ADFでは原則実行しない |
また、ADFがAzure integration runtimeでAzure SQLへ接続する場合、SQL Server側でAzureサービスからのアクセスを許可するサーバーレベルのFirewall設定が必要になることがあります。Self-hosted integration runtimeなら接続元マシンのIPレンジを許可します。ネットワーク要件は認証方式とは別軸で必ず確認しましょう。
ADF側のLinked Service設定で迷わないポイント
権限を付けたら、ADF Studio(Manage > Linked services)で認証方式を切り替えます。UIの表現やコネクタの推奨/レガシー区分は更新されることがありますが、考え方は同じです。
ADLS Gen2 Linked Service
- 認証方式で「Managed identity」を選ぶ(SAMI/UAMI)
- “アカウントキーを入力する欄”が消える=秘密情報が不要
- 接続テストが通っても、実行時はACL不足で落ちることがある(必ず実行で検証)
ADLS Gen2コネクタは、アカウントキー/サービスプリンシパル/マネージドID等の認証方式をサポートしています。
Azure SQL Database Linked Service
- SQL認証に加え、サービスプリンシパル(Entraアプリ)やマネージドIDでのコピーがサポートされている
- 認証方式で「SystemAssignedManagedIdentity」または「UserAssignedManagedIdentity」を選択できる
- Firewall/Private Linkなどネットワーク制御は別途要件として詰める
Azure SQL Databaseコネクタの対応認証や注意事項(推奨版/レガシー版、Firewall要件など)は、公式ドキュメント側にまとまっています。
移行時におすすめの進め方(安全に切り替える)
- ADFにマネージドIDを有効化(Azure PortalのData Factoryリソース > Identity)
- ADLS Gen2にRBACロール付与(Storage Blob Data Reader/Contributor)
- ADLS Gen2にACL付与(パイプラインが触るディレクトリだけ)
- Azure SQLにEntra管理者を設定
- Azure SQLでユーザー作成+権限付与(最初はロールで動作確認→その後GRANTで絞る)
- ADFのLinked ServiceをマネージドIDに切り替え
- Publish後に手動実行(トリガーと同じ定義で動くことをMonitorで確認)
- 安定後にキー/パスワード運用を縮退(ロールバック手順は残す)
それでもAccount Key/SQL認証を使うなら:最低限の守り方
組織事情で「今すぐEntra認証にできない」こともあります。その場合は、少なくとも次を徹底すると事故率が下がります。
- アカウントキー/SQLパスワードはADFに直書きしない(Key Vault参照を使う)
- Key Vaultのシークレット取得権限(Get)をADFのマネージドIDに付与し、アクセスログも監査する
- ローテーション手順をドキュメント化し、更新忘れで夜間バッチが止まらないようにする
- SQL認証ユーザーは最小権限にし、用途別にアカウントを分離する
ADFのマネージドIDは、Key Vaultから資格情報を取得する用途にも使えるため、「秘密情報はKey Vaultに寄せる」「アクセス権は最小化する」だけでもアカウントキー直運用より一段安全になります。
サービスプリンシパルを選ぶべきケース
マネージドIDが万能というわけではありません。次の条件に当てはまるなら、サービスプリンシパル(アプリ登録)を検討します。
- アクセス先が別テナント(クロステナント)で、マネージドIDが使いにくい
- アクセス先がAzureリソースではない、またはマネージドID未対応
- 要件として証明書認証やアプリ単位の明確な監査が求められる
この場合も、シークレット/証明書をKey Vaultに保管し、期限切れ・ローテ作業を運用に組み込むのが前提になります。
運用チェックリスト:スケジュール停止や権限不足を未然に防ぐ
- トリガーは「開始済み」か(Publishしただけでは動かない)
- トリガーの時刻(タイムゾーン)と実データ到着タイミングが噛み合っているか
- Monitorで「Debug実行」と「Trigger実行」の入力パラメータ差分を確認したか
- ADLSの対象パスにACLが付いているか(親フォルダのx不足が多い)
- SQLのEntra管理者設定、DBユーザー作成、権限付与を確認したか
- Azure SQL/StorageのFirewall変更時に、ADFの実行経路が遮断されないか
- “緊急時に旧方式へ戻す手順”を用意しているか
まとめ:おすすめの結論
- スケジュールトリガーのためにサービスプリンシパルを用意する必要はありません。重要なのはLinked Serviceが使う主体に権限があることです。
- Account Key+SQL認証でも動作はしますが、ローテーション・漏洩時の影響・監査の面で長期運用には不利です。
- 同一テナント内のAzureリソース連携なら、ADFのマネージドIDを使い、ADLSはRBAC+ACL、Azure SQLはEntra管理者設定+DB権限付与で最小権限にするのが最も堅牢です。

コメント