diff --git a/examples/nauth/manifests/scenarios/cross-account-jetstream/export-jetstream.yaml b/examples/nauth/manifests/scenarios/cross-account-jetstream/export-jetstream.yaml index d80c760..b88a784 100644 --- a/examples/nauth/manifests/scenarios/cross-account-jetstream/export-jetstream.yaml +++ b/examples/nauth/manifests/scenarios/cross-account-jetstream/export-jetstream.yaml @@ -28,6 +28,9 @@ metadata: annotations: argocd.argoproj.io/sync-options: Prune=false spec: + natsClusterRef: + namespace: nats + name: local-nats accountLimits: conn: 100 exports: 100 diff --git a/examples/nauth/manifests/scenarios/cross-account-jetstream/import-jetstream.yaml b/examples/nauth/manifests/scenarios/cross-account-jetstream/import-jetstream.yaml index 717f9bb..efe2de4 100644 --- a/examples/nauth/manifests/scenarios/cross-account-jetstream/import-jetstream.yaml +++ b/examples/nauth/manifests/scenarios/cross-account-jetstream/import-jetstream.yaml @@ -31,6 +31,9 @@ metadata: annotations: argocd.argoproj.io/sync-options: Prune=false spec: + natsClusterRef: + namespace: nats + name: local-nats accountLimits: conn: 100 exports: 100 diff --git a/examples/nauth/manifests/scenarios/simple-account/simple-account.yaml b/examples/nauth/manifests/scenarios/simple-account/simple-account.yaml index c9e6e32..a02b8be 100644 --- a/examples/nauth/manifests/scenarios/simple-account/simple-account.yaml +++ b/examples/nauth/manifests/scenarios/simple-account/simple-account.yaml @@ -10,6 +10,9 @@ metadata: name: example-account namespace: simple-account spec: + natsClusterRef: + namespace: nats + name: local-nats accountLimits: conn: 100 exports: 10 diff --git a/local/README.md b/local/README.md index db9b814..74645d6 100644 --- a/local/README.md +++ b/local/README.md @@ -35,8 +35,8 @@ The task scripts live under `.mise-tasks/nauth` and can be run individually. ## Local overrides - `local/nats/values.yaml`: NATS chart overrides for the test environment. -- `local/nauth/values.yaml`: Nauth chart overrides for the test environment. -- `local/nauth/manifests/operator.yaml`: extra manifests applied during setup. Do not modify as it is also used by KUTTL tests. +- `local/nauth/values.yaml`: Nauth chart overrides for the test environment (no legacy `nats.url` override). +- `local/nauth/manifests/operator.yaml`: shared bootstrap manifests applied during setup, including `NatsCluster` (`local-nats`) and referenced secrets. - `local/prometheus/values.yaml`: Prometheus chart overrides (if used). ## Cleanup diff --git a/local/nauth/manifests/operator.yaml b/local/nauth/manifests/operator.yaml index fc609bd..24c9e03 100644 --- a/local/nauth/manifests/operator.yaml +++ b/local/nauth/manifests/operator.yaml @@ -1,4 +1,5 @@ -# DO NOT MODIFY THIS FILE +# Local development and E2E bootstrap resources for NAUTH. +# Includes shared test secrets and a default NatsCluster in the `nats` namespace. # The values in this file is bound to the secrets used in `local/nauth/values.yaml` apiVersion: v1 @@ -15,8 +16,6 @@ kind: Secret type: Opaque metadata: name: operator-op-sign - labels: - nauth.io/secret-type: operator-sign data: default: U09BSUZQVEZJNllHM1ZPTlBBMjRCTkgyNzYyR0lTVEJYSU5VVE1PVFpBUjJESkFMRUY0TE9WRElBQQ== @@ -44,7 +43,19 @@ kind: Secret type: Opaque metadata: name: operator-sau-creds - labels: - nauth.io/secret-type: system-account-user-creds data: default: LS0tLS1CRUdJTiBOQVRTIFVTRVIgSldULS0tLS0KZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKbFpESTFOVEU1TFc1clpYa2lmUS5leUpxZEdraU9pSklXbEJCUjFKUFJsTlZRVFphVkU5UVNEVkZObGxSTjAxYVdGRldSVGRKV2s5UE5FeEtSVXBaTlU1U05WbEdXRmt6TTBoUklpd2lhV0YwSWpveE56UTVOakkwT0RjNUxDSnBjM01pT2lKQlFraFBVelpXU0U1VU4xSk9Na3BEVDAxSlZqWk5WRFExV0VWV01rTlVORTVWUVZrMFRUUXlSVkJaUms5VVVVMU1VRWxYTkZkVVVpSXNJbTVoYldVaU9pSnplWE4wWlcwaUxDSnpkV0lpT2lKVlFUTkhVbEpOUlZVMVIwRTBWMFJXTkRjeVJVRkVSRlF5VkVsWVYxVktVVWd5VmxkVVMxVlBVa2xDVkZWRVQwd3lURGMyVGxkTlFTSXNJbTVoZEhNaU9uc2ljSFZpSWpwN2ZTd2ljM1ZpSWpwN2ZTd2ljM1ZpY3lJNkxURXNJbVJoZEdFaU9qRXdOek0zTkRFNE1qUXNJbkJoZVd4dllXUWlPaTB4TENKcGMzTjFaWEpmWVdOamIzVnVkQ0k2SWtGQ04wTk9XRGRHTWtKSlRVVkVXa2xQTTBFME5UWkxVVk5QVWxsSlZVbFNObEpITWxkRVdWTlNUbEpUVjAxVk4weFdRMEpYVmxnMklpd2lkSGx3WlNJNkluVnpaWElpTENKMlpYSnphVzl1SWpveWZYMC5ra0ZtMGlDaC1HVzR2OFBSRi1DWmI4QzJxYnNFRVZFMWoyQzltakNtaVppRDEyMVdFR25mdUFVS2FoNHhxU0VUSW9udGN4RURGSGhBc09qcUt3LVdCZwotLS0tLS1FTkQgTkFUUyBVU0VSIEpXVC0tLS0tLQoKKioqKioqKioqKioqKioqKioqKioqKioqKiBJTVBPUlRBTlQgKioqKioqKioqKioqKioqKioqKioqKioqKgpOS0VZIFNlZWQgcHJpbnRlZCBiZWxvdyBjYW4gYmUgdXNlZCB0byBzaWduIGFuZCBwcm92ZSBpZGVudGl0eS4KTktFWXMgYXJlIHNlbnNpdGl2ZSBhbmQgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgc2VjcmV0cy4KCi0tLS0tQkVHSU4gVVNFUiBOS0VZIFNFRUQtLS0tLQpTVUFLS0lUR0VBTTQ0SlgyUTVTS0lIWE9WVjVCSlI2VFRNT1RNVEVVSkpSWUxFRzMyV0hQNlNTSEs0Ci0tLS0tLUVORCBVU0VSIE5LRVkgU0VFRC0tLS0tLQoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgo= + +--- +apiVersion: nauth.io/v1alpha1 +kind: NatsCluster +metadata: + name: local-nats +spec: + url: nats://nats.nats.svc.cluster.local:4222 + operatorSigningKeySecretRef: + name: operator-op-sign + key: default + systemAccountUserCredsSecretRef: + name: operator-sau-creds + key: default diff --git a/local/nauth/values.yaml b/local/nauth/values.yaml index ae91854..d6582a9 100644 --- a/local/nauth/values.yaml +++ b/local/nauth/values.yaml @@ -1,6 +1,3 @@ -nats: - url: nats://nats.nats.svc.cluster.local:4222 - # # Uncomment if running observability stack locally # monitoring: # enabled: false diff --git a/test/e2e/account-deletion/01-account-creation.yaml b/test/e2e/account-deletion/01-account-creation.yaml index 8a34866..4d5995f 100644 --- a/test/e2e/account-deletion/01-account-creation.yaml +++ b/test/e2e/account-deletion/01-account-creation.yaml @@ -3,5 +3,8 @@ kind: Account metadata: name: example-account spec: + natsClusterRef: + namespace: nats + name: local-nats accountLimits: conn: 100 diff --git a/test/e2e/account-import-observe/03-account-import.yaml b/test/e2e/account-import-observe/03-account-import.yaml index b6dd35e..4635b6f 100644 --- a/test/e2e/account-import-observe/03-account-import.yaml +++ b/test/e2e/account-import-observe/03-account-import.yaml @@ -5,3 +5,7 @@ metadata: labels: account.nauth.io/id: ADDS6I3G7LBIBNDMZ5Q32VUJN2XNSW2QK4HY2SY5ZA7I2JLBFYF4KJDO nauth.io/management-policy: observe +spec: + natsClusterRef: + namespace: nats + name: local-nats diff --git a/test/e2e/basic-test/00-assert-operator-secrets.yaml b/test/e2e/basic-test/00-assert-operator-secrets.yaml index 33f64a4..7b88454 100644 --- a/test/e2e/basic-test/00-assert-operator-secrets.yaml +++ b/test/e2e/basic-test/00-assert-operator-secrets.yaml @@ -1,52 +1,47 @@ apiVersion: v1 kind: Secret -type: Opaque -metadata: - name: operator-op-root - namespace: nats -data: - default: U09BR1MySVVEVFBJTE9ZQkZaMkY0QUlGVlBWM0VKQk1QQVpaTVI3VUI3NERIUTdYSkQzNUJKTzY0QQ== - ---- -apiVersion: v1 -kind: Secret -type: Opaque metadata: name: operator-op-sign namespace: nats - labels: - nauth.io/secret-type: operator-sign -data: - default: U09BSUZQVEZJNllHM1ZPTlBBMjRCTkgyNzYyR0lTVEJYSU5VVE1PVFpBUjJESkFMRUY0TE9WRElBQQ== --- apiVersion: v1 kind: Secret -type: Opaque metadata: - name: operator-sa-root + name: operator-sau-creds namespace: nats -data: - default: U0FBREpESU9BTklQRUJMVTZPNFROVVhES0w1Rk1PRFZJWTUzTjNZNTVWNktTRFBOV1hISkwzS0ZBNA== --- -apiVersion: v1 -kind: Secret -type: Opaque +apiVersion: nauth.io/v1alpha1 +kind: NatsCluster metadata: - name: operator-sa-sign + name: local-nats namespace: nats -data: - default: U0FBT1dLM0dCSUNZTTZaWjZSM0U0N0hQN00yQUI1UERPWUJYS0NOVUJJS1dRRlVIMko2VUhHNUU1QQ== +spec: + url: nats://nats.nats.svc.cluster.local:4222 + operatorSigningKeySecretRef: + name: operator-op-sign + key: default + systemAccountUserCredsSecretRef: + name: operator-sau-creds + key: default --- -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - name: operator-sau-creds - namespace: nats - labels: - nauth.io/secret-type: system-account-user-creds -data: - default: LS0tLS1CRUdJTiBOQVRTIFVTRVIgSldULS0tLS0KZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKbFpESTFOVEU1TFc1clpYa2lmUS5leUpxZEdraU9pSklXbEJCUjFKUFJsTlZRVFphVkU5UVNEVkZObGxSTjAxYVdGRldSVGRKV2s5UE5FeEtSVXBaTlU1U05WbEdXRmt6TTBoUklpd2lhV0YwSWpveE56UTVOakkwT0RjNUxDSnBjM01pT2lKQlFraFBVelpXU0U1VU4xSk9Na3BEVDAxSlZqWk5WRFExV0VWV01rTlVORTVWUVZrMFRUUXlSVkJaUms5VVVVMU1VRWxYTkZkVVVpSXNJbTVoYldVaU9pSnplWE4wWlcwaUxDSnpkV0lpT2lKVlFUTkhVbEpOUlZVMVIwRTBWMFJXTkRjeVJVRkVSRlF5VkVsWVYxVktVVWd5VmxkVVMxVlBVa2xDVkZWRVQwd3lURGMyVGxkTlFTSXNJbTVoZEhNaU9uc2ljSFZpSWpwN2ZTd2ljM1ZpSWpwN2ZTd2ljM1ZpY3lJNkxURXNJbVJoZEdFaU9qRXdOek0zTkRFNE1qUXNJbkJoZVd4dllXUWlPaTB4TENKcGMzTjFaWEpmWVdOamIzVnVkQ0k2SWtGQ04wTk9XRGRHTWtKSlRVVkVXa2xQTTBFME5UWkxVVk5QVWxsSlZVbFNObEpITWxkRVdWTlNUbEpUVjAxVk4weFdRMEpYVmxnMklpd2lkSGx3WlNJNkluVnpaWElpTENKMlpYSnphVzl1SWpveWZYMC5ra0ZtMGlDaC1HVzR2OFBSRi1DWmI4QzJxYnNFRVZFMWoyQzltakNtaVppRDEyMVdFR25mdUFVS2FoNHhxU0VUSW9udGN4RURGSGhBc09qcUt3LVdCZwotLS0tLS1FTkQgTkFUUyBVU0VSIEpXVC0tLS0tLQoKKioqKioqKioqKioqKioqKioqKioqKioqKiBJTVBPUlRBTlQgKioqKioqKioqKioqKioqKioqKioqKioqKgpOS0VZIFNlZWQgcHJpbnRlZCBiZWxvdyBjYW4gYmUgdXNlZCB0byBzaWduIGFuZCBwcm92ZSBpZGVudGl0eS4KTktFWXMgYXJlIHNlbnNpdGl2ZSBhbmQgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgc2VjcmV0cy4KCi0tLS0tQkVHSU4gVVNFUiBOS0VZIFNFRUQtLS0tLQpTVUFLS0lUR0VBTTQ0SlgyUTVTS0lIWE9WVjVCSlI2VFRNT1RNVEVVSkpSWUxFRzMyV0hQNlNTSEs0Ci0tLS0tLUVORCBVU0VSIE5LRVkgU0VFRC0tLS0tLQoKKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgo= +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 20 +commands: + - script: | + set -eu + + op_sign="$(kubectl get secret -n nats operator-op-sign -o jsonpath='{.data.default}')" + test -n "$op_sign" + + sys_creds="$(kubectl get secret -n nats operator-sau-creds -o jsonpath='{.data.default}')" + test -n "$sys_creds" + + ref="$(kubectl get natscluster.nauth.io local-nats -n nats -o jsonpath='{.spec.operatorSigningKeySecretRef.name}')" + test "$ref" = "operator-op-sign" + + ref="$(kubectl get natscluster.nauth.io local-nats -n nats -o jsonpath='{.spec.systemAccountUserCredsSecretRef.name}')" + test "$ref" = "operator-sau-creds" diff --git a/test/e2e/basic-test/01-create-account.yaml b/test/e2e/basic-test/01-create-account.yaml index 6e6dfa7..5428265 100644 --- a/test/e2e/basic-test/01-create-account.yaml +++ b/test/e2e/basic-test/01-create-account.yaml @@ -3,6 +3,9 @@ kind: Account metadata: name: example-account spec: + natsClusterRef: + namespace: nats + name: local-nats displayName: My Example Account accountLimits: conn: 100 @@ -26,4 +29,4 @@ spec: exports: - name: export-test subject: foo.> - type: stream \ No newline at end of file + type: stream diff --git a/test/script/nats-jwt-upload.sh b/test/script/nats-jwt-upload.sh index 64f8f8b..245e9dd 100755 --- a/test/script/nats-jwt-upload.sh +++ b/test/script/nats-jwt-upload.sh @@ -1,22 +1,20 @@ #!/bin/bash -# Usage: nats-jwt-upload.sh -# Example: ./nats-jwt-upload.sh /tmp/account.jwt +# Usage: nats-jwt-upload.sh [nats-cluster-name] [nats-cluster-namespace] +# Example: ./nats-jwt-upload.sh /tmp/account.jwt local-nats nats # -# This script uploads an account JWT to the NATS server using the system account credentials. -# It mimics what the nauth operator does when it calls UploadAccountJWT(). -# Note: NATS server and system account credentials are always in the 'nats' namespace. +# Uploads an account JWT to NATS using system account credentials resolved from +# a NatsCluster resource. set -euo pipefail -if [ "$#" -ne 1 ]; then - echo "[$0] Usage: $0 " >&2 +if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then + echo "[$0] Usage: $0 [nats-cluster-name] [nats-cluster-namespace]" >&2 exit 1 fi JWT_FILE="$1" - -# NATS server and operator are always deployed in the 'nats' namespace -NATS_NAMESPACE="nats" +NATS_CLUSTER_NAME="${2:-local-nats}" +NATS_CLUSTER_NAMESPACE="${3:-nats}" if [ ! -f "$JWT_FILE" ]; then echo "[$0] ERROR: JWT file not found: $JWT_FILE" >&2 @@ -24,77 +22,105 @@ if [ ! -f "$JWT_FILE" ]; then exit 2 fi -# Extract JWT filename for use in temporary file names JWT_FILENAME=$(basename "$JWT_FILE") -# Get the system account credentials from the secret in the nats namespace -CREDS_SECRET=$(kubectl get secret -n "$NATS_NAMESPACE" \ - -l "nauth.io/secret-type=system-account-user-creds" \ - -o jsonpath='{.items[0].metadata.name}' 2>&1) +if ! kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" >/dev/null 2>&1; then + echo "[$0] ERROR: NatsCluster $NATS_CLUSTER_NAMESPACE/$NATS_CLUSTER_NAME not found" >&2 + exit 3 +fi -CREDS_SECRET_EXIT_CODE=$? +NATS_URL="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.url}')" + +if [ -z "$NATS_URL" ]; then + URL_FROM_KIND="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.urlFrom.kind}')" + URL_FROM_NAME="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.urlFrom.name}')" + URL_FROM_KEY="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.urlFrom.key}')" + URL_FROM_NAMESPACE="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.urlFrom.namespace}')" + + if [ -z "$URL_FROM_NAMESPACE" ]; then + URL_FROM_NAMESPACE="$NATS_CLUSTER_NAMESPACE" + fi + + case "$URL_FROM_KIND" in + ConfigMap|configmap) + NATS_URL="$(kubectl get configmap "$URL_FROM_NAME" -n "$URL_FROM_NAMESPACE" -o "go-template={{ index .data \"$URL_FROM_KEY\" }}" 2>/dev/null || true)" + ;; + Secret|secret) + URL_B64="$(kubectl get secret "$URL_FROM_NAME" -n "$URL_FROM_NAMESPACE" -o "go-template={{ index .data \"$URL_FROM_KEY\" }}" 2>/dev/null || true)" + if [ -n "$URL_B64" ] && [ "$URL_B64" != "" ]; then + NATS_URL="$(printf '%s' "$URL_B64" | base64 -d)" + fi + ;; + "") + ;; + *) + echo "[$0] ERROR: Unsupported spec.urlFrom.kind '$URL_FROM_KIND' for NatsCluster $NATS_CLUSTER_NAMESPACE/$NATS_CLUSTER_NAME" >&2 + exit 4 + ;; + esac +fi -if [ $CREDS_SECRET_EXIT_CODE -ne 0 ] || [ -z "$CREDS_SECRET" ] || echo "$CREDS_SECRET" | grep -q "error:"; then - echo "[$0] ERROR: System account credentials secret not found in namespace $NATS_NAMESPACE" >&2 - kubectl get secrets -n "$NATS_NAMESPACE" 2>&1 | head -20 >&2 - exit 3 +if [ -z "$NATS_URL" ]; then + echo "[$0] ERROR: Unable to resolve NATS URL from NatsCluster $NATS_CLUSTER_NAMESPACE/$NATS_CLUSTER_NAME" >&2 + exit 4 fi -# Extract the credentials to a temp file -CREDS_FILE=$(mktemp) -trap 'rm -f "$CREDS_FILE"' EXIT +CREDS_SECRET="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.systemAccountUserCredsSecretRef.name}')" +CREDS_KEY="$(kubectl get natsclusters.nauth.io "$NATS_CLUSTER_NAME" -n "$NATS_CLUSTER_NAMESPACE" -o jsonpath='{.spec.systemAccountUserCredsSecretRef.key}')" + +if [ -z "$CREDS_SECRET" ]; then + echo "[$0] ERROR: NatsCluster $NATS_CLUSTER_NAMESPACE/$NATS_CLUSTER_NAME does not define spec.systemAccountUserCredsSecretRef.name" >&2 + exit 5 +fi -kubectl get secret -n "$NATS_NAMESPACE" "$CREDS_SECRET" -o jsonpath='{.data.default}' | base64 -d > "$CREDS_FILE" +if [ -z "$CREDS_KEY" ]; then + CREDS_KEY="default" +fi +CREDS_B64="$(kubectl get secret "$CREDS_SECRET" -n "$NATS_CLUSTER_NAMESPACE" -o "go-template={{ index .data \"$CREDS_KEY\" }}" 2>/dev/null || true)" +if [ -z "$CREDS_B64" ] || [ "$CREDS_B64" = "" ]; then + echo "[$0] ERROR: Secret $NATS_CLUSTER_NAMESPACE/$CREDS_SECRET does not contain key '$CREDS_KEY'" >&2 + exit 5 +fi -# Instead of running nats CLI locally, we'll use kubectl exec to run it inside a pod -# This avoids DNS and networking issues when running outside the cluster +CREDS_FILE=$(mktemp) +trap 'rm -f "$CREDS_FILE"' EXIT +printf '%s' "$CREDS_B64" | base64 -d > "$CREDS_FILE" -# Find nats-box pod by name pattern (it has nats CLI installed) -EXEC_POD=$(kubectl get pods -n "$NATS_NAMESPACE" --field-selector=status.phase=Running -o name 2>&1 | grep "pod/nats-box" | head -1 | cut -d'/' -f2) +EXEC_POD=$(kubectl get pods -n "$NATS_CLUSTER_NAMESPACE" --field-selector=status.phase=Running -o name 2>&1 | grep "pod/nats-box" | head -1 | cut -d'/' -f2) if [ -z "$EXEC_POD" ]; then - echo "[$0] ERROR: nats-box pod not found in namespace $NATS_NAMESPACE" >&2 + echo "[$0] ERROR: nats-box pod not found in namespace $NATS_CLUSTER_NAMESPACE" >&2 echo "[$0] Available pods:" >&2 - kubectl get pods -n "$NATS_NAMESPACE" -o wide 2>&1 >&2 + kubectl get pods -n "$NATS_CLUSTER_NAMESPACE" -o wide 2>&1 >&2 echo "[$0] Note: nats-box pod is required (has nats CLI installed)" >&2 exit 6 fi -# Copy credentials to the pod (using PID and JWT filename for unique identification) REMOTE_CREDS_PATH="/tmp/nauth-upload-creds-$$-${JWT_FILENAME%.jwt}.default" -kubectl cp "$CREDS_FILE" "$NATS_NAMESPACE/$EXEC_POD:$REMOTE_CREDS_PATH" 2>&1 | grep -v "tar:" || true +kubectl cp "$CREDS_FILE" "$NATS_CLUSTER_NAMESPACE/$EXEC_POD:$REMOTE_CREDS_PATH" 2>&1 | grep -v "tar:" || true -# Copy JWT to the pod (using PID and JWT filename for unique identification) REMOTE_JWT_PATH="/tmp/nauth-upload-$$-${JWT_FILENAME%.jwt}.jwt" -kubectl cp "$JWT_FILE" "$NATS_NAMESPACE/$EXEC_POD:$REMOTE_JWT_PATH" 2>&1 | grep -v "tar:" || true +kubectl cp "$JWT_FILE" "$NATS_CLUSTER_NAMESPACE/$EXEC_POD:$REMOTE_JWT_PATH" 2>&1 | grep -v "tar:" || true -# Use the cluster-internal DNS name -NATS_URL="nats://nats.${NATS_NAMESPACE}.svc.cluster.local:4222" - -# Use nats CLI inside the pod to publish the JWT to $SYS.REQ.CLAIMS.UPDATE -# Note: JWT must be passed as an argument, not via stdin -set +e # Don't exit on error, capture it -RESPONSE=$(kubectl exec -i -n "$NATS_NAMESPACE" "$EXEC_POD" -- sh -c \ +set +e +RESPONSE=$(kubectl exec -i -n "$NATS_CLUSTER_NAMESPACE" "$EXEC_POD" -- sh -c \ "nats req --creds='$REMOTE_CREDS_PATH' --server='$NATS_URL' '\$SYS.REQ.CLAIMS.UPDATE' \"\$(cat '$REMOTE_JWT_PATH')\"" 2>&1) NATS_EXIT_CODE=$? set -e -# Cleanup remote files -kubectl exec -n "$NATS_NAMESPACE" "$EXEC_POD" -- rm -f "$REMOTE_CREDS_PATH" "$REMOTE_JWT_PATH" 2>/dev/null || true +kubectl exec -n "$NATS_CLUSTER_NAMESPACE" "$EXEC_POD" -- rm -f "$REMOTE_CREDS_PATH" "$REMOTE_JWT_PATH" 2>/dev/null || true if [ $NATS_EXIT_CODE -ne 0 ]; then echo "[$0] ERROR: nats CLI command failed" >&2 echo "[$0] Response: $RESPONSE" >&2 - exit 4 + exit 7 fi -# Check if the response indicates success (code 200) if echo "$RESPONSE" | grep -q '"code":200'; then exit 0 -else - echo "[$0] ERROR: Failed to upload account JWT" >&2 - echo "[$0] Response: $RESPONSE" >&2 - exit 4 fi +echo "[$0] ERROR: Failed to upload account JWT" >&2 +echo "[$0] Response: $RESPONSE" >&2 +exit 7