列レベルの権限
機密性の高い列を非表示にします。
「列レベルの権限」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
列レベル権限が重要な理由
すべてのユーザーに、テーブル内のすべての列を見せるべきとは限りません。salary 列、password_hash、credit_card_number などは、ユーザー名やメールアドレスのような一般公開可能なデータと同じテーブルに保存されている場合があります。
列レベル権限を使うと、テーブル全体ではなく特定の列へのアクセスだけを許可できます。これにより、閲覧する業務上の理由がないユーザーから機密データを隠せます。
テーブル全体に対する GRANT
デフォルトでは、GRANT SELECT ON table によって、ロールはすべての列を読み取れるようになります。一般公開データには適していますが、機密列と非機密列が混在するテーブルでは問題になります。
以下のクエリは、analyst ロールに employees テーブルへの完全な読み取りアクセスを付与します。salary と SSN も含め、すべての列を読み取れるようになります。
GRANT SELECT ON employees TO analyst;列レベル GRANT の構文
PostgreSQL(および標準 SQL)では、GRANT 文の中に特定の列名を列挙できます。構文は次のとおりです。
GRANT privilege (col1, col2) ON table TO role;
以下の例では、analyst ロールに id、name、department の読み取り権限だけを付与します。salary と ssn は読み取れません。
GRANT SELECT (id, name, department) ON employees TO analyst;列権限の確認
PostgreSQL では、information_schema.column_privileges ビューをクエリして、列レベルの権限を確認できます。このビューには、どの権限受領者が、どの列に対して、どの権限を持っているかが一覧表示されます。
SELECT grantee, table_name, column_name, privilege_type
FROM information_schema.column_privileges
WHERE table_name = 'employees'
ORDER BY grantee, column_name;適切な列への権限がない場合の動作
ロールがアクセス権を付与されていない列を読み取ろうとすると、データベースは permission denied エラーを返します。アクセスを許可された列だけを参照する場合に限り、成功します。
analyst に id、name、department だけが付与されているとすると、以下の最初のクエリは失敗し、2番目のクエリは成功します。
-- This will fail for analyst (no permission on salary):
-- SELECT id, name, salary FROM employees;
-- This succeeds:
SELECT id, name, department FROM employees;列レベルの UPDATE 権限
列レベルの制限は UPDATE にも適用されます。特定の列だけを更新できるようにロールを設定できます。たとえば、ヘルプデスク用ロールにユーザーの status の更新を許可し、email や password_hash は変更できないようにできます。
GRANT UPDATE (status) ON users TO helpdesk;
-- helpdesk can now run:
UPDATE users SET status = 'suspended' WHERE id = 42;ビューによる列の非表示
別の一般的な方法として、安全な列だけを公開する view を作成し、ベーステーブルではなくそのビューへのアクセスを許可できます。これは、列レベルの GRANT をサポートするデータベースに限らず、すべてのデータベースで利用できます。
CREATE VIEW public_employees AS
SELECT id, name, department, hire_date
FROM employees;
GRANT SELECT ON public_employees TO analyst;列レベルのアクセス権の取り消し
GRANT と同様に、列リストを指定した REVOKE を使って、特定の列へのアクセス権を削除できます。ロールにテーブル全体への広範なアクセス権がある場合は、制限付きの列レベルアクセスを付与する前に、その権限を完全に取り消す必要がある場合があります。
-- Remove all SELECT on the table first
REVOKE SELECT ON employees FROM analyst;
-- Then grant only safe columns
GRANT SELECT (id, name, department) ON employees TO analyst;列権限と行レベルセキュリティの併用
列レベル権限と行レベルセキュリティ(RLS)は、互いに補完する仕組みです。RLS はユーザーが参照できる行を制御し、列レベル権限は、その行の中で表示できる列を制御します。
この2つを組み合わせることで、2次元の強力なアクセス制御を実現できます。対象となる行を制限し、さらに各行内の機密フィールドを非表示にできます。
-- RLS policy: employees can see only their own row
CREATE POLICY own_row ON employees
FOR SELECT
USING (user_id = current_user_id());
-- Column grant: hide salary even for own row
GRANT SELECT (id, name, department) ON employees TO employee_role;Security-Definer 関数の使用
単純な列リストでは対応できないきめ細かなロジックが必要な場合は、SECURITY DEFINER 関数を橋渡しとして利用できます。この関数は所有者(すべての列にアクセスできる権限を持つユーザー)の権限で実行され、呼び出したユーザーにかかわらず、公開するように指定したデータだけを返します。
CREATE OR REPLACE FUNCTION get_employee_summary(emp_id INT)
RETURNS TABLE(id INT, name TEXT, department TEXT)
SECURITY DEFINER
LANGUAGE sql AS
$$
SELECT id, name, department
FROM employees
WHERE id = emp_id;
$$;
GRANT EXECUTE ON FUNCTION get_employee_summary(INT) TO analyst;実践的な設計: 多層的な列セキュリティ
堅牢な本番環境のパターンでは、次の3つの層を組み合わせます。
- テーブル所有権 — ベーステーブルの所有者をアプリのサービスアカウントだけにします。
- ビューまたは列 GRANT — 読み取り用ロールには、機密性のない列だけへのアクセスを許可します。
- 監査列 — トリガーを使って、機密データにアクセスしたユーザーとタイムスタンプを記録します。
これにより、ある層でロールに誤って過剰な権限が付与されても、他の層でデータを保護できます。
-- Layer 1: revoke public access
REVOKE ALL ON employees FROM PUBLIC;
-- Layer 2: expose safe columns via view
CREATE VIEW employee_public AS
SELECT id, name, department, hire_date FROM employees;
GRANT SELECT ON employee_public TO reporting_role;
-- Layer 3: audit trigger logs sensitive field reads (pseudocode)
-- CREATE TRIGGER audit_salary AFTER SELECT ON employees ...クイックチェック
employees テーブルの name 列と department 列だけを読み取れる権限を hr_viewer ロールに正しく付与する SQL 文はどれでしょうか。
まとめ: 列レベル権限
列レベル権限を使うと、テーブル全体ではなく個々のフィールドへのアクセスを制限できます。これにより、給与、SSN、パスワードハッシュなどの機密データを、権限のないロールから隠せます。
重要なポイント:
GRANT SELECT (col1, col2) ON table TO roleを使用して、読み取り可能な列を制限します。- 列リストを指定した
REVOKEを使用して、特定の列へのアクセス権を削除します。 - ビューは、すべてのデータベースで利用できる移植性の高い代替手段です。
- 列レベル権限と RLS を組み合わせて、2次元のアクセス制御を実現します。
- SECURITY DEFINER 関数を使うと、追加のロジックを含むプログラムによる列レベルのフィルタリングを実装できます。
列レベルセキュリティを一貫して適用することは、データ層で最小権限の原則を実現する、最も簡単で効果的な方法の1つです。
よくある質問
「列レベルの権限」レッスンは無料ですか?
はい。「列レベルの権限」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「列レベルの権限」で何を学びますか?
機密性の高い列を非表示にします。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「列レベルの権限」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。