Skip to content

chore(rest-api): Add ingress based TLS support for REST API#3351

Open
thossain-nv wants to merge 3 commits into
NVIDIA:mainfrom
thossain-nv:chore/rest-api-tls
Open

chore(rest-api): Add ingress based TLS support for REST API#3351
thossain-nv wants to merge 3 commits into
NVIDIA:mainfrom
thossain-nv:chore/rest-api-tls

Conversation

@thossain-nv

Copy link
Copy Markdown
Contributor

Currently we don't have a way to configure REST API to support TLS. Following K8s best practices, this PR introduces:

  • Ingress based TLS termination
  • Enhances Helm chart, installation and docs to enable TLS termination
  • Provides a quick option for cert-manager based self-signed TLS cert
  • Allows deeper configuration for adding FQDN if user wishes
  • TLS support is optional, it's not enabled by default to prevent breaking existing installations where users may be terminating TLS themselves

Related issues

#2587

Type of Change

  • Add - New feature or capability

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4f86e83e-9392-44f6-ab98-d66ec3f49fdb

📥 Commits

Reviewing files that changed from the base of the PR and between 14ace92 and fef6396.

📒 Files selected for processing (1)
  • helm-prereqs/health-check.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • helm-prereqs/health-check.sh

Summary by CodeRabbit

  • New Features
    • Added optional Ingress support for exposing the REST API, with configurable host/path routing, class name, and annotations.
    • Added optional cert-manager–managed TLS certificate generation for the REST Ingress.
    • Added optional installation of an Ingress controller (ingress-nginx) via setup flag/environment toggle and Helm configuration.
  • Documentation
    • Expanded quick-start and prerequisites guidance for TLS/Ingress exposure and optional ingress-nginx installation.
  • Bug Fixes
    • Improved health checks and teardown/cleanup to better handle partial or optional ingress-nginx installs.
  • Tests
    • Added Helm unittest coverage for Ingress and certificate rendering.

Walkthrough

Adds optional ingress-nginx installation and lifecycle management, plus configurable nico-rest-api Ingress and cert-manager TLS resources with Helm tests and setup documentation.

Changes

Ingress TLS exposure

Layer / File(s) Summary
Chart ingress and certificate rendering
helm/rest/nico-rest/charts/nico-rest-api/values.yaml, helm/rest/nico-rest/charts/nico-rest-api/templates/*, helm/rest/nico-rest/charts/nico-rest-api/tests/ingress_test.yaml
Adds disabled-by-default Ingress and certificate configuration, renders host/path routing and cert-manager Certificate resources, and tests enabled, disabled, TLS, and existing-secret scenarios.
Optional ingress-nginx installation
helm-prereqs/operators/values/ingress-nginx.yaml, helm-prereqs/helmfile.yaml, helm-prereqs/setup.sh
Adds the ingress-nginx Helm release and LoadBalancer configuration, with environment-variable and CLI controls, validation, installation, and readiness waiting.
Ingress lifecycle and health operations
helm-prereqs/health-check.sh, helm-prereqs/clean.sh
Discovers and reports the optional controller, conditionally checks readiness, and removes its namespaces, cluster-scoped resources, and released persistent volumes during cleanup.
Ingress usage documentation
docs/getting-started/*, helm-prereqs/README.md, helm-prereqs/values/nico-rest.yaml
Documents optional ingress-nginx installation and TLS exposure for the REST API, including setup phases, prerequisites, configuration, and deployed components.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant setup.sh
  participant helmfile
  participant MetalLB
  participant ingress-nginx-controller
  participant nico-rest-api-Service
  Operator->>setup.sh: Enable ingress-nginx installation
  setup.sh->>helmfile: Sync ingress-nginx release
  helmfile->>ingress-nginx-controller: Create controller and LoadBalancer Service
  ingress-nginx-controller->>MetalLB: Request LoadBalancer address
  ingress-nginx-controller->>nico-rest-api-Service: Route configured Ingress traffic
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding ingress-based TLS support for the REST API.
Description check ✅ Passed The description matches the changeset by describing optional ingress TLS, Helm updates, cert-manager support, and docs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

🔐 TruffleHog Secret Scan

No secrets or credentials found!

Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉

🔗 View scan details

🕐 Last updated: 2026-07-10 01:48:51 UTC | Commit: b131a4b

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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.

Inline comments:
In `@helm-prereqs/clean.sh`:
- Line 245: Update the PV filtering logic in the cleanup script so it does not
automatically select every PV claimed in the ingress-nginx namespace; instead,
restrict deletion to explicitly stack-owned resources using ownership metadata
or known claim names, or remove ingress-nginx from the namespace allowlist
unless the script can verify it created and owns the namespace.
- Around line 157-164: Update the ingress-nginx cleanup logic in clean.sh to
delete resources only when this installation recorded ownership or the resources
have matching Helm ownership metadata; never unconditionally delete the global
nginx IngressClass, ingress-nginx ClusterRoles/ClusterRoleBindings, or
namespace. Preserve idempotency and safely skip shared or externally managed
resources, including the corresponding cleanup block around the namespace
deletion.

In `@helm-prereqs/health-check.sh`:
- Around line 109-112: Update the namespace discovery logic around
INGRESS_NGINX_NS to avoid selecting kubectl’s arbitrary .items[0]. Identify the
intended ingress-nginx-controller using Helm/release labels or a configured
namespace, and explicitly fail or report ambiguity when multiple matching
deployments remain; ensure the health-check lifecycle status is reliable.

In `@helm-prereqs/helmfile.yaml`:
- Around line 60-74: Ensure the optional ingress-nginx release cannot be
destroyed unless this setup explicitly installed it: update the helmfile and
related setup/cleanup logic around the ingress-nginx release so installation
ownership is tracked and clean.sh’s teardown is limited to owned releases, while
preserving idempotent lifecycle behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b618f86f-45cd-4c71-b3f9-1becb2b4b0cb

📥 Commits

Reviewing files that changed from the base of the PR and between 699951d and b131a4b.

📒 Files selected for processing (13)
  • docs/getting-started/installation-options/reference-install.md
  • docs/getting-started/quick-start.md
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh
  • helm-prereqs/health-check.sh
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/operators/values/ingress-nginx.yaml
  • helm-prereqs/setup.sh
  • helm-prereqs/values/nico-rest.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/templates/ingress-certificate.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/templates/ingress.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/tests/ingress_test.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/values.yaml

Comment thread helm-prereqs/clean.sh
Comment thread helm-prereqs/clean.sh
Comment thread helm-prereqs/health-check.sh
Comment thread helm-prereqs/helmfile.yaml
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
boot-artifacts-aarch64 3 0 0 3 0 0
boot-artifacts-x86_64 3 0 0 3 0 0
forge-admin-cli-x86_64 271 13 34 91 7 126
machine-validation-runner 804 40 237 296 36 195
machine_validation 804 40 237 296 36 195
machine_validation-aarch64 804 40 237 296 36 195
nvmetal-carbide 804 40 237 296 36 195
TOTAL 3493 173 982 1281 151 906

Per-CVE detail lives in the per-service grype-* artifacts (JSON + SARIF). Severity counts only — no CVE IDs published here.

@shayan1995 shayan1995 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

generally looks good - there is a small issue with the healthcheck script.

Comment thread helm-prereqs/health-check.sh Outdated
-o jsonpath='{.items[0].metadata.namespace}' 2>/dev/null || printf 'metallb-system')
fi
if [[ -z "${INGRESS_NGINX_NS:-}" ]]; then
INGRESS_NGINX_NS=$(kubectl get deployment ingress-nginx-controller -A \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@thossain-nv This autodetect can never succeed I've tried kubectl get deployment <name> -A to confirm and it is rejected on client-side with "a resource cannot be retrieved by name across all namespaces", so INGRESS_NGINX_NS is always empty and the health check always reports "not installed" even when ingress-nginx is deployed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for detecting this issue @shayan1995, I'll add a fix.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
helm/rest/nico-rest/charts/nico-rest-api/templates/ingress.yaml (1)

24-38: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Guard against empty rules when ingress.hosts is empty.

If ingress.hosts is empty, rules: renders with no list items — Kubernetes' networking.k8s.io/v1 Ingress schema requires rules (when using host-based rules) to be a populated array, so this would fail server-side validation with an unhelpful error rather than a clear chart-level failure.

🛡️ Proposed defensive guard
+  {{- if not .Values.ingress.hosts }}
+  {{- fail "ingress.hosts must contain at least one entry when ingress.enabled is true" }}
+  {{- end }}
   rules:
     {{- range .Values.ingress.hosts }}
🤖 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 `@helm/rest/nico-rest/charts/nico-rest-api/templates/ingress.yaml` around lines
24 - 38, Guard the Ingress rules block around the hosts iteration so an empty
.Values.ingress.hosts cannot render rules: without entries. Update the template
containing the range over .Values.ingress.hosts to either fail explicitly with a
clear Helm error or omit the rules field when no hosts are configured, while
preserving the existing host and path rendering for populated values.
helm/rest/nico-rest/charts/nico-rest-api/templates/ingress-certificate.yaml (1)

30-37: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Guard against an empty dnsNames list.

If ingress.certificate.dnsNames is unset and ingress.hosts is empty, this block renders dnsNames: with no items underneath — an invalid value for a required, non-empty list in the cert-manager Certificate CRD schema, causing the apply to fail.

🛡️ Proposed defensive guard
   dnsNames:
     {{- if .Values.ingress.certificate.dnsNames }}
     {{- toYaml .Values.ingress.certificate.dnsNames | nindent 4 }}
-    {{- else }}
+    {{- else if .Values.ingress.hosts }}
     {{- range .Values.ingress.hosts }}
     - {{ .host }}
     {{- end }}
+    {{- else }}
+    {{- fail "ingress.certificate.dnsNames or ingress.hosts must be set when ingress.certificate.enabled is true" }}
     {{- end }}
🤖 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 `@helm/rest/nico-rest/charts/nico-rest-api/templates/ingress-certificate.yaml`
around lines 30 - 37, Guard the dnsNames rendering in the Certificate template
so it is emitted only when either ingress.certificate.dnsNames or ingress.hosts
contains entries; otherwise fail template rendering with a clear validation
error (or provide a documented valid fallback), preventing an empty required
list. Update the conditional around the dnsNames block and preserve the existing
explicit-list and host-derived behavior.
🤖 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 `@helm/rest/nico-rest/charts/nico-rest-api/templates/ingress-certificate.yaml`:
- Around line 30-37: Guard the dnsNames rendering in the Certificate template so
it is emitted only when either ingress.certificate.dnsNames or ingress.hosts
contains entries; otherwise fail template rendering with a clear validation
error (or provide a documented valid fallback), preventing an empty required
list. Update the conditional around the dnsNames block and preserve the existing
explicit-list and host-derived behavior.

In `@helm/rest/nico-rest/charts/nico-rest-api/templates/ingress.yaml`:
- Around line 24-38: Guard the Ingress rules block around the hosts iteration so
an empty .Values.ingress.hosts cannot render rules: without entries. Update the
template containing the range over .Values.ingress.hosts to either fail
explicitly with a clear Helm error or omit the rules field when no hosts are
configured, while preserving the existing host and path rendering for populated
values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c77c02b1-cbd7-4b43-a3fe-0700340e8bfa

📥 Commits

Reviewing files that changed from the base of the PR and between b131a4b and 14ace92.

📒 Files selected for processing (13)
  • docs/getting-started/installation-options/reference-install.md
  • docs/getting-started/quick-start.md
  • helm-prereqs/README.md
  • helm-prereqs/clean.sh
  • helm-prereqs/health-check.sh
  • helm-prereqs/helmfile.yaml
  • helm-prereqs/operators/values/ingress-nginx.yaml
  • helm-prereqs/setup.sh
  • helm-prereqs/values/nico-rest.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/templates/ingress-certificate.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/templates/ingress.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/tests/ingress_test.yaml
  • helm/rest/nico-rest/charts/nico-rest-api/values.yaml
✅ Files skipped from review due to trivial changes (5)
  • helm-prereqs/operators/values/ingress-nginx.yaml
  • helm-prereqs/values/nico-rest.yaml
  • docs/getting-started/quick-start.md
  • helm-prereqs/README.md
  • docs/getting-started/installation-options/reference-install.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • helm/rest/nico-rest/charts/nico-rest-api/values.yaml
  • helm-prereqs/health-check.sh
  • helm/rest/nico-rest/charts/nico-rest-api/tests/ingress_test.yaml
  • helm-prereqs/clean.sh
  • helm-prereqs/setup.sh
  • helm-prereqs/helmfile.yaml

@ajf

ajf commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

AFAIK there's already an envoy-based ingress controller that was part of the site controller deployments. Is that still there in the helm prerequisites @shayan1995 ? Should we use that instead?

@thossain-nv

thossain-nv commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@ajf Contour/Envoy is mentioned in the pre-requisite in docs/getting-started/prerequisites/software.md but Helm prereqs doesn't install either.

Another place that references Envoy is dev/envoy.yaml

Other pre-requisites e.g. MetalLB/cert-manager are installed by Helm. Are existing Helm installed NICo using something else?

Installing the nginx ingress controller is optional but I can switch to contour/envoy instead and make it mandatory.

@@ -114,6 +123,7 @@ printf " %-26s %s\n" "postgres namespace:" "${POSTGRES_NS}"
printf " %-26s %s\n" "cert-manager ns:" "${CERT_MANAGER_NS}"
printf " %-26s %s\n" "external-secrets ns:" "${ESO_NS}"
printf " %-26s %s\n" "metallb ns:" "${METALLB_NS}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to METALLB_NS needed here?

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.

4 participants