From 6182a0ef6887726eafe227cea24a0d2fa0d1c6cd Mon Sep 17 00:00:00 2001 From: Leo Parente <23251360+leoparente@users.noreply.github.com> Date: Thu, 3 Sep 2026 13:52:25 -0300 Subject: [PATCH 1/4] fix(scripts): surface the NetBox plugin credential in quickstart output Both quickstart scripts create a netbox-to-diode OAuth2 client but only ever printed the diode-ingest one, labelled for orb-agent. That is the only secret a user is handed, so it is the one they paste into the plugin's configuration.py, where it cannot work: the plugin authenticates as netbox-to-diode. The result is Failed to obtain access token: ... Connection refused or an auth failure, with nothing pointing at the credential being for a different client. GET_STARTED.md already documents the correct jq incantation, but users follow the script's output rather than re-reading the guide. In #414 one reporter rediscovered that exact command and posted it as a workaround; it resolved the issue for another reporter in the same thread. Print both credentials, each labelled with what it configures, and name the client the plugin secret belongs to. netbox_to_diode_client_id is not printed as a setting to add: it already defaults to "netbox-to-diode" in the plugin. Also document that diode_target_override must be reachable from inside NetBox. Three reporters in #414 independently worked out that localhost resolves to the NetBox container rather than the Diode server when NetBox is containerised. Closes #414 Co-Authored-By: Claude Opus 5 --- GET_STARTED.md | 5 +++++ charts/diode/scripts/quickstart.sh | 11 +++++++++++ diode-server/docker/scripts/quickstart.sh | 16 +++++++++++++++- docs/getting-started.md | 5 +++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/GET_STARTED.md b/GET_STARTED.md index 7e6036cc..e9e43c2d 100644 --- a/GET_STARTED.md +++ b/GET_STARTED.md @@ -90,6 +90,11 @@ We provide a `quickstart.sh` script to automate the setup process. The script wi } ``` + `diode_target_override` must be an address reachable **from inside NetBox**. + If NetBox itself runs in a container, `localhost` resolves to that container + rather than to the Diode server, so use the host's IP address or FQDN + instead, for example `grpc://192.168.1.10:8080/diode`. + 4. **Apply Database Migrations** ```bash cd /opt/netbox/netbox diff --git a/charts/diode/scripts/quickstart.sh b/charts/diode/scripts/quickstart.sh index 77840530..44c49da6 100755 --- a/charts/diode/scripts/quickstart.sh +++ b/charts/diode/scripts/quickstart.sh @@ -226,8 +226,19 @@ else fi fi +# The NetBox Diode plugin authenticates as netbox-to-diode, a different client +# to the ingest one used by orb-agent. Surfacing it here avoids pasting the +# wrong secret and hitting "Failed to obtain access token". +NETBOX_TO_DIODE_CLIENT_ID="netbox-to-diode" +NETBOX_TO_DIODE_CLIENT_SECRET=$(jq -r '.[] | select(.client_id == "'$NETBOX_TO_DIODE_CLIENT_ID'") | .client_secret' "$PWD/client-credentials.json") + echo "----------------------------------------" ok "Environment setup completed!" +info "Configure the NetBox Diode plugin in configuration.py with:" +info " netbox_to_diode_client_secret: $NETBOX_TO_DIODE_CLIENT_SECRET" +info "That is the $NETBOX_TO_DIODE_CLIENT_ID client secret, not the ingest one." +info "diode_target_override must point at the ingress, reachable from NetBox." +echo info "You can now install the diode helm chart by running:" if [[ "$CLUSTER_DOMAIN" == "cluster.local" ]]; then info " helm install diode/diode --namespace $NAMESPACE" diff --git a/diode-server/docker/scripts/quickstart.sh b/diode-server/docker/scripts/quickstart.sh index 5c7fa5bd..14db47a3 100755 --- a/diode-server/docker/scripts/quickstart.sh +++ b/diode-server/docker/scripts/quickstart.sh @@ -192,14 +192,28 @@ fi DIODE_NGINX_PORT=$(grep -oP 'DIODE_NGINX_PORT=\K[0-9]+' "$ENV_FILE" 2>/dev/null || echo "8080") DIODE_TARGET="grpc://localhost:$DIODE_NGINX_PORT/diode" -# Get diode-ingest client credentials +# Get diode-ingest client credentials, used by orb-agent to ingest data DIODE_INGEST_CLIENT_ID="diode-ingest" DIODE_INGEST_CLIENT_SECRET=$(jq -r '.[] | select(.client_id == "'$DIODE_INGEST_CLIENT_ID'") | .client_secret' oauth2/client/client-credentials.json) +# Get netbox-to-diode client credentials, used by the NetBox Diode plugin. These +# are a different client to the ingest one above; pasting the ingest secret into +# the plugin fails with "Failed to obtain access token". +NETBOX_TO_DIODE_CLIENT_ID="netbox-to-diode" +NETBOX_TO_DIODE_CLIENT_SECRET=$(jq -r '.[] | select(.client_id == "'$NETBOX_TO_DIODE_CLIENT_ID'") | .client_secret' oauth2/client/client-credentials.json) + echo "----------------------------------------" ok "Environment setup completed!" info "You can now start the diode by running:" info " $DOCKER_COMPOSE up -d" +echo info "Configure orb-agent with diode target $DIODE_TARGET to use the following credentials:" info " DIODE_CLIENT_ID: $DIODE_INGEST_CLIENT_ID" info " DIODE_CLIENT_SECRET: $DIODE_INGEST_CLIENT_SECRET" +echo +info "Configure the NetBox Diode plugin in configuration.py with:" +info " netbox_to_diode_client_secret: $NETBOX_TO_DIODE_CLIENT_SECRET" +info " diode_target_override: $DIODE_TARGET" +info "That is the $NETBOX_TO_DIODE_CLIENT_ID client secret, not the ingest one above." +info "If NetBox runs in a container, diode_target_override must be an address" +info "reachable from inside it: the host's IP or FQDN, not localhost." diff --git a/docs/getting-started.md b/docs/getting-started.md index 3e240180..34de09f1 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -90,6 +90,11 @@ We provide a `quickstart.sh` script to automate the setup process. The script wi } ``` + `diode_target_override` must be an address reachable **from inside NetBox**. + If NetBox itself runs in a container, `localhost` resolves to that container + rather than to the Diode server, so use the host's IP address or FQDN + instead, for example `grpc://192.168.1.10:8080/diode`. + 4. **Apply Database Migrations** ```bash cd /opt/netbox/netbox From 3e6cbac4e5db371eb66aff5406851748890d3332 Mon Sep 17 00:00:00 2001 From: Leo Parente <23251360+leoparente@users.noreply.github.com> Date: Thu, 3 Sep 2026 14:01:20 -0300 Subject: [PATCH 2/4] chore(chart): bump version to 1.15.4 This PR changes charts/diode/scripts/quickstart.sh, so ct lint requires a chart version bump. 1.15.3 is already released as helm-chart-diode-1.15.3. Co-Authored-By: Claude Opus 5 --- charts/diode/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/diode/Chart.yaml b/charts/diode/Chart.yaml index 3dd114ee..4cf761da 100644 --- a/charts/diode/Chart.yaml +++ b/charts/diode/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: diode description: A Helm chart for Diode type: application -version: "1.15.3" +version: "1.15.4" appVersion: "1.5.0" home: https://github.com/netboxlabs/diode sources: From 38b3345c83b6c5d22c6f6fd873b483b3600569d7 Mon Sep 17 00:00:00 2001 From: Leo Parente <23251360+leoparente@users.noreply.github.com> Date: Thu, 3 Sep 2026 14:39:28 -0300 Subject: [PATCH 3/4] fix(scripts): read the plugin credential from the deployed Secret The helm quickstart regenerates client-credentials.json whenever the local file is absent (line 110), but skips creating the oauth2 Secret when it already exists in the namespace (line 185). Re-running against an existing namespace from a fresh working directory therefore produces local credentials that were never applied to the cluster. Printing the netbox-to-diode secret from that local file would hand out a credential that cannot authenticate, which is the exact failure this PR exists to prevent. Read it from the deployed Secret instead, falling back to the local file when the Secret is absent, unreadable, or does not contain the client. On a first run the Secret does not exist yet and the local file is what will be applied, so the fallback is correct there. Caught in review by Codex on #590. Co-Authored-By: Claude Opus 5 --- charts/diode/scripts/quickstart.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/charts/diode/scripts/quickstart.sh b/charts/diode/scripts/quickstart.sh index 44c49da6..2e255e46 100755 --- a/charts/diode/scripts/quickstart.sh +++ b/charts/diode/scripts/quickstart.sh @@ -230,7 +230,21 @@ fi # to the ingest one used by orb-agent. Surfacing it here avoids pasting the # wrong secret and hitting "Failed to obtain access token". NETBOX_TO_DIODE_CLIENT_ID="netbox-to-diode" -NETBOX_TO_DIODE_CLIENT_SECRET=$(jq -r '.[] | select(.client_id == "'$NETBOX_TO_DIODE_CLIENT_ID'") | .client_secret' "$PWD/client-credentials.json") + +# Read it from the deployed Secret rather than the local file. When the Secret +# already existed we skipped creating it above, so a client-credentials.json +# regenerated in a fresh working directory holds values that were never applied +# to the cluster; printing those would hand out a credential that cannot +# authenticate. Fall back to the local file only when the Secret is unreadable. +NETBOX_TO_DIODE_CLIENT_SECRET=$(kubectl get secret "$DIODE_AUTH_OAUTH2_SECRET" -n "$NAMESPACE" \ + -o jsonpath='{.data.client-credentials\.json}' 2>/dev/null | base64 -d 2>/dev/null \ + | jq -r --arg id "$NETBOX_TO_DIODE_CLIENT_ID" \ + 'try (.[] | select(.client_id == $id) | .client_secret) // empty' 2>/dev/null) + +if [[ -z "$NETBOX_TO_DIODE_CLIENT_SECRET" ]]; then + NETBOX_TO_DIODE_CLIENT_SECRET=$(jq -r --arg id "$NETBOX_TO_DIODE_CLIENT_ID" \ + '.[] | select(.client_id == $id) | .client_secret' "$PWD/client-credentials.json") +fi echo "----------------------------------------" ok "Environment setup completed!" From 326d991b1ba750d79cbcc9e8e6f6d1c6a455a125 Mon Sep 17 00:00:00 2001 From: Leo Parente <23251360+leoparente@users.noreply.github.com> Date: Thu, 3 Sep 2026 14:48:24 -0300 Subject: [PATCH 4/4] fix(scripts): emit pasteable plugin config, not a localhost target Two problems with the plugin block printed at the end of both quickstarts. It was emitted as `key: value`, which is not valid Python. Users are told to put it in configuration.py, where the setting names and string values must be quoted, and generated secrets end in `=` so an unquoted value is a syntax error. Now emits quoted dictionary entries that paste directly into PLUGINS_CONFIG["netbox_diode_plugin"]. The docker quickstart also advertised grpc://localhost:PORT/diode as the target to configure. That address is reused from the orb-agent hint, where it is usually right, but for the plugin it only works when NetBox runs directly on this host outside a container. The getting-started guide explicitly supports NetBox on a separate host, and the previous warning mentioned only the containerised case. Now prints a placeholder with a note covering both. Verified by parsing the emitted lines: they exec as valid Python inside a PLUGINS_CONFIG dict, the secret round-trips intact including its trailing '=', and the target contains no localhost. Caught in review by Codex on #590. Co-Authored-By: Claude Opus 5 --- charts/diode/scripts/quickstart.sh | 6 +++--- diode-server/docker/scripts/quickstart.sh | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/charts/diode/scripts/quickstart.sh b/charts/diode/scripts/quickstart.sh index 2e255e46..973b5b82 100755 --- a/charts/diode/scripts/quickstart.sh +++ b/charts/diode/scripts/quickstart.sh @@ -248,10 +248,10 @@ fi echo "----------------------------------------" ok "Environment setup completed!" -info "Configure the NetBox Diode plugin in configuration.py with:" -info " netbox_to_diode_client_secret: $NETBOX_TO_DIODE_CLIENT_SECRET" +info "Add the following to PLUGINS_CONFIG[\"netbox_diode_plugin\"] in configuration.py:" +info " \"netbox_to_diode_client_secret\": \"$NETBOX_TO_DIODE_CLIENT_SECRET\"," info "That is the $NETBOX_TO_DIODE_CLIENT_ID client secret, not the ingest one." -info "diode_target_override must point at the ingress, reachable from NetBox." +info "Set \"diode_target_override\" to the ingress address, reachable from NetBox." echo info "You can now install the diode helm chart by running:" if [[ "$CLUSTER_DOMAIN" == "cluster.local" ]]; then diff --git a/diode-server/docker/scripts/quickstart.sh b/diode-server/docker/scripts/quickstart.sh index 14db47a3..f168c81f 100755 --- a/diode-server/docker/scripts/quickstart.sh +++ b/diode-server/docker/scripts/quickstart.sh @@ -211,9 +211,9 @@ info "Configure orb-agent with diode target $DIODE_TARGET to use the following c info " DIODE_CLIENT_ID: $DIODE_INGEST_CLIENT_ID" info " DIODE_CLIENT_SECRET: $DIODE_INGEST_CLIENT_SECRET" echo -info "Configure the NetBox Diode plugin in configuration.py with:" -info " netbox_to_diode_client_secret: $NETBOX_TO_DIODE_CLIENT_SECRET" -info " diode_target_override: $DIODE_TARGET" +info "Add the following to PLUGINS_CONFIG[\"netbox_diode_plugin\"] in configuration.py:" +info " \"netbox_to_diode_client_secret\": \"$NETBOX_TO_DIODE_CLIENT_SECRET\"," +info " \"diode_target_override\": \"grpc://:$DIODE_NGINX_PORT/diode\"," info "That is the $NETBOX_TO_DIODE_CLIENT_ID client secret, not the ingest one above." -info "If NetBox runs in a container, diode_target_override must be an address" -info "reachable from inside it: the host's IP or FQDN, not localhost." +info "Replace with an address reachable from NetBox. localhost only" +info "works when NetBox runs directly on this host, outside a container."