From 66493c0b86cbc94e4aea7e4cf1cc718a2367030e Mon Sep 17 00:00:00 2001 From: ekoby <7406535+ekoby@users.noreply.github.com> Date: Tue, 29 Jun 2021 10:49:29 -0400 Subject: [PATCH] More diagnostics in Ziti feedback (#203) * add '/current-identity/edge-routers' api * get current edge routers and report in ZitiContext.dump() * include contents of Ziti DNS in feedback --- .../main/java/org/openziti/android/Ziti.kt | 4 +++ .../kotlin/org/openziti/api/Controller.kt | 5 ++++ .../src/main/kotlin/org/openziti/api/types.kt | 6 +++- .../org/openziti/impl/ZitiContextImpl.kt | 14 ++++++++- .../main/kotlin/org/openziti/net/Transport.kt | 29 +++++-------------- .../org/openziti/net/dns/DNSResolver.kt | 5 +++- .../org/openziti/net/dns/ZitiDNSManager.kt | 7 +++++ .../org/openziti/net/nio/AsyncTLSChannel.kt | 1 - .../kotlin/org/openziti/net/nio/NetUtils.kt | 3 +- 9 files changed, 46 insertions(+), 28 deletions(-) diff --git a/ziti-android/src/main/java/org/openziti/android/Ziti.kt b/ziti-android/src/main/java/org/openziti/android/Ziti.kt index 25af1ed9..60a88b91 100644 --- a/ziti-android/src/main/java/org/openziti/android/Ziti.kt +++ b/ziti-android/src/main/java/org/openziti/android/Ziti.kt @@ -268,6 +268,10 @@ object Ziti: CoroutineScope, Logged by ZitiLog() { writer.flush() } + zip.putNextEntry(ZipEntry("ziti_dns.info")) + getDnsResolver().dump(writer) + writer.flush() + zip.putNextEntry(ZipEntry("ziti.log")) writer.appendLine("logcat result: ${logrc.get()}") writer.write(log.get()) diff --git a/ziti/src/main/kotlin/org/openziti/api/Controller.kt b/ziti/src/main/kotlin/org/openziti/api/Controller.kt index 747d6c93..94ebda1f 100644 --- a/ziti/src/main/kotlin/org/openziti/api/Controller.kt +++ b/ziti/src/main/kotlin/org/openziti/api/Controller.kt @@ -67,6 +67,9 @@ internal class Controller(endpoint: URL, sslContext: SSLContext, trustManager: X @DELETE("current-api-session") fun logout(): Deferred + @GET("/current-identity/edge-routers") + fun getEdgeRouters(): Deferred>> + @GET("/current-identity/mfa") fun getMFA(): Deferred> @@ -303,6 +306,8 @@ internal class Controller(endpoint: URL, sslContext: SSLContext, trustManager: X api.sendPosture(pr).await() } + internal suspend fun getEdgeRouters() = api.getEdgeRouters().await().data ?: emptyList() + private fun convertError(t: Throwable): Nothing { val errCode = when (t) { is HttpException -> getZitiError(getError(t.response())) diff --git a/ziti/src/main/kotlin/org/openziti/api/types.kt b/ziti/src/main/kotlin/org/openziti/api/types.kt index 449ef1e1..bfd5a37a 100644 --- a/ziti/src/main/kotlin/org/openziti/api/types.kt +++ b/ziti/src/main/kotlin/org/openziti/api/types.kt @@ -177,7 +177,11 @@ class PostureResponse (val id: String, val typeId: PostureQueryType, val data: D } } -internal data class EdgeRouter(val name: String, val hostname: String, val urls: Map) +internal data class EdgeRouter( + val name: String, + val hostname: String, + val supportedProtocols: Map, + @Deprecated("use supportedProtocols") val urls: Map) internal data class Session(val id: String, val token: String, val service: Id, val type: SessionType, var edgeRouters: Array?) { diff --git a/ziti/src/main/kotlin/org/openziti/impl/ZitiContextImpl.kt b/ziti/src/main/kotlin/org/openziti/impl/ZitiContextImpl.kt index 46c2636e..c2917bec 100644 --- a/ziti/src/main/kotlin/org/openziti/impl/ZitiContextImpl.kt +++ b/ziti/src/main/kotlin/org/openziti/impl/ZitiContextImpl.kt @@ -71,6 +71,7 @@ internal class ZitiContextImpl(internal val id: Identity, enabled: Boolean) : Zi get() = Dispatchers.IO + supervisor private val apiSession = MutableStateFlow(null) + private val currentEdgeRouters = MutableStateFlow>(emptyList()) private val controller: Controller = Controller(URI.create(id.controller()).toURL(), sslContext(), trustManager()) private val postureService = PostureService() @@ -313,6 +314,12 @@ internal class ZitiContextImpl(internal val id: Identity, enabled: Boolean) : Zi } } + controller.runCatching { getEdgeRouters() } + .onSuccess { + i{"current edge routers = $it"} + currentEdgeRouters.value = it } + .onFailure { w("failed to get current edge routers: $it") } + oneUpdate.join() oneUpdate.invokeOnCompletion { when (it) { @@ -585,9 +592,14 @@ internal class ZitiContextImpl(internal val id: Identity, enabled: Boolean) : Zi servicesByName.forEach { (name, s) -> writer.appendLine("name: $name id: ${s.id} permissions: ${s.permissions.joinToString()} intercept: ${s.interceptConfig}") } + writer.flush() writer.appendLine() - writer.appendLine("=== Channels ===") + writer.appendLine("=== Available Edge Routers[${currentEdgeRouters.value.size}] ===") + currentEdgeRouters.value.forEach { + writer.appendLine(it.toString()) + } + writer.appendLine("=== Channels[${channels.size}] ===") channels.forEach { (name, ch) -> writer.appendLine("ER: $name status: ${ch.state}") } diff --git a/ziti/src/main/kotlin/org/openziti/net/Transport.kt b/ziti/src/main/kotlin/org/openziti/net/Transport.kt index 6a69c454..aa60bf1d 100644 --- a/ziti/src/main/kotlin/org/openziti/net/Transport.kt +++ b/ziti/src/main/kotlin/org/openziti/net/Transport.kt @@ -19,15 +19,12 @@ package org.openziti.net import org.openziti.net.nio.AsyncTLSChannel import org.openziti.net.nio.connectSuspend import org.openziti.net.nio.readSuspend -import org.openziti.net.nio.writeSuspend -import org.openziti.util.Logged -import org.openziti.util.ZitiLog +import org.openziti.net.nio.writeCompletely import java.io.Closeable import java.net.InetAddress import java.net.InetSocketAddress import java.net.URI import java.nio.ByteBuffer -import java.nio.channels.AsynchronousSocketChannel import javax.net.ssl.SSLContext internal interface Transport : Closeable { @@ -47,22 +44,14 @@ internal interface Transport : Closeable { suspend fun write(buf: ByteBuffer) suspend fun read(buf: ByteBuffer, full: Boolean = true): Int - class TLS(host: String, port: Int, sslContext: SSLContext) : Transport, Logged by ZitiLog("ziti-tls") { - val socket: AsynchronousSocketChannel + class TLS(host: String, port: Int, sslContext: SSLContext) : Transport { + val socket = AsyncTLSChannel(sslContext) val addr = InetSocketAddress(InetAddress.getByName(host), port) - init { - v { "connecting to $host:$port on t[${Thread.currentThread().name}" } - socket = AsyncTLSChannel(sslContext) - } - override suspend fun connect(timeout: Long) { - socket.connectSuspend(addr, timeout) - } + override suspend fun connect(timeout: Long) = socket.connectSuspend(addr, timeout) override suspend fun write(buf: ByteBuffer) { - while(buf.hasRemaining()) { - socket.writeSuspend(buf) - } + socket.writeCompletely(buf) } override suspend fun read(buf: ByteBuffer, full: Boolean): Int { @@ -77,14 +66,10 @@ internal interface Transport : Closeable { return res } - override fun close() { - socket.close() - } + override fun close() = socket.close() override fun isClosed(): Boolean = !socket.isOpen - override fun toString(): String { - return "TLS:${socket.remoteAddress}" - } + override fun toString(): String = "TLS:${socket.remoteAddress}" } } diff --git a/ziti/src/main/kotlin/org/openziti/net/dns/DNSResolver.kt b/ziti/src/main/kotlin/org/openziti/net/dns/DNSResolver.kt index c2755f0b..ce8ad686 100644 --- a/ziti/src/main/kotlin/org/openziti/net/dns/DNSResolver.kt +++ b/ziti/src/main/kotlin/org/openziti/net/dns/DNSResolver.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 NetFoundry, Inc. + * Copyright (c) 2018-2021 NetFoundry, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.openziti.net.dns +import java.io.Writer import java.net.InetAddress import java.util.function.Consumer @@ -25,4 +26,6 @@ interface DNSResolver { data class DNSEvent(val hostname: String?, val ip: InetAddress, val removed: Boolean) fun subscribe(sub: (DNSEvent) -> Unit) fun subscribe(sub: Consumer) + + fun dump(writer: Writer) } diff --git a/ziti/src/main/kotlin/org/openziti/net/dns/ZitiDNSManager.kt b/ziti/src/main/kotlin/org/openziti/net/dns/ZitiDNSManager.kt index 8973b8a4..90447b91 100644 --- a/ziti/src/main/kotlin/org/openziti/net/dns/ZitiDNSManager.kt +++ b/ziti/src/main/kotlin/org/openziti/net/dns/ZitiDNSManager.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import org.bouncycastle.util.IPAddress +import java.io.Writer import java.net.Inet4Address import java.net.Inet6Address import java.net.InetAddress @@ -82,4 +83,10 @@ internal object ZitiDNSManager : DNSResolver, CoroutineScope { host2Ip.clear() postfix.set(startPostfix) } + + override fun dump(writer: Writer) { + for ((h,ip) in host2Ip) { + writer.appendLine("$h -> $ip") + } + } } \ No newline at end of file diff --git a/ziti/src/main/kotlin/org/openziti/net/nio/AsyncTLSChannel.kt b/ziti/src/main/kotlin/org/openziti/net/nio/AsyncTLSChannel.kt index 63cbaaeb..0cf13606 100644 --- a/ziti/src/main/kotlin/org/openziti/net/nio/AsyncTLSChannel.kt +++ b/ziti/src/main/kotlin/org/openziti/net/nio/AsyncTLSChannel.kt @@ -205,7 +205,6 @@ class AsyncTLSChannel( } } return async { - println("connecting on ${Thread.currentThread()}") transport.connectSuspend(remote) state = State.connecting null diff --git a/ziti/src/main/kotlin/org/openziti/net/nio/NetUtils.kt b/ziti/src/main/kotlin/org/openziti/net/nio/NetUtils.kt index e0c6b9c2..409eb0a4 100644 --- a/ziti/src/main/kotlin/org/openziti/net/nio/NetUtils.kt +++ b/ziti/src/main/kotlin/org/openziti/net/nio/NetUtils.kt @@ -65,7 +65,6 @@ suspend fun AsynchronousSocketChannel.readSuspend(b: ByteBuffer, timeout: Long, suspend fun AsynchronousSocketChannel.connectSuspend(addr: SocketAddress) = connectSuspend(addr, Long.MAX_VALUE) suspend fun AsynchronousSocketChannel.connectSuspend(addr: SocketAddress, timeout: Long) { - println(coroutineContext) val ch = this return withContext(coroutineContext) { @@ -74,7 +73,7 @@ suspend fun AsynchronousSocketChannel.connectSuspend(addr: SocketAddress, timeou val timeoutDelay = launch { delay(timeout) if (!result.isCompleted) { - val ex = SocketTimeoutException("failed to connect in $timeout millis") + val ex = SocketTimeoutException("failed to connect to $addr in $timeout millis") if (result.completeExceptionally(ex)) { ch.runCatching { close() } }