Skip to content

Drop roxctl dependency, use Central REST API for CRS#234

Open
porridge wants to merge 7 commits into
mainfrom
drop-roxctl-dependency
Open

Drop roxctl dependency, use Central REST API for CRS#234
porridge wants to merge 7 commits into
mainfrom
drop-roxctl-dependency

Conversation

@porridge

@porridge porridge commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace roxctl subprocess call for CRS generation with a direct HTTP POST to Central's REST API (/v1/cluster-init/crs), using Basic auth and proper TLS (CA cert when available, system pool otherwise)
  • Delete internal/deployer/roxctl.go (now unused)
  • Remove roxctl from required tools check, CI workflow, and README prerequisites

The custom TLS code is needed to prevent errors such as:

helpers.go:131: [stderr] Error: deployment failed: failed to deploy secured cluster:
  failed to generate CRS: failed to generate CRS:
  Post "[https://34.69.107.125:443/v1/cluster-init/crs](https://34.69.107.125/v1/cluster-init/crs)":
  tls: failed to verify certificate:
  x509: cannot validate certificate for 34.69.107.125 because it doesn't contain any IP SANs

Closes #160

Resolves: ROX-35666

🤖 Partially Generated with Claude Code

Tested in CI:

helpers.go:131: [stdout] 01:44 ✓ CA certificate saved to: /tmp/roxie-deployer-3951018772/roxie-central-ca-645782106.pem
    helpers.go:131: [stdout] 01:44 Writing environment variables to /tmp/TestDeployBothSimple1448013749/001/.envrc.roxie-test-1970664274
    helpers.go:131: [stdout] 01:44 ✓ Environment variables written to /tmp/TestDeployBothSimple1448013749/001/.envrc.roxie-test-1970664274
    helpers.go:131: [stdout] 01:44 Deploying SecuredCluster to namespace acs-sensor
    helpers.go:131: [stdout] 01:44 🚀 Deploying SecuredCluster via Operator...
    helpers.go:131: [stdout] 01:44 Preparing namespace acs-sensor
    helpers.go:131: [stdout] 01:44 Creating namespace acs-sensor
    helpers.go:131: [stdout] 01:45 Using cluster name: sensor-2711
    helpers.go:131: [stdout] 01:45 Loaded 1 CA certificate(s) from "/tmp/roxie-deployer-3951018772/roxie-central-ca-645782106.pem"
    helpers.go:131: [stdout] 01:45 Generating CRS named "sensor-2711-crs-1" via Central API...
    helpers.go:131: [stdout] 02:15 Transient error generating CRS: Post "[https://136.65.242.140:443/v1/cluster-init/crs](https://136.65.242.140/v1/cluster-init/crs)": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
    helpers.go:131: [stdout] 02:15 Retrying CRS generation (attempt 2/5) after 20s...
    helpers.go:131: [stdout] 02:35 Generating CRS named "sensor-2711-crs-2" via Central API...
    helpers.go:131: [stdout] 02:46 ✓ CRS generated

Also tested manually with the CA cert from wrong central:

     Error: deployment failed: failed to deploy secured cluster: failed to generate CRS: failed to generate CRS: Post "https://127.0.0.1:8443/v1/cluster-init/crs": verifying central certificate errors: [x509: certificate
     signed by unknown authority, x509: certificate signed by unknown authority]

Summary by CodeRabbit

  • New Features

    • Switched cluster initialization to use the native roxie CLI and direct service API calls.
    • Added improved error aggregation for clearer, combined failure messages.
  • Bug Fixes

    • Strengthened connection handling for secure certificate verification and retries.
    • Updated tool checks to require only kubectl during setup.
  • Documentation

    • Revised the quick start guide to reflect the roxie CLI requirement.

Replace the roxctl subprocess call for generating Cluster Registration
Secrets with a direct HTTP POST to Central's REST API endpoint
(/v1/cluster-init/crs). This eliminates the requirement for users to
install a matching roxctl binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy #160 by eliminating the roxctl deployment dependency while preserving CRS generation through a direct API call.
Out of Scope Changes check ✅ Passed All modifications appear tied to the roxctl removal and API-based CRS flow, with no obvious unrelated scope creep.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: removing the roxctl dependency and switching CRS generation to Central's REST API.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drop-roxctl-dependency

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
internal/deployer/crs.go (2)

136-136: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Set an explicit MinVersion on the TLS config.

Consider pinning MinVersion: tls.VersionTLS12 (or TLS13) rather than relying on the implicit default, to make the security posture explicit and future-proof.

🔒 Proposed change
-	tlsConfig := &tls.Config{}
+	tlsConfig := &tls.Config{MinVersion: tls.VersionTLS12}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/deployer/crs.go` at line 136, The TLS configuration in crs.go is
created with the default settings, so make the security baseline explicit by
setting MinVersion on the tls.Config used in the deployment flow. Update the
tlsConfig initialization in the relevant CRS deployment path to pin a minimum
version such as tls.VersionTLS12 (or TLS13 if supported), keeping the change
localized to the tlsConfig setup so the behavior is clear and future-proof.

Source: Linters/SAST tools


143-151: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Prefer CertPool.AppendCertsFromPEM and guard against an empty pool.

The manual pem.Decode/ParseCertificate loop will error out on any non-CERTIFICATE PEM block, and if the file yields no certificates it silently produces an empty pool that is then set as RootCAs, causing all TLS verification to fail rather than falling back. AppendCertsFromPEM handles mixed/extra blocks and lets you detect the empty case.

♻️ Proposed refactor
 	if d.roxCACertFile != "" {
 		pemData, err := os.ReadFile(d.roxCACertFile)
 		if err != nil {
 			return nil, fmt.Errorf("reading CA cert file %s: %w", d.roxCACertFile, err)
 		}
 		pool := x509.NewCertPool()
-		for block, rest := pem.Decode(pemData); block != nil; block, rest = pem.Decode(rest) {
-			cert, err := x509.ParseCertificate(block.Bytes)
-			if err != nil {
-				return nil, fmt.Errorf("parsing CA certificate from %s: %w", d.roxCACertFile, err)
-			}
-			pool.AddCert(cert)
-		}
+		if !pool.AppendCertsFromPEM(pemData) {
+			return nil, fmt.Errorf("no valid certificates found in CA cert file %s", d.roxCACertFile)
+		}
 		tlsConfig.RootCAs = pool
 	}

If you drop the manual loop, the crypto/x509 and encoding/pem imports may need adjustment (x509 is still used for NewCertPool).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/deployer/crs.go` around lines 143 - 151, Replace the manual PEM
parsing in the CA certificate setup with x509.CertPool.AppendCertsFromPEM in the
certificate-loading path inside the deployer logic. In the code that builds
tlsConfig.RootCAs, load the PEM data into a new CertPool, append all certs in
one pass, and explicitly handle the case where no certificates were added so you
don’t assign an empty RootCAs pool. Keep the existing x509.NewCertPool usage as
needed and remove any now-unused pem handling in internal/deployer/crs.go.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/deployer/crs.go`:
- Line 136: The TLS configuration in crs.go is created with the default
settings, so make the security baseline explicit by setting MinVersion on the
tls.Config used in the deployment flow. Update the tlsConfig initialization in
the relevant CRS deployment path to pin a minimum version such as
tls.VersionTLS12 (or TLS13 if supported), keeping the change localized to the
tlsConfig setup so the behavior is clear and future-proof.
- Around line 143-151: Replace the manual PEM parsing in the CA certificate
setup with x509.CertPool.AppendCertsFromPEM in the certificate-loading path
inside the deployer logic. In the code that builds tlsConfig.RootCAs, load the
PEM data into a new CertPool, append all certs in one pass, and explicitly
handle the case where no certificates were added so you don’t assign an empty
RootCAs pool. Keep the existing x509.NewCertPool usage as needed and remove any
now-unused pem handling in internal/deployer/crs.go.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: 4e908d08-6f1d-43cc-84ee-1fe4cb942595

📥 Commits

Reviewing files that changed from the base of the PR and between 9e28369 and 76db84d.

📒 Files selected for processing (5)
  • .github/workflows/e2e-tests.yml
  • README.md
  • internal/deployer/crs.go
  • internal/deployer/deployer.go
  • internal/deployer/roxctl.go
💤 Files with no reviewable changes (3)
  • README.md
  • .github/workflows/e2e-tests.yml
  • internal/deployer/roxctl.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/errorhelpers/format.go (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Typo: missing space in package comment.

✏️ Proposed fix
-// Package errorhelpers was copied fromhttps://github.com/stackrox/stackrox/tree/master/pkg/errorhelpers
+// Package errorhelpers was copied from https://github.com/stackrox/stackrox/tree/master/pkg/errorhelpers
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/errorhelpers/format.go` at line 1, The package comment for
errorhelpers has a typo because it is missing a space in the copied source
reference. Update the comment at the top of the file so the text is properly
spaced and reads naturally, keeping the package comment aligned with the
errorhelpers package declaration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/errorhelpers/format.go`:
- Line 1: The package comment for errorhelpers has a typo because it is missing
a space in the copied source reference. Update the comment at the top of the
file so the text is properly spaced and reads naturally, keeping the package
comment aligned with the errorhelpers package declaration.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: 2165fa01-34ec-41a2-bef2-e0a384e9f4c4

📥 Commits

Reviewing files that changed from the base of the PR and between 76db84d and f82ad1c.

📒 Files selected for processing (3)
  • go.mod
  • internal/deployer/crs.go
  • internal/errorhelpers/format.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/deployer/crs.go

@porridge porridge marked this pull request as ready for review July 9, 2026 12:23
@porridge

porridge commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@mclasmeier one question I have: should we keep roxctl download in Dockerfile?

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.

Get rid of roxctl dependency for deployment

1 participant