Fastlyでオリジン間をBasic認証で保護する

Fastly はVarnish上に構築されているCDNです。
そのため、VCLを自由に書くことができます。これを使用することで CDN - Orign 間通信にBasic認証を追加することも可能です。

TL;DR

FastlyのVCL snippets 設定で以下をvcl_missvcl_passに追加します。値はuser:passwordをBase64でエンコードする必要があるので気をつけてください。

set bereq.http.Authorization = "Basic hogehoge";

オリジンは、対象のパスに対してBasic認証を追加します。

詳しく

Varnish には Built-in サブルーチンというある条件のときに実行されるサブルーチンがあります。以下が、Fastlyの状態遷移図と実行されるサブルーチンとなっています。

Fastly の状態遷移図
Fastly Varnish ⋆ Mark McDonnell より引用

ここで、オリジンサーバーにfetchする部分はvcl_passvcl_missの後となります。そのため、ここでBasic認証のためのAuthorizationヘッダーを付与してオリジンに対してfetchすることでCDN-オリジン間でBasic認証をかけることが可能となります。

vcl_recv などで set req.http.Authorization = ... としても可能ですがreq.httpはCDNにアクセスするユーザーのリクエストであるためバックエンドのリクエストであるbereqを使う方が良いです。bereq変数はどのサブルーチンでも使用できるわけではなくFastlyのドキュメントによると、vcl_miss, vcl_pass, vcl_fetchで利用可能となっています。

ちなみに、この方法でbereq.urlも編集可能なので、

set bereq.url = '/hoge' + bereq.url;

といった、オリジンには別のパスにルーティングさせるといったことも可能です。しかしこちらは、vcl_recvreq.urlを編集してしまうとキャッシュキーがおかしくなってHITしなくなることがあるので必ず、vcl_missなどでbereqに対して編集を行うことをおすすめします。

もっとスマートな方法

こちらうまくできなかったのボツです。

vcl_missvcl_passの2つに同じ設定をするのは面倒くさいというケースに対しては、vcl_backend_fetchのサブルーチンを使用すれば1つのサブルーチンで完結することもできそうです*1。しかし、こちらはFastlyのVCL snippetsには存在しなく、自力で設定する必要があります。

設定する際には、Typeをnoneにしてサブルーチンごと設定します。

sub vcl_backend_fetch {
  set bereq.http.Authorization = "Basic hogehoge";
}