Skip to content

Add MIREN_CLUSTER targeting and cluster export-address command#633

Merged
evanphx merged 2 commits intomainfrom
mir-739-fix-ability-to-target-a-cluster-in-oidc-auth-mode
Feb 26, 2026
Merged

Add MIREN_CLUSTER targeting and cluster export-address command#633
evanphx merged 2 commits intomainfrom
mir-739-fix-ability-to-target-a-cluster-in-oidc-auth-mode

Conversation

@evanphx
Copy link
Copy Markdown
Contributor

@evanphx evanphx commented Feb 26, 2026

Summary

  • MIREN_CLUSTER env var support: LoadCluster now parses MIREN_CLUSTER with optional address;sha1:fingerprint format for targeting clusters without a config file, with TLS certificate fingerprint verification (TOFU protection)
  • cluster export-address command: Exports a cluster's address and CA cert fingerprint in the format consumed by MIREN_CLUSTER. Honors the -C flag (not a positional arg) and falls back to the active cluster
  • cluster add manual mode: When both --cluster and --address are provided, identity is no longer required — supports OIDC and environment-based auth
  • checkFingerprint helper: Extracted from setupClusterFromAddress for direct unit testing of the security-critical fingerprint comparison logic
  • Tests: TestCheckFingerprint (prefix stripping, case insensitivity, mismatch errors), TestLoadClusterEnvVar (known names, address fallthrough, fingerprint splitting), TestClusterExportAddress (active cluster, -C flag, -C priority, error cases)

Test plan

  • go test ./cli/commands/... -run 'TestCheckFingerprint|TestLoadClusterEnvVar|TestClusterExportAddress' -v — all 15 tests pass
  • Full go test ./cli/commands/... suite passes
  • Manual: miren cluster export-address outputs correct fingerprint for active cluster
  • Manual: miren cluster export-address -C <name> targets the right cluster
  • Manual: MIREN_CLUSTER=<exported-value> miren app list connects to the expected cluster

@evanphx evanphx requested a review from a team as a code owner February 26, 2026 06:12
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Adds a new cluster export-address command and tests that print a cluster hostname with a SHA-1 TLS certificate fingerprint. Changes cluster-add flow to detect manual mode when --cluster/--address are provided and treat identity requirements differently in manual vs discovery modes, with improved identity lookup and clearer error messages. extractTLSCertificate now accepts context.Context. Enhances config loading to honor MIREN_CLUSTER (cluster name or address with optional fingerprint), probe TLS/QUIC, and create in-memory cluster entries when needed.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@phinze phinze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice solution - the env var means we can skip a command step in CI and the fingerprint inclusion is 😚 👌

…print verification

- Add MIREN_CLUSTER env var parsing in LoadCluster with address;sha1:fingerprint format
- Add cluster export-address command that outputs address;sha1:<fingerprint> for use
  with MIREN_CLUSTER, honoring the -C flag instead of a positional argument
- Extract checkFingerprint helper from setupClusterFromAddress for testability
- Move extractTLSCertificate to accept context.Context and setupClusterFromAddress
  into config.go alongside the env var logic it supports
- Allow cluster add in manual mode (--cluster + --address) without requiring an identity
- Add tests for fingerprint verification, LoadCluster env var paths, and export-address
@evanphx evanphx force-pushed the mir-739-fix-ability-to-target-a-cluster-in-oidc-auth-mode branch from 99b5ce8 to c6fc9cf Compare February 26, 2026 17:10
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/commands/config.go`:
- Around line 124-131: The checkFingerprint function fails to strip uppercase
"SHA1:" prefixes because strings.TrimPrefix is case-sensitive; update
checkFingerprint to remove the "sha1:" prefix case-insensitively (e.g., check
strings.HasPrefix(strings.ToLower(expected), "sha1:") and then slice off the
prefix from the original expected string, or lowercase a copy and TrimPrefix on
that copy) before the case-insensitive comparison with strings.EqualFold; change
the existing strings.TrimPrefix(expected, "sha1:") usage in checkFingerprint
accordingly.
- Around line 39-42: Replace direct equality checks against
clientconfig.ErrNoConfig with the idiomatic errors.Is(...) pattern: where the
code currently does `if err == clientconfig.ErrNoConfig &&
os.Getenv("MIREN_CLUSTER") != "" { ... }` (and the similar check around lines
47-50), change to `if errors.Is(err, clientconfig.ErrNoConfig) &&
os.Getenv("MIREN_CLUSTER") != "" { ... }`; import the standard "errors" package
if not already imported and keep the existing behavior of creating a new config
via clientconfig.NewConfig() and returning c.cfg, nil.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99b5ce8 and c6fc9cf.

📒 Files selected for processing (6)
  • cli/commands/cluster_add.go
  • cli/commands/cluster_export.go
  • cli/commands/cluster_export_test.go
  • cli/commands/commands.go
  • cli/commands/config.go
  • cli/commands/config_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • cli/commands/config_test.go
  • cli/commands/cluster_export.go
  • cli/commands/cluster_export_test.go

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
cli/commands/config.go (1)

124-131: ⚠️ Potential issue | 🟡 Minor

checkFingerprint does not handle uppercase SHA1: prefix.

strings.TrimPrefix(expected, "sha1:") is case-sensitive, so an expected value like SHA1:abcdef... will fail comparison even though the fingerprint matching is otherwise case-insensitive.

🔧 Proposed fix for case-insensitive prefix handling
 func checkFingerprint(expected, actual string) error {
 	if expected == "" {
 		return nil
 	}
-	expected = strings.TrimPrefix(expected, "sha1:")
+	if strings.HasPrefix(strings.ToLower(expected), "sha1:") {
+		expected = expected[len("sha1:"):]
+	}
 	if !strings.EqualFold(expected, actual) {
 		return fmt.Errorf("TLS certificate fingerprint mismatch: got %s, expected %s", actual, expected)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/commands/config.go` around lines 124 - 131, The checkFingerprint function
fails to strip a case-insensitive "sha1:" prefix because
strings.TrimPrefix("sha1:") is case-sensitive; modify checkFingerprint to remove
the prefix regardless of case (e.g., normalize expected with strings.ToLower or
detect prefix with strings.HasPrefix(strings.ToLower(expected), "sha1:") and
then strip the first len("sha1:") characters) before comparing with
strings.EqualFold, keeping the rest of the logic in checkFingerprint unchanged.
🧹 Nitpick comments (1)
cli/commands/config.go (1)

140-141: Consider adding a timeout for the TLS probe.

The context has no deadline, so extractTLSCertificate could block indefinitely if the target address is reachable but the TLS handshake hangs. For CLI responsiveness, a reasonable timeout (e.g., 10-30 seconds) would improve user experience.

⏱️ Proposed fix to add timeout
-	ctx, cancel := context.WithCancel(context.Background())
+	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	defer cancel()

Note: This requires adding "time" to the imports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/commands/config.go` around lines 140 - 141, The current ctx created with
context.WithCancel in the TLS probe can hang indefinitely; replace it with a
context with deadline (e.g., use context.WithTimeout instead of
context.WithCancel) when calling extractTLSCertificate and set a reasonable
timeout (10–30s, e.g., 20s), keep the defer cancel(), and add the "time" import;
update references to ctx and cancel in this scope so extractTLSCertificate
receives the timed context.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@cli/commands/config.go`:
- Around line 124-131: The checkFingerprint function fails to strip a
case-insensitive "sha1:" prefix because strings.TrimPrefix("sha1:") is
case-sensitive; modify checkFingerprint to remove the prefix regardless of case
(e.g., normalize expected with strings.ToLower or detect prefix with
strings.HasPrefix(strings.ToLower(expected), "sha1:") and then strip the first
len("sha1:") characters) before comparing with strings.EqualFold, keeping the
rest of the logic in checkFingerprint unchanged.

---

Nitpick comments:
In `@cli/commands/config.go`:
- Around line 140-141: The current ctx created with context.WithCancel in the
TLS probe can hang indefinitely; replace it with a context with deadline (e.g.,
use context.WithTimeout instead of context.WithCancel) when calling
extractTLSCertificate and set a reasonable timeout (10–30s, e.g., 20s), keep the
defer cancel(), and add the "time" import; update references to ctx and cancel
in this scope so extractTLSCertificate receives the timed context.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c6fc9cf and e39fe90.

📒 Files selected for processing (1)
  • cli/commands/config.go

@evanphx evanphx merged commit dc1f671 into main Feb 26, 2026
13 checks passed
@evanphx evanphx deleted the mir-739-fix-ability-to-target-a-cluster-in-oidc-auth-mode branch February 26, 2026 17:27
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