From b4615fb7314c89a3c740f840d699962f946e172a Mon Sep 17 00:00:00 2001 From: hbrombeer Date: Tue, 2 Jun 2026 13:08:47 +0200 Subject: [PATCH] feat(nats): present projected SA-token as NATS bearer (B4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The velocity proxy plugin's NatsHandler connected with no credentials, so the v2.2 auth-callout broker rejects it once deny-by-default (B5) lands. Add a tokenSupplier that reads the projected grounds-services SA-token from GROUNDS_TOKEN_FILE and presents it as the NATS bearer (CONNECT auth_token). Re-read per (re)connect for kubelet rotation; skipped when absent so local/dev still connects. Bump jnats 2.21.1 → 2.25.3 (tokenSupplier needs >= 2.21.4). Co-Authored-By: Claude Opus 4.8 --- velocity/build.gradle.kts | 2 +- .../grounds/proxy/velocity/handler/NatsHandler.kt | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 4090e32..49ccf92 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -2,5 +2,5 @@ plugins { id("gg.grounds.velocity") version "0.1.1" } dependencies { implementation(project(":api")) - implementation("io.nats:jnats:2.21.1") + implementation("io.nats:jnats:2.25.3") } diff --git a/velocity/src/main/kotlin/gg/grounds/proxy/velocity/handler/NatsHandler.kt b/velocity/src/main/kotlin/gg/grounds/proxy/velocity/handler/NatsHandler.kt index 73abe4b..e3fca20 100644 --- a/velocity/src/main/kotlin/gg/grounds/proxy/velocity/handler/NatsHandler.kt +++ b/velocity/src/main/kotlin/gg/grounds/proxy/velocity/handler/NatsHandler.kt @@ -7,6 +7,8 @@ import io.nats.client.Nats import io.nats.client.Options import io.nats.client.Subscription import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path import java.time.Duration import org.slf4j.Logger @@ -15,7 +17,7 @@ class NatsHandler(private val natsUrl: String, private val logger: Logger) : Aut private lateinit var dispatcher: Dispatcher fun connect() { - val options = + val builder = Options.Builder() .server(natsUrl) .connectionName("plugin-proxy") @@ -30,8 +32,15 @@ class NatsHandler(private val natsUrl: String, private val logger: Logger) : Aut else -> {} } } - .build() - connection = Nats.connect(options) + // Present the projected SA-token (audience grounds-services) as the NATS + // bearer for the auth-callout broker. Re-read per (re)connect for kubelet + // rotation; skipped when absent (local/dev without the projected volume). + val tokenFile = System.getenv("GROUNDS_TOKEN_FILE") ?: "/var/run/secrets/grounds/token" + val tokenPath = Path.of(tokenFile) + if (Files.exists(tokenPath)) { + builder.tokenSupplier { Files.readString(tokenPath).trim().toCharArray() } + } + connection = Nats.connect(builder.build()) dispatcher = connection.createDispatcher() logger.info("Connected to NATS (url={})", natsUrl) }