Azure StorageでPublic network access Disabled+Private Endpoint構成時に403になる原因と解決策(DNS/RBAC/ACL/リージョン)

Azure Storageアカウントで「Public network access: Disabled(パブリック ネットワーク アクセス無効)」にし、Private Endpoint(PE)経由に切り替えた途端に403(認証/認可エラー)になるケースは珍しくありません。DNS・PE状態・サブネット設定・ルーティング・権限のどこかが少しでも外れると発生するため、原因を最短で切り分ける手順を整理します。

目次

症状の整理:なぜ「403」になりやすいのか

Azure Storageの403は、単純に「権限がない」だけでなく、ネットワーク制限で拒否されたときも同じように403で返ることがあります。Public network access を Disabled にした場合、許可される入口が極端に狭くなり、少しでも経路がズレると(本人はPEで行っているつもりでも)結果として403になりがちです。

まずは「403=RBAC不足」と決め打ちせず、どの種類の403なのかを切り分けるのが近道です。

観点よくある状況現象次に確認すること
ネットワーク由来の403DNSがパブリックIPに向く/PE未承認/経路がPEを通っていない「権限不足」に見える403だが、実際は入口が不一致DNS、PE接続状態、NSG/UDR、アクセス元がVNet内か
認証(トークン)由来の403/401意図せずSAS/キーで実行、トークンの対象が違うAuthenticationFailed 等で失敗認証方式(Azure AD/OAuth2)とツールの設定
認可(RBAC/ACL)由来の403データプレーン権限が不足、ADLS Gen2のACL不足AuthorizationPermissionMismatch 等で失敗RBACの付与スコープ、ロール種別、ACL

前提:Public network access を Disabled にしたときの挙動

ここが一番の落とし穴です。Storageアカウントのネットワーク設定で Public network access を Disabled にすると、基本的にパブリックエンドポイント(例:account.blob.core.windows.net)からの到達は全面的にブロックされます。

つまり「PEがあるから大丈夫」ではなく、実際の通信が必ずPrivate EndpointのプライベートIPに向かい、PEが正常(承認済み・到達可能)で、必要なサブリソース(blob/dfs/file/queue/table等)まで揃っている必要があります。どこか1つでも欠けると、結果として403になります。

最短で切り分けるチェック(上から潰す)

Private Endpoint接続が「Approved(承認済み)」か

まずはストレージアカウント側で、該当PEの接続状態が Approved になっているか確認します。作成直後や手動承認が必要な構成だと、Pending のままになっていることがあります。

  • ストレージアカウント → ネットワーク → Private endpoint connections
  • 該当の接続が Approved になっているか
  • 対象のサブリソース(blob / dfs / file / queue / table)が要件に合っているか

ポイント:たとえばBlob操作だけのつもりでも、利用しているSDK/ツールが dfs エンドポイント(ADLS Gen2系)を叩いていると、blobのPEだけでは足りず403に見える失敗になります。

DNSが「必ず」Private EndpointのプライベートIPを引いているか

Public network access が Disabled の状態で最も多いのがこれです。クライアントが名前解決した結果、パブリックエンドポイントのIPを引いてしまうと、到達はできても(あるいは到達したように見えても)ストレージ側で拒否され、403になります。

確認はシンプルで、アクセス元(実際に実行しているVM/コンテナ/Functionsの実行環境など)で名前解決結果がプライベートIPになっているかを見ます。

nslookup <storage-account-name>.blob.core.windows.net
nslookup <storage-account-name>.dfs.core.windows.net

返ってくるIPが 10.x / 172.16-31.x / 192.168.x のようなプライベートレンジで、しかもPEに割り当てられたIPになっていることが条件です。

Private DNS Zone を使う場合は、少なくとも次の組み合わせを押さえると事故が減ります。

用途アクセスするFQDN必要になりやすいPrivate DNS ZonePEで選ぶサブリソース例
Blob(一般的なBlob操作)<account>.blob.core.windows.netprivatelink.blob.core.windows.netblob
ADLS Gen2(階層型名前空間/HNS、abfs/dfs系)<account>.dfs.core.windows.netprivatelink.dfs.core.windows.netdfs
Azure Files<account>.file.core.windows.netprivatelink.file.core.windows.netfile
Queue<account>.queue.core.windows.netprivatelink.queue.core.windows.netqueue
Table<account>.table.core.windows.netprivatelink.table.core.windows.nettable

さらに、Private DNS Zone を用意しただけで終わりではありません。

  • Private DNS Zone が対象VNetにリンクされているか
  • クライアントが参照するDNS(Azure提供DNS、独自DNS、オンプレDNS)がそのゾーンを引ける経路になっているか
  • 複数VNet/複数DNS(Hub-Spoke、NVA、カスタムDNS)を使う場合、条件付きフォワーダー名前解決の優先順位で外れていないか

現場のあるある:「DNS解決できている」は、しばしば「名前が引ける」だけの意味になりがちです。重要なのは“どのIPを引いているか”です。Public access無効時はここで勝負が決まります。

PE用サブネットの必須設定(network policies)

Private Endpoint を置くサブネットには、PE要件としてサブネット側のネットワークポリシー(Private Endpoint network policies)を無効化する必要があります。これが未設定だと、PE自体は作れても通信が不安定になったり、想定外の拒否につながることがあります。

ポータルでも設定できますが、IaC/CLIで統一するなら次のように確認・設定します(例)。

# サブネットでPrivate Endpoint network policiesを無効化(例)
az network vnet subnet update \
  --resource-group &lt;rg&gt; \
  --vnet-name &lt;vnet&gt; \
  --name &lt;subnet-for-pe&gt; \
  --disable-private-endpoint-network-policies true

組織によっては「サブネットはNSG必須」などのルールがありますが、PE用サブネットは一般サブネットと同じ感覚で固めすぎると詰まります。PEのサブネットは“PE専用”にし、要件に沿ってシンプルに保つのが安全です。

NSG・UDR・NVA・プロキシが443を邪魔していないか

Private Endpoint は「VNet内のプライベートIP(NIC)宛ての通信」なので、通信経路上の制御(NSG、ユーザー定義ルート、NVA、透過プロキシ、SSLインスペクション)が強い環境だと、想定外のブロックや迂回が発生します。

  • アクセス元サブネットのNSGで、PEのIP宛てのTCP/443が許可されているか
  • UDRで0.0.0.0/0をNVAへ向けている場合、PE宛てが強制的にNVAへ吸い込まれていないか
  • NVAでプライベート宛てトラフィックが落ちていないか(ログ/フローで確認)

「ネットワークを緩めると成功する」場合、DNSがずれているか、NSG/UDR/NVAでPE宛てが正しく通っていない可能性が高いです。

そもそも実行場所は“本当に”VNet内か

意外と見落とされるのがこれです。たとえば次のようなケースでは、実行主体がVNet外にいて、Private DNS Zone を見ていない(または見れていない)ことがあります。

  • CI/CD(GitHub-hosted runner / SaaS型のビルド環境)から実行している
  • Functions/Container Apps などで VNet 統合が未完了、または別の環境スロットで未設定
  • 踏み台(Bastion等)で接続しているつもりが、実際は別ネットワークから叩いている

この場合は、同じコマンドでも実行場所を変えるだけで結果が変わります。切り分けとして、VNet内の検証用VMから同じ操作を行い、DNS・到達性・権限を確認すると速いです。

RBAC(データプレーン権限)でよくある落とし穴

ストレージは「管理プレーン(ARM)」と「データプレーン(Blob/Filesなどの中身)」が別物です。サービス プリンシパル(FIC含む)にRBACを付けたつもりでも、ARM操作のロールしか付いていない、またはスコープがズレていると、データアクセスは403になります。

用途ごとの代表的なロールを整理すると次の通りです(最小権限の設計は別途必要ですが、切り分けではまず要件を満たすロールを付与して動作確認するのが確実です)。

やりたいこと代表的なロール備考
Blobの読み取りStorage Blob Data Reader一覧取得・ダウンロード中心
Blobの読み書きStorage Blob Data Contributorアップロード/削除/上書きを含む
ACL変更や所有者/権限管理(ADLS Gen2)Storage Blob Data OwnerHNS/ACL操作が絡む場合に必要になりやすい

スコープの注意:「リソースグループに付けたからOK」と思いがちですが、運用の癖や構成によっては、対象が想定とズレて403になることがあります。切り分け段階では、まずストレージアカウントスコープでロールを付け、動作を安定させてから、必要に応じてコンテナ/ファイルシステム単位へ絞るのが安全です。

反映遅延:RBACは付与直後に反映しないことがあります。テストのたびにロールを付け替えると混乱しやすいので、ロール変更後はログの時刻を揃えて検証し、失敗が古いトークンによるものではないかも疑ってください。

サービスプリンシパル(FIC)の「どのID」に付与するか

Federated Identity Credential(FIC)を使う場合、アクセス時の主体は「アプリ登録(Application)」ではなくサービスプリンシパル(Enterprise application)側のオブジェクトとして評価されます。ロールを付ける相手(オブジェクトID)がズレると、付与したのに403になります。

  • ロール付与対象が、実際にトークンを出している主体(SP)と一致しているか
  • 同名アプリが複数ある、テナントを跨いでいる、作り直しで古いSPに付与している…などを疑う

認証方式の確認:本当にAzure AD(OAuth2)で叩いているか

「RBAC付与済みなのに403」の裏で、実はツールがSAS/アカウントキーでアクセスしている、または逆にAzure ADでアクセスしているつもりが別方式になっている、ということがあります。

特にCLI系はオプション次第で認証方式が変わります。代表例として、Azure CLIのストレージ操作は –auth-mode login を付けないと別方式になりやすいものがあります(環境変数・既定値・接続文字列などの影響を受けます)。

# 例:Azure ADでの認証を明示(環境やコマンドにより異なる)
az storage blob list \
  --account-name &lt;account&gt; \
  --container-name &lt;container&gt; \
  --auth-mode login

SDKの場合は、DefaultAzureCredential を使っているか、Managed Identityを使うならその割り当てが正しいか、Workload Identity/FICなら環境変数やフェデレーション設定が正しいかを確認します。ここでの狙いは「正しい主体で、正しいリソース(Storage向け)のトークンを取得し、そのトークンで呼んでいる」ことです。

ADLS Gen2(階層型名前空間)なら「RBAC+ACL」の二段階で403が起きる

ストレージアカウントで 階層型名前空間(HNS)を有効にしている(= ADLS Gen2として使っている)場合、403の原因はRBACだけではありません。POSIXライクなACL(ディレクトリ/ファイルの権限)でも弾かれます。

このときの典型パターンは次の通りです。

  • RBACは付いているのに、特定のコンテナ(ファイルシステム)配下だけ403になる
  • 一覧は取れるが、ディレクトリ作成や書き込みだけ403になる
  • 別のユーザー/別のSPは成功する(= ACLが主体ごとに違う)

ADLS Gen2でハマりやすい要点を表にまとめます。

操作RBACの例ACLの例よくある落とし穴
ファイルの読み取りBlob Data Reader 以上対象パスに r(read)親ディレクトリに x(execute)がなく辿れない
ファイルの書き込み/作成Blob Data Contributor 以上対象ディレクトリに w(write)+xデフォルトACLが未設定で新規作成が失敗
ACLの変更Blob Data Owner が必要になることが多いACLを変更できる権限権限設計がRBACだけで完結すると誤認

「blobのPEはあるのにdfsで失敗」パターン

HNS有効のストレージを、Spark/Hadoop系(abfs://)、Data Lake SDK、あるいは一部のツールで扱うと、裏で dfs.core.windows.net を叩きます。ここで、PEやDNSが blob しか用意されていないと、Public network access Disabled の条件下では破綻し、403に見える失敗になります。

対処は明快で、要件に応じて以下を揃えます。

  • dfs サブリソースのPrivate Endpointを作る
  • privatelink.dfs.core.windows.net のPrivate DNS Zoneを用意し、VNetへリンク
  • アクセス元で <account>.dfs.core.windows.net がPEのプライベートIPを引くことを確認

リージョン違い(PEとストレージが別リージョン)をどう捉えるべきか

Private Endpoint は「VNet内に作るNIC」であり、接続先リソース(ストレージ)が別リージョンでも成立するケースはあります。ただし、実務上は切り分け難易度が上がりやすいため、403の調査段階ではまず同一リージョンに寄せて正常化させるのが安全です。

同一リージョン/別リージョンの比較観点を整理します。

観点同一リージョン別リージョン
トラブルシュート構成が単純で原因追跡がしやすいDNS/ルーティング/組織ポリシーの影響が増え、ハマりどころが増える
レイテンシ最小になりやすい遅延が増える可能性(業務要件で影響が出る場合あり)
運用設計監視・障害時対応が分かりやすいネットワーク/組織境界を跨ぐと運用責任が分散しやすい

結論としては、次の順番が堅実です。

  • まず同一リージョンで PE+DNS+権限 を揃えて100%成功する状態を作る
  • その後、要件上どうしても別リージョンが必要なら、レイテンシ・コスト・運用を評価して再設計する

診断の順番テンプレート(403を最短で潰す)

実際の現場では、検証が散らかるほど調査時間が伸びます。次の順番で潰すと、403の大半は短時間で切れます。

  1. 実行環境を固定する
    • まずVNet内の検証VMなど「ネットワークが見える環境」でテストする
    • CI/CDやPaaSは、切り分け後に戻す
  2. DNS(blob/dfs等)を確認する
    • nslookup の結果がPEのプライベートIPであること
    • HNSなら dfs も同様に確認する
  3. PE接続の状態(Approved)とサブリソースを確認する
    • 必要なサブリソース(blob/dfs/file…)が揃っているか
  4. NSG/UDR/NVAでPE宛て443が落ちていないか
    • 特にUDRで強制トンネルしている環境は最優先で疑う
  5. 認証方式がAzure ADになっているか
    • ツールの既定認証がSAS/キーに寄っていないか
    • FICの場合は対象SPが正しいか
  6. RBAC(データプレーン)をストレージアカウントスコープで確認する
    • 必要なら一時的にBlob Data Contributor/Ownerで検証する
    • 付与後は反映遅延を考慮して再ログイン/再取得する
  7. ADLS Gen2ならACLを確認する
    • 書き込み系の403はACL不足の可能性が高い

ログで裏取りする:403の“種類”を確定させる

推測で直すと遠回りになります。403の根拠を取るなら、次の観測が有効です。

  • クライアント側のエラー詳細(例:SDK例外のエラーコード、レスポンスヘッダーの x-ms-error-code、AzCopyログ)
  • ストレージの診断ログ(Azure Monitor / Diagnostic settings)
    • 読み取り/書き込み/削除系のログを有効化し、対象時間帯の StatusCode、認証種別、要求元IP などを見る
    • 要求元IPがプライベートIPになっていればPE経由の可能性が高く、そうでなければDNS/経路を疑う
  • ネットワーク側ログ(NSGフローログ、NVAログ、Firewallログなど)
    • PEのIP宛て443が許可/拒否どちらになっているかを確認

ログで「要求元IPが想定外」「認証種別が想定外」が見えた瞬間に、原因がほぼ確定します。

原因別の対処まとめ(チェックリスト)

最後に、典型パターンを“症状→原因→対処”でまとめます。運用メモとしてそのまま使える形にしています。

症状原因候補対処
Public access有効だと成功、Disabledにすると403DNSがパブリックIPを解決しているPrivate DNS Zone(privatelink.*)の作成、VNetリンク、クライアントのDNS参照を修正。nslookupでPEのプライベートIPを引くまで固定
PEを作ったのに改善しないPE接続が未承認 / サブリソース不足(dfs等)Private endpoint connectionをApprovedに。必要なサブリソース(blob/dfs/file…)のPEを追加
同じVNet内でも環境によって成功/失敗が分かれるNSG/UDR/NVA/プロキシでPE宛てが阻害PEのIP宛てTCP/443を許可。強制トンネル時は例外ルートやNVA設定を見直し
一覧は取れるが書き込みだけ403(HNS有効)ACL不足(RBACだけでは不足)対象ディレクトリ/ファイルのACL(w/x等)とデフォルトACLを確認。必要ならBlob Data Ownerも検討
RBACを付けたのに403が変わらない付与対象(SPのオブジェクト)やスコープがズレている/反映遅延付与先が実際の主体か確認。ストレージアカウントスコープで付与し、トークン再取得後に再検証
リージョンが跨っていて不安構成が複雑化し、DNSや経路のズレを招きやすい切り分け目的で同一リージョンにPEを作り正常化→要件があれば別リージョン構成へ段階的に戻す

まとめ:Public network access Disabled は「経路が1本」になる

Public network access を Disabled にすること自体は、データ保護として非常に強力です。その一方で、許可される経路が“Private Endpoint経由だけ”に収束するため、DNS・PE状態・サブネット要件・NSG/UDR・RBAC/ACLのどれかが少しでも外れると403として顕在化します。

対処のコツは、DNS(プライベートIP解決)→PE状態(承認/サブリソース)→ネットワーク到達性→認証方式→RBAC→(ADLSなら)ACL、の順に上から固めることです。ここまで揃えると、ネットワーク制限を緩めなくても、PE経由で安定してアクセスできる状態を作れます。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次