feat: make DDS demo data plane independent

This commit is contained in:
devmrko
2026-06-29 22:21:41 +09:00
parent 9eccf98e11
commit e7ca656a0f
5 changed files with 134 additions and 14 deletions

View File

@@ -5,6 +5,7 @@
- 기본 포트: `8083`
- 기본 화면: `/` 또는 `/dds`
- 기본 보호 객체: `ADMIN.V_DDS_CUSTOMERS_PG`, `ADMIN.V_DDS_CUSTOMERS_MY`
- DDS 전용 사용자: `dds_demo_my`, `dds_demo_pg`, `dds_demo_both`, `dds_demo_none`
- 조회 방식: 선택한 DDS `END USER` 자격으로 직접 Oracle JDBC 연결
## 두 데모의 관계
@@ -28,10 +29,10 @@ ORDS Handler가 Bearer 값을 `cb_dds_hr` 같은 문자열로 매핑하는 것
## 실행
먼저 기존 DDS SQL을 적용합니다.
먼저 DDS 데모 전용 로컬 데이터셋과 권한 객체를 적용합니다. 이 스크립트는 VPD VIEW나 외부 RDS DB Link를 사용하지 않습니다.
```bash
./run.sh dds-setup
sqlplus "$ADB_USER/$ADB_PASSWORD@$ADB_TNS" @sql/adb/31_dds_standalone_demo_setup.sql
```
그 다음 DDS 인스턴스를 실행합니다.

View File

@@ -47,12 +47,12 @@ public class DdsQueryService {
public List<DdsSourceOption> sources() {
return List.of(
new DdsSourceOption(
"PG", "PostgreSQL 원본", properties.pgObject(),
"DDS DATA GRANT가 허용한 PostgreSQL 데이터만 반환합니다."
"PG", "PG 데이터셋", properties.pgObject(),
"DDS 전용 로컬 PG 데이터셋에서 허용된 행만 반환합니다."
),
new DdsSourceOption(
"MY", "MySQL 원본", properties.myObject(),
"DDS DATA GRANT가 허용한 MySQL 데이터만 반환합니다."
"MY", "MY 데이터셋", properties.myObject(),
"DDS 전용 로컬 MY 데이터셋에서 허용된 행만 반환합니다."
)
);
}

View File

@@ -31,20 +31,20 @@ dds:
my:
label: MY 전용 사용자
description: MySQL 원본만 허용하는 DATA ROLE
username: ${DDS_BACKOFFICE_MY_USERNAME:ddsuser_my}
username: ${DDS_BACKOFFICE_MY_USERNAME:dds_demo_my}
password: ${DDS_BACKOFFICE_MY_PASSWORD:${DDSUSER_MY_PASSWORD:}}
pg:
label: PG 전용 사용자
description: PostgreSQL 원본만 허용하는 DATA ROLE
username: ${DDS_BACKOFFICE_PG_USERNAME:ddsuser_pg}
username: ${DDS_BACKOFFICE_PG_USERNAME:dds_demo_pg}
password: ${DDS_BACKOFFICE_PG_PASSWORD:${DDSUSER_PG_PASSWORD:}}
both:
label: 통합 사용자
description: 두 원본을 모두 허용하는 DATA ROLE
username: ${DDS_BACKOFFICE_BOTH_USERNAME:ddsuser_both}
username: ${DDS_BACKOFFICE_BOTH_USERNAME:dds_demo_both}
password: ${DDS_BACKOFFICE_BOTH_PASSWORD:${DDSUSER_BOTH_PASSWORD:}}
none:
label: 차단 사용자
description: 접속만 가능하고 DATA GRANT가 없는 사용자
username: ${DDS_BACKOFFICE_NONE_USERNAME:ddsuser_none}
username: ${DDS_BACKOFFICE_NONE_USERNAME:dds_demo_none}
password: ${DDS_BACKOFFICE_NONE_PASSWORD:${DDSUSER_NONE_PASSWORD:}}

View File

@@ -98,10 +98,10 @@
</div>
</div>
<div class="matrix-grid">
<div class="matrix-card"><strong>ddsuser_my</strong><span>MY 원본 허용</span><small>PG 객체는 ORA-00942</small></div>
<div class="matrix-card"><strong>ddsuser_pg</strong><span>PG 원본 허용</span><small>MY 객체는 ORA-00942</small></div>
<div class="matrix-card"><strong>ddsuser_both</strong><span>PG + MY 허용</span><small>두 DATA GRANT 모두 적용</small></div>
<div class="matrix-card muted"><strong>ddsuser_none</strong><span>접속만 허용</span><small>데이터 권한 없음 · default deny</small></div>
<div class="matrix-card"><strong>dds_demo_my</strong><span>MY 데이터셋 허용</span><small>PG 객체는 ORA-00942</small></div>
<div class="matrix-card"><strong>dds_demo_pg</strong><span>PG 데이터셋 허용</span><small>MY 객체는 ORA-00942</small></div>
<div class="matrix-card"><strong>dds_demo_both</strong><span>PG + MY 허용</span><small>두 DATA GRANT 모두 적용</small></div>
<div class="matrix-card muted"><strong>dds_demo_none</strong><span>접속만 허용</span><small>데이터 권한 없음 · default deny</small></div>
</div>
</section>

View File

@@ -0,0 +1,119 @@
-- ============================================================
-- 31_dds_standalone_demo_setup.sql
-- Independent local Deep Data Security demo.
--
-- This script deliberately does not use VPD views, application
-- permission tables, or external database links. It creates a
-- local PG/MY-shaped matrix so the DDS demo can run independently
-- when the VPD demo's RDS links are unavailable.
-- ============================================================
WHENEVER SQLERROR EXIT SQL.SQLCODE
SET ECHO OFF
SET FEEDBACK ON
SET DEFINE ON
SET VERIFY OFF
PROMPT === 1. Creating DDS-only local source tables ===
BEGIN
EXECUTE IMMEDIATE 'DROP VIEW v_dds_customers_pg';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP VIEW v_dds_customers_my';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE cb_dds_demo_customers_pg PURGE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE cb_dds_demo_customers_my PURGE';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
CREATE TABLE cb_dds_demo_customers_pg (
customer_id NUMBER PRIMARY KEY,
full_name VARCHAR2(100) NOT NULL,
email VARCHAR2(200),
signup_date DATE DEFAULT SYSDATE NOT NULL,
region VARCHAR2(30) NOT NULL
);
CREATE TABLE cb_dds_demo_customers_my (
customer_id NUMBER PRIMARY KEY,
full_name VARCHAR2(100) NOT NULL,
email VARCHAR2(200),
signup_date DATE DEFAULT SYSDATE NOT NULL,
region VARCHAR2(30) NOT NULL
);
INSERT INTO cb_dds_demo_customers_pg VALUES (101, 'PG Alice', 'pg.alice@example.test', DATE '2026-01-10', 'APAC');
INSERT INTO cb_dds_demo_customers_pg VALUES (102, 'PG Bob', 'pg.bob@example.test', DATE '2026-01-11', 'EMEA');
INSERT INTO cb_dds_demo_customers_pg VALUES (103, 'PG Carol', 'pg.carol@example.test', DATE '2026-01-12', 'AMER');
INSERT INTO cb_dds_demo_customers_my VALUES (201, 'MY Alice', 'my.alice@example.test', DATE '2026-02-10', 'APAC');
INSERT INTO cb_dds_demo_customers_my VALUES (202, 'MY Bob', 'my.bob@example.test', DATE '2026-02-11', 'EMEA');
INSERT INTO cb_dds_demo_customers_my VALUES (203, 'MY Carol', 'my.carol@example.test', DATE '2026-02-12', 'AMER');
CREATE OR REPLACE VIEW v_dds_customers_pg AS
SELECT customer_id, full_name, email, signup_date, region
FROM cb_dds_demo_customers_pg;
CREATE OR REPLACE VIEW v_dds_customers_my AS
SELECT customer_id, full_name, email, signup_date, region
FROM cb_dds_demo_customers_my;
COMMIT;
PROMPT === 2. Creating independent DDS END USERs ===
CREATE END USER "dds_demo_my" IDENTIFIED BY "&DDSUSER_MY_PASSWORD";
CREATE END USER "dds_demo_pg" IDENTIFIED BY "&DDSUSER_PG_PASSWORD";
CREATE END USER "dds_demo_both" IDENTIFIED BY "&DDSUSER_BOTH_PASSWORD";
CREATE END USER "dds_demo_none" IDENTIFIED BY "&DDSUSER_NONE_PASSWORD";
PROMPT === 3. Creating independent DATA ROLEs ===
CREATE ROLE dds_demo_connect_role;
GRANT CREATE SESSION TO dds_demo_connect_role;
CREATE DATA ROLE dds_demo_my_role;
CREATE DATA ROLE dds_demo_pg_role;
CREATE DATA ROLE dds_demo_both_role;
CREATE DATA ROLE dds_demo_none_role;
GRANT dds_demo_connect_role TO dds_demo_my_role;
GRANT dds_demo_connect_role TO dds_demo_pg_role;
GRANT dds_demo_connect_role TO dds_demo_both_role;
GRANT dds_demo_connect_role TO dds_demo_none_role;
GRANT DATA ROLE dds_demo_my_role TO "dds_demo_my";
GRANT DATA ROLE dds_demo_pg_role TO "dds_demo_pg";
GRANT DATA ROLE dds_demo_both_role TO "dds_demo_both";
GRANT DATA ROLE dds_demo_none_role TO "dds_demo_none";
PROMPT === 4. Creating independent DATA GRANTs ===
CREATE DATA GRANT admin.dds_demo_my_grant
AS SELECT
ON admin.v_dds_customers_my
TO dds_demo_my_role;
CREATE DATA GRANT admin.dds_demo_pg_grant
AS SELECT
ON admin.v_dds_customers_pg
TO dds_demo_pg_role;
CREATE DATA GRANT admin.dds_demo_both_pg_grant
AS SELECT
ON admin.v_dds_customers_pg
TO dds_demo_both_role;
CREATE DATA GRANT admin.dds_demo_both_my_grant
AS SELECT
ON admin.v_dds_customers_my
TO dds_demo_both_role;
PROMPT === Independent DDS demo setup complete ===
EXIT;