UPDATE構文のセキュリティモデル
今日は、SQLのUPDATE構文実行時に強制アクセス制御を実行するためのコードを実装した。
UPDATE構文の実行時には、以下のパーミッションがチェックされる。
- UPDATEを行うテーブルに対する table:update 権限
- UPDATEを行うカラムに対する column:update 権限
- UPDATEを行うタプルに対する tuple:update 権限
- UPDATE条件句でカラムが指定されていた場合、カラムに対する column:select 権限と、そのカラムが属するテーブルに対する table:select 権限
- UPDATE条件句で関数を使用する場合、関数に対する procedure:execute 権限
- さらにこの関数がドメイン遷移を引き起こす場合、procedure:entrypoint 権限
- UPDATEはセキュリティコンテキスト行を更新しようとする場合、tuple:{relabelfrom relabelto}権限
UPDATE構文は最も単純なDDL命令の一つなので、これで網羅できてしまう。モデル的にはこれでOKだと思う。
但し、例外があり、pg_database, pg_class, pg_attribute, pg_proc, pg_largeobject の各テーブルを更新する場合には特別な操作が必要になる。なぜなら、これらのテーブルはシステムカタログと呼ばれる特殊なテーブルで、例えば pg_class はテーブルのメタデータを保持しており、pg_proc は関数のメタデータを保持している。
このため、SE-PgSQLはこれらのテーブルへのアクセスをメタ情報の参照として扱い、一般のテーブルとは異なった権限を必要とするように設計してある。
例えば、pg_classテーブルへの SELECT 操作は、pg_classテーブルへの table:select 権限のほかに、pg_classテーブルの各タプルによって表現されているテーブルへのメタ情報の参照、即ち table:getattr 権限を必要とする。
同様に、pg_classテーブルへの UPDATE 操作は table:setattr で、DELETE 操作は table:drop と等価となる。通常、これらのシステムカタログは CREATE TABLE 文によって自動的に生成されるため、ユーザは意識しないが、UPDATE文などのDDL構文によってもアクセスが可能であるため、このような扱いが必要になる。
あと、PostgreSQLでちょっと面倒なのがテーブルの継承の扱いだけれども、、、これは後の宿題にしておくか。