Skip to content

Add Helm subchart for cert-manager to manage TLS certificates#325

Open
maneeshaxyz wants to merge 1 commit intoLSFLK:mainfrom
maneeshaxyz:322-task-create-helm-sub-chart-for-certificates
Open

Add Helm subchart for cert-manager to manage TLS certificates#325
maneeshaxyz wants to merge 1 commit intoLSFLK:mainfrom
maneeshaxyz:322-task-create-helm-sub-chart-for-certificates

Conversation

@maneeshaxyz
Copy link
Copy Markdown
Member

📌 Description

Implemented automated TLS certificate management with cert-manager and Let’s Encrypt in the existing Silver Helm deployment flow. Certificates are generated per configured domain, renewed automatically, and stored as Kubernetes Secrets for downstream services.


🔍 Changes Made

1. Certificate templating in Helm

  • Added dynamic Certificate rendering based on chart values.
  • Generates one Certificate per configured domain.
  • Includes both apex and wildcard SANs for each domain.
  • Supports configurable renewal window through values.

2. Issuer integration

  • Certificate resources reference a configurable ClusterIssuer.
  • Supports staging and production issuer usage through configuration.

3. ACME + DNS challenge bootstrap

  • Added cluster bootstrap automation to create:
  1. Cloudflare API token Secret (for DNS-01)
  2. Let’s Encrypt staging ClusterIssuer
  3. Let’s Encrypt production ClusterIssuer
  • ACME account keys are managed via cert-manager private key references.

4. Operational documentation

  • Documented cert-manager prerequisite installation.
  • Documented issuer bootstrap and validation steps.
  • Documented staging-to-production promotion guidance.
  • Documented certificate verification commands and expected readiness state.

Design Decisions

  • Implemented within the existing umbrella chart, not as a standalone tls-certificates subchart.
  • Issuer resources are provisioned through infrastructure bootstrap, not Helm templates.
  • DNS-01 flow currently targets Cloudflare bootstrap path.
  • Generic multi-provider DNS-01 and HTTP-01 solver templating are not yet fully chart-driven.

✅ Checklist (Email System)

  • Core services tested (SMTP, IMAP, mail storage, end-to-end delivery)
  • Security & compliance verified (auth via Thunder IDP, TLS, DKIM/SPF/DMARC, spam/virus filtering)
  • Configuration & deployment checked (configs generated, Docker/Compose updated)
  • Reliability confirmed (error handling, logging, monitoring)
  • Documentation & usage notes updated (README, deployment, API)

🧪 Testing Instructions

  1. Documented in README.md

@maneeshaxyz maneeshaxyz requested a review from Aravinda-HWK April 3, 2026 11:31
@maneeshaxyz
Copy link
Copy Markdown
Member Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements TLS support for Silver services via cert-manager and Let's Encrypt, adding a bootstrap script for Cloudflare DNS-01 challenges and updating Helm templates to manage Certificate resources. Review feedback suggests removing restrictive domain selectors in the ClusterIssuers to support multiple domains, utilizing the provided Helm helper for issuer references, and replacing a hardcoded sleep with a kubectl wait command for better reliability.

Comment on lines +66 to +74
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
selector:
dnsZones:
- "${DOMAIN}"
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.

high

The dnsZones selector restricts this ClusterIssuer to only the domain provided during the bootstrap process. This will prevent the issuer from working with any other domains added to the Helm chart later. Removing this selector allows the issuer to handle any domain authorized by the Cloudflare API token.

Suggested change
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
selector:
dnsZones:
- "${DOMAIN}"
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token

Comment on lines +90 to +98
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
selector:
dnsZones:
- "${DOMAIN}"
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.

high

Similar to the staging issuer, this dnsZones selector limits the production issuer to a single domain. Removing it provides better support for the multi-domain configuration allowed by the Helm chart.

Suggested change
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
selector:
dnsZones:
- "${DOMAIN}"
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token

Comment on lines +14 to +15
name: {{ $.Values.tls.issuer }}
kind: ClusterIssuer
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.

medium

The silver.issuerRef helper defined in _helpers.tpl should be used here to maintain consistency and reduce duplication.

{{- include "silver.issuerRef" $ | nindent 4 }}


# --- Verify -------------------------------------------------------------------
info "Waiting for ClusterIssuers to become ready (up to 60s)..."
sleep 5
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.

medium

Using a hardcoded sleep is unreliable. It is better to use kubectl wait to ensure the ClusterIssuer resources are actually ready before proceeding or finishing the script.

Suggested change
sleep 5
kubectl wait --for=condition=Ready clusterissuer/le-staging clusterissuer/le-prod --timeout=60s

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces TLS support for the Silver services using cert-manager and Let's Encrypt. Key additions include a bootstrap script for cluster infrastructure setup, comprehensive documentation in the README, and Helm templates for automated certificate generation. The review feedback suggests enhancing the bootstrap script's idempotency for namespace creation and improving the sanitization logic for Kubernetes resource names to handle a wider range of domain characters.

Comment on lines +41 to +42
kubectl get namespace cert-manager >/dev/null 2>&1 \
|| kubectl create namespace cert-manager
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.

medium

Using kubectl get namespace to check for existence is prone to race conditions. It is safer to use kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f - to ensure idempotency.

Suggested change
kubectl get namespace cert-manager >/dev/null 2>&1 \
|| kubectl create namespace cert-manager
kubectl create namespace cert-manager --dry-run=client -o yaml | kubectl apply -f -

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ . | replace "." "-" }}-tls
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.

medium

The replace function might produce invalid resource names if the domain contains characters other than dots or hyphens. Consider using a more robust sanitization method or ensuring the input is validated.

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.

[TASK] Create Helm Sub chart for Certificates

1 participant