The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
64 lines
3.5 KiB
Plaintext
64 lines
3.5 KiB
Plaintext
# 검증기 자신의 javadoc 이 하는 주장
|
|
18: * <p>The verification runs at startup and fails closed. Discovering after an incident that the
|
|
19: * application's own credential could drop tables is discovering it too late.
|
|
|
|
# 정책이 검사하는 네 항목
|
|
40: if (!allowedRoles.contains(currentUser)) {
|
|
44: if (report.canCreateInSchema()) {
|
|
51: if (report.canCreateInDatabase()) {
|
|
55: searchPathPolicy.requireSafe(report.searchPath());
|
|
|
|
# 검증기는 프로덕션에서 실제로 불린다 — 다만 기동이 아니라 리포트를 만들 때다
|
|
110: private DatabasePrivilegeReport readPrivileges(DataSource dataSource) {
|
|
111- try {
|
|
112- return roleVerifier.verify(dataSource);
|
|
113- } catch (IllegalStateException unverified) {
|
|
114- return null;
|
|
115- }
|
|
112: return roleVerifier.verify(dataSource);
|
|
|
|
# 정책을 넘기는 두 인자짜리 호출
|
|
55: public void requireSafe(DataSource dataSource, DatabaseRolePolicy policy) {
|
|
56- Objects.requireNonNull(policy, "policy");
|
|
57- policy.requireSafe(verify(dataSource));
|
|
58- }
|
|
# 그 호출을 하는 곳 (레포 전체): 1
|
|
adapter/outbound/persistence-jpa/src/postgresqlIntegrationTest/java/dev/caskeleton/adapter/outbound/persistence/platform/PostgreSqlSecurityContractTest.java:92: new PostgreSqlRuntimeRoleVerifier().requireSafe(runtime, policy);
|
|
# DatabaseRolePolicy 를 만드는 main 코드: 0
|
|
# DatabaseRolePolicy 를 언급하는 파일 전부: PostgreSqlSecurityContractTest.java DatabaseRolePolicyTest.java PostgreSqlRuntimeRoleVerifier.java DatabaseRolePolicy.java
|
|
|
|
# 기동 검사 빈이 실행하는 것
|
|
194: public InitializingBean jpaPlatformStartupCheck(
|
|
195- JpaDangerousConfigurationGuard guard, Environment environment) {
|
|
196- // A refresh-time failure beats a runtime one: OSIV left on, or a schema-mutating ddl-auto in a
|
|
197- // profile that forbids it, is a deployment mistake and not a request-time condition.
|
|
198- return () -> guard.validate(environment);
|
|
199- }
|
|
200-
|
|
|
|
# 액추에이터의 검증 완료 표시가 보는 것
|
|
36: * Builds the report, deriving only bounded values from the privilege report.
|
|
37: *
|
|
38: * <p>The privilege report's {@code currentUser} and {@code searchPath} are deliberately reduced
|
|
39: * to a single boolean here: an operator needs to know the runtime role passed verification, not
|
|
40: * which role it is.
|
|
41: */
|
|
56: privileges != null && !privileges.holdsCreatePrivilege(),
|
|
62: return openInViewDisabled && runtimeRoleVerified;
|
|
|
|
# 그 표시를 고정하는 시험이 넣는 입력
|
|
37: new DatabasePrivilegeReport("app_runtime", "app, pg_catalog", false, false),
|
|
58: new DatabasePrivilegeReport("app_runtime", "app", true, false),
|
|
# 정책 쪽 단위 시험은 그 두 조합을 실제로 넣는다
|
|
21: policy.requireSafe(new DatabasePrivilegeReport("app_runtime", "app, pg_catalog", false, false));
|
|
29: policy.requireSafe(new DatabasePrivilegeReport("app_runtime", "app", true, false)))
|
|
38: () -> policy.requireSafe(new DatabasePrivilegeReport("postgres", "app", false, false)))
|
|
49: new DatabasePrivilegeReport("app_runtime", "app, public", false, false)))
|
|
57: policy.requireSafe(new DatabasePrivilegeReport("app_runtime", "\"$user\", app", false, false));
|
|
58: assertThat(policy.isSafe(new DatabasePrivilegeReport("app_runtime", "app", false, false)))
|
|
|
|
# 안정 등급의 정의
|
|
10-
|
|
11- /** Verified by the Stable contract suite on the whole PostgreSQL Stable matrix. */
|
|
12: STABLE,
|