$30 off During Our Annual Pro Sale. View Details »

Row Level Securityはマルチテナントの銀の弾丸になりうるのか / Row Level Security is silver bullet for multitenancy?

yudppp
August 31, 2019

Row Level Securityはマルチテナントの銀の弾丸になりうるのか / Row Level Security is silver bullet for multitenancy?

builderscon 2019の発表資料です

yudppp

August 31, 2019
Tweet

More Decks by yudppp

Other Decks in Technology

Transcript

  1. RowLevelSecurityは
    マルチテナントの
    銀の弾丸になりうるのか
    #builderscon 2019 (20 min)

    View Slide

  2. ⾃⼰紹介
    @yudppp
    株式会社HRBrain CTO
    好きな⾔葉: 冪等性
    Go / TypeScript / React
    ○△□ - https://blog.yudppp.com/
    いつかSaaSのDevカンファレンス開くのが夢

    View Slide

  3. ⽬標評価管理クラウド

    View Slide

  4. 導⼊企業500社以上の
    HRTechのSaaSを
    週2リリースのペースで
    運⽤・改善を
    ⾏なっています。

    View Slide

  5. テナントとは
    • SaaSを利⽤する組織の単位のこと
    • HRBrainだと企業のこと
    • HRBrainだと企業の中にユーザーがいる
    • テナント間でのデータをやりとりはしない

    View Slide

  6. SaaSのアーキテクチャ

    View Slide

  7. アーキテクチャ
    • シングルテナントアーキテクチャ(ASP)
    • マルチテナントアーキテクチャ(SaaS)

    View Slide

  8. シングルテナントアーキテクチャ
    اۀ" اۀ# اۀ$
    اۀ"޲͚

    "1αʔόʔ
    اۀ"޲͚

    %#
    اۀ"޲͚

    Πϯϑϥ
    اۀ#޲͚

    "1αʔόʔ
    اۀ#޲͚

    %#
    اۀ#޲͚

    Πϯϑϥ
    اۀ$޲͚

    "1αʔόʔ
    اۀ$޲͚

    %#
    اۀ$޲͚

    Πϯϑϥ

    View Slide

  9. シングルテナントのメリット
    • ⽐較的安全
    • 特定のテナントでアクセスが増えても場合に
    他の会社は影響を受けない
    • DB障害時の影響範囲がテナントごとになる

    View Slide

  10. シングルテナントのデメリット
    • サーバーが完全に分かれているのでデプロイ
    をテナントごとに⾏う必要がある
    • テナントごとにサーバーを⽤意するためコス
    トがかかる
    • 単価がすごく⾼く、リリース頻度が少ないも
    のであれば成り⽴つ

    View Slide

  11. マルチテナントとは
    • ⼀つのシステムで複数利⽤者組織の情報やア
    プリケーションを管理すること
    ࢀߟ4BB4޲͚4-"ΨΠυϥΠϯܦࡁ࢈ۀল
    IUUQXBSQEBOEMHPKQJOGPOEMKQQJEXXXNFUJHPKQDPNNJUUFFNBUFSJBMTEPXOMPBEpMFTHDKQEG

    View Slide

  12. マルチテナントアーキテクチャの種類
    • クラウド内での単純な仮想化により、ハード
    ウェアのみを共有
    • 1つのアプリケーションで、テナントごとに
    異なるデータベースを使⽤
    • 1つのアプリケーションでデータベースを共
    有 (最も効率的な真のマルチテナンシー)
    ࢀߟ8FCΞϓϦέʔγϣϯΛϚϧνςφϯτܕ4BB4ιϦϡʔγϣϯʹม׵͢Δ
    IUUQTXXXJCNDPNEFWFMPQFSXPSLTKQDMPVEMJCSBSZDMNVMUJUFOBOUTBBTJOEFYIUNM

    View Slide

  13. 1つのクラウドサーバーに全ての企業
    اۀ" اۀ# اۀ$
    اۀ"޲͚

    "1αʔόʔ
    اۀ"޲͚

    %#
    اۀ#޲͚

    "1αʔόʔ
    اۀ#޲͚

    %#
    اۀ$޲͚

    "1αʔόʔ
    اۀ$޲͚

    %#

    View Slide

  14. 1つのクラウドサーバーに全ての企業のメリット
    • 1テナントごとのスケールはしやすい
    • アプリケーションのリリースがテナントごと
    にできる(テナントごとに異なるVersionのア
    プリケーションがありえる)
    • 特定のテナントでアクセスが増えても場合に
    他の会社は影響を受けにくい

    View Slide

  15. 1つのクラウドサーバーに全ての企業のデメリット
    • テナントごとにアプリケーションサーバーや
    データベースを個別に⽤意する必要がありコ
    ストが⾼い
    • デプロイをテナントごとに⾏う必要がある。
    • こちらをシングルアーキテクチャに含めてし
    まう場合もある

    View Slide

  16. 1つのアプリケーションで異なるDBを使⽤
    اۀ" اۀ# اۀ$
    اۀ"޲͚

    %#
    "1αʔόʔ
    اۀ#޲͚

    %#
    اۀ$޲͚

    %#

    View Slide

  17. • 物理データベースは1つで論理データベース
    を分けているケースが多そう
    • アプリケーションは全てのテナントで同じ
    サーバーを利⽤する
    • DBを⽔平分割している状態に近いのでDB⽬
    線ではスケールさせやすい
    1つのアプリケーションで異なるDBを使⽤のメリット

    View Slide

  18. • DBのスキーマ変更のマイグレーションをテナ
    ントごとに⾏う必要がある
    1つのアプリケーションで異なるDBを使⽤のデメリット

    View Slide

  19. 1 つのアプリケーションでDBを共有
    اۀ" اۀ# اۀ$
    "1αʔόʔ
    %#

    View Slide

  20. • 最も効率的な真のマルチテナンシー
    • スキーマの変更のマイグレーションの更新が
    ⼀回で済む
    • インフラコストが⼀番安くなる
    1 つのアプリケーションでDBを共有のメリット

    View Slide

  21. • DBに障害が起きた時に全テナントが影響を受
    ける
    • アプリケーションが複雑になりやすい
    • セキュリティに不安がある
    1 つのアプリケーションでDBを共有のデメリット

    View Slide

  22. どんな不安があるのか
    • あるテナントが別のテナントのデータを⾒れ
    てしまう可能性がある(data violation)

    View Slide

  23. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    こんな感じのusersテーブルがあった時に

    View Slide

  24. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    本来Where句を指定するところを
    4&-&$5'30.VTFST

    8)&3&UFOBOU@JElձࣾ#z

    View Slide

  25. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    本来Where句を指定するところを
    4&-&$5'30.VTFST

    8)&3&UFOBOU@JElձࣾ#z

    View Slide

  26. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    Where句を指定忘れてしまうと
    4&-&$5'30.VTFST

    View Slide

  27. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    Where句を指定忘れてしまうと
    4&-&$5'30.VTFST
    ΋ͪΖΜ
    શͯͷձࣾͷ
    ϝϯόʔ৘ใ͕
    औΕͯ͠·͏

    View Slide

  28. 複雑なアプリケーションになると
    絶対起きないとはいえない

    View Slide

  29. これらのメリデメを受けて
    弊社のケースについて考える

    View Slide

  30. 導⼊企業500社以上の
    HRTechのSaaSを
    週2リリースのペースで
    運⽤・改善を
    ⾏なっています。
    弊社のケース(再訂)

    View Slide

  31. ビジネスモデル的に
    100社導⼊しただけでは
    会社が成り⽴たない

    View Slide

  32. マルチテナントアーキテクチャ(再訂)
    • クラウド内での単純な仮想化により、ハード
    ウェアのみを共有
    • 1つのアプリケーションで、テナントごとに
    異なるデータベースを使⽤
    • 1つのアプリケーションでデータベースを共
    有 (最も効率的な真のマルチテナンシー)

    View Slide

  33. リリース後も
    継続的に機能追加によって
    スキーマ変更が必要に
    なることがわかっていた

    View Slide

  34. マルチテナントアーキテクチャ(再訂)
    • クラウド内での単純な仮想化により、ハード
    ウェアのみを共有
    • 1つのアプリケーションで、テナントごとに
    異なるデータベースを使⽤
    • 1つのアプリケーションでデータベースを共
    有 (最も効率的な真のマルチテナンシー)

    View Slide

  35. ⽬標や評価の情報は
    もちろんとても⼤事

    (⽬標が他の会社に漏れたら⼤問題)

    View Slide

  36. マルチテナントアーキテクチャ(再訂)
    • クラウド内での単純な仮想化により、ハード
    ウェアのみを共有
    • 1つのアプリケーションで、テナントごとに
    異なるデータベースを使⽤
    • 1つのアプリケーションでデータベースを共
    有 (最も効率的な真のマルチテナンシー)

    View Slide

  37. 全ての選択肢が
    なくなってしまった、、、

    View Slide

  38. 何かを犠牲にするしか、、

    View Slide

  39. 事例について
    調べて⾒た

    View Slide

  40. Bit Journeyさん
    • apartment gemを利⽤
    • 1つのアプリケーションで、テナントごとに
    異なるデータベースを使⽤した場合に便利に
    なるライブラリー?
    ࢀߟSBJMTENͰϚϧνςφϯτɾ΢ΣϒΞϓϦͷ࿩Λ͠·ͨ͠
    IUUQTHGYIBUFOBCMPHDPNFOUSZ

    View Slide

  41. SmartHRさん
    • apartment gemからCitus Cloud(DBaaS)へ移

    • マイグレーションは⾟くなりがち
    • なるほど:thinking:
    ࢀߟͭΒ͘ͳ͍ϚϧνςφϯγʔΛٻΊͯશͯݟͤ·͢ʂ4NBSU)3σʔλϕʔεҠߦϓϩδΣΫτͷཪଆ
    IUUQTTQFBLFSEFDLDPNQVSJOUBJCVJMEFSTDPO

    View Slide

  42. Viewを使ってマルチテナントを実現する⽅法
    • 最も効率的な真のマルチテナンシーをViewを使って実現
    する
    • テナント×テーブルごとにViewを作り権限管理を⾏う。
    • SELECT/UPDATE/DELETEに対してはViewから⾏う
    • INSERTはオリジナルのテーブルに⾏う必要があり安全
    かどうかはアプリケーションの実装依存になってしま
    う。

    View Slide

  43. 他にも⾊んな⼈に聞いたり、
    調べたりしているうちに
    ⾒つけた

    View Slide

  44. 我らの銀の弾丸

    View Slide

  45. Row Level Security

    View Slide

  46. Row Level Securityとは
    • データベーステーブル内の⾏へのアクセスを
    制御できる
    • OracleやPostgreSQL(9.5以上)やSQL
    Server(13.x以上) などで実装されている
    • (以降RLSとする。)

    View Slide

  47. 権限ごとにRoleを作って
    ୅දऔక໾ Ϧʔμʔ ϝϯόʔ
    શͯݟ͑Δਓ ࣗ෼ͷ
    νʔϜϝϯόʔͷΈ
    ݟ͑Δਓ
    ࣗ෼ͷ৘ใͷΈ
    ݟ͑Δਓ

    View Slide

  48. ୅දऔక໾
    ։ൃϦʔμʔ
    ։ൃϝϯόʔ
    Ӧۀ
    こんな感じのusersテーブルがあった時に

    View Slide

  49. ୅දऔక໾
    Ӧۀ
    代表取締役のロールでアクセスすると
    4&-&$5'30.VTFST
    ։ൃϦʔμʔ
    ։ൃϝϯόʔ

    View Slide

  50. ୅දऔక໾
    Ӧۀ
    代表取締役のロールでアクセスすると
    શͯݟ͑Δ
    4&-&$5'30.VTFST
    ։ൃϦʔμʔ
    ։ൃϝϯόʔ

    View Slide

  51. ୅දऔక໾
    Ӧۀ
    開発リーダーのロールでアクセスすると
    4&-&$5'30.VTFST
    ։ൃϦʔμʔ
    ։ൃϝϯόʔ

    View Slide

  52. ୅දऔక໾
    Ӧۀ
    開発リーダーのロールでアクセスすると
    ։ൃϝϯόʔͷ
    ৘ใͷΈݟ͑Δ
    4&-&$5'30.VTFST
    ։ൃϦʔμʔ
    ։ൃϝϯόʔ

    View Slide

  53. 雑なQuery叩いても

    権限範囲のデータしか
    ⾒えなくて安全

    View Slide

  54. マルチテナントに応⽤していく

    View Slide

  55. テナントごとにRoleを作る
    اۀ"
    اۀ"ͷ৘ใͷΈ
    ݟ͑Δ
    اۀ#
    اۀ#ͷ৘ใͷΈ
    ݟ͑Δ
    اۀ$
    اۀ$ͷ৘ใͷΈ
    ݟ͑Δ

    View Slide

  56. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    こんな感じのusersテーブルがあった時に

    View Slide

  57. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    会社Bのロールでアクセスすると
    4&-&$5'30.VTFST

    View Slide

  58. ձࣾ"
    ձࣾ#
    ձࣾ#
    ձࣾ$
    会社Bのロールでアクセスすると
    4&-&$5'30.VTFST
    ձࣾ#ͷϝϯόʔͷ
    ৘ใͷΈݟ͑Δ

    View Slide

  59. これは安⼼!

    View Slide

  60. Tableの実体⾃体は
    全てのテナントで共通なので
    マイグレーションも楽々

    View Slide

  61. 実際に導⼊してみました
    (PostgreSQL v10.4)

    View Slide

  62. 最初の実装や検証が
    ⼤変そうだったけど
    なんとか導⼊しました。

    (リリース三ヶ⽉前に⾃分以外のメンバーが1ヶ⽉くらいで諸々対応してくれた記憶)

    View Slide

  63. どうやっているか①
    • 全てのテーブルにcompany_idのカラムを⽤意
    • サブドメインをテナントごとに追加する
    • Ex) mosquitone.hrbrain.jp

    View Slide

  64. どうやっているか②
    • テナントごとにロールを⽤意
    • RLSを利⽤するテーブルに下記のPolicyを追加
    • テナントごとに別のコネクションを使う

    View Slide

  65. そしてリリース1ヶ⽉半前

    View Slide

  66. ⼤量のデータを⼊れて
    確認していた時に
    問題が発覚した

    View Slide

  67. GET /usersheets 1.8[sec]

    View Slide

  68. pprofで諸々確認

    (GoのPeformance計測ツール)

    View Slide

  69. DBアクセスしている層が
    想定より数倍遅い

    View Slide

  70. :thinking:

    View Slide

  71. ⼀度試しにRLSを
    使わないでみたら

    View Slide

  72. レイテンシーが4分の1に

    View Slide

  73. RLSを⼊れたことによって
    起きていることはわかった

    View Slide

  74. ただ安全第⼀

    RLSをやめる訳にはいかない

    View Slide

  75. N+1とIndex周りの修正をして
    1秒以内にできたのでリリース

    View Slide

  76. ただし根本解決はされないまま

    View Slide

  77. リリース後の落ち着いた
    タイミングで再挑戦

    View Slide

  78. 検証結果

    View Slide

  79. コネクションの使い⽅
    • RLSを利⽤していない時は全てのコネクショ
    ンプールをまとめて管理していた。
    • RLSを利⽤時はテナントごとにロールを作っ
    ていた結果、コネクション管理が煩雑になっ
    ていて、そこでオーバーヘッドが⽣じてい
    た。

    View Slide

  80. リクエストごとにコネクションを張るように変更
    • Middlewareでコネクションを発⾏して、
    contextに詰める(本当はcontext使いたくない)
    • リクエストの終了時にClose

    View Slide

  81. リクエストごとにコネクション貼ってみた結果
    • 遅かった特定のAPIで調査
    • 中央値、平均値を⾒る限りすごく速くなった。
    • 速くなったが詰まる時は詰まってそう。
    NFBO λΠϧ λΠϧ λΠϧ NBY
    #FGPSF NT NT NT NT T
    "GUFS NT NT NT NT NT

    View Slide

  82. テナントごとのロールについて
    • RLSを適応したい全てのテーブルに下記のような
    POLICYを追加していた。
    • current_userを⽤いて、dbのユーザーをどの⾏に
    対して権限があるかを判断していた。

    View Slide

  83. Indexについて
    • テーブルに下記のUNIQUE INDEXを貼っていた
    • リクエスト⾃体は
    • 叩いた時にindexが効いていなかった。

    View Slide

  84. EXPLAIN結果
    • 全件検索してからFilterしている、、

    View Slide

  85. EXPLAIN結果
    • company_idを必ずつけるようにすれば問題起きなかった。

    View Slide

  86. USINGしている中⾝がよくない
    • ロール名に直接company_idではなく
    prefixをつけていたそのせいで⾃動で
    INDEX効いていなかった
    • もともと数字だけでやろうとしていたが
    ロール名に数字始まりはInvalidだった。

    View Slide

  87. ロールの作り⽅を変更した
    • 下記のようにcurrent_settingを利⽤したPOLICYを
    作成すればテナントごとのロールが不要だった。
    • またこの場合はリクエストごとに予めテナントを
    セットしておく必要がある

    View Slide

  88. EXPLAIN結果
    • ちゃんとINDEXかかった!
    • どちらにしてもcompany_id始まりのINDEXを貼るべき

    View Slide

  89. クエリーパフォーマンス
    • ある簡単なAPIを並列で実⾏した時に1.4倍くらい時間
    がかかるようになっていた
    λΠϧ λΠϧ λΠϧ
    3-4ͳ͠ NT NT NT
    3-4͋Γ NT NT NT

    View Slide

  90. 結論

    View Slide

  91. 銀の弾丸ではなかった。

    View Slide

  92. マルチテナントにRLSを使うメリット
    • 安全に「最も効率的な真のマルチテナン
    シー」が実現できた。

    View Slide

  93. マルチテナントにRLSを使うデメリット
    • コネクションの管理が煩雑になってしまっ
    た。
    • パフォーマンスが多少悪くなる。
    • 導⼊事例が少なく検証しないとわからないこ
    とが多い。

    View Slide

  94. この先使う上での不安事項
    • DBを⽔平分割していく必要が出た場合にどうするか
    • マイクロサービスにしてDBも垂直分割していく想
    定はあるが、それでも増えた時にどうするか
    • 今利⽤されている⼈数の10倍、20倍のテナントが
    ⼊ってきた場合に問題なくRLSが動くのか
    • テナントをまたがるユーザーを作りたくなった時にど
    うするか

    View Slide

  95. まとめ
    • SaaS作る時にパフォーマンスをそこまでシビ
    アに作る必要がないものを安全に作りたいの
    であればオススメ
    • データが増えた時にまた別の対策が必要

    View Slide

  96. 参考資料
    • SaaS 向け SLA ガイドライン - 経済産業省 (http://warp.da.ndl.go.jp/info:ndljp/pid/
    11094748/www.meti.go.jp/committee/materials/downloadfiles/g80207c05j.pdf)
    • マルチテナント SaaS データベース テナント パターン(https://docs.microsoft.com/ja-
    jp/azure/sql-database/saas-tenancy-app-design-patterns)
    • Web アプリケーションをマルチテナント型 SaaS ソリューションに変換する(https://
    www.ibm.com/developerworks/jp/cloud/library/cl-multitenantsaas/index.html)
    • PostgreSQL: Documentation: 11: 5.7. Row Security Policies (https://
    www.postgresql.org/docs/current/ddl-rowsecurity.html)
    • PostgreSQLのRow Level Securityを使ってマルチテナントデータを安全に扱う -
    HRBrain blog (https://times.hrbrain.co.jp/entry/postgresql-row-level-security)

    View Slide