🔒

フロントエンドエンジニアがpostgresのRLSで大ゴケした記録

2023/03/10に公開

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);

まとめ

乗り越えると大したことじゃないですね。エンジニアあるあるだと思います。

フィシルコム

Discussion