test(android): consolidate connection TLS fixtures (#118532)

This commit is contained in:
Peter Steinberger
2026-08-02 23:29:37 -07:00
committed by GitHub
parent b65cc592cc
commit 4b3d0b37be

View File

@@ -3,6 +3,7 @@ package ai.openclaw.app.node
import ai.openclaw.app.LocationMode
import ai.openclaw.app.SecurePrefs
import ai.openclaw.app.gateway.GatewayEndpoint
import ai.openclaw.app.gateway.GatewayTlsParams
import ai.openclaw.app.gateway.isLocalCleartextGatewayHost
import ai.openclaw.app.gateway.isLoopbackGatewayHost
import ai.openclaw.app.protocol.OpenClawCallLogCommand
@@ -26,268 +27,62 @@ import org.robolectric.RuntimeEnvironment
@RunWith(RobolectricTestRunner::class)
class ConnectionManagerTest {
@Test
fun resolveTlsParamsForEndpoint_prefersStoredPinOverAdvertisedFingerprint() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
fun resolveTlsParamsForEndpoint_prefersStoredPinOverAdvertisedFingerprint() =
assertTls(
resolveDiscoveredTls(
host = "10.0.0.2",
port = 18789,
tlsEnabled = true,
tlsFingerprintSha256 = "attacker",
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = "legit",
manualTlsEnabled = false,
)
assertEquals("legit", params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
tlsEnabled = true,
advertisedFingerprint = "attacker",
),
expectedFingerprint = "legit",
)
@Test
fun resolveTlsParamsForEndpoint_doesNotTrustAdvertisedFingerprintWhenNoStoredPin() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
fun resolveTlsParamsForEndpoint_doesNotTrustAdvertisedFingerprintWhenNoStoredPin() =
assertTls(
resolveDiscoveredTls(
host = "10.0.0.2",
port = 18789,
tlsEnabled = true,
tlsFingerprintSha256 = "attacker",
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
advertisedFingerprint = "attacker",
),
)
@Test
fun resolveTlsParamsForEndpoint_manualRespectsManualTlsToggle() {
val endpoint = GatewayEndpoint.manual(host = "127.0.0.1", port = 443)
val off =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(off)
val on =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = true,
)
assertNull(on?.expectedFingerprint)
assertEquals(false, on?.allowTOFU)
assertNull(resolveManualTls(host = "127.0.0.1", port = 443))
assertTls(resolveManualTls(host = "127.0.0.1", port = 443, manualTlsEnabled = true))
}
@Test
fun resolveTlsParamsForEndpoint_manualNonLoopbackForcesTlsWhenToggleIsOff() {
val endpoint = GatewayEndpoint.manual(host = "example.com", port = 443)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_manualNonLoopbackForcesTlsWhenToggleIsOff() = assertTlsRequired(resolveManualTls(host = "example.com", port = 443))
@Test
fun resolveTlsParamsForEndpoint_manualPrivateLanRespectsManualTlsToggle() {
val endpoint = GatewayEndpoint.manual(host = "192.168.1.20", port = 18789)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_manualPrivateLanRespectsManualTlsToggle() = assertNull(resolveManualTls("192.168.1.20"))
@Test
fun resolveTlsParamsForEndpoint_manualMdnsRespectsManualTlsToggle() {
val endpoint = GatewayEndpoint.manual(host = "gateway.local", port = 18789)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_manualMdnsRespectsManualTlsToggle() = assertNull(resolveManualTls("gateway.local"))
@Test
fun resolveTlsParamsForEndpoint_manualPrivateLanCleartextCanOverrideStoredPin() {
val endpoint = GatewayEndpoint.manual(host = "192.168.1.20", port = 18789)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = "pinned",
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_manualPrivateLanCleartextCanOverrideStoredPin() = assertNull(resolveManualTls(host = "192.168.1.20", storedFingerprint = "pinned"))
@Test
fun resolveTlsParamsForEndpoint_discoveryTailnetWithoutHintsStillRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "100.64.0.9",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryTailnetWithoutHintsStillRequiresTls() = assertDiscoveredHostRequiresTls("100.64.0.9")
@Test
fun resolveTlsParamsForEndpoint_discoveryPrivateLanWithoutHintsStillRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "192.168.1.20",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryPrivateLanWithoutHintsStillRequiresTls() = assertDiscoveredHostRequiresTls("192.168.1.20")
@Test
fun resolveTlsParamsForEndpoint_discoveryMdnsWithoutHintsStillRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "gateway.local",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryMdnsWithoutHintsStillRequiresTls() = assertDiscoveredHostRequiresTls("gateway.local")
@Test
fun resolveTlsParamsForEndpoint_discoveryLoopbackWithoutHintsCanStayCleartext() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "127.0.0.1",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_discoveryLoopbackWithoutHintsCanStayCleartext() = assertDiscoveredHostCanStayCleartext("127.0.0.1")
@Test
fun resolveTlsParamsForEndpoint_discoveryLocalhostWithoutHintsCanStayCleartext() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "localhost",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_discoveryLocalhostWithoutHintsCanStayCleartext() = assertDiscoveredHostCanStayCleartext("localhost")
@Test
fun resolveTlsParamsForEndpoint_discoveryAndroidEmulatorWithoutHintsCanStayCleartext() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "10.0.2.2",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_discoveryAndroidEmulatorWithoutHintsCanStayCleartext() = assertDiscoveredHostCanStayCleartext("10.0.2.2")
@Test
fun isLoopbackGatewayHost_onlyTreatsEmulatorBridgeAsLocalWhenAllowed() {
@@ -311,120 +106,19 @@ class ConnectionManagerTest {
}
@Test
fun resolveTlsParamsForEndpoint_discoveryIpv6LoopbackWithoutHintsCanStayCleartext() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "::1",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_discoveryIpv6LoopbackWithoutHintsCanStayCleartext() = assertDiscoveredHostCanStayCleartext("::1")
@Test
fun resolveTlsParamsForEndpoint_discoveryMappedIpv4LoopbackWithoutHintsCanStayCleartext() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "::ffff:127.0.0.1",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertNull(params)
}
fun resolveTlsParamsForEndpoint_discoveryMappedIpv4LoopbackWithoutHintsCanStayCleartext() = assertDiscoveredHostCanStayCleartext("::ffff:127.0.0.1")
@Test
fun resolveTlsParamsForEndpoint_discoveryNonLoopbackIpv6WithoutHintsRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "2001:db8::1",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryNonLoopbackIpv6WithoutHintsRequiresTls() = assertDiscoveredHostRequiresTls("2001:db8::1")
@Test
fun resolveTlsParamsForEndpoint_discoveryUnspecifiedIpv4WithoutHintsRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "0.0.0.0",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryUnspecifiedIpv4WithoutHintsRequiresTls() = assertDiscoveredHostRequiresTls("0.0.0.0")
@Test
fun resolveTlsParamsForEndpoint_discoveryUnspecifiedIpv6WithoutHintsRequiresTls() {
val endpoint =
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = "::",
port = 18789,
tlsEnabled = false,
tlsFingerprintSha256 = null,
)
val params =
ConnectionManager.resolveTlsParamsForEndpoint(
endpoint,
storedFingerprint = null,
manualTlsEnabled = false,
)
assertEquals(true, params?.required)
assertNull(params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
fun resolveTlsParamsForEndpoint_discoveryUnspecifiedIpv6WithoutHintsRequiresTls() = assertDiscoveredHostRequiresTls("::")
@Test
fun buildOperatorConnectOptions_requestsNativeClientOperatorScopes() {
@@ -650,6 +344,54 @@ class ConnectionManagerTest {
assertEquals(permissionSnapshot.gatewayPermissions(), options.permissions)
}
private fun resolveDiscoveredTls(
host: String,
storedFingerprint: String? = null,
tlsEnabled: Boolean = false,
advertisedFingerprint: String? = null,
): GatewayTlsParams? =
ConnectionManager.resolveTlsParamsForEndpoint(
GatewayEndpoint(
stableId = "_openclaw-gw._tcp.|local.|Test",
name = "Test",
host = host,
port = 18789,
tlsEnabled = tlsEnabled,
tlsFingerprintSha256 = advertisedFingerprint,
),
storedFingerprint = storedFingerprint,
manualTlsEnabled = false,
)
private fun resolveManualTls(
host: String,
port: Int = 18789,
storedFingerprint: String? = null,
manualTlsEnabled: Boolean = false,
): GatewayTlsParams? =
ConnectionManager.resolveTlsParamsForEndpoint(
GatewayEndpoint.manual(host = host, port = port),
storedFingerprint = storedFingerprint,
manualTlsEnabled = manualTlsEnabled,
)
private fun assertTls(
params: GatewayTlsParams?,
expectedFingerprint: String? = null,
) {
assertEquals(expectedFingerprint, params?.expectedFingerprint)
assertEquals(false, params?.allowTOFU)
}
private fun assertTlsRequired(params: GatewayTlsParams?) {
assertEquals(true, params?.required)
assertTls(params)
}
private fun assertDiscoveredHostRequiresTls(host: String) = assertTlsRequired(resolveDiscoveredTls(host))
private fun assertDiscoveredHostCanStayCleartext(host: String) = assertNull(resolveDiscoveredTls(host))
private fun newManager(
cameraEnabled: Boolean = false,
locationMode: LocationMode = LocationMode.Off,