列レベルの権限管理
バージョン 8.5.6 以降、TiDB は MySQL と互換性のある列レベルの権限管理メカニズムをサポートしています。列レベルの権限を使用すると、指定したテーブルの特定の列に対してSELECT 、 INSERT UPDATE 、およびREFERENCES権限を付与または取り消すことができ、よりきめ細かなデータアクセス制御を実現できます。
注記:
MySQLの構文では
REFERENCES(col_name)のような列レベルの構文が使用できますが、REFERENCES自体は外部キー関連の権限チェックに使用されるデータベースレベルまたはテーブルレベルの権限です。そのため、列レベルのREFERENCESMySQLでは実際の列レベルの権限効果を生み出しません。TiDBの動作はMySQLと一貫しています。
構文
列レベルの権限を付与および取り消すための構文は、テーブルレベルの権限の構文と似ていますが、以下の点が異なります。
- 列名リストは、テーブル名の後ではなく、権限タイプの後に記述してください。
- 複数の列名はカンマで区切られます(
,)。
GRANT priv_type(col_name [, col_name] ...) [, priv_type(col_name [, col_name] ...)] ...
ON db_name.tbl_name
TO 'user'@'host';
REVOKE priv_type(col_name [, col_name] ...) [, priv_type(col_name [, col_name] ...)] ...
ON db_name.tbl_name
FROM 'user'@'host';
どこ:
priv_typeはSELECT、INSERT、UPDATE、およびREFERENCES。ON句では、例えばtest.tblのようにテーブルを指定する必要があります。- 単一の
GRANTまたはREVOKEステートメントには、複数の特権項目を含めることができ、各特権項目は独自の列名のリストを指定できます。
例えば、次のステートメントはSELECTのcol1に対する権限と、 col2のUPDATEのcol3に対する権限をユーザーに付与します。
GRANT SELECT(col1, col2), UPDATE(col3) ON test.tbl TO 'user'@'host';
例:列レベルの権限を付与する
次の例では、ユーザーnewuserにテーブルSELECT内のcol1およびcol2に対するtest.tbl権限を付与し、同じユーザーにUPDATEに対するcol3権限を付与します。
CREATE DATABASE IF NOT EXISTS test;
USE test;
DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl (col1 INT, col2 INT, col3 INT);
DROP USER IF EXISTS 'newuser'@'%';
CREATE USER 'newuser'@'%';
GRANT SELECT(col1, col2), UPDATE(col3) ON test.tbl TO 'newuser'@'%';
SHOW GRANTS FOR 'newuser'@'%';
+---------------------------------------------------------------------+
| Grants for newuser@% |
+---------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'newuser'@'%' |
| GRANT SELECT(col1, col2), UPDATE(col3) ON test.tbl TO 'newuser'@'%' |
+---------------------------------------------------------------------+
SHOW GRANTSを使用する以外にも、 INFORMATION_SCHEMA.COLUMN_PRIVILEGESクエリすることで列レベルの権限情報を表示することもできます。
例:列レベルの権限を取り消す
次の例は、ユーザーSELECTから列col2に対するnewuser権限を取り消します。
REVOKE SELECT(col2) ON test.tbl FROM 'newuser'@'%';
SHOW GRANTS FOR 'newuser'@'%';
+---------------------------------------------------------------+
| Grants for newuser@% |
+---------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'newuser'@'%' |
| GRANT SELECT(col1), UPDATE(col3) ON test.tbl TO 'newuser'@'%' |
+---------------------------------------------------------------+
例:列レベルの権限アクセス制御
列レベルの権限を付与または取り消した後、TiDB は SQL ステートメントで参照されている列に対して権限チェックを実行します。例:
SELECTステートメント:SELECT列の権限は、SELECTリストで参照される列、およびWHERE、ORDER BY、その他の句に影響します。UPDATEステートメント:SET句で更新される列にはUPDATE列権限が必要です。式または条件で読み込まれる列には、通常、SELECT列権限も必要です。INSERTステートメント:INSERT列の権限を必要とする列が書き込まれます。INSERT INTO t VALUES (...)テーブル定義の順序ですべての列に値を書き込むことと同じです。
次の例では、ユーザーnewuserはcol1を照会し、 col3を更新することしかできません。
-- Execute as newuser
SELECT col1 FROM tbl;
SELECT * FROM tbl; -- Error (missing SELECT column privilege for col2, col3)
UPDATE tbl SET col3 = 1;
UPDATE tbl SET col1 = 2; -- Error (missing UPDATE column privilege for col1)
UPDATE tbl SET col3 = col1;
UPDATE tbl SET col3 = col3 + 1; -- Error (missing SELECT column privilege for col3)
UPDATE tbl SET col3 = col1 WHERE col1 > 0;
MySQLとの互換性の違い
TiDBの列レベルの権限は、一般的にMySQLと互換性があります。ただし、以下のシナリオでは違いがあります。
ビューシナリオにおけるカラムの削除と権限チェック
ビューに対してSELECT権限チェックを実行する場合、MySQLとTiDBでは以下の点が異なります。
- MySQLはまずビューの内部クエリ内の列を削除し、次に内部テーブルの列権限をチェックするため、状況によってはチェックが比較的緩やかになる場合があります。
- TiDBは権限チェックの前に列の削除を行わないため、追加の列権限が必要になる場合があります。
-- Prepare the environment by logging in as root
DROP USER IF EXISTS 'u'@'%';
CREATE USER 'u'@'%';
DROP TABLE IF EXISTS t;
CREATE TABLE t (a INT, b INT, c INT, d INT);
DROP VIEW IF EXISTS v;
CREATE SQL SECURITY INVOKER VIEW v AS SELECT a, b FROM t WHERE c = 0 ORDER BY d;
GRANT SELECT ON v TO 'u'@'%';
-- Log in as u
SELECT a FROM v;
-- MySQL: Error, missing access privileges for t.a, t.c, t.d
-- TiDB: Error, missing access privileges for t.a, t.b, t.c, t.d
-- Log in as root
GRANT SELECT(a, c, d) ON t TO 'u'@'%';
-- Log in as u
SELECT a FROM v;
-- MySQL: Success (internal query is pruned to `SELECT a FROM t WHERE c = 0 ORDER BY d`)
-- TiDB: Error, missing access privileges for t.b
SELECT * FROM v;
-- MySQL: Error, missing access privileges for t.b
-- TiDB: Error, missing access privileges for t.b
-- Log in as root
GRANT SELECT(b) ON t TO 'u'@'%';
-- Log in as u
SELECT * FROM v;
-- MySQL: Success
-- TiDB: Success