Improve data access control UX guidance
This commit is contained in:
@@ -116,6 +116,36 @@
|
||||
<div class="mt-2" th:if="${showSupportCommand}"><code>./run.sh backoffice-support</code></div>
|
||||
</div>
|
||||
|
||||
<section class="content-band">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<span class="architecture-kicker">전체 그림</span>
|
||||
<h2>토큰은 사용자를 식별하고, DB 정책이 행과 컬럼을 나눠서 제어합니다</h2>
|
||||
<p class="section-subtitle">이 백오피스는 토큰 자체에 권한을 복사하지 않습니다. 요청 시점에 토큰으로 사용자를 찾고, 저장된 역할·규칙을 DB 세션 context와 VPD/ASO 정책에 반영합니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="effective-preview">
|
||||
<dl>
|
||||
<div>
|
||||
<dt>1. 사용자 식별</dt>
|
||||
<dd>Bearer Token으로 <code>CB_AGENT_CTX</code>에 사용자·부서·이해관계자 정보를 설정합니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>2. 행 접근(VPD)</dt>
|
||||
<dd>행 접근 규칙이 대상 테이블의 WHERE predicate로 변환되어 볼 수 있는 행만 남깁니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>3. 컬럼 마스킹(ASO)</dt>
|
||||
<dd>허용된 행 안에서 민감 컬럼을 원문으로 줄지, 마스킹해서 줄지 결정합니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>4. 접근 검증</dt>
|
||||
<dd>토큰으로 실제 ORDS 조회를 실행하고, 결과 행·마스킹 컬럼·감사 증적을 확인합니다.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="dashboard-menu-flow" aria-labelledby="menu-flow-title">
|
||||
<div class="dashboard-section-heading">
|
||||
<span class="architecture-kicker">업무 흐름</span>
|
||||
@@ -132,6 +162,13 @@
|
||||
<section class="dashboard-command-center" aria-label="주요 권한 작업">
|
||||
<div class="dashboard-primary-action">
|
||||
<h2>바로 시작</h2>
|
||||
<ol class="guided-check-list">
|
||||
<li><a href="/users">사용자</a>와 <a href="/roles">역할</a>을 준비합니다.</li>
|
||||
<li><a href="/permissions">행 접근 규칙</a>에서 역할별 대상 객체와 행 조건을 저장합니다.</li>
|
||||
<li><a href="/vpd-policies">보호 상태</a>에서 대상 테이블의 VPD 연결 상태를 확인합니다.</li>
|
||||
<li><a href="/masking-rules">컬럼 마스킹</a>에서 민감 컬럼의 ASO 정책을 연결합니다.</li>
|
||||
<li><a href="/tokens">검증 세션</a>을 발급하고 <a href="/probe">접근 검증</a>에서 실제 결과를 확인합니다.</li>
|
||||
</ol>
|
||||
<div class="dashboard-action-grid">
|
||||
<a class="dashboard-action" href="/permissions">
|
||||
<span><strong>행 접근 규칙</strong><small>역할별 객체·행 조건을 설정합니다. 컬럼은 ASO 마스킹에서 관리합니다.</small></span>
|
||||
|
||||
@@ -16,6 +16,35 @@
|
||||
|
||||
<p class="probe-summary" th:text="${result.plainSummary()}">결과 설명</p>
|
||||
|
||||
<section class="result-section">
|
||||
<div class="section-heading compact-heading">
|
||||
<h3>검증 흐름 요약</h3>
|
||||
<span class="badge text-bg-light">토큰 → VPD → ASO → FGA</span>
|
||||
</div>
|
||||
<div class="effective-preview">
|
||||
<dl>
|
||||
<div>
|
||||
<dt>1. 토큰 해석</dt>
|
||||
<dd th:if="${tokenContext}" th:text="${tokenContext.username() + ' 사용자로 해석됐습니다.'}">사용자 확인</dd>
|
||||
<dd th:unless="${tokenContext}">유효한 사용자로 해석되지 않았습니다. 이 경우 DB context가 설정되지 않아 권한이 없습니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>2. 행 접근(VPD)</dt>
|
||||
<dd th:text="${result.rowCount() == 0 ? 'VPD 적용 후 반환 가능한 행이 없습니다.' : 'VPD 적용 후 반환 가능한 행이 있습니다.'}">행 접근 결과</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>3. 컬럼 마스킹(ASO)</dt>
|
||||
<dd th:if="${!#lists.isEmpty(result.maskedColumns())}" th:text="${#strings.listJoin(result.maskedColumns(), ', ') + ' 컬럼이 마스킹 또는 NULL로 관찰됐습니다.'}">마스킹 컬럼</dd>
|
||||
<dd th:if="${#lists.isEmpty(result.maskedColumns())}">응답에서 마스킹 또는 NULL로 관찰된 민감 컬럼이 없습니다. 원문 허용이거나 해당 컬럼이 결과에 없을 수 있습니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>4. DB 감사 증적(FGA)</dt>
|
||||
<dd th:text="${result.hasFgaExecutionEvidence() ? '이번 요청 ID와 일치하는 DB 감사 행을 찾았습니다.' : '이번 결과에 연결된 DB 감사 행은 찾지 못했습니다.'}">FGA 결과</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="result-section">
|
||||
<div class="section-heading compact-heading">
|
||||
<h3>적용된 사용자와 권한</h3>
|
||||
|
||||
@@ -70,6 +70,27 @@
|
||||
<dt>원문 표시 허용</dt>
|
||||
<dd>예외 사용자는 <a href="/user-masking-rules">컬럼 원문 표시 허용 사용자</a>에서 지정합니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>DB 적용 상태 확인</dt>
|
||||
<dd>아래 DB ASO 정책 동기화 표에서 백오피스 활성 컬럼과 실제 Redaction 컬럼이 일치하는지 확인합니다.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="effective-preview mt-3">
|
||||
<div class="field-block-title">사용자별 실제 결과 해석</div>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>행 접근 권한 없음</dt>
|
||||
<dd>VPD에서 행이 제외되므로 컬럼 마스킹 여부와 무관하게 조회 결과가 없습니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>행 접근 허용 + 원문 허용 없음</dt>
|
||||
<dd>행은 보이지만, 이 화면에서 연결한 민감 컬럼은 ASO/Data Redaction 정책에 따라 마스킹됩니다.</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>행 접근 허용 + 원문 허용 있음</dt>
|
||||
<dd>행은 VPD 기준으로 제한되고, 원문 허용된 컬럼만 마스킹 없이 반환됩니다.</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -13,6 +13,48 @@
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<section class="content-band">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<span class="architecture-kicker">운영 요약</span>
|
||||
<h2>지금 먼저 확인할 상태</h2>
|
||||
<p class="section-subtitle">아래 요약은 이 화면의 DB 조회 결과에서 계산한 운영자용 triage입니다. 최종 증적은 행별 상세와 접근 검증 결과로 확인합니다.</p>
|
||||
</div>
|
||||
<span class="badge"
|
||||
th:classappend="${' ' + summary.overallBadgeClass()}"
|
||||
th:text="${summary.overallLabel()}">정상</span>
|
||||
</div>
|
||||
<div class="effective-preview">
|
||||
<dl>
|
||||
<div>
|
||||
<dt>전체 판단</dt>
|
||||
<dd>
|
||||
<strong th:text="${summary.overallLabel()}">정상</strong><br>
|
||||
<small th:text="${summary.primaryAction()}">현재 요약 기준으로 즉시 조치할 항목은 없습니다.</small>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>행 접근 정책(VPD)</dt>
|
||||
<dd th:text="${summary.rowPolicySummary()}">정상 0 · 확인 0 · 오류 0</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>컬럼 마스킹 정책(ASO)</dt>
|
||||
<dd th:text="${summary.maskingSummary()}">적용 0 · 미적용 정상 0 · 불일치 0</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>검증 필요</dt>
|
||||
<dd th:text="${summary.unverifiedCount() + '개 보호 객체'}">0개 보호 객체</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="result-metrics mt-3">
|
||||
<div><span>보호 객체</span><strong th:text="${summary.protectedObjectCount()}">0</strong></div>
|
||||
<div><span>ORDS handler 없음</span><strong th:text="${summary.missingHandlerCount()}">0</strong></div>
|
||||
<div><span>VPD 정책 없음</span><strong th:text="${summary.missingPolicyCount()}">0</strong></div>
|
||||
<div><span>ASO 불일치</span><strong th:text="${summary.maskingMismatchCount()}">0</strong></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-band">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
|
||||
@@ -182,6 +182,47 @@
|
||||
<p class="wizard-hint"><strong>조건 코드</strong>는 토큰 context로 치환됩니다. 예를 들어 <code>본인 담당 고객 / CUST_ID</code>는 계약원장에서 토큰 사용자 ID의 담당 고객을 찾아 현재 객체의 <code>CUST_ID</code>에 적용합니다. <strong>정적 SQL 조건식</strong>은 <code>CONTRACT_STATUS = '정상'</code>처럼 현재 객체 컬럼을 사용한 WHERE 절을 그대로 추가합니다. 한 권한 안의 규칙은 모두 AND로 좁혀지고, 서로 다른 역할의 ALLOW 권한은 OR로 합쳐집니다. 역할명은 최종 WHERE 절에 직접 들어가지 않습니다.</p>
|
||||
<p class="wizard-hint"><strong>컬럼 원문/마스킹은 제외했습니다.</strong> 행 접근 필터는 행만 남기고, ASO/Data Redaction이 허용된 행 안에서 컬럼을 원문 또는 마스킹으로 반환합니다.</p>
|
||||
</details>
|
||||
<details class="explanation-details">
|
||||
<summary>조건 코드가 실제 VPD WHERE 조각으로 바뀌는 방식</summary>
|
||||
<p class="wizard-hint">이 표는 저장 규칙이 <code>CB_AGENT_DOC_VPD_FILTER</code>에서 어떤 predicate로 변환되는지 설명하기 위한 예시입니다. 실제 컬럼 존재 여부와 대상 객체는 DB에서 다시 검증됩니다.</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm align-middle">
|
||||
<thead><tr><th>저장 조건 코드</th><th>업무 의미</th><th>VPD filter가 만드는 조건</th></tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>ALL</code></td>
|
||||
<td>해당 객체의 전체 행 허용</td>
|
||||
<td><code>1 = 1</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>TOKEN_SUBJECT</code></td>
|
||||
<td>토큰으로 식별된 이해관계자 본인 행</td>
|
||||
<td><code>USER_ID = SYS_CONTEXT('CB_AGENT_CTX', 'STAKEHOLDER_USER_ID')</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>OWN_CONTRACT</code></td>
|
||||
<td>토큰 사용자가 담당 설계사인 계약</td>
|
||||
<td><code>FC_ID = SYS_CONTEXT('CB_AGENT_CTX', 'STAKEHOLDER_USER_ID')</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>CHANNEL_CONTRACT</code></td>
|
||||
<td>토큰 사용자의 채널에 속한 계약</td>
|
||||
<td><code>FC_CHANNEL = SYS_CONTEXT('CB_AGENT_CTX', 'STAKEHOLDER_CHANNEL')</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>OWN_CUSTOMER</code> / <code>CHANNEL_CUSTOMER</code></td>
|
||||
<td>계약원장에서 담당자 또는 채널 기준으로 연결되는 고객·청구·담보·외부보유 행</td>
|
||||
<td><code>EXISTS (SELECT 1 FROM POC_2.KB_CONTRACTS ...)</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>STATIC_SQL</code></td>
|
||||
<td>현재 객체 컬럼으로 표현한 고정 조건</td>
|
||||
<td><code>CONTRACT_STATUS = '정상'</code>처럼 검증된 현재 객체 컬럼 조건</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -85,9 +85,10 @@
|
||||
<div class="empty-result-guide">
|
||||
<strong>검증 결과</strong>
|
||||
<ul>
|
||||
<li>토큰이 어떤 사용자와 역할로 해석됐는지</li>
|
||||
<li>VPD 적용 후 실제로 몇 행이 보였는지</li>
|
||||
<li>예상과 다를 때 어디를 확인해야 하는지</li>
|
||||
<li>토큰이 어떤 사용자와 역할로 해석됐는지 확인합니다.</li>
|
||||
<li>VPD 행 접근 정책을 지난 뒤 실제로 몇 행이 남았는지 확인합니다.</li>
|
||||
<li>ASO/Data Redaction이 어떤 민감 컬럼을 마스킹했는지 확인합니다.</li>
|
||||
<li>FGA 감사 증적이 있으면 DB가 실제 실행한 SQL과 VPD predicate를 확인합니다.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user