[Developer] #567 clarify SQL evidence privilege status

This commit is contained in:
devmrko
2026-07-01 14:02:36 +09:00
parent bf393bffa5
commit 07ce6c038a
3 changed files with 42 additions and 9 deletions

View File

@@ -46,6 +46,12 @@ public class OrdsProbeService {
};
private static final Logger log = LoggerFactory.getLogger(OrdsProbeService.class);
private record ExecutionEvidenceLookup(
SqlExecutionEvidence evidence,
boolean sqlCatalogAccessUnavailable
) {
}
private final BearerTokenService tokenService;
private final ProtectedObjectService protectedObjectService;
private final AuditService auditService;
@@ -248,11 +254,17 @@ public class OrdsProbeService {
*/
private ProbeResult attachRecentExecutionEvidence(ProbeResult result, ProtectedObject object) {
try {
SqlExecutionEvidence evidence = findRecentExecutionEvidence(object);
ExecutionEvidenceLookup lookup = findRecentExecutionEvidence(object);
SqlExecutionEvidence evidence = lookup.evidence();
if (evidence == null) {
if (lookup.sqlCatalogAccessUnavailable()) {
return result.withExecutionEvidence(null,
"SQL_ID 실행 증적을 수집할 권한이 없습니다. 현재 권한 검증 결과는 정상입니다. "
+ "DBA에게 ORDS 실행 계정의 V$SQL 및 DBMS_XPLAN 조회 권한을 요청하세요.");
}
return result.withExecutionEvidence(null,
"최근 2분 내 이 보호 대상의 SQL_ID를 shared pool에서 찾지 못했습니다. "
+ "ORDS 실행 계정의 V$SQL 보존 시간과 대상 SQL을 확인하세요.");
"최근 2분 내 이 보호 대상의 실행 cursor를 찾지 못했습니다. "
+ "해당 ORDS 요청이 DB까지 실행됐는지 확인하세요.");
}
String message = evidence.hasPredicatePlan() ? null
: "SQL_ID는 찾았지만 DBMS_XPLAN Predicate Information을 읽지 못했습니다. "
@@ -266,17 +278,37 @@ public class OrdsProbeService {
}
}
private SqlExecutionEvidence findRecentExecutionEvidence(ProtectedObject object) {
private ExecutionEvidenceLookup findRecentExecutionEvidence(ProtectedObject object) {
JdbcTemplate evidenceJdbcTemplate = ordsMetadataService.executionEvidenceJdbcTemplate();
boolean sqlCatalogAccessUnavailable = false;
try {
SqlExecutionEvidence evidence = findRecentExecutionEvidence(evidenceJdbcTemplate, object);
if (evidence != null || evidenceJdbcTemplate == jdbcTemplate) {
return evidence;
return new ExecutionEvidenceLookup(evidence, false);
}
} catch (RuntimeException exception) {
sqlCatalogAccessUnavailable = isSqlCatalogAccessUnavailable(exception);
log.debug("ORDS parsing-schema cursor evidence is unavailable: {}", exception.getMessage());
}
return findRecentExecutionEvidence(jdbcTemplate, object);
try {
return new ExecutionEvidenceLookup(
findRecentExecutionEvidence(jdbcTemplate, object), sqlCatalogAccessUnavailable);
} catch (RuntimeException exception) {
log.debug("Backoffice cursor evidence is unavailable: {}", exception.getMessage());
return new ExecutionEvidenceLookup(null,
sqlCatalogAccessUnavailable || isSqlCatalogAccessUnavailable(exception));
}
}
private boolean isSqlCatalogAccessUnavailable(RuntimeException exception) {
String message = exception.getMessage();
if (message == null) {
return false;
}
String normalized = message.toUpperCase(Locale.ROOT);
return normalized.contains("ORA-00942")
|| normalized.contains("V_$SQL")
|| normalized.contains("V$SQL");
}
private SqlExecutionEvidence findRecentExecutionEvidence(

View File

@@ -37,7 +37,8 @@ class ProbeResultTemplateRenderTest {
"{}",
"{}",
"{}"
).withExecutionEvidence(null, "최근 SQL_ID를 찾지 못했습니다.");
).withExecutionEvidence(null,
"SQL_ID 실행 증적을 수집할 권한이 없습니다. 현재 권한 검증 결과는 정상입니다.");
var context = new Context(Locale.KOREAN);
context.setVariable("result", result);
context.setVariable("vectorSearch", false);
@@ -46,6 +47,6 @@ class ProbeResultTemplateRenderTest {
String rendered = engine.process("fragments/probe-result", context);
assertThat(rendered).contains("최근 SQL_ID를 찾지 못했습니다.");
assertThat(rendered).contains("SQL_ID 실행 증적을 수집할 권한이 없습니다.");
}
}