본문 바로가기
6. 보안 Security

Data보안을 위한 DBMS_RLS활용

by primely 2022. 12. 14.

아래 2 Link의 내용을 저의 환경에 맞게 약간 수정한 내용입니다.

자세한 내용은 아래 Link를 통해서 보시면 더 좋습니다.

 

Row Level Security: https://mentor75.tistory.com/entry/%ED%8E%8CDBMSRLS-%ED%96%89%EB%8B%A8%EC%9C%84-%EB%B3%B4%EC%95%88-%EC%84%A4%EC%A0%95

Column Masking: https://asktom.oracle.com/pls/apex/asktom.search?tag=column-masking 

 

1. Row Level Security

1.1 테스트를 위한 기본적인 환경 설정

- secman 계정은 row level security를 설정하고, 관리하기 위한 securiy 계정

- bank 계정은 실제 원본 데이터의 소유 계정
- lion 계정의 bank의 데이터를 조작할 수 있는 계정

 

> secman 유저 생성 및 권한부여

CREATE USER c##secman IDENTIFIED BY QWEasdfg123_#
DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS
TEMPORARY TABLESPACE TEMP;

GRANT CONNECT, RESOURCE TO c##secman;

 

> bank 유저 생성 및 권한부여

CREATE USER c##bank IDENTIFIED BY QWEasdfg123_#
DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS
TEMPORARY TABLESPACE TEMP;

GRANT CONNECT, RESOURCE TO c##bank;

 

> lion 유저 생성 및 권한부여

CREATE USER c##lion IDENTIFIED BY QWEasdfg123_#
DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS
TEMPORARY TABLESPACE TEMP;
 
GRANT CONNECT, RESOURCE TO c##lion;

 

> bank유저에 접속해서 테스트용 테이블 생성

-- 테스트용 테이블 생성

CREATE TABLE customers(
    cust_id   NUMBER  NOT NULL,
    cust_name VARCHAR(10)  NOT NULL);
 
CREATE TABLE accounts(
    acct_id  NUMBER       NOT NULL,
    cust_id  NUMBER       NOT NULL,
    balance  NUMBER(15,2));

-- 테스트용 테이터 생성
INSERT INTO customers VALUES(123, '강명규');
INSERT INTO customers VALUES(456, '여운형');
INSERT INTO accounts VALUES (101, 123, 10000000);
INSERT INTO accounts VALUES (102, 123, 15000000);
INSERT INTO accounts VALUES (201, 456, 10000000);
INSERT INTO accounts VALUES (202, 456, 10000000);
COMMIT;

 

> secman유저에 접속해서 접근관리 테이블 생성

-- 접근을 제어하는 테이블 생성

-- 어떤 User가 어떤 Customer에 대해 어떤 권한을 가지고 있는지 설정

CREATE TABLE access_policy(
    am_name      VARCHAR(20) NOT NULL,
    cust_id      NUMBER      NOT NULL,
    access_type  CHAR(1)     NOT NULL ); --S,I,D,U
 
-- 접근을 제어하는 샘플 데이터 등록
INSERT INTO access_policy VALUES('C##LION', 123, 'I');
INSERT INTO access_policy VALUES('C##LION', 123, 'D');
INSERT INTO access_policy VALUES('C##LION', 123, 'U');
INSERT INTO access_policy VALUES('C##LION', 456, 'S');
INSERT INTO access_policy VALUES('C##LARA', 456, 'I');
INSERT INTO access_policy VALUES('C##LARA', 456, 'D');
INSERT INTO access_policy VALUES('C##LARA', 456, 'U');
INSERT INTO access_policy VALUES('C##LARA', 456, 'S');
COMMIT;

 

1.2. 정책함수(Policy Function) 생성

사용자, 테이블명을 인자로 주면 질의에 추가될 WHERE절을 리턴하는 함수를 생성

> secman유저에 접속해서 SELECT용 정책함수 생성

CREATE OR REPLACE FUNCTION get_sel_cust_id(
    p_schema IN VARCHAR2,
    p_table IN VARCHAR2
)
    RETURN VARCHAR2
AS
    l_retstr VARCHAR2(2000);
BEGIN
    IF(p_schema = USER) THEN
        l_retstr := null;
    -- 소유자 계정이 아닐 경우 access_policy을 조회해서 IN 조건절을 추가해서 생성 합니다.
    ELSE
        FOR cust_rec IN (SELECT cust_id FROM access_policy WHERE am_name = USER AND access_type='S')
        LOOP
            l_retstr := l_retstr || ',' || cust_rec.cust_id;
        END LOOP;
        l_retstr := LTRIM(l_retstr, ',');
        l_retstr := 'CUST_ID IN (' || l_retstr || ')';
    END IF;
    RETURN l_retstr;
END;
/

 

1.3 정책(Policy)의 정의

정책은 DBMS_RLS패키지를 이용하여 정의

secman에게 DBMS_RLS에 대한 실행권한을 부여하고, secman에서 정책을 설정

> SYSDBA권한으로 접속

GRANT EXECUTE ON DBMS_RLS TO c##secman;

 

> secman유저에 접속해서 정책을 정의

-- CUST_SEL_POLICY 정책 생성
BEGIN
DBMS_RLS.ADD_POLICY(
    OBJECT_SCHEMA   => 'C##BANK',
    OBJECT_NAME     => 'CUSTOMERS',
    POLICY_NAME     => 'CUST_SEL_POLICY',
    FUNCTION_SCHEMA => 'C##SECMAN',
    POLICY_FUNCTION => 'GET_SEL_CUST_ID',
    UPDATE_CHECK    => TRUE
);
END;
/

 

-- CUST_IUD_POLICY 정책 생성
BEGIN
DBMS_RLS.ADD_POLICY(
    OBJECT_SCHEMA   => 'C##BANK',
    OBJECT_NAME     => 'CUSTOMERS',
    POLICY_NAME     => 'CUST_IUD_POLICY',
    FUNCTION_SCHEMA => 'C##SECMAN',
    POLICY_FUNCTION => 'GET_IUD_CUST_ID',
    STATEMENT_TYPES => 'INSERT,UPDATE,DELETE',
    UPDATE_CHECK    => TRUE
);
END;
/

 

> 지정한 정책 제거방법

EXEC DBMS_RLS.DROP_POLICY('C##BANK','CUSTOMERS','CUST_SEL_POLICY');

 

1.4 정잭적용 테스트로 확인

우선 lion에게 bank.customers에 접근할 수 있는 권한을 부여

> bank유저에 접속해서 lion유저에게 권한을 부여

GRANT SELECT,INSERT,UPDATE,DELETE ON CUSTOMERS TO C##LION;
GRANT SELECT,INSERT,UPDATE,DELETE ON ACCOUNTS TO C##LION;

 

> bank유저에 접속해서 테스트

bank는 customers객체(테이블)의 소유자이므로 모든 데이터 조회가능

SELECT * FROM CUSTOMERS;

> lion유저에 접속해서 테스트

lion은 정책에 의해 'WHERE cust_id IN (456)'이 질의에 추가되어 실행

 

2. Column Masking

조회 시 특정User에게 Column Masking을 적용할 수 있다.

2.1 정책함수(Policy Function) 생성

create or replace function foo( p_schema in varchar2, p_table in varchar2 ) return varchar2
as
begin
        if(p_schema = USER)
        then
                return null;
        else
                return '1=0';
        end if;
end;
/

 

2.2 정책(Policy)의 정의

위에서 정의한 정책함수를 가지고 Column Masking정책을 설정한다.

BEGIN
DBMS_RLS.ADD_POLICY(
     object_schema   => 'C##BANK',
     object_name     => 'CUSTOMERS',
     policy_name     =>'SEC_SSN',
     function_schema=>'C##SECMAN',
     policy_function=>'foo',
     sec_relevant_cols=>'CUST_ID',
     sec_relevant_cols_opt=>dbms_rls.ALL_ROWS);
END;
/

 

2.3 정책적용 테스트로 확인

> bank유저에 접속해서 테스트

bank는 customers객체(테이블)의 소유자이므로 모든 컬럼 조회가능

> lion유저에 접속해서 테스트

lion은 정책에 의해 CUST_ID컬럼의 Data를 조회할 수 없다

 

참고
- DBMS_RLS

https://docs.oracle.com/database/121/ARPLS/d_rls.htm#ARPLS052

손창호

 

개인의 시간을 할애하여 작성된 글로서 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.

댓글