데이터 개인 정보 보호는 개인 식별 정보(PII)와 같은 데이터를 이 데이터에 액세스하면 안 되는 사용자로부터 보호합니다. 이 페이지에서는 Cloud SQL에서 PII를 보호하는 데 사용할 수 있는 몇 가지 데이터 개인 정보 보호 접근 방식을 설명합니다.
Cloud SQL을 사용하여 PII를 안전하게 저장할 수 있습니다. 의도치 않게 액세스를 허용하지 않도록 최고 수준의 개인 정보 보호 기능으로 이 정보를 처리해야 합니다. 예를 들어 신용카드 정보 또는 의료 데이터를 데이터베이스에 저장하는 경우 Cloud SQL을 사용하여 권한이 없는 사용자에게서 PII를 숨기거나 마스킹할 수 있습니다.
다음 전략을 사용하여 Cloud SQL에서 PII를 보호하세요.
열 수준 보안
열 수준 보안을 사용하면 데이터베이스 테이블의 특정 열에 있는 콘텐츠를 볼 수 있는 사용자를 제한할 수 있습니다. 열 수준 권한은 INSERT
, UPDATE
, SELECT
, REFERENCES
문에 적용됩니다.
예를 들어 소매업체 웹사이트에서 잭과 앨리스라는 두 사용자의 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은 이러한 열에서 잭과 앨리스의 PII를 보호합니다.
단일 GRANT
문을 사용하여 여러 권한을 결합할 수도 있습니다.
GRANT SELECT (id,name,age), UPDATE (name) ON secure_schema.user_details TO analyst_ro;
뷰 기반 접근 방식
또한 테이블에 뷰를 만들고, 다른 사용자에게 숨기려는 열을 제외하거나 마스킹하고, 테이블 대신 뷰에 대한 액세스 권한을 제공하여 열 수준 보안을 달성할 수 있습니다.
다음 예시에서는 소매업체 웹사이트에 대한 뷰 기반 접근 방식을 사용하여 잭과 앨리스의 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
이 예시에서는 뷰의 이름을 테이블과 동일하게 유지하기 위해 별도의 스키마가 생성됩니다. 뷰 기반 접근 방식의 경우 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에서는 테이블에 사용자가 쿼리를 만들어서 볼 수 있는 행이나 데이터 수정 명령어를 실행하여 삽입, 업데이트, 삭제할 수 있는 행을 사용자별로 제한하는 행 수준 보안 정책이 있을 수 있습니다.
소매업체 웹사이트 예시의 경우, 잭과 앨리스에게 행 수준 보안을 구현하면 이들이 자신의 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 flag
를on
으로 설정합니다. 플래그 설정에 대한 정보와 이 확장 프로그램에서 지원되는 플래그를 검토하려면 데이터베이스 플래그 구성을 참조하세요.다음 명령어를 실행하여 데이터베이스에 확장 프로그램을 만듭니다.
--Connect to the PostgreSQL database CREATE EXTENSION IF NOT EXISTS anon CASCADE; SELECT anon.init();
확장 프로그램을 설치하고 구성한 후 인스턴스에서 확장 프로그램을 사용하여 동적 마스크, 정적 마스크, 익명 덤프 익명 처리 전략을 구현합니다.
동적 마스크
동적 마스크를 사용하여 특정 사용자의 마스킹 규칙을 정의합니다. 이 사용자는 PII를 볼 수 없습니다. 대신 이들에게는 마스킹된 데이터가 표시됩니다. 다른 모든 사용자에게는 마스킹 해제된 데이터가 표시됩니다. PII를 변경하지 않고 특정 사용자에게만 숨겨야 하는 프로덕션 환경에서 유용합니다.
소매업체 웹사이트 예시의 경우, 자신은 잭과 앨리스의 마스킹 해제된 이메일 주소와 비밀번호를 볼 수 있지만 분석가에게는 마스킹된 데이터만 표시되도록 동적 마스크를 구현할 수 있습니다.
--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를 변경하려고 하는데 다른 사용자가 이 정보를 보지 못하도록 하려는 경우에 유용합니다.
소매업체 웹사이트 예시의 경우 정적 마스크를 구현하여 사용자가 잭과 앨리스의 마스킹 해제된 이메일 주소 및 비밀번호를 볼 수 없도록 할 수 있습니다. 대신 사용자에게 마스킹된 데이터만 표시됩니다.
--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
확장 프로그램을 사용하여 PII를 저장하기 전에 암호화합니다. 이렇게 하면 유효한 암호화 키를 가진 사용자만 정보를 복호화하고 일반 텍스트로 볼 수 있습니다.
pgcrypto
확장 프로그램에는 여러 해시와 암호화 함수가 포함되어 있습니다.
해시
해시는 사용자가 PII 암호화만 관리하는 단방향 암호화 함수입니다. 해싱된 형식으로 비밀번호를 저장하고 사용자가 입력한 비밀번호를 해싱된 비밀번호와 일치시키는 데 유용합니다. 해싱된 비밀번호는 일반 텍스트로 복호화되지 않습니다.
소매업체 웹사이트 예시의 경우 pgcrypto
확장 프로그램을 사용하여 잭의 비밀번호를 해싱한 후 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를 읽을 수 있는 형식으로 가져오는 신용카드 정보 및 은행 세부정보를 저장하는 데 유용합니다.
소매업체 웹사이트의 경우, 잭의 비밀번호와 이메일 주소가 암호화됩니다. 암호화 키가 있는 사용자는 이 정보를 복호화하고 일반 텍스트로 볼 수 있습니다. 다른 모든 사용자에게는 오류 메시지가 표시됩니다.
--"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를 보호하는 데 사용할 수 있는 다음과 같은 추가 관리 기능에 대해 알아보세요.