ドキュメント化されていないようですが、Azure Functions でも host.json
によるカスタム HTTP ヘッダーの追加と HSTS の設定が行えるようようになっていました。Function App 全体で適用されるので、セキュリティに関係するヘッダーを追加するには最適です。
Azure Functions Proxy で HTML を返している場合には、通常の Web アプリと同じ考慮が必要です。一般的に必要になるヘッダーは以下に書いた時とほぼ変わっていないと思います。
HSTS や CSP もヘッダーで追加できますが、HSTS はともかく CSP はなかなか適用が難しいですね。とはいえ、グローバルに設定しないと意味がないので、抜け漏れなく対応できる host.json
での設定は有益です。
カスタム HTTP ヘッダーを追加する
ドキュメントには載っていないですが、host.json
の extensions/http
以下に customHeaders
という要素が書けるようになっています。
たまたま関係ない調べ物をしていた時に、以下の Pull Request を見つけたので気が付きました。
微妙にテストコードが間違っている気がしますが、Azure Functions v2 / v3 の場合は以下のように書けばカスタム HTTP ヘッダーを追加できます。
{ "version": "2.0", "extensions": { "http": { "customHeaders": { "X-Kazuakix": "50" } } } }
条件付きでの追加などは出来ないので、前述したように基本はセキュリティ向けヘッダーなどの固定値になるもので使うのが良いでしょう。
実行してみると、ちゃんと追加した HTTP ヘッダーが返ってきます。
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 日なので、以下のようなヘッダーになります。
以前に別のエントリで書いたように、HSTS が 30 日だと短すぎるので本番向けではもっと長くしておきます。同時にサブドメインに対しても有効化しておきたいので、設定を追加します。
オプション名は camelCase にしたものを使えば良いですが、maxAge
だけは TimeSpan
型なので指定に少し悩みそうです。以下のように日数だけ書いても良いですし、ddd.hh:MM:ss
形式で指定しても良いです。
{ "version": "2.0", "extensions": { "http": { "hsts": { "isEnabled": true, "maxAge": 365, "includeSubDomains": true } } } }
再度 Azure にデプロイして実行すると、max-age
と includeSubDomains
が設定されています。
Windows の Azure Functions の場合は XDT を使ってカスタマイズという、何でもありな方法も取れそうでしたが、host.json
を使った方法は Linux でも問題なく動作するはずなので安心です。