fix(kas): well-known missing kas → default KAS URL + Stage-1 xtest CI - #48
Conversation
Local platforms often serve /.well-known/opentdf-configuration with IdP metadata but no kas block. resolveConfiguration treated a successful fetch as complete, then KasEndpoints.from failed with "missing a 'kas' block". - OpenTDFConfiguration.withKasFallback synthesizes Connect endpoints while preserving IdP fields - CLI default base: PLATFORMURL, else KASURL with /kas stripped - Unit tests for missing/incomplete kas and preserve-usable-well-known - CI: X-Test Stage-1 pulls floating latest arkavo-org/opentdf-tests release (branch fallback) and runs swift × go Base TDF stage1
withKasFallback no longer uses try? KasEndpoints.from, which swallowed SSRF and scheme validation errors and rewrote hostile well-known kas blocks to the fallback base (changing kas.uri / identity). Fallback only when kas is nil, uri is empty, or neither Connect nor REST endpoint pairs are advertised. Present endpoint URLs keep their identity; KasEndpoints.from still enforces validateKasURL.
Code Review ✅ Approved 1 resolved / 1 findingsImplements a fallback to default KAS URLs when the well-known configuration is missing endpoints, resolving the identified error-handling issue. CI coverage is now extended with a new Stage-1 test suite. ✅ 1 resolved✅ Edge Case: withKasFallback swallows SSRF/validation errors, silently replaces KAS
Was this helpful? React with 👍 / 👎 | Gitar |
Normalize localhost → 127.0.0.1 in the token endpoint URL so Keycloak issues JWTs whose iss matches server.auth.issuer (CI sets 127.0.0.1). Use strict form-urlencoded encoding for client credentials. Also track community-xtest-stage1 branch tip for floating tests-ref so Stage-1 infra fixes land without waiting on a new tests release.
Stage-1 failures after auth was fixed: 1. Rewrap responses include X-Required-Obligations as a JSON array; metadata was [String:String] and decode aborted after a successful permit. Accept heterogeneous RewrapMetadataValue. 2. policyBinding used base64(raw HMAC over policy bytes). Go/KAS expect base64(hex(HMAC-SHA256(DEK, base64(policyJSON)))) — wrong hash made go rewrap report "tamper detected" on Swift-produced TDFs.
- SwiftFormat: preferKeyPath / drop redundant throws in policy binding tests
- RewrapMetadataValue.stringValue: integral doubles without trailing .0
- Standard TDF EC session unwrap salt = SHA256("TDF") (go tdfSalt), not empty
- Honor XT_WITH_ATTRIBUTES when building default encrypt policy (go attributeObject)
Workflow file, display name, job id, step titles, and artifact names drop stage1/Stage-1. Pytest still filters with -m stage1 (suite marker) and still pins the community-xtest-stage1 tests branch by ref.
OpenTDF platform/go encrypt DEKs with rsa.EncryptOAEP(sha1.New(), …). Swift used SecKey .rsaEncryptionOAEPSHA256, so KAS could not unwrap the DEK and returned a non-permit rewrap result (surfaced as "Access denied by policy"). Match go OAEP-SHA1 for wrap/unwrap. Also surface full rewrap metadata on deny for easier CI diagnosis.
Gitar: share Config.defaultPolicyData / attributeObjectsFromEnvironment for XT_WITH_ATTRIBUTES instead of duplicating parse in main+Commands. Integrity: go hexless GMAC is last 16 bytes of the encrypted segment (AES-GCM tag), base64-encoded — not a synthetic GMAC. Root is base64(HMAC-SHA256(DEK, concat(raw tags))). Fixes go decrypt "failed integrity check on segment hash". Naming: Base/standard TDF is called tdf; ztdf kept only as a silent legacy wire alias for xtest shims (not NATO STANAG ZTDF).
Code Review ✅ Approved 3 resolved / 3 findingsImplements KAS discovery fallback and cross-repo Stage-1 testing while standardizing TDF crypto formats for Go SDK interoperability. Resolved findings include SSRF validation errors, metadata rendering quirks, and logic duplication in attribute parsing. ✅ 3 resolved✅ Edge Case: withKasFallback swallows SSRF/validation errors, silently replaces KAS
✅ Quality: RewrapMetadataValue.stringValue renders numbers with .0 suffix
✅ Quality: Duplicated XT_WITH_ATTRIBUTES policy-parsing logic
Was this helpful? React with 👍 / 👎 | Gitar |
Summary
/.well-known/opentdf-configurationreturns 200 without a usablekasblock, fall back to Connect endpoints on the default KAS base (PLATFORMURL/ strippedKASURL) instead of failing withwell-known configuration is missing a 'kas' block.X-Test Stage-1workflow pulls floating latest release ofarkavo-org/opentdf-tests(falls back tocommunity-xtest-stage1if no release) and runs swift × go Base TDF stage1 on macOS with the native platform stack.Cross-repo coordination
tests-ref: latest→ community-xtest-stage1-v0.1.0 (created)swift-ref: latest; until a post-fix OpenTDFKit release, useswift-ref: main/ this PR SHA for green Stage-1After merge, cut an OpenTDFKit release (or keep community-xtest on
main) so floatinglatestincludes this fallback.Test plan
swift test --filter KASDiscoveryTests(24 tests, 0 failures)X-Test Stage-1on this PRswift-ref= this SHA or main after mergeSummary by Gitar
policyBindingto encode HMAC-SHA256 of the base64-encoded policy, fixing interoperability with the Go SDK.wrapSymmetricKeyWithRSAto useRSA-OAEP-SHA1for alignment with existing KAS unwrap expectations.TDFEncryptorto use new hexless 4.3.0 root signature logic (base64(HMAC-SHA256(DEK, concat(raw segment sigs)))).localhostto127.0.0.1and applying strict form-urlencoding.XT_WITH_ATTRIBUTESsupport for injecting FQN-based attribute objects during CLI TDF policy generation.RewrapMetadataValueenum to handle heterogeneous metadata (strings, arrays, objects) in rewrap responses.withKasFallbackto automatically synthesize platform Connect endpoints when well-known configuration is incomplete.xtest.ymlfor Stage-1 cross-testing between the Swift SDK and the Go platform peer.This will update automatically on new commits.