Skip to content

Fix #5857: Add cert-manager auto-discovery to the Ingress trait - #6818

Merged
squakez merged 9 commits into
apache:mainfrom
Thundercloud12:feature/5857-cert-manager-auto-discovery
Sep 18, 2026
Merged

squakez merged 9 commits into
apache:mainfrom
Thundercloud12:feature/5857-cert-manager-auto-discovery

Conversation

@Thundercloud12

Copy link
Copy Markdown
Contributor

Summary

Adds cert-manager auto-discovery to the Ingress trait. When enabled, Camel K detects whether cert-manager is installed, resolves a ClusterIssuer or Issuer (either forced by name or auto-discovered), and annotates the generated Ingress so cert-manager's own ingress-shim handles certificate issuance and renewal.

Camel K never creates Certificate resources itself — this keeps certificate lifecycle management entirely inside cert-manager, where it belongs.

Fixes #5857

New Trait Options

  • tls-cert-manager-auto — enable cert-manager auto-discovery
  • tls-issuer-name — force a specific issuer, bypassing auto-discovery
  • tls-issuer-kindIssuer or ClusterIssuer (defaults to ClusterIssuer)

Design Notes / Tradeoffs for Reviewers

  • Multiple issuers: When auto-discovery finds more than one ClusterIssuer/Issuer, the first one is selected rather than requiring exactly one unambiguous match. This was chosen for simplicity over correctness-by-refusal. Happy to switch to an "only when exactly one issuer is found" behavior if reviewers prefer.

  • t.Host fallback: The cert-manager path also activates when only ingress.host is set. This is intentional because ingress.host is the field most users actually configure. This fallback is scoped strictly to the cert-manager path (only when tlsSecretName is empty) and does not change the existing manual-TLS behavior covered by TestConfigureTLSWithoutHostsIngressTraitDoesSucceed.

  • RBAC widening: Adds get/list/watch permissions for issuers and clusterissuers (cert-manager.io) to the operator's ClusterRole/Role. These permissions are read-only. clusterissuers are cluster-scoped even in the namespaced installation mode; this is flagged for review against the project's RBAC threat model.

  • E2E scope: Rather than performing a live HTTPS round-trip through a real ingress controller—which would require additional infrastructure such as DNS, a tunnel, or an ingress addon—the E2E test verifies the issued certificate cryptographically. It parses the TLS secret and checks the DNS SAN and certificate expiry after confirming that cert-manager populated it.

Implementation

  • pkg/util/certmanager/ — new cert-manager detection package (IsInstalled, ListClusterIssuers, GetClusterIssuer, GetIssuer), built on unstructured without introducing a cert-manager Go client dependency. Absence of cert-manager degrades cleanly to "not found" rather than returning an error.

  • pkg/trait/ingress.go — adds resolveCertManagerIssuer() and reworks the TLS block in Apply() to merge the manual-TLS and cert-manager paths.

  • RBAC: Adds the required ClusterRole/Role/RoleBinding permissions for issuers and clusterissuers.

  • e2e/cert-manager/ — new cert-manager E2E workflow with its own Makefile target, mirroring the structure of the existing e2e/gateway suite.

Test Plan

  • Unit tests: pkg/util/certmanager — 8 tests covering installation detection and all three "absent" failure modes

  • Unit tests: pkg/trait/ingress_test.go — 6 additional tests covering:

    • cert-manager not installed → no-op
    • no issuer found → no-op
    • successful auto-discovery
    • successful forced-issuer resolution
    • forced issuer missing → error
    • forced issuer configured but cert-manager not installed → error
  • Existing Ingress trait tests — 12 tests pass unmodified, confirming no regression to manual TLS behavior

  • go build ./...

  • gofmt

  • ./script/check_licenses.sh

  • E2E suite (make test-e2e) — not run in this environment; reviewers/CI to confirm


🤖 Generated with Claude Code on behalf of Thundercloud12

@Thundercloud12

Copy link
Copy Markdown
Contributor Author

@squakez this is the fix, there are two assumptions i should say that i have taken while building this written above too but writing it here so you can deal a good focus on it:

  1. If clientissuer finds more than one issuer it falls back to the first issuer taking precendence alphabetically
  2. The cert manager path will also activate WHEN ONLY t.Host is set, it is strictly done when tlssecretname is not there
    If you find anything wrong or not upto mark with your architecture or codebase please do let me know, Thank you for giving time to review this pr!!

@squakez squakez 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.

Thanks for the work. It's a good ground we can use to reason about the feature. The logic seems to be fine overall, beside a few optimization. However there are important design decision we need to take to make it more performant and reliable. See each comment and we can add more information in each thread.

Comment thread pkg/trait/ingress.go
// secret name. It may fall back to t.Host so that auto-discovery also works for the
// common single-host case, without changing the pre-existing manual TLS behavior
// (which requires TLSHosts to be set explicitly and never considers t.Host).
if secretName == "" {

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.

I think we miss a check on the auto parameter. If disabled on purpose, we should not proceed. Ideally the check has to be done in the Configure. And in fact, you can use in general the Configure func to compute any configuration that you will later use in Apply by storing private scoped variables.

Comment thread pkg/trait/ingress.go Outdated
Comment thread pkg/trait/ingress.go Outdated
Comment thread pkg/trait/ingress.go Outdated
Comment thread pkg/trait/ingress_test.go Outdated
Comment thread pkg/util/certmanager/enabled.go Outdated
Comment thread pkg/util/certmanager/enabled.go Outdated
…on of concerns clear among configure and apply
@github-actions

Copy link
Copy Markdown
Contributor

✔️ Unit test coverage report - coverage increased from 63.8% to 64% (+0.2%)

…nabled by default and added a function to disable it
…e test client, matching the Knative default, and exclude cert-manager duck types from the generic fake Kubernetes clientset (they are only ever accessed via the typed controller-runtime client).added types to prevent unstructured, ingress_test made it enabled by default and added a function to disable it
@Thundercloud12

Copy link
Copy Markdown
Contributor Author

@squakez thanks for the compehensive comment going carefully through this code, after your comments i decided that a seperation of concerns was a must thereby seperating into configure and apply as would be visible and seconly tookl up on your untyped fileds and followed the example elsewhere shown in this repo, thirdly the very last one i should say i have followed up on your advice, downside being cert-manager detection static for the operator's lifetime if someone installs cert-manager into a running cluster, the operator won't notice until it restarts.

@squakez

squakez commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

downside being cert-manager detection static for the operator's lifetime if someone installs cert-manager into a running cluster, the operator won't notice until it restarts.

This is certainly a side effect that we can document. We have a similar "problem" with Knative and it's documented as well.

@Thundercloud12

Copy link
Copy Markdown
Contributor Author

@squakez mirroring the knative's approach i have added the required docs

@squakez squakez 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.

Nice. Only a minor check on a potential bootstrap error, but the rest LGTM.

Comment thread pkg/cmd/operator/operator.go Outdated
@github-actions

Copy link
Copy Markdown
Contributor

✔️ Unit test coverage report - coverage increased from 63.8% to 63.9% (+0.1%)

…orced-issuer branch of resolveCertManagerIssuer() into its own resolveForcedCertManagerIssuer() method to bring nesting complexity under golangci-lint's nestif threshold, and switch to plain (unnamed) return values to satisfy nonamedreturns.
@github-actions

Copy link
Copy Markdown
Contributor

✔️ Unit test coverage report - coverage increased from 63.8% to 63.9% (+0.1%)

@Thundercloud12

Copy link
Copy Markdown
Contributor Author

@squakez i have also fixed the issue that were failing some checks

@squakez
squakez merged commit e6c5cc0 into apache:main Sep 18, 2026
14 checks passed
@Thundercloud12
Thundercloud12 deleted the feature/5857-cert-manager-auto-discovery branch September 18, 2026 07:16
@Thundercloud12
Thundercloud12 restored the feature/5857-cert-manager-auto-discovery branch September 18, 2026 07:16
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.

CertManager automatic discover

2 participants