資料隱私權是指保護個人識別資訊 (PII) 等資料,避免不應存取這些資料的人員存取。本頁面說明幾種資料隱私權方法,可用於保護 Cloud SQL 中的 PII。
您可以使用 Cloud SQL 安全地儲存 PII。您希望確保這類資訊受到最高等級的隱私保護服務,以免在無意間遭到存取。舉例來說,如果您在資料庫中儲存信用卡資訊或健康照護資料,可以使用 Cloud SQL 向沒有權限的使用者隱藏或遮蓋 PII。
請採用下列策略,確保 Cloud SQL 中的 PII 安全無虞:
資料欄層級的安全防護機制
資料欄層級安全性可限制哪些使用者能查看資料庫資料表特定資料欄的內容。資料欄層級的權限適用於 INSERT、UPDATE、SELECT 和 REFERENCES 陳述式。
舉例來說,假設您想控管零售網站上兩位使用者 (Jack 和 Alice) 的 PII。
--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 OR REPLACE 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 或商業機密資料。
相較於以檢視區塊為基礎的方法,使用擴充功能可享有下列優點:
您可以使用各種遮蓋函式,例如替代、隨機化、偽造、匿名化、部分擾亂、重組、加入雜訊和一般化。
您可以產生有意義的遮蓋資料,用於功能測試和資料處理。
您可以使用 PostgreSQL 資料定義語言 (DDL) 宣告遮蓋規則,並在資料表定義中指定匿名化策略。
安裝及設定 postgresql_anonymizer 擴充功能
如要在 Cloud SQL 執行個體上使用這項擴充功能,請完成下列步驟:
編輯例項,然後將
cloudsql.enable_anon旗標設為on。如要瞭解如何設定旗標,以及查看擴充功能支援的旗標,請參閱「設定資料庫旗標」。如果您打算使用動態遮蓋,但要遮蓋的資料表不在
public結構定義中,請將anon.sourceschema旗標設為包含這些資料表的結構定義名稱。在本頁的範例中,請將旗標設為secure_schema。執行下列指令,在資料庫中建立擴充功能:
--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)';
--Verify that the masked user is configured. The search_path must include
--the mask schema followed by the schema set in the anon.sourceschema flag.
SELECT rolconfig FROM pg_roles WHERE rolname = 'analyst_ro';
rolconfig
--------------------------------------
{"search_path=mask, secure_schema"}
--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" (open a new connection; 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 user_details;
id | name | age | email_id | password
----+-------+-----+------------------------+-----------------
1 | jack | 34 | alisontodd@example.com | 13d249f2cb4127b
2 | alice | 37 | amanda35@example.com | 13d249f2cb4127b
--The masked user can't query the source table directly.
SELECT * FROM secure_schema.user_details;
ERROR: permission denied for schema secure_schema
開始動態遮蓋時,擴充功能會為 anon.sourceschema 旗標設定的結構定義中每個資料表,在 mask 結構定義中建立檢視畫面。將角色標示為 MASKED 時,擴充功能會執行下列操作:
- 撤銷直接授予來源結構定義角色的權限。
- 授予角色
mask結構定義的USAGE權限,以及其中每個檢視區塊的SELECT權限,包括角色先前無法查詢的資料表檢視區塊。 - 將角色的
search_path設為mask結構定義,然後是來源結構定義。
遮蓋使用者查詢資料表時,如果未指定結構定義名稱,名稱會解析為 mask 結構定義中的檢視區塊,這時使用者只會看到遮蓋資料。指定結構定義名稱 (例如 SELECT * FROM secure_schema.user_details) 的查詢會略過 mask 結構定義,並因權限錯誤而失敗。search_path 設定會在使用者連線時套用,因此遮蓋的使用者必須在您標記角色後開啟新連線。
靜態遮罩
根據遮蓋規則中定義的條件,使用靜態遮蓋移除資料表中的 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 | 13d249f2cb4127b
2 | alice | 37 | annebenitez@example.com | 13d249f2cb4127b
匿名傾印
使用匿名傾印將遮蓋資料匯出至 SQL 檔案。以零售網站為例,您可以為 user_details 資料表中的遮蓋資料建立 dump 檔案。
--Launch pg_dump_anon to apply earlier defined masking rules. pg_dump_anon
--reads the source table directly, so connect as a user that has the SELECT
--privilege on the table and that isn't labeled as MASKED.
pg_dump_anon -h HOSTIP -p 5432 -d DATABASE_NAME -U admin --table=secure_schema.user_details --file=user_details_anonymized.sql
加密資料
雖然您可以遮蓋 PII,但資訊會以純文字形式儲存在資料庫中。管理員可以查看這項資訊。
使用 pgcrypto 擴充功能加密 PII,再儲存。這樣一來,只有擁有有效加密金鑰的使用者才能解密資訊,並以純文字形式查看。
雜湊
雜湊是單向加密函式,您只須加密 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
後續步驟
瞭解下列額外控管措施,保護 PII 免於未經授權的存取: