Skip to content

radar-hub: install enrollment key and a stable self-signed certificate - #61

Merged
arlenskh merged 9 commits into
mainfrom
radar-enrollment-keys
Oct 26, 2026
Merged

arlenskh merged 9 commits into
mainfrom
radar-enrollment-keys

Conversation

@hisco

@hisco hisco commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

The hub chart needs two things for shared enrollment keys on a self-hosted hub: a way to set an install key for automation that installs the hub before anyone signs in, and a self-signed certificate that stays the same, because clusters that joined with a key verify the hub's certificate.

What the change does

  • Install key. enrollment.key or enrollment.existingSecret (plus existingSecretKey) sets HUB_ENROLLMENT_KEY. enrollment.trustByDefault sets whether clusters joining with it are trusted on hubs that pass people's sign-ins to clusters, and enrollment.approval (auto or manual) whether new clusters on it wait for an owner to approve them. Owners can also create keys in the hub itself; this one is optional.
  • Stable self-signed certificate. With the in-cluster TLS path, the chart renders <fullname>-web-tls once and reuses it through lookup on upgrades (helm.sh/resource-policy: keep). It can instead come from web.tls.certificate and web.tls.privateKey, or from your own web.tls.existingSecret. The web pods mount it and the web image's script uses it instead of making a new one per pod.
  • Certificate in the install steps. With web.tls.selfSigned, the hub pod mounts only the certificate's public part and the hub always includes it in the cluster install steps.
  • User-token mode with a self-signed hub is no longer refused, because clusters joining with a key verify the hub with that certificate. The install notes print a warning in that setup: anyone who can read the certificate Secret can pose as the hub and collect people's tokens. It is still refused with localCluster.

Where to look hardest

templates/_web-tls.tpl and templates/web-tls-secret.yaml: the certificate is generated once per render and shared by the Secret and the values checksum. Argo CD renders without lookup, so it would get a new certificate on each sync; the README tells Argo CD users to supply their own (values or a Secret).

Release

Staged as chart 1.14.0-rc.1, with appVersion left at 1.13.0, which shipped without shared enrollment keys. The chart's enrollment guard therefore asks for hub 1.14.0 or later. Tagging radar-hub v1.14.0 (after radar-hub-web v1.14.0) promotes this chart to 1.14.0 with appVersion 1.14.0, so the chart and image versions match.

Tests

helm lint (with tests/values/required-base.yaml), tests/render-matrix.sh (including a duplicate-key check on the values files) and helm unittest (66) pass, on the branch merged with main.

https://claude.ai/code/session_01SxLwuGLtodCbE7pfsPHdtv

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add enrollment key configuration to the radar-hub chart

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Let self-hosted hubs accept Radar agents through an inline or existing enrollment key.
• Reject unsupported enrollment settings and older compatible-looking Hub image versions before
 deployment.
• Keep enrollment disabled by default and cover rendering, Secret references, and upgrade
 compatibility.
Diagram

graph TD
  Values["Enrollment values"] --> Guard{"Key source?"} -->|inline| ChartSecret["Chart Secret"] --> Deployment["Hub Deployment"] --> Agents["Radar agents"]
  Guard -->|external| ExistingSecret["Existing Secret"] --> Deployment
  Guard -->|none| Unchanged["Unchanged render"]
Loading
High-Level Assessment

Reusing the chart’s inline-or-existing-Secret pattern is appropriate: it supports direct configuration and operator-managed secrets while preserving the default render. Review the 1.13.0 minimum against the Hub release that actually introduces enrollment; the guard must track that release.

Files changed (5) +138 / -0

Enhancement (2) +55 / -0
deployment-hub.yamlWire enrollment settings into the Hub container +20/-0

Wire enrollment settings into the Hub container

• Adds a Secret-backed enrollment key and approval and rejoin environment variables when a key source is configured. Supports either the chart Secret or an operator-managed Secret.

charts/radar-hub/templates/deployment-hub.yaml

secret.yamlValidate enrollment configuration and store inline keys +35/-0

Validate enrollment configuration and store inline keys

• Rejects conflicting key sources, malformed inline keys, unsupported modes, and semver Hub tags below 1.13.0 when enrollment is enabled. Writes inline keys to the chart Secret and handles an absent enrollment map.

charts/radar-hub/templates/secret.yaml

Tests (1) +33 / -0
render-matrix.shExercise enrollment rendering and rejection cases +33/-0

Exercise enrollment rendering and rejection cases

• Adds render checks for both key sources, environment variables, validation failures, image-version boundaries, and an absent enrollment map. Also verifies that enrollment remains absent by default.

charts/radar-hub/tests/render-matrix.sh

Documentation (1) +23 / -0
values.yamlDocument enrollment defaults and key sources +23/-0

Document enrollment defaults and key sources

• Adds disabled-by-default enrollment values with guidance for generating a key, using an existing Secret, and selecting approval and rejoin behavior.

charts/radar-hub/values.yaml

Other (1) +27 / -0
values.schema.jsonDefine the enrollment values schema +27/-0

Define the enrollment values schema

• Adds documented enrollment fields and rejects unknown properties within the enrollment map.

charts/radar-hub/values.schema.json

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Rotated enrollment keys stay inactive ✓ Resolved
Description
HUB_ENROLLMENT_KEY reads enrollment.existingSecret into an environment variable, while the
Deployment checksum covers only the chart-rendered Secret. When an operator rotates the external
Secret, the pod is not restarted and keeps accepting the old key until it is restarted manually.
Code

charts/radar-hub/templates/deployment-hub.yaml[R361-366]

+            - name: HUB_ENROLLMENT_KEY
+              valueFrom:
+                secretKeyRef:
+                  {{- if $en.existingSecret }}
+                  name: {{ $en.existingSecret | quote }}
+                  key: {{ $en.existingSecretKey | default "key" | quote }}
Evidence
The new external Secret reference supplies a startup environment variable. The rollout checksum
hashes only secret.yaml, whose inline-key condition excludes enrollment.existingSecret; the
deployment's existing license comment also explains that externally sourced Secret environment
variables do not refresh in a running process.

charts/radar-hub/templates/deployment-hub.yaml[16-20]
charts/radar-hub/templates/deployment-hub.yaml[218-229]
charts/radar-hub/templates/deployment-hub.yaml[359-370]
charts/radar-hub/templates/secret.yaml[348-352]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rotating an externally managed enrollment Secret leaves running Hub pods using the old key because its environment variable is fixed at startup and the chart's checksum does not cover that Secret.
## Fix Focus Areas
- charts/radar-hub/templates/deployment-hub.yaml[16-20]
- charts/radar-hub/templates/deployment-hub.yaml[361-370]
## Recommended Fix
Provide a reliable pod-restart mechanism for external enrollment Secret changes. If the chart cannot observe those changes, document that rotating the key requires an explicit Hub rollout and provide the operator command.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

hisco added 2 commits October 24, 2026 08:27
…gned certificate

enrollment.key / existingSecret / trustByDefault set the hub's install key. The self-signed web certificate is generated once and kept, or comes from web.tls.certificate/privateKey or web.tls.existingSecret; with web.tls.showInInstallSteps the hub hands its public part to the install steps. User-token mode with a self-signed hub is allowed except with localCluster.

Claude-Session: https://claude.ai/code/session_01SxLwuGLtodCbE7pfsPHdtv
@cursor

cursor Bot commented Oct 25, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@hisco hisco changed the title radar-hub: enrollment key values radar-hub: install enrollment key and a stable self-signed certificate Oct 25, 2026
hisco and others added 5 commits October 26, 2026 10:22
…ficate

Adds enrollment.approval for the install key. The install steps always
include the hub's public certificate on a self-signed hub
(web.tls.showInInstallSteps is gone). Token mode on a self-signed hub now
prints a warning in the install notes.

Claude-Session: https://claude.ai/code/session_01SxLwuGLtodCbE7pfsPHdtv
Chart CI requires a version bump for the new enrollment and TLS values.
appVersion stays 1.13.0; the radar-hub v1.13.1 tag promotes this to 1.14.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hub release that ships shared enrollment keys is 1.14.0, matching
the chart version, so the guard, its message and the tests name it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@arlenskh
arlenskh merged commit 3e65801 into main Oct 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants