Skip to content

feat(federation): add side-effect-free SAML preflight validation - #43

Merged
seonghobae merged 49 commits into
mainfrom
feat/federation-preflight-validation
Aug 4, 2026
Merged

feat(federation): add side-effect-free SAML preflight validation#43
seonghobae merged 49 commits into
mainfrom
feat/federation-preflight-validation

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What

Add an operator-authenticated, side-effect-free federation preflight endpoint and fail-closed SAML/ADFS desired-state validation before anything is persisted or sent to Keycloak.

Buyer-visible gap

The runtime federation API previously enforced only generic size and alias bounds. An operator could persist unresolved {{...}} placeholders, omit issuer pinning, disable signature validation, or configure no trusted certificate source and learn about the error only after convergence failed. The committed employer ADFS artifact also used a raw Keycloak representation that the closed Keyverse desired-state API could not accept.

Runtime contract

  • POST /federation/identity-providers:validate
  • authenticated by the existing operator bearer boundary
  • no KV write, Keycloak Admin REST call, DNS lookup, redirect traversal, or metadata fetch
  • redacted response using the existing safe configuration allowlist
  • unresolved-template rejection for every provider configuration value
  • bounded absolute-URI validation for SAML SP and IdP entity identifiers, including interoperable urn: identifiers
  • HTTPS-only SSO and metadata locations
  • rejection of userinfo, fragments, malformed authorities, whitespace, backslashes, raw C0/DEL controls, percent-encoded controls, and invalid or out-of-range ports
  • explicit idpEntityId so issuer validation cannot silently fall back to disabled
  • required validateSignature=true
  • explicit metadata-backed or manual-certificate trust mode
  • strict Base64 DER X.509 parsing for one or more comma-separated manual signing certificates, including rollover pairs
  • optional manual certificate material is still validated when metadata trust mode is selected
  • the same validation runs before the existing PUT persistence boundary

Deployment and interoperability

  • converts saml-idp-employer-adfs.json to the IdentityProviderRegistration API shape
  • parameterizes SP entity ID, IdP entity ID, metadata URL, and SSO URL
  • documents secure render → exact-200 preflight → ready_to_apply=true → apply and outage recovery
  • protects bearer material from process arguments and shell xtrace
  • disables HTTP redirects in privileged operator examples
  • documents active previous-plus-next certificate trust during manual rollover
  • defines the WAF exposure boundary: public Keyverse admin/SCIM and permitted OIDC endpoints only; federation internals and Keycloak Admin REST stay private
  • requires the Keycloak egress layer or outbound proxy to allow only approved HTTPS hosts and reject HTTPS-to-HTTP redirect downgrade
  • preserves standalone deployment and CWL/Naruon module embedding

Supply-chain security

  • pins cryptography==50.0.0, released July 31, 2026
  • remediates CVE-2026-69247 / GHSA-g6cj-pr64-35w5 reported against 49.0.0
  • refreshes uv.lock, runtime requirements, and development requirements from the reviewed project manifest
  • retains the supported x509.load_der_x509_certificate API used by manual trust validation

Standards basis

The design follows the OASIS SAML metadata interoperability profile’s absolute-URI entity identifier model and Keycloak’s current SAML identity-provider configuration semantics. Network-reachable SSO and metadata locations are restricted more narrowly to HTTPS, while standards-valid non-HTTP entity identifiers remain accepted.

TDD and verification

  • tests-only head 99b88fe74376ff42718660bd7dec6df38906cb11 failed because the preflight route returned HTTP 404
  • URL-hardening head 3dd95ba154823c1c9d1d344e3005d86b2c169378 failed on internal whitespace, backslash, and percent-encoded control cases
  • locked federation workflow run 30884274720 completed successfully and verified Ruff, interrogate 100%, compileall, the complete pytest suite, production statement and branch coverage 100%, package build, documentation shell syntax, realm validation, Compose validation, JSON validation, and git diff --check
  • exact security-upgrade workflow run 30885938322 upgraded and re-locked cryptography 50.0.0 and repeated the complete service, 100% coverage, package-build, and deployment-contract verification successfully
  • exact CodeRabbit remediation workflow run 30887527803 then required HTTPS for SSO and metadata URLs, validated optional manual certificate material in metadata mode, strengthened rollover redaction and shared-lock wiring tests, updated the operator/design contracts, and repeated focused tests, complete tests, production statement/branch coverage 100%, package build, documentation shell validation, and deployment validation successfully
  • the current head has the exact verified tree from workflow commit b90795f8078592ed2621b79048a03930977af9ee; its final user-authored commit exists only to obtain normal exact-head protected-branch checks after the one-shot workflow committed as github-actions[bot]
  • all actionable inline review threads are resolved; merge remains gated on exact-current-head required checks and independent review

Release

CHANGELOG.md is updated under [Unreleased]. No version bump or release is included because broader 0.2.0 release criteria are not yet satisfied.

Closes #3

Summary by CodeRabbit

  • 새 기능

    • 외부 ID 공급자 등록 전 사전 검증 기능을 추가했습니다.
    • 검증 결과에서 민감한 정보가 자동으로 제외됩니다.
    • 유효하지 않은 등록 정보는 저장 전에 차단됩니다.
  • 버그 수정

    • SSO와 metadata 네트워크 위치를 HTTPS로 제한했습니다.
    • 잘못된 포트, 제어 문자, 잘못된 인증서 및 인증서 롤오버 입력을 거부합니다.
    • 운영 예시에서 토큰 노출과 안전하지 않은 리다이렉트를 방지했습니다.
    • 취약한 cryptography 49.0.0을 50.0.0으로 교체했습니다.
  • 문서

    • 외부 페더레이션 온보딩, 운영, 복구 및 egress 절차를 보강했습니다.
    • ADFS 배포 템플릿과 설정 안내를 최신 계약에 맞게 갱신했습니다.
  • 테스트

    • 핵심 기능의 production statement·branch coverage 100% 검증을 추가했습니다.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

외부 IdP desired state에 대한 인증된 preflight 검증을 추가했습니다. SAML URI, 보안 설정, 인증서를 저장 전에 검증하고 민감값을 제거한 결과를 반환합니다. ADFS 템플릿과 온보딩·복구 문서, CI 커버리지 검증도 갱신했습니다.

Changes

외부 페더레이션 사전 검증

Layer / File(s) Summary
검증 계약과 운영 조건
docs/superpowers/..., docs/federation-onboarding.md
preflight 요청·응답, SAML 필수 조건, URL 정책, 인증서 소스, redaction 및 기존 라우트 호환 조건을 정의했습니다.
등록 검증과 preflight 라우트
services/account_unification/app/federation.py, services/account_unification/pyproject.toml
템플릿, URI, URL, boolean, SAML 식별자, 서명 인증서를 검증하고 저장 없이 IdentityProviderValidationResult를 반환합니다.
검증 경계와 회귀 테스트
services/account_unification/tests/test_federation*.py, services/account_unification/tests/test_full_coverage_federation.py
성공·실패 입력, URL hardening, redaction, OIDC 중립 동작, PUT 전 부작용 차단을 검증합니다.
배포 템플릿과 온보딩 절차
deploy/templates/*, docs/federation-onboarding.md, CHANGELOG.md
ADFS 템플릿을 desired-state 계약으로 변경하고 render→preflight→PUT, 수렴, 삭제 및 복구 절차를 문서화했습니다.
저장소 지침과 커버리지 검증
CLAUDE.md, README.md, .github/workflows/ci.yml, services/account_unification/requirements-dev.txt, services/account_unification/tests/test_full_coverage_*.py
저장소 운영 지침과 의존성 잠금을 갱신하고 브랜치 커버리지 100% 검증 및 서비스 경계 테스트를 추가했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant ValidateEndpoint
  participant FederationService
  participant DesiredState
  participant Keycloak
  Operator->>ValidateEndpoint: POST /federation/identity-providers:validate
  ValidateEndpoint->>FederationService: validate_registration(registration)
  FederationService-->>ValidateEndpoint: redacted result and ready_to_apply
  Operator->>DesiredState: PUT /federation/identity-providers/{alias}
  DesiredState->>FederationService: validate registration before persistence
  DesiredState->>Keycloak: converge provider configuration
  Keycloak-->>DesiredState: apply status
Loading

Possibly related PRs

Suggested labels: dependencies, python

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 핵심 변경과 무관한 전체 코드 커버리지 테스트, CI 100% 커버리지 설정, 광범위한 기존 기능 테스트가 포함되었습니다. 연합 기능과 직접 관련 없는 커버리지·CI·기존 기능 테스트 변경을 제거하거나 별도 PR로 분리하십시오.
Linked Issues check ❓ Inconclusive ADFS용 SAML 템플릿과 사전 검증은 확인되지만, 이슈 #3의 LDAP 연동과 고용주별 SSO 요구 지원은 검증할 수 없습니다. LDAP 연동과 고용주별 SSO 요구 지원을 구현한 파일 또는 테스트 근거를 추가하십시오.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 부작용 없는 SAML 사전 검증 기능이라는 PR의 주요 변경 사항을 정확하고 간결하게 설명합니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/federation-preflight-validation

Comment @coderabbitai help to get the list of available commands.

Comment thread .github/workflows/bootstrap-federation-url-hardening.yml Fixed
@seonghobae
seonghobae marked this pull request as ready for review August 4, 2026 03:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (1)
docs/federation-onboarding.md (1)

8-13: 🔒 Security & Privacy | 🔵 Trivial

네트워크 노출 경계를 이 운영 절차에 명시하십시오.

이 절은 operator API의 인증과 토큰 보관만 설명합니다. WAF에서 어떤 endpoint를 공개할 수 있는지 설명하지 않습니다. 배포 지침에 Keyverse admin/SCIM API와 허용된 Keycloak OIDC endpoint만 WAF에 공개하고, federation service 내부망과 Keycloak Admin REST는 공개하지 않는 규칙을 추가하십시오.

Based on learnings, 내부 네트워크는 공개하지 않고 WAF에는 Keycloak OIDC 엔드포인트와 admin/SCIM API만 노출해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/federation-onboarding.md` around lines 8 - 13, Update the “Trust
boundary” section to document the network exposure boundary: instruct
deployments to expose only the Keyverse admin/SCIM APIs and permitted Keycloak
OIDC endpoints through the WAF, while keeping the federation service internal
network and Keycloak Admin REST inaccessible publicly.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/measure-account-unification-coverage.yml:
- Around line 3-10: Update the workflow trigger and job condition so coverage
runs for pull_request events and pushes to the repository’s default branch, not
only feat/federation-preflight-validation. Extend the paths list to include
services/account_unification/pyproject.toml and
services/account_unification/uv.lock, and keep the job’s if condition aligned
with the supported events and branches.

In `@deploy/templates/README.md`:
- Around line 27-33: Protect the bearer token from shell tracing by wrapping
token retrieval and AUTH_CONFIG creation in both deploy/templates/README.md
lines 27-33 and docs/federation-onboarding.md lines 42-48 with xtrace-disabled
handling; after unset TOKEN, restore the trace state that was active before the
protected section.
- Around line 37-52: Update the preflight-and-PUT command sequences in
deploy/templates/README.md lines 37-52 and docs/federation-onboarding.md lines
52-67 so the PUT runs only when the preflight returns HTTP 200 and its JSON
response has ready_to_apply set to true; do not rely solely on curl’s exit
status or --fail-with-body, which permits 3xx responses.

In `@docs/federation-onboarding.md`:
- Around line 79-95: Make the recovery command block independently executable by
recreating BASE and AUTH_CONFIG within that block, retrieving the token from KV,
and generating a temporary curl config with 0600 permissions. Ensure both the
provider-list and provider-apply calls use these locally initialized values,
then remove the temporary config after both operations complete.
- Around line 110-114: Update the manual rollover procedure in the
metadata-disabled path to set both the previous and new certificates,
comma-separated, in the PUT payload’s signingCertificate field during the
rollover window. Explicitly retain both as active trusted certificates, then
remove the previous certificate after the upstream rollover period ends; do not
describe storing the old certificate separately as sufficient.

In `@docs/superpowers/specs/2026-08-04-keyverse-federation-preflight-design.md`:
- Around line 124-127: Update the signingCertificate validation described in the
preflight specification to require a non-empty value that Base64-decodes and
parses as a valid X.509 certificate, excluding PEM headers and footers. Ensure
validation failures prevent ready_to_apply=true, and add coverage for both a
valid certificate and an invalid value such as "MIIC-test-certificate".

In `@services/account_unification/app/federation.py`:
- Around line 383-407: Update the URL validation logic around invalid_text and
invalid_uri to reject every C0 control character (U+0000–U+001F) and DEL, not
only whitespace, while preserving the existing encoded-control checks. Force
validation of parsed.port and treat any ValueError from that access as an
invalid URI, including out-of-range ports such as 65536. Add regression tests
covering a raw NUL character and an out-of-range port in
test_federation_url_hardening.py.

---

Nitpick comments:
In `@docs/federation-onboarding.md`:
- Around line 8-13: Update the “Trust boundary” section to document the network
exposure boundary: instruct deployments to expose only the Keyverse admin/SCIM
APIs and permitted Keycloak OIDC endpoints through the WAF, while keeping the
federation service internal network and Keycloak Admin REST inaccessible
publicly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 38c32967-a36c-4e81-bdb7-dbab605759e4

📥 Commits

Reviewing files that changed from the base of the PR and between aac0ef4 and 0de4f6c.

📒 Files selected for processing (13)
  • .github/workflows/measure-account-unification-coverage.yml
  • CHANGELOG.md
  • CLAUDE.md
  • README.md
  • deploy/templates/README.md
  • deploy/templates/saml-idp-employer-adfs.json
  • docs/federation-onboarding.md
  • docs/superpowers/plans/2026-08-04-keyverse-federation-preflight.md
  • docs/superpowers/specs/2026-08-04-keyverse-federation-preflight-design.md
  • services/account_unification/app/federation.py
  • services/account_unification/tests/test_federation.py
  • services/account_unification/tests/test_federation_preflight.py
  • services/account_unification/tests/test_federation_url_hardening.py

Comment thread .github/workflows/measure-account-unification-coverage.yml Outdated
Comment thread deploy/templates/README.md Outdated
Comment thread deploy/templates/README.md Outdated
Comment thread docs/federation-onboarding.md
Comment thread docs/federation-onboarding.md Outdated
Comment thread services/account_unification/app/federation.py
@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 06:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
services/account_unification/app/federation.py (2)

37-42: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Security Misconfiguration (CWE-319): Cleartext Transmission of Sensitive Information

Reachability: External · Exploitability: Moderate

singleSignOnServiceUrl에는 HTTPS만 허용하십시오.

_HTTP_SCHEMEShttp를 허용하고, 해당 값은 Keycloak payload에 그대로 전달됩니다. 활성 네트워크 공격자는 SSO 트래픽을 읽거나 변경할 수 있습니다. _HTTP_SCHEMES에서 http를 제거하고, http:// 입력이 400을 반환하는 회귀 테스트를 추가하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/account_unification/app/federation.py` around lines 37 - 42,
Restrict singleSignOnServiceUrl to HTTPS by removing “http” from the
_HTTP_SCHEMES allowlist used by the federation validation flow. Add a regression
test covering an http:// value and assert that the request returns 400, while
preserving acceptance of https:// URLs.

37-42: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Security Misconfiguration (CWE-345)

Reachability: External · Exploitability: Moderate

metadataDescriptorUrl에 HTTPS 전용 정책과 redirect 재검증을 적용하십시오.

useMetadataDescriptorUrl=true이면 _validate_http_urlhttphttps를 모두 허용하고, signingCertificate 검증 없이 반환합니다. HTTP metadata와 HTTPS→HTTP redirect를 거부하고, 두 경우의 회귀 테스트를 추가하십시오.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/account_unification/app/federation.py` around lines 37 - 42,
useMetadataDescriptorUrl=true 경로의 _validate_http_url을 수정해 metadataDescriptorUrl과
redirect 최종 URL 모두 HTTPS만 허용하도록 재검증하고 HTTP 및 HTTPS→HTTP redirect를 거부하십시오. 해당
경로에서 signingCertificate 검증을 생략하지 않도록 기존 검증 흐름을 적용하고, 두 거부 사례에 대한 회귀 테스트를 추가하십시오.
🧹 Nitpick comments (2)
services/account_unification/tests/test_federation_preflight.py (1)

299-325: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

롤오버 인증서를 각각 redaction 검사하십시오.

현재 assertion은 쉼표로 결합한 전체 signing_certificates 값만 검사합니다. 응답이 한 certificate body만 노출하면 전체 결합 문자열은 없으므로 테스트가 통과합니다. 각 비어 있지 않은 certificate body를 개별적으로 검사하십시오.

수정 예시
-    assert signing_certificates not in response.text
+    for certificate_body in signing_certificates.split(","):
+        certificate_body = certificate_body.strip()
+        if certificate_body:
+            assert certificate_body not in response.text
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/account_unification/tests/test_federation_preflight.py` around lines
299 - 325, Update test_saml_preflight_accepts_valid_manual_signing_certificates
to validate redaction for each non-empty certificate body separately, rather
than only checking the combined signing_certificates string. Split the
parameterized value on commas and assert every individual certificate is absent
from response.text while preserving the existing status, redacted configuration,
and side-effect assertions.
services/account_unification/tests/test_full_coverage_core.py (1)

326-390: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

공유 잠금 인수도 검증하세요.

UnificationService에 설정한 람다는 생성자 인수를 버립니다. 따라서 이 테스트는 merge 경로가 app.state.user_operation_locks와 같은 locks 인스턴스를 받는지 확인하지 못합니다. 다른 잠금 인스턴스가 전달되면 SCIM replace와 account merge의 상호 배제가 사라질 수 있습니다. 생성자 인수를 캡처하고 user_operation_locks is locks를 assert하세요.

수정 예시
     locks = object()
     unification = object()
     federation = object()
+    wired_locks: object | None = None
+
+    def build_unification(
+        _api: object,
+        _audit: object,
+        _config: object,
+        user_operation_locks: object,
+    ) -> object:
+        """Capture the lock manager assigned to the merge service."""
+        nonlocal wired_locks
+        wired_locks = user_operation_locks
+        return unification
+
     descriptor = SimpleNamespace(namespace="runtime")
@@
     monkeypatch.setattr(
         main,
         "UnificationService",
-        lambda *args: unification,
+        build_unification,
     )
@@
     assert app.state.user_operation_locks is locks
+    assert wired_locks is locks

Based on learnings: SCIM replacement와 merge 흐름은 하나의 공유 동기화 메커니즘으로 보호해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@services/account_unification/tests/test_full_coverage_core.py` around lines
326 - 390, Update test_build_service_wires_all_state so the UnificationService
test double captures its constructor arguments instead of discarding them, then
assert that the user-operation-lock argument is the same locks instance assigned
to app.state.user_operation_locks. Preserve the existing service wiring
assertions.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@services/account_unification/app/federation.py`:
- Around line 37-42: Restrict singleSignOnServiceUrl to HTTPS by removing “http”
from the _HTTP_SCHEMES allowlist used by the federation validation flow. Add a
regression test covering an http:// value and assert that the request returns
400, while preserving acceptance of https:// URLs.
- Around line 37-42: useMetadataDescriptorUrl=true 경로의 _validate_http_url을 수정해
metadataDescriptorUrl과 redirect 최종 URL 모두 HTTPS만 허용하도록 재검증하고 HTTP 및 HTTPS→HTTP
redirect를 거부하십시오. 해당 경로에서 signingCertificate 검증을 생략하지 않도록 기존 검증 흐름을 적용하고, 두 거부
사례에 대한 회귀 테스트를 추가하십시오.

---

Nitpick comments:
In `@services/account_unification/tests/test_federation_preflight.py`:
- Around line 299-325: Update
test_saml_preflight_accepts_valid_manual_signing_certificates to validate
redaction for each non-empty certificate body separately, rather than only
checking the combined signing_certificates string. Split the parameterized value
on commas and assert every individual certificate is absent from response.text
while preserving the existing status, redacted configuration, and side-effect
assertions.

In `@services/account_unification/tests/test_full_coverage_core.py`:
- Around line 326-390: Update test_build_service_wires_all_state so the
UnificationService test double captures its constructor arguments instead of
discarding them, then assert that the user-operation-lock argument is the same
locks instance assigned to app.state.user_operation_locks. Preserve the existing
service wiring assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e1b5c62b-044b-4638-8595-94d357f807b1

📥 Commits

Reviewing files that changed from the base of the PR and between 0de4f6c and d62c700.

⛔ Files ignored due to path filters (2)
  • services/account_unification/requirements.lock is excluded by !**/*.lock
  • services/account_unification/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • deploy/templates/README.md
  • docs/federation-onboarding.md
  • docs/superpowers/specs/2026-08-04-keyverse-federation-preflight-design.md
  • services/account_unification/app/federation.py
  • services/account_unification/pyproject.toml
  • services/account_unification/requirements-dev.txt
  • services/account_unification/tests/test_federation_preflight.py
  • services/account_unification/tests/test_federation_url_hardening.py
  • services/account_unification/tests/test_full_coverage_core.py
  • services/account_unification/tests/test_full_coverage_federation.py
  • services/account_unification/tests/test_full_coverage_http_clients.py
  • services/account_unification/tests/test_full_coverage_registration_scim.py
  • services/account_unification/tests/test_full_coverage_remaining.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • services/account_unification/tests/test_federation_url_hardening.py
  • deploy/templates/README.md
  • docs/federation-onboarding.md
  • docs/superpowers/specs/2026-08-04-keyverse-federation-preflight-design.md

Comment thread .github/workflows/bootstrap-upgrade-cryptography.yml Fixed
@opencode-agent
opencode-agent Bot disabled auto-merge August 4, 2026 07:31

Copy link
Copy Markdown
Contributor Author

Addressed the current CodeRabbit review on the exact implementation tree verified by workflow run 30887527803:

  • singleSignOnServiceUrl and metadataDescriptorUrl now require absolute HTTPS URLs; direct http:// regressions return HTTP 400.
  • Metadata mode validates optional signingCertificate material when supplied, while correctly keeping metadata itself as the selected trust source when no manual certificate is present.
  • Each rollover certificate body is independently checked for response redaction.
  • The application-wiring test now proves SCIM and merge receive the same user-operation lock instance.
  • Operator and design documentation now specify approved-host HTTPS-only Keycloak egress and redirect-downgrade rejection.

The preflight endpoint intentionally performs no DNS lookup, metadata fetch, or redirect traversal, so it cannot observe a remote final redirect URL without violating its side-effect-free/SSRF boundary. Redirect-target enforcement is therefore documented at the Keycloak outbound proxy or network-egress layer, where the redirect actually occurs. The current user-authored head preserves the verified workflow tree and exists only to obtain normal exact-head protected-branch checks.

@seonghobae
seonghobae merged commit 1083577 into main Aug 4, 2026
27 of 28 checks passed
@seonghobae
seonghobae deleted the feat/federation-preflight-validation branch August 4, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feelanet-adfs federation compatibility (external IdP)

2 participants