資料隱私權策略

資料隱私權是指保護個人識別資訊 (PII) 等資料,不讓不應存取資料的使用者存取。本頁面說明可用於保護 Cloud SQL 中 PII 的多種資料隱私權方法。

您可以使用 Cloud SQL 安全地儲存 PII。您希望確保這類資訊在處理過程中享有最高程度的隱私權保護,以免不小心遭到他人存取。舉例來說,如果您在資料庫中儲存信用卡資訊或醫療資料,可以使用 Cloud SQL 隱藏或遮蓋 PII,避免未經授權的使用者存取。

請採用下列策略,保護 Cloud SQL 中的 PII:

資料欄層級的安全防護機制

資料欄層級安全性可讓您限制哪些使用者可以查看資料庫資料表的特定欄內容。資料欄層級權限適用於 INSERTUPDATESELECTREFERENCES 陳述式。

舉例來說,假設您想在零售網站上管理兩位使用者的 PII:Jack 和 Alice。

--User: "admin"

CREATE SCHEMA secure_schema;

CREATE TABLE secure_schema.user_details(id bigint, name text, age smallint, email_id text, password text);

--For this example, passwords are stored in plain text for demonstration
--purposes only. In production, never store passwords in plain text.

INSERT INTO secure_schema.user_details VALUES(1,'jack',34,'jack@example.com','testpass');
INSERT INTO secure_schema.user_details VALUES(2,'alice',37,'alice@example.com','testpass');

GRANT USAGE ON SCHEMA secure_schema TO analyst_ro;

--Grant read permissions on specific columns only.

GRANT SELECT (id, name, age) ON secure_schema.user_details TO analyst_ro;

--User: "analyst_ro"

SELECT * FROM secure_schema.user_details;
ERROR:  permission denied for table user_details

SELECT name, age, password FROM secure_schema.user_details;
ERROR:  permission denied for table user_details

SELECT id, name,age FROM secure_schema.user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

如果您在 SELECT 陳述式中加入受限制的資料欄,或輸入 SELECT *,系統會顯示錯誤訊息。Cloud SQL 會保護這些欄位中 Jack 和 Alice 的 PII。

您也可以使用單一 GRANT 陳述式來結合不同的權限。

GRANT SELECT (id,name,age), UPDATE (name) ON secure_schema.user_details TO analyst_ro;

以檢視畫面為基礎的方法

您也可以在資料表上建立資料檢視,排除或遮蔽要隱藏的資料欄,並提供資料檢視的存取權,而非資料表的存取權,藉此實現資料欄層級的安全性。

以下範例說明如何針對零售網站使用以檢視為基礎的方法,以保護 Jack 和 Alice 的 PII:

--User: "admin"

CREATE SCHEMA analyst_ro;
CREATE VIEW analyst_ro.user_details AS SELECT id, name, age FROM secure_schema.user_details;
GRANT USAGE ON SCHEMA analyst_ro TO analyst_ro;
GRANT SELECT ON analyst_ro.user_details TO analyst_ro;

--User: "analyst_ro"

SELECT id,name,age FROM user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

SELECT * FROM user_details;
 id | name  | age
----+-------+----
  1 | jack  |  34
  2 | alice |  37

在這個範例中,系統會為檢視表建立單獨的結構定義,讓檢視表的名稱與資料表相同。採用以 View 為基礎的方法時,您可以使用 SELECT *

您也可以建立檢視畫面並遮蔽資料庫資料表的資料欄,讓沒有權限的使用者無法查看已遮蔽的 PII。

CREATE VIEW analyst_ro.user_details AS SELECT id, name, age, 'redacted@example.com' as email_id,'*****'::text as password FROM secure_schema.user_details;

SELECT * FROM user_details;
 id | name  | age |     email_id         | password
----+-------+-----+----------------------+---------
  1 | jack  |  34 | redacted@example.com | *****
  2 | alice |  37 | redacted@example.com | *****

資料列層級安全性

您可以透過資料欄層級安全性和以視圖為基礎的方法,隱藏特定使用者在資料庫資料表的資料欄中輸入的 PII。不過,有時您可能會想篩選這類資料,並授予資料表特定資料列的存取權。這份表格列出只有特定使用者可存取的 PII,取決於符合資格的使用者條件。這就是所謂的資料列層級安全性

在多租用戶應用程式中,使用者只能讀取和寫入自己的 PII,因此資料列層級安全性就很實用。在 Cloud SQL 中,資料表可以設有資料列層級安全性政策,以便針對個別使用者限制他們可透過建立查詢查看哪些資料列,或透過執行資料修改指令插入、更新或刪除哪些資料列。

以零售網站為例,您可以為 Jack 和 Alice 實作資料列層級安全性,讓他們可以查看自己的 PII,但無法修改或刪除。

--User: "admin"
--Create and enable a policy for row-level security

CREATE POLICY user_details_rls_pol ON secure_schema.user_details FOR ALL TO PUBLIC USING (name=current_user);
ALTER TABLE secure_schema.user_details ENABLE ROW LEVEL SECURITY;

SELECT * FROM secure_schema.user_details;
 id | name  | age |     email_id      | password
----+-------+-----+-------------------+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--User: "jack"

SELECT * FROM secure_schema.user_details;
 id | name | age |    email_id      | password
----+------+-----+------------------+---------
  1 | jack |  34 | jack@example.com | testpass

--User: "alice"

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+-------------------+---------
  2 | alice |  37 | alice@example.com | testpass

指派給具有 BYPASSRLS 屬性的角色的使用者,在存取資料表時可以略過資料列層級安全防護機制。資料表擁有者也可以略過資料列層級安全性。如要讓表格擁有者受到資料列層級安全性保護,請使用 ALTER TABLE ... FORCE ROW LEVEL SECURITY 指令。

有時候,您可能不想將資料列層級安全防護機制套用至資料庫資料表的資料列。舉例來說,如果您使用 pg_dump 備份資料表,則不希望備份中遺漏任何資料列。為避免發生這種情況,請為備份使用者將 row_security 設定參數設為 OFF。如果任何資料列是根據資料列層級安全性篩選,就會顯示錯誤訊息。

遮蓋及去識別化資料

除了使用以檢視畫面為基礎的方法遮蓋資料之外,您也可以使用 postgresql_anonymizer 擴充功能遮蓋資料。這個擴充功能會遮蔽或取代 PostgreSQL 資料庫中的 PII 或商業機密資料。

使用擴充功能取代以 View 為基礎的方法,可享有下列優點:

  • 您可以使用各種遮蓋函式,例如替換、隨機化、偽造、匿名化、部分雜訊、洗牌、雜訊加入和泛化。

  • 您可以產生有意義的遮罩資料,用於功能測試和資料處理。

  • 您可以使用 PostgreSQL 資料定義語言 (DDL) 宣告遮蓋規則,並在資料表定義中指定匿名化策略。

安裝及設定 postgresql_anonymizer 擴充功能

如要在 Cloud SQL 執行個體上使用這個擴充功能,請完成下列步驟:

  1. 編輯例項,然後將 cloudsql.enable_anon flag 設為 on。如要瞭解如何設定旗標,以及查看擴充功能支援的旗標,請參閱「設定資料庫標記」。

  2. 請執行下列指令,在資料庫中建立擴充功能:

    --Connect to the PostgreSQL database
    
    CREATE EXTENSION IF NOT EXISTS anon CASCADE;
    SELECT anon.init();
    

安裝及設定擴充功能後,請在執行個體上使用該擴充功能,以實作動態遮罩靜態遮罩匿名傾印匿名化策略。

動態遮罩

使用動態遮罩定義特定使用者的遮罩規則。這些使用者無法查看 PII。而是會看到經過遮蓋的資料。其他使用者則會看到未遮蓋的資料。在實際工作環境中,如果您不想變更 PII,只想隱藏特定使用者的 PII,這項功能就很實用。

以零售網站為例,您可以實作動態遮罩,讓管理員可以查看 Jack 和 Alice 的未遮罩電子郵件地址和密碼,但分析師只能查看遮罩資料。

--Activate the dynamic masking engine

SELECT anon.start_dynamic_masking();

--Declare the masking user and masking rules
--analyst_ro is the masked user with select privileges on the
--user_details table

SECURITY LABEL FOR anon ON ROLE analyst_ro IS 'MASKED';

SECURITY LABEL FOR anon ON COLUMN secure_schema.user_details.email_id IS 'MASKED WITH FUNCTION anon.fake_email()';
SECURITY LABEL FOR anon ON COLUMN secure_schema.user_details.password  IS 'MASKED WITH FUNCTION anon.hash(password)';

--User: "admin" (can see all unmasked data)

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+------------  -----+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--User:"analyst_ro" (note that the "email_id" and "password" columns are
--replaced with masked data,)
--Data in the password column is truncated for better formatting.

SELECT * FROM secure_schema.user_details;
 id | name  | age |       email_id         | password
----+-------+-----+-----------------  -----+----------------
  1 | jack  |  34 | alisontodd@example.com | 13d249f2cb4127b
  2 | alice |  37 | amanda35@example.com   | 13d249f2cb4127b

靜態遮罩

使用靜態遮罩,根據遮罩規則中定義的條件,移除資料表中的 PII,並以遮罩資料取代這些資訊。使用者無法擷取未遮蓋的資料。在測試環境中,如果您想變更 PII,但不希望任何使用者查看這項資訊,這項功能就很實用。

以零售網站為例,您可以實作靜態遮罩,讓使用者無法查看 Jack 和 Alice 未遮罩的電子郵件地址和密碼。而是只會查看已遮蓋的資料。

--User: "admin"

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id       | password
----+-------+-----+--------------  ---+---------
  1 | jack  |  34 | jack@example.com  | testpass
  2 | alice |  37 | alice@example.com | testpass

--Apply earlier defined masking rules to the table permanently.
--Now all users see masked data only.

SELECT anon.anonymize_table('secure_schema.user_details');
 anonymize_table
-----------------
 t

--User: "analyst_ro"
--Data in the password column is truncated for better formatting.

select * from secure_schema.user_details;
 id | name  | age |           email_id              |  password
----+-------+-----+-------------------------  ------+---------------
  1 | jack  |  34 | christophercampbell@example.com | 13d249f2cb412c
  2 | alice |  37 | annebenitez@example.com         | 13d249f2cb4127

匿名傾印

使用匿名傾印功能,將經過遮罩的資料匯出至 SQL 檔案。以零售網站範例來說,您可以為 user_details 資料表中含有的遮罩資料建立傾印檔案。

--Launch pg_dump_anon with the masked user to apply earlier defined --masking rules

pg_dump_anon -h HOSTIP -p 5432 -d DATABASE_NAME -U analyst_ro --table=secure_schema.user_details --file=user_details_anonysms.sql

加密資料

雖然您可以遮蓋 PII,但該資訊會以純文字形式儲存在資料庫中。管理員可以查看這項資訊。

請使用 pgcrypto 擴充功能,在儲存個人資訊時先加密。如此一來,只有擁有有效加密金鑰的使用者才能解密資訊,並以純文字形式查看。

pgcrypto 擴充功能包含多個雜湊加密函式。

雜湊

雜湊是單向密碼編譯函式,您只需要加密 PII。這項功能可用於以雜湊格式儲存密碼,並將使用者輸入的密碼與雜湊密碼比對。系統絕不會以純文字解密雜湊密碼。

以零售網站範例來說,您可以使用 pgcrypto 擴充功能對 Jack 的密碼進行雜湊運算,然後再將密碼儲存在 user_details 資料表中。

--Hash passwords before storing them in the user_details table.

TRUNCATE TABLE secure_schema.user_details;
INSERT INTO secure_schema.user_details VALUES(1,'jack',34,'jack@example.com',crypt('testpassword', gen_salt('bf')));

--Match the hashed data with user entered password

SELECT id, name FROM secure_schema.user_details WHERE email_id = 'jack@example.com' AND password = crypt('testpassword', password);
 id | name
----+-----
  1 | jack

加密

使用加密加密編譯函式,以金鑰加密 PII。使用者需要這個金鑰,才能將資訊解密為純文字。在應用程式想要以可讀格式擷取 PII 的情況下,這項功能可用於儲存信用卡資訊和銀行詳細資料。

以零售網站範例來說,Jack 的密碼和電子郵件地址會經過加密。擁有加密金鑰的使用者可以解密這項資訊,並以純文字形式查看。其他使用者則會收到錯誤訊息。

--"user_acc_key" is the encryption key

TRUNCATE TABLE secure_schema.user_details;
INSERT INTO secure_schema.user_details VALUES(1,'jack',34,pgp_sym_encrypt('jack@example.com','user_acc_key'),pgp_sym_encrypt('testpassword','user_acc_key'));

--User: "admin" (queries without an encryption key)
--Data in the email_id and password columns are truncated for better
--formatting.

SELECT * FROM secure_schema.user_details;
 id | name  | age |    email_id     | password
----+-------+-----+-----------------+-------------------
  1 | jack |  34 | \xc30d0407030209 | \xc30d040703028962

--User: "app_user" (queries with a valid encryption key)

SELECT name,pgp_sym_decrypt(email_id::bytea,'user_acc_key'),pgp_sym_decrypt(password::bytea,'user_acc_key') FROM secure_schema.user_details;
 name | pgp_sym_decrypt   | pgp_sym_decrypt
------+-------------------+----------------
 jack | jack@example.com  | testpassword

--If a user uses the wrong encryption key, then the following error message appears:

SELECT name,pgp_sym_decrypt(email_id::bytea,'user_bad_key'),
pgp_sym_decrypt(password::bytea,'user_bad_key') FROM secure_schema.user_details;
ERROR:  Wrong key or corrupt data

後續步驟

瞭解下列其他控制項,可用於保護個人識別資訊,避免遭到不當存取: