AzureアプリでCSPとHSTSを徹底設定:セキュリティ監査に備える実践ガイド

企業や個人が運用するWebサービスの品質向上には、セキュリティ対策が欠かせません。特に、カスタムドメインで公開されているAzureアプリにおいては、CSP(Content Security Policy)やHSTS(HTTP Strict Transport Security)といったセキュリティヘッダーの設定が重要です。

AzureアプリにおけるCSPとHSTSの概要

Azureアプリを安全に運用するうえで、CSP(Content Security Policy)とHSTS(HTTP Strict Transport Security)は非常に有効なセキュリティヘッダーです。CSPは主にブラウザがロードするコンテンツの種類やソースを制御する仕組みで、クリックジャッキングやクロスサイトスクリプティング(XSS)などを防ぐ一助となります。一方のHSTSは、サイトへアクセスする際に常にHTTPS通信を強制する仕組みで、中間者攻撃やHTTPダウングレード攻撃を防ぐことができます。
しかしながら、Azureポータルの各サービス画面を眺めても、CSPやHSTSを直接設定するための項目は見つからないことが多いです。これは、Azureが様々なサービス群から成り立っており、セキュリティヘッダーを設定する場所がアプリケーション側、またはリバースプロキシ(Front Door、Application Gateway等)、あるいはCDNなど複数に分かれているためです。そこで、Azure環境でCSPやHSTSを設定するうえでの代表的な方法を網羅的に解説します。

まずはアプリ側でヘッダーを設定する方法

CSPやHSTSといったセキュリティヘッダーは、Webアプリケーションのレスポンスに付与される仕組みです。多くの場合、最も直接的かつ確実なのはアプリのコードや設定ファイルでレスポンスヘッダーを追加する方法です。フレームワークやプラットフォームによって設定方法が異なるため、代表的な例をいくつか紹介します。

ASP.NETでの設定例

ASP.NET(またはASP.NET Core)では、IIS構成ファイルであるweb.configを編集することでレスポンスヘッダーを追加できます。以下は、web.configにセキュリティヘッダーを追記するサンプルです。

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <!-- HSTSヘッダー -->
      <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
      <!-- CSPヘッダー -->
      <add name="Content-Security-Policy" value="default-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

この設定により、ブラウザは常にHTTPSでのアクセスを期待し、またCSPポリシーに応じて外部リソースの読み込みを制限します。特に“'self'”の設定は自ドメインのみを許可する指定となるため、外部リソースを利用する場合は追加でホワイトリストを設定する必要があります。また、JavaScriptやスタイルシートをインラインで書いている場合、'unsafe-inline'の指定を加えるなど、運用に合わせて詳細を調整しましょう。

Node.js(Express)での設定例

Node.jsのExpressフレームワークを利用している場合は、レスポンスを返却する際にヘッダーを設定します。Expressではhelmetというセキュリティ対策用の便利なミドルウェアが存在するため、これを活用することが多いです。以下は、helmetを使ったサンプルです。

const express = require('express');
const helmet = require('helmet');

const app = express();

// Helmetで基本的なセキュリティヘッダーを追加
app.use(helmet());

// HSTSを有効化したい場合
app.use(
  helmet.hsts({
    maxAge: 31536000, // 1年間を秒で指定
    includeSubDomains: true
  })
);

// CSPを独自設定したい場合
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:"],
      // 必要に応じて他の設定
    }
  })
);

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

helmetを使用すると、一度の導入で多くのセキュリティヘッダーを自動的に追加してくれます。さらに細かなカスタマイズも上記のように可能です。

Python(Flask)での設定例

PythonのFlaskフレームワークでは、レスポンスに直接ヘッダーを付与する方法が一般的です。以下は簡単な例です。

from flask import Flask, make_response

app = Flask(__name__)

@app.route("/")
def index():
    response = make_response("Hello, Flask!")
    # HSTSヘッダーの付与
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    # CSPヘッダーの付与
    response.headers["Content-Security-Policy"] = "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self';"
    return response

if __name__ == "__main__":
    # HTTPS化が前提
    app.run(ssl_context='adhoc')

Flaskの場合も、HTTPSでアプリを起動できるようにするか、もしくはリバースプロキシ側でHTTPS終端を行う必要があります。CSPについては運用に合わせてポリシーを細かく設定していきましょう。

Azure Static Web Appsでの設定例

Azure Static Web Appsを利用している場合は、staticwebapp.config.jsonファイルでカスタムヘッダーを設定できます。以下はその例です。

{
  "routes": [
    {
      "route": "/*",
      "headers": {
        "Strict-Transport-Security": "max-age=31536000; includeSubDomains",
        "Content-Security-Policy": "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self';"
      }
    }
  ]
}

このファイルをプロジェクトのルートに配置することで、静的ファイルに対してもCSPやHSTSを付与できます。Static Web Apps特有の認証周りやAPIの呼び出しがある場合は、追加のルート設定を行う場合もあります。

リバースプロキシ(Azure Front Door / Application Gateway)での設定

アプリケーションコード側ではなく、Azureのリバースプロキシ機能(Azure Front DoorやApplication Gateway)でセキュリティヘッダーを追加・変更できる場合もあります。特にマルチリージョンでの負荷分散やWAF(Web Application Firewall)ポリシーと組み合わせるケースでは、こちらの方法が有力です。

Azure Front Doorのカスタムルール

Azure Front Doorでは、フロントエンドホスト単位でWAFポリシーを設定し、そこに「カスタムルール」を追加することでレスポンスヘッダーを操作できます。大まかな流れは以下のとおりです。

  1. Azure PortalでFront Doorのリソースを開く。
  2. 「WAF(Web Application Firewall)」のメニューからポリシーを選択する。
  3. 「カスタムルール」を作成または編集し、アクションとして「Header Modification(レスポンスヘッダーの追加・上書きなど)」を設定する。
  4. ヘッダー名に「Strict-Transport-Security」や「Content-Security-Policy」などを指定し、値にポリシーを記述する。

Front Door側で設定すると、アプリのコードを変更しなくてもすべてのレスポンスに対してヘッダーを付与できます。ただし、すでにアプリケーション側で設定されたヘッダーとの競合や重複に注意が必要です。

Application Gateway+WAFポリシーでのレスポンスヘッダー操作

Application Gatewayを導入している場合も、WAFポリシーのカスタムルールを用いてレスポンスヘッダーを追加したり上書きしたりできます。Front Doorと同様の手順になりますが、違いとしてはAppGwのリスナーやバックエンドプールの設定で細かく振り分けを行う点があります。以下のようなシーンで利用が多いです。

  • 同一VNET内の複数アプリをApplication Gatewayで振り分けし、共通のセキュリティヘッダーを与えたい。
  • 独自のWAFポリシーセットを活用しつつ、HTTPS終端を行う場所をコントロールしたい。

これらのシナリオでは、Application Gateway側でHSTSやCSPヘッダーを追加すれば、バックエンドアプリ側の実装を変更することなく一元管理が可能になります。

Azure CDNでヘッダー操作をするケース

Azure CDNを挟んでいる場合は、CDNの機能でレスポンスヘッダーを付与できるケースがあります。ただし、Azure CDNには複数のプロバイダー(VerizonやAkamaiなど)があり、それぞれ設定画面や機能が異なるため注意が必要です。一般的にはAzure CDNの「ルールエンジン」や「ルールセット」などで、「レスポンスヘッダーの追加/上書き」アクションを指定し、CSPやHSTSを付けることが可能です。

HTTPS設定を忘れずに

HSTSを有効にする前提として、サイト全体がHTTPS通信に対応していることが必須です。AzureのカスタムドメインをHTTPS化する方法はいくつかありますが、代表的なのは以下の通りです。

  • Azure Web Apps(App Service)で独自ドメインを設定し、「TLS/SSL設定」から証明書をアップロードするか、App Service証明書を利用する。
  • Azure Front DoorやApplication GatewayでHTTPS終端を行い、そこへ証明書を設定する。
  • Azure CDNが提供するカスタムドメイン用のSSL証明書を設定する。

いずれにしても、有効な証明書を使ってHTTPS通信を行う環境下でのみHSTSヘッダーは意味を持ちます。SSL証明書が期限切れにならないよう、期限管理も忘れずに行いましょう。

実運用時の注意点とベストプラクティス

CSPやHSTSを運用するうえでのベストプラクティスをいくつか紹介します。

1. ブラウザ互換性を考慮する

CSPの各ディレクティブ(policy)はブラウザによってサポート状況が異なる場合があります。最新のChrome、Firefox、Edgeなどはほぼ問題ありませんが、古いIEなどに対応が必要な場合はポリシーの組み方を調整する必要があります。

2. CSPのレポートURIを活用する

CSPでreport-urireport-toを設定すると、CSP違反時にブラウザがレポートを送ってくれます。これにより、どのリソースがブロックされたか把握でき、CSPポリシーの改善につながります。運用開始前にContent-Security-Policy-Report-Onlyを利用し、ブロックはしないけれどレポートだけを受け取るテスト運用を行うのも効果的です。

3. HSTSのプリロードリストを検討する

HSTSプリロードリストとは、主要なブラウザベンダーが提供するドメインリストに登録することで、ユーザーが初回アクセスする前からHTTPSのみでアクセスされるようにする仕組みです。プリロードを希望する場合は、Strict-Transport-Securityヘッダーにpreloadオプションを追加し、includeSubDomainsを有効にするなどの要件を満たした上で、ブラウザベンダーのサイトに申請します。

4. 設定変更時はキャッシュ期間に注意

HSTSのmax-ageで指定した期間中、ブラウザはHTTPアクセスを強制的にHTTPSへリダイレクトします。そのため、設定を誤ると長期間にわたって影響が残る可能性があります。初めは小さなmax-age(例:1日)から始め、問題が無ければ徐々に期間を伸ばしていく運用が安全です。

5. 実際にヘッダーを確認・検証する

設定が正しく効いているかどうかは、ブラウザの開発者ツールやオンラインのレスポンスヘッダーチェックツールで簡単に確認できます。Chromeなら「デベロッパーツール」→「Network」タブでレスポンスヘッダーを確認することができます。
さらに、セキュリティスキャンツール(例えばQualys SSL Labsのようなサイト)を使えば、HTTPS設定やHSTSの有効性、CSPの評価などを包括的にチェックできます。

複数の設定箇所と競合の可能性

Azure環境では、App ServiceやContainer Appsなど、アプリそのものに加え、Front Door、Application Gateway、Azure CDNなど複数の層が存在し、どこでヘッダーを設定すべきか迷うこともあります。以下の表に代表的なメリット・注意点をまとめます。

方法設定場所メリット注意点
アプリ側で設定web.config、コードなど実装がシンプルで一番直接的。個々のアプリの事情に合わせやすいアプリごとに設定・変更が必要。複数サービスを管理していると煩雑になりやすい
Front Doorで設定Front Doorポリシーやカスタムルール複数リージョンや複数アプリで統一的に設定を行えるルールの競合に注意。特にアプリ側との重複設定を整理する必要がある
Application Gatewayで設定WAFポリシーのカスタムルールバックエンドとの通信を細かくコントロール可能。VNET内でも柔軟に適用Front Door同様、複数レイヤーでの設定重複がないか管理が必要
Azure CDNで設定ルールエンジンやカスタムルールキャッシュ管理と合わせ、エッジサーバーで一元的にヘッダーを付与可能CDNの種類(VerizonやAkamaiなど)によって設定方法が異なる

運用規模やアプリの特性に合わせて、どこでCSPやHSTSを設定するのがベストか検討しましょう。大企業のように多数のWebアプリが存在する場合、リバースプロキシ(Front DoorやApplication Gateway)で統制した方が管理しやすいケースが多いです。逆にシンプルな構成の小規模サービスであれば、アプリ側(コードや設定ファイル)に埋め込む方が理解しやすいでしょう。

具体的なCSPポリシー例

実際の運用では、CSPポリシーの細かい指定が課題になることが多いです。サイトに外部のアナリティクスや広告、SNSウィジェットなどを読み込む場合は、そのドメインをホワイトリストに追加しなければいけません。以下にもう少し詳しいポリシー例を示します。

Content-Security-Policy: 
  default-src 'self'; 
  script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://analytics.google.com; 
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; 
  img-src 'self' data: https://cdn.example.com; 
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  report-uri https://csp-report.example.com;

上記例では、スクリプトは自ドメインおよびGoogle関連のアナリティクスのみ許可し、スタイルは自ドメインとGoogle Fontsを利用し、画像は自ドメインとdata:スキームおよび指定のCDNから許可しています。また、CSP違反時にレポートが飛ぶようreport-uriを指定しています。これらのルールは運用に合わせて随時見直しを行い、不要な許可を減らす(ホワイトリストを最小限に抑える)ことがセキュリティの観点では望ましいです。

まとめ: Azure環境でCSP・HSTSを確実に設定しよう

Azureアプリをセキュアに運用するには、CSPとHSTSは非常に効果的な手段です。しかし、AzureにはApp Serviceやコンテナサービス、Front Door、Application Gateway、CDNなど多岐にわたるサービスが存在し、どこで設定するのが最適かはアーキテクチャや運用体制によって変わります。最もシンプルなのはアプリケーション側でレスポンスヘッダーを追加する方法ですが、複数アプリを一元管理するのであればFront DoorやApplication Gatewayなどのリバースプロキシ側での設定も検討しましょう。
また、CSPやHSTSの動作確認は、ブラウザやオンラインツールを用いてこまめに行い、誤設定によるトラブルや稼働停止を未然に防ぐことが大切です。HSTSは特にキャッシュ期間が長い設定をすると取り返しがつきにくくなるため、まずは短めで様子を見つつ、本番運用に耐えられる設定を慎重に構築するのがベストプラクティスといえます。
しっかりとHTTPS対応とヘッダー設定を行えば、セキュリティ監査でも指摘されにくい強固なサイトを実現できます。ぜひ本記事を参考に、AzureアプリへのCSPやHSTSの導入を検討してみてください。

コメント

コメントする