しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Functions でカスタム HTTP ヘッダーや HSTS のグローバル設定を行う

ドキュメント化されていないようですが、Azure Functions でも host.json によるカスタム HTTP ヘッダーの追加と HSTS の設定が行えるようようになっていました。Function App 全体で適用されるので、セキュリティに関係するヘッダーを追加するには最適です。

Azure Functions Proxy で HTML を返している場合には、通常の Web アプリと同じ考慮が必要です。一般的に必要になるヘッダーは以下に書いた時とほぼ変わっていないと思います。

HSTS や CSP もヘッダーで追加できますが、HSTS はともかく CSP はなかなか適用が難しいですね。とはいえ、グローバルに設定しないと意味がないので、抜け漏れなく対応できる host.json での設定は有益です。

カスタム HTTP ヘッダーを追加する

ドキュメントには載っていないですが、host.jsonextensions/http 以下に customHeaders という要素が書けるようになっています。

たまたま関係ない調べ物をしていた時に、以下の Pull Request を見つけたので気が付きました。

微妙にテストコードが間違っている気がしますが、Azure Functions v2 / v3 の場合は以下のように書けばカスタム HTTP ヘッダーを追加できます。

{
  "version": "2.0",
  "extensions": {
    "http": {
      "customHeaders": {
        "X-Kazuakix": "50"
      }
    }
  }
}

条件付きでの追加などは出来ないので、前述したように基本はセキュリティ向けヘッダーなどの固定値になるもので使うのが良いでしょう。

実行してみると、ちゃんと追加した HTTP ヘッダーが返ってきます。

f:id:shiba-yan:20200526174550p:plain

HttpTrigger ではなく Azure Funcion Proxy を使った場合も試してみましたが、問題なくカスタム HTTP ヘッダーが付いた状態で返ってきました。

Function Filter や個別に対応する必要がないので、結構使い勝手は良いです。

HSTS に対応させる

カスタム HTTP ヘッダーを使っても対応できますが、Azure Functions は HSTS に関しては個別設定になっているので、こっちを使った方がローカルホストでは HSTS のヘッダーが出ないので便利です。

これもまたドキュメントには載っていなかったので Pull Requrst で気が付きました。

ベースは ASP.NET Core の HSTS なので、オプション項目も大体共通です。有効化したい場合に isEnabled を明示的に指定すればデフォルトのヘッダーが出力されます。

{
  "version": "2.0",
  "extensions": {
    "http": {
      "hsts": {
        "isEnabled": true
      }
    }
  }
}

ローカルホストでは HSTS のヘッダーは出力されないようになっているので、Azure にデプロイして実行する必要があります。これは地味にはまりそうなので注意したいです。

ASP.NET Core のデフォルト HSTS は max-age が 30 日なので、以下のようなヘッダーになります。

f:id:shiba-yan:20200526174602p:plain

以前に別のエントリで書いたように、HSTS が 30 日だと短すぎるので本番向けではもっと長くしておきます。同時にサブドメインに対しても有効化しておきたいので、設定を追加します。

オプション名は camelCase にしたものを使えば良いですが、maxAge だけは TimeSpan 型なので指定に少し悩みそうです。以下のように日数だけ書いても良いですし、ddd.hh:MM:ss 形式で指定しても良いです。

{
  "version": "2.0",
  "extensions": {
    "http": {
      "hsts": {
        "isEnabled": true,
        "maxAge": 365,
        "includeSubDomains": true
      }
    }
  }
}

再度 Azure にデプロイして実行すると、max-ageincludeSubDomains が設定されています。

f:id:shiba-yan:20200526174609p:plain

Windows の Azure Functions の場合は XDT を使ってカスタマイズという、何でもありな方法も取れそうでしたが、host.json を使った方法は Linux でも問題なく動作するはずなので安心です。