1) WRAP 유틸리티
데이터베이스 조작 언어 중에 하나인 PL-SQL은 SQL언어가 가지지 못한 많은 장점들을 가지고 있습니다.
그럼에도 불구하고 가장 큰 단점은 소스 프로그램의 비효율적 관리 방법과 디스크에 남아 있는 소스 내용의 노출로 인해 보안에 지대한 문제점을 가지고 있다는 점입니다.
이와 같은 문제점을 보완하기 위해 오라클 사에서는 운영체계 상에서 작성된 PL-SQL의 소스 프로그램의 노출 방지를 위해 WRAP 유틸리티를 제공합니다.
먼저, 테스트할 프로시저를 생성하기 위한 스크립트를 작성하십시오.

### html
[C:\] EDIT  wrap_test.sql
 CREATE PROCEDURE wraptest
IS  TYPE emp_tab IS TABLE OF employees%ROWTYPE  INDEX BY PLS_INTEGER;
all_emps emp_tab;
BEGIN
        SELECT * BULK COLLECT INTO all_emps FROM employees;
        FOR i IN 1..10 LOOP
           DBMS_OUTPUT.PUT_LINE('Emp Id: ' || all_emps(i).employee_id); END
LOOP;
END;
 /
C:\> WRAP iname=wrap_test.sql  oname=wrap_test.plb

Input file에는 방금 생성한 스토어드 프로시저의 이름을 정의하시고 Output file에는 암호화하고자 하는 파일 이름을 정의해 주시면 됩니다.

다음은 HR 사용자 계정으로 접속하여 암호화된 파일을 이용하여 프로시저를 생성하고 실행하십시오.

### html
C:\> SQLPLUS  HR/HR
SQL> @wrap_test.plb 암호화된 파일을 실행하면 프로시저가 생성됩니다.
프로시저가 생성되었습니다.
SQL> SET SERVEROUTPUT ON
SQL> CALL WRAPTEST();생성된 프로시저를 실행합니다.
Emp Id: 198
……………..
Emp Id: 100 출력된 결과 호출이 완료되었습니다.

2) DBMS_DDL 패키지
앞서 소개 드린 WRAP 유틸리티는 디스크에 저장되어 있는 PL-SQL의 소소 프로그램을 암호화할 수 있다면 DBMS_DDL.CREATE_WRAPPED는 데이터베이스 내에서 생성되는 PL-SQL의 소스 프로그램을 암호화시킬 수 있는 방법입니다.

### html

SQL> CONNECT  SYSTEM/MANAGER
SQL> DECLARE
package_text VARCHAR2(32767);
FUNCTION generate_spec (pkgname VARCHAR2)
RETURN VARCHAR2 AS
BEGIN
        RETURN
'CREATE PACKAGE ' || pkgname || '
AS PROCEDURE raise_salary (emp_id NUMBER, amount
NUMBER); PROCEDURE fire_employee (emp_id NUMBER); END ' || pkgname || ';';
END generate_spec;
BEGIN  package_text := generate_spec('emp_actions');    
SYS.DBMS_DDL.CREATE_WRAPPED(package_text);
END;

? EMP_ACTIONS 패키지를 생성하면서 소스 프로그램을 DBMS_DDL.CREATE_WRAPPED로 암호화하는 방법입니다.

### html
(SQL) SELECT text FROM USER_SOURCE WHERE name = 'EMP_ACTIONS';
TEXT
---------------------------------------------------------------
PACKAGE emp_actions wrapped
a000000
1f


3) DBMS_CRYPTO 패키지
최근 사회적 이슈가 되고 있는 내용 중에 개인 정보의 유출로 인해 심각한 사회 문제가 되고 있는 것이 현실입니다.
이러한 문제를 해소하기 위해 오라클 사에서는 컬럼 단위와 블록 단위의 암호화 기능을 제공하고 있습니다.
다음 예제는 DBMS_CRYPTO 패키지를 이용하여 컬럼 단위의 암호화를 적용하는 예제입니다.

### html
SQL> CONNECT  /as sysdba           
SQL> DECLARE
       input_string VARCHAR2 (200) := 'Secret Message';
       output_string VARCHAR2 (200);
       encrypted_raw RAW (2000);           -- stores encrypted binary text
       decrypted_raw RAW (2000);           -- stores decrypted binary text
       num_key_bytes NUMBER := 256/8;      -- key length 256 bits (32 bytes)
       key_bytes_raw RAW (32);             -- stores 256-bit encryption key
       encryption_type PLS_INTEGER :=      -- total encryption type
DBMS_CRYPTO.ENCRYPT_AES256+DBMS_CRYPTO.CHAIN_CBC+DBMS_CRYPTO
.PAD_PKCS5;
BEGIN
      DBMS_OUTPUT.PUT_LINE ( 'Original string: ' || input_string);
      key_bytes_raw := DBMS_CRYPTO.RANDOMBYTES (num_key_bytes);
      encrypted_raw := DBMS_CRYPTO.ENCRYPT (
            src => UTL_I18N.STRING_TO_RAW (input_string, 'AL32UTF8'),
                      typ => encryption_type, key => key_bytes_raw );
      decrypted_raw := DBMS_CRYPTO.DECRYPT (
 src => encrypted_raw, typ => encryption_type,
                       key => key_bytes_raw );
      output_string := UTL_I18N.RAW_TO_CHAR (decrypted_raw, 'AL32UTF8');
      DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || output_string);
END;
/

1) AUDIT 명령어
이 명령어는 4가지 모드의 데이터베이스 감시 기능을 제공합니다.
먼저, 첫 번째 감시 기능은 데이터베이스 내에서 특정 SQL 언어(CONNECT문, DROP TABLE, ALTER TABLE 등)가 실행될 때 언제, 어떤 사용자에 의해, 어떤 명령어가 실행되었고 실행 결과가 성공했는지, 실패했는지에 대한 로그 정보를 남기는 방법입니다.
두 번째 감시 기능은 특정 권한(SYSTEM Privilege 또는 OBJECT Privilege)이 실행되었을 때 그 상태 정보를 남기는 방법이며 세 번째 감시 기능은 특정 사용자가 특정 객체(테이블, 인덱스, 뷰 등)을 조작할 때 상태 정보를 남기며 네 번째 방법은 네트워크 상태를 감시하며 특정 Action(V$SESSION의 COMMAND 컬럼 참조)이 발생할 때 관련 로그정보를 남김으로써 데이터베이스 내에서 일어나는 의심스러운 행위를 감시하고 데이터에 대한 안전한 보안 기능을 설정하는 방법입니다.

### html
SQL> AUDIT connect BY scott BY SESSION WHENEVER SUCCESSFUL;       ? 문장 Level
SQL> AUDIT create table BY scott BY SESSION WHENEVER SUCCESSFUL;  ? 권한 Level
SQL> AUDIT delete on emp BY SESSION WHENEVER NOT SUCCESSFUL;      ? 객체 Level 
SQL> AUDIT 12 BY scott BY SESSION  WHENEVER NOT SUCCESSFUL;       ? 네트워크 Level

2) DBMS_FGA 패키지
앞서 소개 드린 AUDIT 명령어를 통해 특정 테이블에 대한 보안, 감시활동의 수행은 다소 제한적인 기능 만을 제공한다면 다음에 소개하는 DBMS_FGA 패키지는 구체적이며 상세한 조건의 감시 활동이 가능하도록 만들어진 기능입니다.

### html
DBMS_FGA.ADD_POLICY  ( object_schema => 'SCOTT',
                       object_name => 'EMP',
                       policy_name => 'MYPOLICE1',
                       audit_condition => 'SAL < 100',
                       audit_column => 'COMM, SAL',
                       handler_schema => NULL,
                       handler_module => NULL,
                       enable => TRUE,
                       statement_types => 'INSERT, UPDATE',
                       audit_trail => DBMS_FGA.DB,
                       audit_column_opts => DBMS_FGA.ANY_COLUMNS);

위 예제는 DBMS_FGA 패키지의 ADD_POLICY 프로시저를 통해 SCOTT 사용자의 EMP 테이블에 대한 감시 내역입니다.
감시 대상은 EMP 테이블의 COMM, SAL 컬럼이며 누군가가 INSERT, UPDATE문을 실행할 때 SAL 컬럼의 데이터가 100보다 작은 경우 로그 정보를 남길 수 있도록 환경 설정하는 방법입니다.

### html
SQL> SELECT * FROM DBA_AUDIT_POLICIES;
OBJECT_SCHEMA     OBJECT_NAME            ENA SEL INS UPD DEL
-------------- ------------------------- --- --- --- --- --- 
SCOTT                EMP                 YES  NO YES YES  NO

DBMS_FGA.DROP_POLICY    : 생성된 감시 정책을 삭제할 때 사용됩니다.
DBMS_FGA.ENABLE_POLICY  : 생성된 감시 정책을 사용 가능하도록 환경 설정해 줍니다.
DBMS_FGA.DIABLE_POLICY  : 생성된 감시 정책을 사용 없도록 환경 설정해 줍니다.

3) 데이터베이스 트리거를 이용한 의심스러운 사용자의 세션 제한 기능
데이터베이스를 운영, 관리하다 보면 중요한 테이블에 대해 누군가가 의심스런 입력, 수정, 삭제, 조회 작업을 수행하는 경우들이 종종 발생합니다.
하나의 기업 내에 근무하는 개발자, 데이터베이스 관리자라고 하더라도 인가되지 않은 사용자가 관련 없는 데이터를 참조하는 것은 때에 따라서는 제한되어야 합니다.

### html
[C:\] SQLPLUS  SYSTEM/MANAGER
SQL> CREATE OR REPLACE TRIGGER  ip_control
AFTER  LOGON ON SCOTT.SCHEMA
BEGIN
      IF SUBSTR(sys_context('USERENV','IP_ADDRESS'),1, 15)
        in (‘192.168.123.101’)  then  
        RAISE_APPLICATION_ERROR ( - 
                  20002, 'IP '||ORA_CLIENT_IP_ADDRESS
                  || ' is not allowed to connect database as SCOTT!');
       END IF;
END;

이것을 구현할 수 있는 방법은 여러 가지가 있지만 그 중에서도 SYS_CONTEXT 함수를 사용하여 원치 않는 IP Address를 가진 사용자의 접속을 근본적으로 차단하는 보안 설정방법에 대해 알아 보겠습니다.

### html
[C:\] SQLPLUS  scott/tiger
192.168.123.101 is not allowed to connect database as SCOTT!

192.168.123.101 IP Address를 가진 클라이언트가 SCOTT 계정으로 데이터베이스에 접속을 시도할 때 "192.168.123.101 is not allowed to connect database as SCOTT!"이라는 메시지를 클라이언트의 화면에 출력하고 접속을 제한하게 됩니다.

192.168.123.101 IP Address를 가진 사용자의 PC에서 다음 문장을 실행합니다.

Oracle Flashback 기능 이란?

  DB 관리중에 실수로 데이타를 삭제하거나 데이타의 값을 잘못 변경 하는 실수가 가끔 발생을 합니다.

  이러한 오류를 바로 인식할 경우는 Rollback이라는 명령으로 바로 전에 수행한 작업을 원상복귀시킬 수 있지만, COMMIT을 한 이후 시점이나, 한참 시간이 지난 후에 알았다면 간단하게 복구하기가 난감 합니다.

  이러한 경우에 특정한 시간 또는 시점으로 되돌릴 수 있는 기능이 Oracle Flashback 기능 입니다.

  간단하게 말해서 Flashback 기능은 특정한 과거시점의 질의를 실행할 수 있게 해 줍니다. 데이타베이스에 구조적인 변화를 가하지 않고 과거 일정 시점의 데이타 상태를 확인할 수 있는 기능 입니다.

  일종의 오라클에서 지원하는 타임머신이라고 할 수 있죠.

Flashback을 사용하기 위한 요구조건

  자동 언두 관리 시스템을 사용해야 합니다. (UNDO_MANAGEMENT 파라미터를 AUTO로 설정)
    - UNDO_MANAGEMENT = AUTO

  이전의 어느 시점까지의 언두(UNDO)정보를 보유하여 Flashback Query를 수행할것인지 UNDO_RETENTION 파라미터를 설정해야 합니다.
    - ALTER SYSTEM SET UNDO_RETENTION=1800

  일반사용자가 Flashback 기능을 이용하기 위해서 DBMS_FLASHBACK 패키지에 대한 EXECUTE권한이 있어야 합니다.

Flashback 사용하기

  Flashback의 사용 방법은 과거시점의 특정 시간으로 사용하는 방법과 SCN(System Change Number)을 사용하는 방법이 있습니다.

  과거시점의 시간 사용: DBMS_FLASHBACK.ENABLE_AT_TIME(query_time IN TIMESTAMP);

  SCN 사용 : DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(query_scn IN NUMBER);

  과거시점의 시간을 지정하여 Flashback 기능을 사용 할 경우 오라클은 내부적으로 이를 SCN으로 전환하여 처리 합니다. 시간 정보를 SCN으로 Mapping하는 시간이 필요한데 통상 5분 주기로 이루어 집니다. 따라서, 시간으로 지정할때는 현재보다 5분이상 차이가 나는 과거시점을 지정해야 합니다.

  또한 Flashback 기능은 무한대로 이전의 데이터를 조회할 수 있는 기능이 아니고, 관리자가 UNDO_RETENTION 파라미터를 통해서 정해준 시간(초) 동안의 데이터를 조회할 수 있습니다. 디폴트 UNDO_RETENTION 시간은 10800(3시간) 입니다.

  그리고 Flashback data를 참고하는 경우엔 DML, DDL등의 작업을 직접 수행 할 수 없습니다.

Flashback 사용을 위한 환경설정

 
C:\> SQLPLUS /NOLOG
 
 
-- SYSDBA 권한으로 접속
SQL> CONN / AS SYSDBA
 
 
-- UNDO MANAGEMENT MODE 확인
SQL> SHOW PARAMETER UNDO;
NAME                        TYPE        VALUE
--------------------------- ----------- ---------
undo_management             string       AUTO
undo_retention              integer      10800
undo_suppress_errors        boolean      FALSE
undo_tablespace             string       UNDOTBS1
 
   
-- undo_management가 MANUAL로 되어있을경우 아래와 같이 변경하고 
-- UNDO 테이블스페이스를 생성하고 지정합니다..
SQL> ALTER SYSTEM SET UNDO_MANAGEMENT = AUTO
     SCOPE=SPFILE;
 
 
-- UNDO 테이블 스페이스 생성
SQL> CREATE UNDO TABLESPACE UNDOTBS2
     DATAFILE 'D:\oracle\oradata\oracle\UNDOTBS2.dbf' 
     SIZE 1000M;
 
 
-- UNDO 테이블 스페이스 지정
SQL> ALTER SYSTEM SET UNDO_TABLESPACE=UNDOTBS2
 
 
-- UNDO_RETENTION 시간을 변경하시면 
-- 실제 적용을 위해 5분정도 기다려야 합니다.
SQL> ALTER SYSTEM SET UNDO_RETENTION=1800
 
 
-- scott유저에게 DBMS_FLASHBACK EXEUCTE 권한 부여 
SQL> GRANT EXECUTE ON DBMS_FLASHBACK TO SCOTT;  
    

Flashback 사용예제

 
-- 테스트를 위해서 scott 유저에 접속을 합니다. 
SQL> CONN scott/tiger
 
 
-- emp 테이블 14건의 데이터 확인
SQL> SELECT * FROM emp;
14 개의 행이 선택되었습니다...
  
 
-- 데이터 삭제하기전의 날짜를 확인 합니다. 
-- Flashback을 이용하여 이 시점에서 데이터를 조회, 복구 할 것입니다. 
SQL> SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') 
     FROM DUAL;
 
TO_CHAR(SYSDATE,'YY
-------------------
2006-01-21 17:16:51
 
 
-- 데이터를 삭제 합니다. 
SQL> DELETE FROM emp;
14 행이 삭제되었습니다.
 
 
-- commit 수행
SQL> COMMIT;
 
 
-- 데이터 확인
SQL> SELECT * FROM emp;
선택된 레코드가 없습니다.
 
 
-- Flashback 과거시점의 시간사용 모드 Enable로 데이터 확인
SQL> EXEC DBMS_FLASHBACK.ENABLE_AT_TIME
     (TO_TIMESTAMP('2006-01-21 17:16:51', 'YYYY-MM-DD HH24:MI:SS'))'
 
 
-- 데이터를 확인 할 수 있습니다.
SQL>SELECT * FROM emp;
14 개의 행이 선택되었습니다.
 
 
-- Flashback Disable로 변경
SQL> EXEC DBMS_FLASHBACK.DISABLE;
PL/SQL 처리가 정상적으로 완료되었습니다.
 
 
-- Flashback Disable로 변경하면 데이터를 확인 할 수 없습니다.
SQL>SELECT * FROM emp;
선택된 레코드가 없습니다.
 
 
-- Flashback Disable 상태에서도 이전데이터를 보기위해서는 
-- 데이터 복구 작업을  진행해야 합니다. 
-- 아래는 삭제된 데이터 복구 예제 입니다.   
    

삭제된 데이터 복구

  Oracle9i Database Release 2이상 버전에서는 SELECT...AS OF 명령을 사용하여 쉽게 Flashback 데이터를 복구 할 수 있습니다.

  Oracle9i Database Release1 버전에서는 DBMS_FLASHBACK프로시저를 이용해서 데이터를 복구해야 합니다.

 
-- 삭제된 데이터 복구(오라클 버전 Release 9.2.0.1.0 실행)
SQL>INSERT INTO emp
    (SELECT * 
     FROM emp AS OF TIMESTAMP 
          TO_TIMESTAMP('2006-01-21 17:16:51', 'YYYY-MM-DD HH24:MI:SS'))
 
 
-- 복구된 데이터 확인
SQL>SELECT * FROM emp;
14 개의 행이 선택되었습니다.
 
  
-- 위에 복구된 데이타를 Rollback으로 지우고 DBMS_FLASHBACK 패키지를 이용해서 복구해 봅니다. 
-- 삭제된 데이터 복구
SQL> DECLARE 
    
     CURSOR emp_cursor is
       SELECT * FROM emp;
     
      v_emp emp%ROWTYPE;
      
    BEGIN
    
     DBMS_FLASHBACK.ENABLE_AT_TIME
     (TO_TIMESTAMP('2006-01-21 17:16:51', 'YYYY-MM-DD HH24:MI:SS'));
     
     OPEN emp_cursor;
     
     -- Flashback을 Disable했지만 커서(test_cursor)는 
     -- 여전히 과거시점의 데이터를 가지고 있습니다.
     DBMS_FLASHBACK.DISABLE;
                             
     LOOP
        FETCH emp_cursor INTO v_emp;
            EXIT WHEN emp_cursor%NOTFOUND;
            INSERT INTO emp 
            VALUES (v_emp.empno, v_emp.ename, v_emp.job, v_emp.mgr, 
                    v_emp.hiredate, v_emp.sal, v_emp.comm, v_emp.deptno);
     END LOOP;
     CLOSE emp_cursor;
     COMMIT;
    END;
    /
 
PL/SQL 처리가 정상적으로 완료되었습니다.

-- 복구된 데이터 확인
SQL>SELECT * FROM emp;
14 개의 행이 선택되었습니다. 

ORA-39001: invalid argument value
ORA-39000: bad dump file specification
ORA-39142: incompatible version number 2.1 in dump file "/oracle/mikyungnet/dnshop/z_dnshop_target.dmp"

--------------------------------------------------------------------------------------------------------------------

11g에서 10g로 스키마째 밀어 넣어야 되는데
버전이 틀려서 import/export는 동작 안한다.
벌써 이거가지고 몇번을 삽질한건지.. 정리 좀 해야겠다.

검색해보니까 data pump란게 있다. 버전이 상관없댄다. 그래서 그런줄 알았다.

그래서 expdp test/test@SID schemas=TEST dumpfile=TEST.dmpdp
이렇게 덤프를 뜨고

impdp test/test schemas=TEST dumpfile=TEST.dmpdp 했다.

그랬더니 디렉토리가 없다고 에러를 뱉어 낸다.
또 뒤졌다.

기본으로 잡혀있는 디렉토리가 있는데 해당 유저에게 권한을 줘야 한다.
디렉토리를 path로 주는게 아니라 오라클 객체를 사용하나보다.
grant read, write on directory DATA_PUMP_DIR to test;

아니면 디렉토리를 하나 만들고 아래처럼
CREATE OR REPLACE DIRECTORY data_pump_dir AS '/home/oracle/admin/ora10/dpdump';
GRANT read, write ON DIRECTORY data_pump_dir TO test;

이렇게 해주고

impdp test/test schemas=TEST directory=data_pump_dir dumpfile=TEST.dmpdp 했다.

근데 또 안된다. 망할..

ORA-39142: incompatible version number 2.1 in dump file 라고 뜬다.

또 검색..

뒤져보니 덤프를 뜰때 버전을 명시해줘야 한댄다..
그러니까 같은 11g라고 하더라도 서브버전이 틀린 경우는 그냥 되는데 메이저 버전이 틀린 경우는 그러니까 이번같이 11g에서 10g로 내려가는 경우는 덤프를 뜰때 버전을 명시해줘야 한다.

expdp test/test@SID schemas=TEST dumpfile=TEST.dmpdp VERSION=10.2

이렇게 해야되는건가 보다.

원래 EXPDP할때도 directory를 지정해줘야 하지만 지정안하면 기본 디렉토리에 덤프파일이 깔린다. 기본디렉토리는.. 아 쓰기 귀찮다. 덤프 다 뜨면 경로 나온다.

추가로 import할 곳에 스키마가 다른 경우라면 impdp ~~~~ REMAP_SCHEMA=test:test1 를 추가해주고 테이블 스페이스가 다른 경우 REMAP_TABLESPACE=test:test1 로 변경할 수도 있다.

돌려보니까. expdp를 아무 옵션안주고 뜨면 그 스키마에 걸려 있던 롤까지 통째로 가져와서 impdp할때 에러가 난다. 그다지 중요한 롤이 아니었으니 일단 skip하지만 나중엔 좀 챙겨놔야할 듯.

결론. 오라클의 data pump로 하위 호환성을 가지게 덤프를 뜨려면(스키마를 다른이름의 스키마로 다른 테이블 스페이스에)

expdp test/test@SID schemas=TEST dumpfile=TEST.dmpdp VERSION=10.2

요렇게 떠서

impdp test/test schemas=TEST directory=data_pump_dir dumpfile=TEST.dmpdp REMAP_SCHEMA=test:test1 REMAP_TABLESPACE=test:test1

요렇게 밀어 넣는다.

이것 외에 db를 통채로 이관하거나 특정테이블만 골라서 덤프를 뜰 수도 있으며 여러가지(스키마, 테이블스페이스, datafile 등) 리매핑 작업이 가능하다. 또한 덤프를 뜰때 타겟 버전만 명시해주면 타버전 호환도 가능하다.(물론 10g부터 나온거니까 그 이후로만)

+ Recent posts