Archived
fix: remove conflicting ATS CA pin and verify physical LiveKit trust
This commit is contained in:
1 parent
15c6389ffb
commit
5b41b3924a
5 files changed
+32
-22
No files matched your search
@@ -24,21 +24,6 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSPinnedDomains</key>
|
|
||||||
<dict>
|
|
||||||
<key>192.168.86.2</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSIncludesSubdomains</key>
|
|
||||||
<true/>
|
|
||||||
<key>NSPinnedCAIdentities</key>
|
|
||||||
<array>
|
|
||||||
<dict>
|
|
||||||
<key>SPKI-SHA256-BASE64</key>
|
|
||||||
<string>vmrfRuHv1oHBBiEmJP4WX3C7mtVy3C4+UJ1Yk/Q5hMU=</string>
|
|
||||||
</dict>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>Hope Voice uses the microphone for live voice conversation.</string>
|
<string>Hope Voice uses the microphone for live voice conversation.</string>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import LiveKit
|
||||||
import Testing
|
import Testing
|
||||||
@testable import Voice
|
@testable import Voice
|
||||||
|
|
||||||
@@ -15,6 +16,14 @@ struct TLSLiveTests {
|
|||||||
#expect(!data.isEmpty)
|
#expect(!data.isEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test func systemTrustedLANHTTPS() async throws {
|
||||||
|
guard ProcessInfo.processInfo.environment["HOPE_TLS_LIVE"] == "1" else { return }
|
||||||
|
print("HOPE_TLS_PROBE system trust validation started")
|
||||||
|
let (_, response) = try await URLSession.shared.data(from: URL(string: "https://192.168.86.2:9178/api/auth/me")!)
|
||||||
|
#expect((response as? HTTPURLResponse)?.statusCode == 401)
|
||||||
|
print("HOPE_TLS_PROBE system trust validation completed")
|
||||||
|
}
|
||||||
|
|
||||||
@Test func nativeAccountLogin() async throws {
|
@Test func nativeAccountLogin() async throws {
|
||||||
let env = ProcessInfo.processInfo.environment
|
let env = ProcessInfo.processInfo.environment
|
||||||
guard env["HOPE_TLS_LIVE"] == "1", let username = env["HOPE_TEST_USERNAME"],
|
guard env["HOPE_TLS_LIVE"] == "1", let username = env["HOPE_TEST_USERNAME"],
|
||||||
@@ -25,6 +34,12 @@ struct TLSLiveTests {
|
|||||||
let login = try await client.login(username: username, password: password)
|
let login = try await client.login(username: username, password: password)
|
||||||
#expect(login.user.username == username)
|
#expect(login.user.username == username)
|
||||||
#expect(try await client.me(token: login.token).id == login.user.id)
|
#expect(try await client.me(token: login.token).id == login.user.id)
|
||||||
|
let bootstrap = try await TokenClient(config: config, bearerToken: login.token).fetchToken()
|
||||||
|
let room = Room()
|
||||||
|
try await room.connect(url: config.livekitURL.absoluteString, token: bootstrap.token)
|
||||||
|
#expect(room.connectionState == .connected)
|
||||||
|
await room.disconnect()
|
||||||
|
print("HOPE_TLS_PROBE authenticated LiveKit WSS connected and disconnected; microphone not enabled")
|
||||||
try await client.logout(token: login.token)
|
try await client.logout(token: login.token)
|
||||||
print("HOPE_TLS_PROBE native login/me/logout completed")
|
print("HOPE_TLS_PROBE native login/me/logout completed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ Read [PROJECT_STATUS.md](PROJECT_STATUS.md) for the current product scope.
|
|||||||
- Gate live TLS tests with explicit opt-in and print started/skipped scope; a test
|
- Gate live TLS tests with explicit opt-in and print started/skipped scope; a test
|
||||||
returning early is not runtime proof. Regenerate XcodeGen for added test membership.
|
returning early is not runtime proof. Regenerate XcodeGen for added test membership.
|
||||||
Physical test bundles require a development team override, not just app signing.
|
Physical test bundles require a development team override, not just app signing.
|
||||||
|
- Proven device ATS trap: `NSPinnedCAIdentities` can still reject a manually
|
||||||
|
full-trusted self-signed server with -1202/-9807. Same-phone A/B removal of this
|
||||||
|
redundant rule made system HTTPS and actual LiveKit WSS pass. Retain exact app
|
||||||
|
HTTP pin + normal SDK system trust; do not infer validity-length cause from dates.
|
||||||
- Certificate profiles require public-only verified data, user installation/full
|
- Certificate profiles require public-only verified data, user installation/full
|
||||||
trust, and persistent hosting. Copying a file into an active container is erased
|
trust, and persistent hosting. Copying a file into an active container is erased
|
||||||
at redeploy. Exact nginx alias may expose a public profile from cert mount; never
|
at redeploy. Exact nginx alias may expose a public profile from cert mount; never
|
||||||
|
|||||||
+13
-2
@@ -104,8 +104,19 @@ unit suite:58 passed, including two explicit-opt-in live TLS cases skipped in of
|
|||||||
run. Actual opted-in physical HTTPS test passed separately. New live tests use
|
run. Actual opted-in physical HTTPS test passed separately. New live tests use
|
||||||
environment-only credentials, never fixtures/source/argv. Updated signed phone
|
environment-only credentials, never fixtures/source/argv. Updated signed phone
|
||||||
build passed (`/tmp/hope-square-phone-build.log`) and app installed/launch succeeded
|
build passed (`/tmp/hope-square-phone-build.log`) and app installed/launch succeeded
|
||||||
on the iPhone14ProMax (`dev.shane.voice`, 18:00 local). Real WSS/login after profile trust and
|
on the iPhone14ProMax (`dev.shane.voice`, 18:00 local). Physical speech remains user qualification.
|
||||||
physical speech remain user qualification.
|
|
||||||
|
Follow-up: user installed profile/full trust but SDK still reported validation cert
|
||||||
|
invalid. Reproduced physically: exact pinned HTTPS passed; system URLSession HTTPS
|
||||||
|
failed -1202/-9807. Controlled A/B removed redundant `NSPinnedCAIdentities` in
|
||||||
|
XcodeGen (normal iOS trust, HTTPS/WSS and exact HTTP leaf pin remain unchanged).
|
||||||
|
System trust then passed on same phone, establishing ATS CA-only rule conflict,
|
||||||
|
not proven certificate validity-length rejection. Final physical native live test
|
||||||
|
**3 passed**: pinned HTTPS, system-trusted HTTPS, and admin login/me/bootstrap →
|
||||||
|
actual LiveKit SDK authenticated WSS connect/disconnect → logout; no microphone
|
||||||
|
enabled. Evidence `/tmp/hope-phone-wss-qualified.log`. John Doe remains deleted.
|
||||||
|
Signed corrected build passed `/tmp/hope-square-tls-fixed-build.log`.
|
||||||
|
|
||||||
|
|
||||||
## Current direction
|
## Current direction
|
||||||
|
|
||||||
|
|||||||
@@ -38,11 +38,6 @@ targets:
|
|||||||
NSMicrophoneUsageDescription: "Hope Voice uses the microphone for live voice conversation."
|
NSMicrophoneUsageDescription: "Hope Voice uses the microphone for live voice conversation."
|
||||||
NSAppTransportSecurity:
|
NSAppTransportSecurity:
|
||||||
NSAllowsLocalNetworking: true
|
NSAllowsLocalNetworking: true
|
||||||
NSPinnedDomains:
|
|
||||||
192.168.86.2:
|
|
||||||
NSIncludesSubdomains: true
|
|
||||||
NSPinnedCAIdentities:
|
|
||||||
- SPKI-SHA256-BASE64: vmrfRuHv1oHBBiEmJP4WX3C7mtVy3C4+UJ1Yk/Q5hMU=
|
|
||||||
settings:
|
settings:
|
||||||
base:
|
base:
|
||||||
PRODUCT_BUNDLE_IDENTIFIER: dev.shane.voice
|
PRODUCT_BUNDLE_IDENTIFIER: dev.shane.voice
|
||||||
|
|||||||
Reference in new issue
Block a user