🔒
フロントエンドエンジニアがpostgresのRLSで大ゴケした記録
RLSとは
Row-Level Securityの略で、これが有効化されたテーブルではレコードレベルで読み書きの権限を設定できる。考え方はfirestoreのセキュリティルールと同じ。
また、DBレベルでのセキュリティなのでapiを違う言語にするときも楽。その代わりDBにロジックが集まってdbは大変
重要だったポイント
-
ALTER TABLE User ENABLE ROW LEVEL SECURITY;
のように明示的に書く必要がある。 - RLSが有効な場合、デフォルトでは何も権限が与えられていない。
- スーパーユーザー(rootのような)やテーブルの所有者、BYPASSRLS権限やUNRESTRICTED_TABLE権限持つロールは、RLSが有効化されていても無視する。
- insertだけ権限を与えても追加できない。insertのあとに読み取りを行うためらしい。したがってselectにも権限を与える必要がある。
例
開発環境なので適当にrootとして接続していた
postgraphileで接続していたが、postgres://root:password@localhost:5432/testdb
のようにしていた。ユーザーがrootなのでRLSは効かない。
解決策は以下など
- pgSettingsとかdefaultRoleとか使ってリクエストごとに権限を絞ったユーザーを指定する
- 本番ではrootでログインしない(絶対に)
動作確認時にselect忘れ
以下のsqlだけでは動かない
ALTER TABLE User ENABLE ROW LEVEL SECURITY;
CREATE POLICY insert_user ON User FOR INSERT WITH CHECK(true);
初めて触るときこんな感じにtrueとfalseを切り替えて試そうとしたが、これはselectの権限がないため動かなかった。したがってとりあえず動くのを見たいなら、以下のようにすればok。
ALTER TABLE User ENABLE ROW LEVEL SECURITY;
CREATE POLICY insert_user ON User FOR INSERT WITH CHECK(true);
CREATE POLICY insert_user ON User FOR SELECT USING(true);
まとめ
乗り越えると大したことじゃないですね。エンジニアあるあるだと思います。
フィシルコムのテックブログです。マーケティングSaaSを開発しています。 マイクロサービス・AWS・NextJS・Golang・GraphQLに関する発信が多めです。 カジュアル面談はこちら(ficilcom.notion.site/bbceed45c3e8471691ee4076250cd4b1)から
Discussion