あ、しんのきです

趣味とか技術系とか

Hasura Japan User Group 3 - Hasuraの本番運用とセキュリティ

はじめに

これは 2020/11/28 の Hasura Japan User Group 3 という勉強会で発表する内容です。

hasura-japan.connpass.com

今日話すこと

  • Hasuraを本番運用している話
  • Hasuraとセキュリティ

の大きく二部構成で話します。

詳しく聞きたいことがあれば途中でも掘り下げていただければと思います。

自己紹介

これまでの道のり

  • 5月 βリリース
  • 6月 iOS/Androidアプリリリース
    • React Native(Expo)
  • 8月 正式サービス開始
    • クレカ課金はStripeを採用
  • 9月 チャット機能
    • GraphQL Subscription
  • 10月 画像添付機能
    • Amplify Storage
  • 11月 位置情報機能

Hasuraを本番運用している話

国内スタートアップのHasura採用例(勝手に参照)

プロジェクト構成

ロールとパーミッションの設定

  • 現在、user(ログイン済)、anonymous(匿名)、support(運営)の3ロール(とadminロール)
    • 今のところロール毎にWebフロントエンドが分かれる形に落ち着いている
    • 1つのApolloClient x-hasura-role を動的に切り替えるのは 🙅‍♀️
      • キャッシュが混ざって見えないはずのデータが見えてしまったり不具合の温床になる
      • ApolloClient(というよりApolloProvider)ごと分離するべき
      • そこまでやるのであればプロジェクトごとまるっと分けてしまったほうが良い
    • ロール = 境界づけられたコンテキスト として、明確に分けることができるはず
    • 公式ドキュメントのauthor-reviewer-editorのサンプル はミスリードだと思う
  • codegenの設定に x-hasura-role をセットするのは非常にオススメ
schema:
  - http://localhost:8080/v1/graphql
      headers:
        x-hasura-admin-secret: myadminsecretkey
        x-hasura-role: user

Hasuraを使っててよかったこと

  • スケールに合わせてインフラを選びやすい
    • Hasura: Heroku → Fargate(isolated) → Fargate(private)
      • Fargateに移したときにガチガチにprivate network内に閉じるようにしたら辛かったので少しゆるくした
      • Hasura Cloud使ってみたいけど英語サポートとやりとりするコストを考え踏みとどまっている
    • DB: Heroku Hobby → Amazon RDS for PostgreSQLAmazon Aurora PostgreSQL
    • Serverless Function: Serverless Framework → AWS CDK → Serverless Framework
      • デプロイ遅かったので出戻りした
    • Frontend: S3+CloudFront→ Amplify Console → Vercel
      • コスト重視から機能重視に徐々に移行できた
      • Next.jsを採用するために最近Vercelに移行
      • monorepo対応や環境変数まわりの改善に合わせて移行できてよかった
  • 日々の開発にジョインするための学習コストが非常に低い
    • docker-compose upyarn start だけで環境が立ち上がる

Hasuraを使っててつらいこと

  • 日々の開発以上のことを勉強しようとすると覚えるべきことが多い
  • パーミッションの設定には頭をつかうしレビューも難しいのでどうしても属人化する
  • 後述するセキュリティまわり等は情報が少ないので自分たちで工夫するしかない

現状の感触

  • もともと辛くなったらバックエンド書こうと考えていたけど、今はHasuraで突っ走れそうな気がしている
  • どこでパフォーマンスの問題に直面するのかが未知
    • DBで障害を起こすと辛いので割と早い段階からAurora db.t3.mediumを採用している
    • 初期にpollingで実装したところをsubscriptionに書き換えたいけど、websocketはネットワーク環境の影響を受けやすいので移行を踏みとどまっている(2ヶ月ほど)

Hasuraとセキュリティ

チェックリスト

  • 公式のProduction Checklistに従って設定すれば大丈夫
    • Production checklist | Hasura GraphQL Docs
    • 最初から全てやろうと思うと大変なので、できるところからやっていきましょう
    • ただしパーミッションの設定についてはプロダクトに依るところがあるので、自分たちで責任をもってチェックする必要がある
  • 大企業様のセキュリティチェックシートや脆弱性診断を通過しました

Actionsのパーミッション

  • Actionsでは、ロールごとに許可/拒否の2種類しかない f:id:konoki_nannoki:20201128140219p:plain
    • DBのデータをもとにパーミッションのようなことがやりたかったら、Action Handler内からHasuraにQueryを投げ返し、引っ張ってきたデータをもとにロジックを書く
    • 基本的にAction Handlerは 1つのQuery → 何かしらのロジックや外部通信 → 1つのMutation になるようにする
      • 複数の更新処理を1つのMutationにまとめることでトランザクションしてくれるので、1つのMutationにまとめるのが大原則
      • GraphQLは前のMutationの結果を拾って次のMutationに渡すことができない(知ってたら教えて下さい)
      • 奥の手としてDatabase Triggerを使う
  • Remote Schemaの場合はどうなんでしょう(あまり使っていない)

データのバリデーション

  • varchar(n) を使う(おすすめ)
    • PostgreSQLvarchar(n) 型は text に文字数制限がついたもの(MySQLとは違う)
    • DBの定義に出てくるのでわかりやすい
    • Hasura Console上の表示が微妙なのが残念...今後の改善に期待
  • Check Constraints を使う
    • 数値の大小や、カラム同士の比較が必要な場合
    • 見通しがあまりよくないので、下の方法に寄せてしまったほうがよさそう
  • ActionsやRemote Schema経由でデータを挿入する
    • 複雑なロジックが必要な場合
    • 何でもできる

実現できていないこと

  • Admin Secretが外部に漏れたら好き勝手やられてしまう
    • とはいえHasura ConsoleやMigrationがあるので、 x-hasura-admin-secret を全て拒否するのは難しい
    • 特定のIP以外だったらロードバランサ側で x-hasura-admin-secret ヘッダーをドロップすることができればよさそう
    • システム側からも x-hasura-admin-secret を持ったリクエストが飛んでくるので、そちらの考慮も必要
  • IP制限
    • マルチテナントSaaSなので、テナント毎やユーザー毎にIP制限をかけられると嬉しい
    • Auth Webhookで頑張ればいけなくもなさそうだけど、全てのクエリに対して毎回処理が走るのはしんどそう
    • Hasura CloudのAPI limitsではこれはできないよね?API limits | Hasura GraphQL Docs

まとめ

  • 0→1、1→10のフェーズのHasura採用は胸をはってオススメできる(パーミッションを理解している人が1人以上居る前提)
  • ここから先どうスケールするかはまたどこかでご報告します

宣伝

  • Hasura、TypeScript、Next.jsなスタックを実務で使ってみたいインターンや業務委託を募集しています!!
    • しんのき @konoki_nannoki までリプやDMください!まずは気軽にお話しましょう
    • フワッとした仕様を手を動かして形にしたい方大歓迎です
    • Material UI、Storybook、テストの知見があると嬉しいです
    • ゲーム、ゲームセンターが好きな人は特に楽しめると思います
      • 昨日も皆でAmong Usやりました