読者です 読者をやめる 読者になる 読者になる

しばやん雑記

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

Azure App Service の認証は POST 時に Referer をチェックしているので注意

Site Extension として公開している phpMyAdmin が何故かボタンなどを押した時に 403 になるという報告があり、App Service チームの人達と調べてました。

普段から Edge を使っている自分は再現できませんでしたが、その時に Referer が必要と知りました。

最初は SCM 側の認証だけかと思ってましたが、調べてみると App Service の認証でも同様に POST 時には Referer をチェックしていて、HTML の書き方によっては特定のブラウザではエラーになることがあります。

App Service の認証については以下のドキュメントを参考にしてください。ぶちぞう RD 推薦の機能です。

phpMyAdmin が動かなかった理由は Referrer Policy が no-referrer になっていたことでした。てっきり、同一オリジンの場合には付いてくるものだと思ってましたが、絶対に出さない設定もあるようです。

http://www.w3.org/TR/referrer-policy/

Edge では動いていた理由は、phpMyAdmin が新しい書き方のみ採用していたからでした。Edge は微妙に古い書き方のみ対応しているので、影響を受けることなく Referer が付いていました。

ちなみに GET では Referer が付いていなくても問題ありません。POST の時に問題となります。

最後に実際に検証してみます。簡単に meta referrer を設定したファイルと、設定していないファイルを用意して F12 開発ツールで通信を確認するだけです。Edge で試したので設定は古いものを使っています。

<html>
    <head>
        <meta name="referrer" content="never" />
        <title>test</title>
    </head>
    <body>
        <form action="no-referrer.php" method="post">
            <input type="text" name="username" />
            <br />
            <button type="submit">submit</button>
        </form>
    </body>
</html>

Chrome や Firefox では never ではなく no-referrer を使います。両方書いておいても良いです。

最初に meta referrer を付けていない方で POST リクエストを行いました。200 が返ってきていて、問題なくリクエストが処理されていることが分かります。

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

今度は meta referrer を付けた方で POST リクエストを行いました。リクエストヘッダーからは Referer が無くなっていて、ステータスコードは 403 が返ってきています。

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

何で POST の Referer をチェックしているのかと思われそうですが、単純に CSRF 対策でしょう。

同じく phpMyAdmin が常に no-referrer を設定しているのはセキュリティのためでしょうが、個人的には origin と no-referrer が選べても良かったのではないのかと思いました。

3 月なので障害に強い Azure の運用を考える(2017 年版)

3/8 に Azure の Japan East で久し振りに大規模な障害が発生しました。既に RCA が上がってきていて、ぶちぞう RD がブログで書いているので、原因についてはそっちを参照で。

2017.03.08 の Azure障害 | ブチザッキ

そして今年も 3/11 を過ぎたことですし、ちゃんとアーキテクチャと運用を最新のサービスや仕組みでリフレッシュしていかないといけないですね。ちょっとポエム臭くなってきたけど、割と中身は真面目に。

さて、障害の継続時間は 2 時間ぐらいでしたが、例によって Storage 周りの障害だったため、数多くの Azure サービスが影響を受けました。障害発生中の Azure Status はこんな感じでした。

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

Azure の Storage はご存知のように Blob / Table / Queue / Disk / File といった、各サービスの土台となる機能を提供しているので、ここに障害が発生すると大体こうなります。

これまでに数回、大規模な Storage 障害発生していますが長時間かつグローバルで影響を受けてます。今回は Japan East だけで 2 時間で回復という、珍しいパターンのように感じます。

Publickey のクラウドサービスの障害まとめは、後から振り返ることが出来て良いですね。

利用したことがない人には想像が付きにくいかもしれないですが、AWS でいうと EBS と S3 と SQS に対して同時に障害が発生したようなものです。以前 EBS に障害が発生した時、やはり規模は大きくなりました。

Azure や AWS に関係なく、クラウドの障害は基本的に発生するものなので、障害発生時にも可用性を維持するための機能が用意されています。Azure だと可用性セットだったり、AWS だと Multi-AZ とかですね。

よく使われているサービスに対して、どのように備えておくべきなのか調べたり考えたのでまとめました。

High availability と Disaster recovery

Azure はこういった場合のアーキテクチャに関してドキュメントを用意しています。まだ英語ですが、徐々に日本語に翻訳されていくはずです。

最初に HA と DR について定義がされています。この違いは重要だと思うので頭に入れておきたいです。

Storage

作成する時に LRS / ZRS / GRS / RA-GRS などを選択します。GRS / RA-GRS は別のリージョンに非同期でレプリケーションが行われているので、6 個のレプリカが常に用意されて安心。という仕組みです。*1

Storage で GRS を使っている場合には、障害発生時にセカンダリリージョンに対してフェールオーバーが行われますが、このフェールオーバーが実施される条件というのは非常にハードルが高いです。

具体的にはデータセンター全体が災害などによってダメージを受けた場合ぐらいのようです。

実際に 3/8 の障害でも、これまでの障害でもフェールオーバーは行われていませんし、これまでに Storage でフェールオーバーが実施されたという情報を見たことがないです。基本的に DR 向けの機能というわけです。

Microsoft としても、まずは「復旧を待つ」という選択肢を最初に持ってきています。

オプション 1: 復旧を待つ
この場合、ユーザーによる操作は必要ありません。 Azure サービスを利用できるようにするために鋭意取り組んでいます。 サービスの状態は Azure サービス正常性ダッシュボードで監視できます。

Azure Storage の停止が発生した場合の対処方法 | Microsoft Docs

障害が数十分で解決するのか、それとも数時間になるのかは予測が出来ないので、サービスによっては復旧を待つという選択は取りにくい場合もあると思います。

なので今回の障害の場合にも Storage の可用性を維持するためには、Japan East / Japan West にそれぞれ Storage を用意して同時に書き込む、もしくは独自にレプリケーションを行うしかなかったでしょう。

Blob の場合は 2 つのアカウントを CDN エンドポイントとして追加することで、比較的簡単に対応できそうです。Queue も普段はランダムで選んだアカウントで読み書きし、障害時には動作しているほうだけ使う、という対応も考えられるでしょう。この辺りは割と簡単ですね。

SQL Database

Stoarge の障害では大体 SQL Database も影響を受けます。理由は言うまでもありません。

しかし Storage の GRS が余程のことがない限りフェールオーバーしないのに対して、SQL Database は Active Geo Replication という機能が用意されているので、実は対応が割と楽になっています。

アプリケーション側では接続文字列をフェールオーバー時に切り替える必要はありますが、実装方法次第で簡単に解決することもできるはずです。

ドキュメントでは SQL Database を利用したアーキテクチャが複数紹介されています。

そして重要なのが実際に障害を発生させて、テストを定期的に行うことでしょう。特に最近は GitLab のデータベース喪失の話もありましたし、注目されているかと思います。

これもまたドキュメントが用意されているのと、Active Geo Replication は手動でフェールオーバーを行うこともできるので、一昔前に比べると圧倒的に行いやすくなっています。

とはいえ、障害がすぐに解消する可能性が基本的には高いので、まずは復旧を待つという選択肢が有効です。

App Service (Web App / Mobile App / API App)

App Service はコンテンツの格納に Storage を使っているので、障害が発生すると Web サーバーとしては動作していても、ファイルが読み込めないため動かないというパターンになります。

基本的に App Service などの Web サーバー系はステートレスに作るべきで、そうすれば複数リージョンに常にアプリケーションをデプロイして、Traffic Manager でフェールオーバーを行うことが出来ます。

複数リージョンに対してアプリケーションをデプロイする方法は、標準では提供されていないので AppVeyor などの CI SaaS からローリングで更新したり、手軽にするなら Site Replicator Extension 方法もあります。

Virtual Machines

VM の SLA は Standard Storage の場合は 2 インスタンス以上、Premium Storage の場合は 1 インスタンスとなってますが、基本的には可用性セットを作成して最低 2 台用意し、障害ドメインを分けておくべきです。

可用性セットや障害ドメイン、更新ドメイン含めて、ドキュメントがちゃんと用意されています。最高。

VM は用途にもよると思いますが、DR のことも考えると App Service と同様に別リージョンに用意しておける作りにしておくのが重要でしょう。つまりステートレスに作っておくということです。

今回の障害では Managed Disk を使って VM を立ち上げていると、影響をほぼ受けなかったとのことです。Managed Disk はかなりイケてるサービスです。

Active Geo Replication を含め、新しくリリースされたサービスに乗っかっておくというのは、割と重要なポイントだと思います。まだまだリージョン間に跨ってサービスを運用させるには手間がかかりますが、どのように対応するかを知っておくだけでも違います。

まとめ

最後の方は疲れて適当になってきた感がありますが、ちょっと何するべきかまとめます。

  • 大前提として Japan East / Japan West の運用をとれる構成にする
  • Storage は DR の観点から GRS を有効にする
    • HA としては複数リージョンでアカウントを分けてアプリケーションレベルでの対応
  • SQL Database は Active Geo Replication を有効にする
    • 必要ならさらに自動バックアップを使う
  • App Service / Virtual Machines はステートレスに作る
    • いつでも破棄、作り直しが出来るような作りに
    • Virtual Machines では可用性セットと Managed Disk を使う

ただし、ダウンタイムが許容できる場合は復旧するまで待つという選択肢で十分です。それでも Storage の GRS や SQL Database のバックアップは行っておきましょう。

余談ですが、今回の障害で Azure を使っている bitFlyer も例外なく影響を受けていたのですが、1 時間後ぐらいに Japan East から Japan West への切り替えが行われていて、真面目にかなり凄いと思いました。

切り替えに至った決断など、その時の話を聞いてみたいものです。

*1:ZRS は正直よくわからない

フリーランスになって初めての確定申告を終わらせた話

これまでの白色申告で確定申告はしてきましたが、今年はフリーランスになった関係で青色申告になったので、少し手間がかかった感じですが終わりました。当然ながらクラウド会計ソフトを使いました。

今朝、家の近くにある税務署に行って提出してきて、freee 上で年度締め処理を行いました。

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

フリーランスになった時にも書きましたが、@daruyanagi が使っていたのでわからなかったら聞けばいいという目論見の元 freee を使って会計処理を行いました。

これまでめんどくさくて、あまりやりたくなかった請求書の発行も、freee なら一瞬なので何の苦でもなくなったのが非常に良いです。郵送が必要な場合にも、freee にお願いできるのは神っぽいです。

途中でプランが変わって料金が今年の 5 月ぐらいから上がるのが少し気になりますが、便利に使えているので今年もそのまま継続する予定です。今のプランとの違いがよくわからないのは説明不足感あります。

無事に確定申告が終わったので、やったこととか便利だったことについて少し書いておきます。

交通費の連携は必須

週に数回、赤坂まで行ってるので交通費の記帳が多いのですが、初期のころは SMART ICOCA を使い、途中からは Apple Pay のモバイル Suica を使って freee に自動で登録するようにしました。

モバイル Suica は同期の時に画像認証が必要なのが少し不満ですが、この辺りは我慢してます。

税理士にチェックしてもらった

大半の処理は freee が自動的に仕分けしてくれるのですが、手動で登録した部分や開業した年だけの特殊なケースがありそうだったので、最後に freee 対応の税理士を紹介してもらって、全体的な記帳をチェックしてもらいました。

家から近くの人を探して、直接会ってチェックしてもらったので、同時に質問も色々と出来て理解度が高まりました。最初の年ぐらいはチェックした方が間違いを早めに正せるので良かったと思いました。

確定申告の手順が分かりやすい

freee の画面から確定申告を選べば、該当する項目を○×で選択していくだけで完了するお手軽さが最高でした。特に今回は 3 月までの給与所得など、源泉徴収されているものがありましたが、迷わず出来ました。

特に振替納税に必要な書類の案内も書いてあるのが良かったです。

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

地味にマイナンバーを書き込むとか、確定申告書と青色申告決算書の 1 枚目には印鑑を押しなさいと書いてくれていたので、実際の提出では何も言われることなくスムーズに終わりました。

去年はわからないことも多く手間と時間を掛けてしまいましたが、今年はもっとスムーズに出来そうです。