Skip to content

feat(cloudflare-tunnel): add optional cloudflared connector module - #92

Merged
chrisleekr merged 1 commit into
mainfrom
feat/cloudflare-tunnel
Jul 1, 2026
Merged

chrisleekr merged 1 commit into
mainfrom
feat/cloudflare-tunnel

Conversation

@chrisleekr

@chrisleekr chrisleekr commented Jul 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

Adds an optional Terraform module that deploys a remotely-managed Cloudflare Tunnel connector (cloudflared), letting services be exposed through Cloudflare without opening inbound ports or relying on public IP/CGNAT traversal. Also fixes a stale bitnami-labs GitHub org reference in the sealed-secrets module that now 404s.

flowchart LR
  CFE["Cloudflare Edge"]:::ext
  CFT["module cloudflare_tunnel<br/>cloudflared replicas<br/>count = cloudflare_tunnel_enable"]:::new
  NGX["module nginx<br/>ingress-nginx"]:::keep
  SVC["In-cluster services"]:::keep

  CFE -- "outbound tunnel<br/>token auth" --> CFT
  CFT -- "depends_on" --> NGX
  NGX --> SVC

  classDef keep fill:#2c3e50,color:#ffffff
  classDef new fill:#27ae60,color:#ffffff
  classDef ext fill:#ecf0f1,color:#2c3e50
Loading

What changed

New: stage2/cloudflare-tunnel/ module

  • main.tf: creates a cloudflare-tunnel namespace and a helm_release for chart cloudflare-tunnel-remote from https://cloudflare.github.io/helm-charts. Tunnel token passed via set_sensitive; replica count and optional image.tag via set.
  • provider.tf: requires hashicorp/kubernetes ~> 3.0 and hashicorp/helm ~> 3.1, Terraform >= 1.5.0.
  • variables.tf: cloudflare_tunnel_token (sensitive, no default), cloudflare_tunnel_chart_version, cloudflare_tunnel_image_tag (default "" = chart default), cloudflare_tunnel_replica_count (default 2, HA-only, not meant to autoscale).
  • README.md: module docs (scope, requirements, how to obtain the tunnel token).
  • Scope is intentionally narrow: this module only runs the connector. Tunnel definition, public hostnames, DNS records, and Cloudflare Access policies stay in the Cloudflare dashboard (remote-managed connector model), so Terraform only ever holds the token, never routing config.

Wiring

  • stage2/main.tf: new module "cloudflare_tunnel" gated by count = var.cloudflare_tunnel_enable ? 1 : 0, with depends_on = [module.nginx] (tunnel's catch-all hostname points at the ingress-nginx service).
  • stage2/variables.tf: root-level cloudflare_tunnel_enable (default false), cloudflare_tunnel_token, cloudflare_tunnel_chart_version (default "0.1.2"), cloudflare_tunnel_image_tag, cloudflare_tunnel_replica_count (default 2).
  • .env.sample: documents the new TF_VAR_cloudflare_tunnel_* variables and how to get a tunnel token from the Cloudflare Zero Trust dashboard.
  • .vscode/settings.json: added cloudflared to the spellcheck word list.
  • README.md: added module table row and optional-module toggle row.

Fix: stage2/bitnami-sealed-secrets/

  • GitHub renamed the org from bitnami-labs to bitnami; the old Helm repo https://bitnami-labs.github.io/sealed-secrets now 404s.
  • Updated the Helm repository URL in sealed-secrets.tf to https://bitnami.github.io/sealed-secrets.
  • Updated all bitnami-labs/sealed-secrets GitHub links in README.md and the values template comment in sealed-secrets-values.tftpl to bitnami/sealed-secrets.
  • No chart/app version change (still 2.18.1 / 0.35.0).

How to enable

  1. Create a tunnel in the Cloudflare dashboard: Zero Trust > Networks > Tunnels > Create a tunnel > cloudflared, and copy the token shown on the install step (the eyJ... value after --token).
  2. Set in .env:
    TF_VAR_cloudflare_tunnel_enable=true
    TF_VAR_cloudflare_tunnel_token=<token>
    TF_VAR_cloudflare_tunnel_chart_version=0.1.2
    
  3. Point the tunnel's public hostname(s) at the ingress-nginx service (https://nginx-ingress-nginx-controller.nginx.svc:443, No TLS Verify) in the Cloudflare dashboard; ingress-nginx continues to route by Host header as usual.
  4. Apply stage2.

Summary by CodeRabbit

  • New Features

    • Added optional Cloudflare Tunnel support for exposing cluster services.
    • New configuration options let you enable the tunnel, provide a token, pin versions, and set replica count.
  • Documentation

    • Updated setup docs to include Cloudflare Tunnel and refreshed Bitnami Sealed Secrets references.
  • Bug Fixes

    • Updated pinned tool and provider versions for more consistent builds.
    • Refined vulnerability ignore entries to match the current approved set.

@chrisleekr chrisleekr self-assigned this Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new Terraform module for deploying a Cloudflare Tunnel connector to Kubernetes, wires it into the stage2 configuration with new variables and README documentation, and includes unrelated maintenance changes: bitnami-labs to bitnami URL updates, Dockerfile version bumps, and a refreshed trivy ignore list.

Changes

Cloudflare Tunnel Module

Layer / File(s) Summary
Module variables and provider constraints
stage2/cloudflare-tunnel/variables.tf, stage2/cloudflare-tunnel/provider.tf, stage2/cloudflare-tunnel/.terraform.lock.hcl
Defines token, chart version, image tag, and replica count variables; declares Terraform/provider version constraints for kubernetes and helm; adds the lockfile pinning provider versions.
Namespace and Helm release implementation
stage2/cloudflare-tunnel/main.tf
Creates the cloudflare-tunnel namespace and deploys the cloudflare-tunnel-remote Helm chart with sensitive token, replica count, and conditional image tag settings.
Stage2 module wiring and variables
stage2/main.tf, stage2/variables.tf
Adds a conditionally-created cloudflare_tunnel module depending on nginx, and defines stage2-level variables for enable flag, token, chart version, image tag, and replica count.
Cloudflare Tunnel documentation and env sample
stage2/cloudflare-tunnel/README.md, README.md, .env.sample, .vscode/settings.json
Adds the module README, updates top-level module tables, adds env sample configuration, and adds "cloudflared" to the spell-check dictionary.

Unrelated maintenance updates

Layer / File(s) Summary
Bitnami Sealed Secrets URL updates
stage2/bitnami-sealed-secrets/README.md, stage2/bitnami-sealed-secrets/sealed-secrets.tf, stage2/bitnami-sealed-secrets/templates/sealed-secrets-values.tftpl
Switches documentation, Helm repository, and template comment URLs from bitnami-labs to bitnami.
Dockerfile tool version pins
Dockerfile
Bumps kubectl, helm, terraform, and trivy version pins, and passes TFLINT_VERSION explicitly to the tflint install script.
Trivy ignore list refresh
.trivyignore.yaml
Replaces the vulnerabilities ignore list with a narrower dependency-specific HIGH/CRITICAL set with updated expiration date.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Terraform
  participant Kubernetes
  participant HelmRelease as cloudflare-tunnel-remote

  Terraform->>Kubernetes: create namespace cloudflare-tunnel
  Terraform->>HelmRelease: install chart with set_sensitive tunnel_token
  Terraform->>HelmRelease: set replica_count
  Terraform->>HelmRelease: conditionally set image.tag
  HelmRelease->>Kubernetes: deploy connector pods
Loading

Related Issues: None specified in the provided information.

Related PRs: None specified in the provided information.

Suggested labels: terraform, documentation, dependencies

Suggested reviewers: chrisleekr

🐰 A tunnel dug beneath the net,
Cloudflare's path now safely set,
Labs became bitnami's name,
Versions bumped, ignores tamed,
Carrots pinned, the burrow's set! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an optional Cloudflare Tunnel/cloudflared connector module.
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.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@chrisleekr
chrisleekr merged commit b73d819 into main Jul 1, 2026
6 of 7 checks passed
@chrisleekr
chrisleekr deleted the feat/cloudflare-tunnel branch July 1, 2026 14:51

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

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 @.trivyignore.yaml:
- Around line 4-73: The ignores in .trivyignore.yaml are currently image-wide,
but this set should be narrowed to the affected artifacts only. Update each
vulnerability entry to use the supported paths and/or purls fields so the CVEs
are scoped to the specific binaries/packages mentioned in the existing
statements (kubectl, go-task, terraform, tflint, and rekor) instead of applying
globally. Keep the same CVE ids and expiry data, but attach the ignore rules to
the matching artifact identifiers so unrelated future occurrences are still
reported.

In `@stage2/cloudflare-tunnel/main.tf`:
- Around line 27-59: The cloudflare_tunnel helm_release allows an empty
cloudflare_tunnel_token, which can let deployment succeed while the tunnel later
crash-loops. Add a lifecycle.precondition on the helm_release
"cloudflare_tunnel" resource that checks var.cloudflare_tunnel_token is
non-empty when the module is enabled, and surface a clear error message so
Terraform fails fast before applying. Use the existing cloudflare_tunnel_token
input and cloudflare_tunnel resource to keep the guard self-contained.

In `@stage2/cloudflare-tunnel/variables.tf`:
- Around line 18-22: Add validation to the cloudflare_tunnel_replica_count
variable so it cannot be set to 0, since that value would disable the tunnel
connector. Update the variable block in variables.tf to enforce a minimum of 1,
and keep the constraint aligned with how cloudflare_tunnel_replica_count is
passed through stage2/cloudflare-tunnel/main.tf into the Helm chart
replicaCount.

In `@stage2/variables.tf`:
- Around line 802-831: Add validation blocks to the new Cloudflare Tunnel
variables in variables.tf to match the stage2 variable guidelines. Update each
of cloudflare_tunnel_enable, cloudflare_tunnel_token,
cloudflare_tunnel_chart_version, cloudflare_tunnel_image_tag, and
cloudflare_tunnel_replica_count with appropriate validation, and make sure
cloudflare_tunnel_chart_version rejects empty strings while
cloudflare_tunnel_replica_count requires a value of at least 1. Keep the checks
close to the variable definitions so they’re easy to find and maintain.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b7c4b811-c695-4c43-91ac-d7dfba00bb07

📥 Commits

Reviewing files that changed from the base of the PR and between 9ebeada and dbd099c.

📒 Files selected for processing (15)
  • .env.sample
  • .trivyignore.yaml
  • .vscode/settings.json
  • Dockerfile
  • README.md
  • stage2/bitnami-sealed-secrets/README.md
  • stage2/bitnami-sealed-secrets/sealed-secrets.tf
  • stage2/bitnami-sealed-secrets/templates/sealed-secrets-values.tftpl
  • stage2/cloudflare-tunnel/.terraform.lock.hcl
  • stage2/cloudflare-tunnel/README.md
  • stage2/cloudflare-tunnel/main.tf
  • stage2/cloudflare-tunnel/provider.tf
  • stage2/cloudflare-tunnel/variables.tf
  • stage2/main.tf
  • stage2/variables.tf

Comment thread .trivyignore.yaml
Comment on lines +4 to +73
#
# Every vulnerability below is a HIGH CVE in a Go dependency vendored by an upstream CLI
# tool (kubectl, go-task, terraform, tflint). All four tools are already pinned to their
# latest stable release in the Dockerfile, so these can only clear when the upstream
# project rebuilds with the fixed dependency. Verified against a local image scan on
# 2026-07-02 (trivy 0.72.0): this is the complete HIGH/CRITICAL set, nothing else remains.
# Re-evaluate on expired_at and drop each entry once its tool ships a fixed release.

vulnerabilities:
# Go stdlib vulnerabilities in upstream tools (helm, kubectl, terraform, tflint, trivy)
# These require upstream maintainers to rebuild with Go 1.24.12+ or 1.25.6+
- id: CVE-2025-61726
statement: Go stdlib net/url - no limit on query parameters - waiting for upstream rebuild
- id: CVE-2025-61728
statement: Go stdlib archive/zip - excessive CPU consumption - waiting for upstream rebuild
- id: CVE-2025-61729
statement: Go stdlib crypto/x509 in tflint - waiting for upstream fix
- id: CVE-2025-66564
statement: sigstore/timestamp-authority in tflint/trivy - waiting for upstream fix
- id: CVE-2026-25679
statement: net/url Incorrect parsing of IPv6 host
- id: CVE-2025-15558
statement: docker/cli Docker CLI for Windows Privilege malicious plugin binaries
- id: CVE-2026-33186
statement: gRPC-Go has an authorization bypass via missing slash in path
- id: CVE-2026-24051
statement: OpenTelemetry Go SDK Vulnerable to Arbitrary via PATH Hijacking
- id: CVE-2026-32280
statement: Go has Denial of Service vulnerability in certificate chain building
- id: CVE-2026-32281
statement: Go has Denial of Service vulnerability via inefficient certificate chain validation
- id: CVE-2026-32283
statement: Go has Denial of Service vulnerability via multiple TLS 1.3 key
# Go stdlib crypto/tls vulnerabilities in all upstream Go binaries
# (helm, kubectl, terraform, task, tflint, trivy)
# NVD CVSS 10.0 (CRITICAL), CISA-ADP 4.8 (MEDIUM) — risk mitigated: CI container not exposed to untrusted TLS
# Requires Go >= 1.25.7 - no upstream tool has been rebuilt yet as of 2026-02-20
# Reference: https://security.snyk.io/vuln/SNYK-GOLANG-STDCRYPTOTLS-15238826
# TODO(CVE-2025-68121): Remove once upstream tools (helm, kubectl, terraform, tflint, trivy) rebuild with Go >= 1.25.7
- id: CVE-2025-68121
statement: Go stdlib crypto/tls session resumption - waiting for upstream rebuild with Go 1.25.7+
# NVD CVSS pending, Ubuntu rates MEDIUM — Requires Go >= 1.25.6
# Fixed in trivy v0.69.1, other tools still pending upstream rebuild
# Reference: https://avd.aquasec.com/nvd/cve-2025-61730
# TODO(CVE-2025-61730): Remove once upstream tools (helm, kubectl, terraform, tflint) rebuild with Go >= 1.25.6
- id: CVE-2025-61730
statement: Go stdlib crypto/tls TLS 1.3 handshake - waiting for upstream rebuild with Go 1.25.6+
# Alpine transitive dependencies - waiting for base image updates
- id: CVE-2026-22695
statement: libpng transitive dependency via graphviz
- id: CVE-2026-22801
statement: libpng transitive dependency via graphviz
# Go stdlib vulnerabilities affecting kubectl/task/terraform/trivy binaries
# Fix landed in Go 1.25.10 / 1.26.3; kubectl 1.36.1 ships Go 1.26.2, task 3.51.1
# and terraform 1.15.4 still on older Go. trivy 0.70.0 is latest but pre-Go-1.26.3.
# Re-evaluate after upstream rebuilds (~30 days).
# TODO: Remove once kubectl >= 1.36.2 and trivy >= 0.71.0 (or equivalent rebuilds) land.
- id: CVE-2026-33811
statement: Go stdlib LookupCNAME cgo DNS resolver - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
# golang.org/x/net HIGH CVEs vendored by kubectl 1.36.2 (x/net v0.49.0) and
# go-task 3.51.1 (x/net v0.54.0). Fixed in x/net 0.53.0-0.55.0.
# Unblocks when kubectl and go-task rebuild with x/net >= 0.55.0.
- id: CVE-2026-25681
statement: golang.org/x/net/html arbitrary code execution via XSS (kubectl/task) - waiting for upstream rebuild with x/net >= 0.55.0
expired_at: 2026-08-15
- id: CVE-2026-27136
statement: golang.org/x/net/html Render XSS (kubectl/task) - waiting for upstream rebuild with x/net >= 0.55.0
expired_at: 2026-08-15
- id: CVE-2026-33814
statement: Go stdlib HTTP/2 SETTINGS frames infinite loop - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-39820
statement: Go stdlib net/mail ParseAddress malformed input - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-39836
statement: Go stdlib net.Dial/LookupPort NUL byte panic (Windows-only, low risk on Alpine) - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-42499
statement: Go stdlib net/mail consumePhrase DoS - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-39823
statement: Go stdlib net/url parsing in kubectl/trivy - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-39825
statement: Go stdlib net/http/httputil ReverseProxy query forwarding in kubectl/trivy - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
- id: CVE-2026-39826
statement: Go stdlib html/template script tag escaping in kubectl/trivy - waiting for upstream rebuild with Go 1.25.10+/1.26.3+
expired_at: 2026-06-22
# Trivy 0.70.0 transitive dependencies - fixed upstream, awaiting next Trivy release
- id: CVE-2026-46680
statement: containerd user ID handling bypass in trivy v0.70.0 (vendored v1.7.30/v2.2.2) - fixed in containerd 1.7.32/2.2.4, awaiting trivy rebuild
expired_at: 2026-06-22
- id: CVE-2026-45022
statement: go-git parsing flaw in trivy v0.70.0 (vendored v5.17.2) - fixed in go-git 5.19.0, awaiting trivy rebuild
expired_at: 2026-06-22
- id: CVE-2026-44973
statement: go-billy path traversal in trivy v0.70.0 (vendored v5.8.0) - fixed in go-billy 5.9.0, awaiting trivy rebuild
expired_at: 2026-06-22
statement: golang.org/x/net HTTP/2 SETTINGS_MAX_FRAME_SIZE DoS (kubectl) - waiting for upstream rebuild with x/net >= 0.53.0
expired_at: 2026-08-15
- id: CVE-2026-39821
statement: golang.org/x/net/idna privilege escalation via Punycode label processing (kubectl/task) - waiting for upstream rebuild with x/net >= 0.55.0
expired_at: 2026-08-15
- id: CVE-2026-42502
statement: golang.org/x/net/html Render XSS (kubectl/task) - waiting for upstream rebuild with x/net >= 0.55.0
expired_at: 2026-08-15

# golang.org/x/crypto SSH HIGH CVEs vendored by go-task 3.51.1 (x/crypto v0.51.0).
# Fixed in x/crypto 0.52.0. go-task main already bumped to 0.53.0; unblocks on next task release.
- id: CVE-2026-39827
statement: golang.org/x/crypto/ssh DoS via repeatedly opened channels (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-39828
statement: golang.org/x/crypto/ssh HIGH (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-39829
statement: golang.org/x/crypto/ssh HIGH (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-39830
statement: golang.org/x/crypto/ssh DoS via resource leak from unsolicited SSH responses (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-39832
statement: golang.org/x/crypto/ssh/agent security bypass via improper key restriction handling (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-39835
statement: golang.org/x/crypto/ssh DoS via crafted SSH certificate (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-42508
statement: golang.org/x/crypto/ssh/knownhosts revocation bypass via unchecked SignatureKey (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-46595
statement: golang.org/x/crypto/ssh authorization bypass via skipped source-address validation (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15
- id: CVE-2026-46597
statement: golang.org/x/crypto/ssh server-side panic via incorrectly placed bytes-to-int cast (task) - waiting for upstream rebuild with x/crypto >= 0.52.0
expired_at: 2026-08-15

# Go stdlib crypto/x509 DoS. Fixed in Go 1.25.11 / 1.26.4. Present in terraform 1.15.7
# (Go 1.25.10), go-task 3.51.1 (Go 1.26.3), tflint 0.63.1 (Go 1.26.3).
# Unblocks when each tool rebuilds with Go >= 1.25.11 / 1.26.4.
- id: CVE-2026-27145
statement: Go stdlib crypto/x509 DoS via excessive DNS name constraint processing (terraform/task/tflint) - waiting for upstream rebuild with Go >= 1.25.11/1.26.4
expired_at: 2026-08-15

# github.com/sigstore/rekor OOM via unbounded gzip, vendored by tflint 0.63.1 (rekor v1.5.0).
# Fixed in rekor 1.5.2. Unblocks on next tflint release bumping rekor.
- id: CVE-2026-48702
statement: github.com/sigstore/rekor OOM via unbounded gzip (tflint) - waiting for upstream rebuild with rekor >= 1.5.2
expired_at: 2026-08-15

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Spot-check a sample of the listed CVE IDs against NVD/GHSA advisories
for id in CVE-2026-25681 CVE-2026-39827 CVE-2026-27145 CVE-2026-48702; do
  echo "== $id =="
  curl -s "https://api.osv.dev/v1/vulns/$id" | jq '.summary, .affected[].ranges'
done

Repository: chrisleekr/homelab-infrastructure

Length of output: 507


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== trivy ignore references =="
git ls-files | rg '(^|/)(\.trivyignore\.ya?ml|container-security\.yml|trivy|security)' || true

echo
echo "== .trivyignore.yaml =="
if git ls-files --error-unmatch .trivyignore.yaml >/dev/null 2>&1; then
  cat -n .trivyignore.yaml
fi

echo
echo "== CI workflow / job references =="
rg -n --hidden --no-ignore-vcs 'trivy image|--ignorefile|--exit-code 1|--format sarif|\.trivyignore\.ya?ml' .github . 2>/dev/null || true

echo
echo "== trivyignore docs / examples in repo =="
rg -n --hidden --no-ignore-vcs 'paths:|pkgs:|statement:|expired_at:|trivyignore' . 2>/dev/null || true

Repository: chrisleekr/homelab-infrastructure

Length of output: 13579


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== trivy ignore schema references =="
rg -n --hidden --no-ignore-vcs 'paths:|pkgs:|vulnerabilities:|misconfigurations:|statement:|expired_at:' . \
  --glob '*.yml' --glob '*.yaml' --glob '*.md' 2>/dev/null || true

echo
echo "== artifact version pins =="
rg -n --hidden --no-ignore-vcs 'kubectl|go-task|terraform|tflint|FROM .*?(kubectl|task|terraform|tflint)|version:' . \
  --glob 'Dockerfile*' --glob '*.yml' --glob '*.yaml' --glob 'Taskfile.yml' --glob '.github/workflows/*.yml' \
  --glob '.gitlab-ci.yml' 2>/dev/null || true

echo
echo "== trivy docs in repo =="
sed -n '1,140p' .pre-commit-config.yaml 2>/dev/null || true

Repository: chrisleekr/homelab-infrastructure

Length of output: 31286


🌐 Web query:

Trivy .trivyignore.yaml vulnerability ignore schema paths pkgs package scoping documentation

💡 Result:

The.trivyignore.yaml file is a configuration file used by Trivy to filter out specific findings (vulnerabilities, misconfigurations, secrets, and licenses) from scan reports [1][2]. Structure and Schema While there is no single official JSON schema document published for.trivyignore.yaml, its structure is defined by the Trivy configuration loader [3][4]. The file is structured by finding type, with each category containing a list of objects specifying filters [1][2]. Common fields for entries include [1][2]: - id: The identifier of the vulnerability, misconfiguration, secret, or license. - paths: A list of file paths (as strings) to which the ignore rule should be applied. If omitted, the rule applies to all files. - purls: A list of Package URLs (PURLs) to ignore. This field is specifically available for vulnerabilities. - expired_at: A date (yyyy-mm-dd) after which the ignore rule is no longer valid. - statement: A field used to record the reasoning for the ignore rule (not used for filtering). As of recent updates, the id field can be omitted in some contexts, allowing rules to be scoped purely by paths or purls [5]. Usage and Scoping - Usage: Because this feature is experimental, the.trivyignore.yaml file must be explicitly loaded using the --ignorefile flag (e.g., trivy repo --ignorefile.trivyignore.yaml.) [1][6]. - Path Scoping: The paths field is used to target specific files. For OS packages, note that this may not work as expected; for projects with dependency files (e.g., go.mod, yarn.lock), the path should point to the specific dependency file [2]. - Package Scoping: PURLs allow for precise scoping of vulnerabilities to specific packages (e.g., pkg:deb/debian/libssl1.1) [1][2]. Example Structure vulnerabilities: - id: CVE-2022-40897 paths: - "usr/local/lib/python3.9/site-packages/setuptools-58.1.0.dist-info/METADATA" statement: "Accept the risk" - id: CVE-2023-3817 purls: - "pkg:deb/debian/libssl1.1" misconfigurations: - id: AVD-DS-0001 paths: - "docs/Dockerfile"

Citations:


🌐 Web query:

CVE-2026-25681 CVE-2026-39827 CVE-2026-27145 CVE-2026-48702 advisory fixed versions x/net x/crypto Go rekor

💡 Result:

The vulnerabilities requested have the following fixed versions and details: CVE-2026-25681: Affects golang.org/x/net (specifically golang.org/x/net/html) [1]. It is fixed in version 0.55.0 [1]. The vulnerability involves improper handling of arbitrary HTML input leading to potential XSS [1]. CVE-2026-39827: Affects golang.org/x/crypto (specifically golang.org/x/crypto/ssh) [2]. It is fixed in version 0.52.0 [2]. The vulnerability involves unbounded memory growth in the SSH server when handling rejected channels [2]. CVE-2026-27145: Affects the Go standard library (crypto/x509) [3]. It is fixed in versions 1.25.11 and 1.26.4 [3]. The vulnerability is a performance issue in (*x509.Certificate).VerifyHostname causing quadratic scaling during DNS SAN verification [3]. CVE-2026-48702: Affects sigstore/rekor [4]. It is fixed in version 1.5.2 [4]. The vulnerability involves an out-of-memory (OOM) condition caused by unbounded gzip decompression when parsing Alpine APK files [4]. Summary of Fixed Versions: - golang.org/x/net: 0.55.0 [1] - golang.org/x/crypto: 0.52.0 [2] - Go standard library (crypto/x509): 1.25.11 or 1.26.4 [3] - sigstore/rekor: 1.5.2 [4]

Citations:


Scope the vulnerability ignores to specific artifacts .trivyignore.yaml supports paths and purls, so these CVEs can be narrowed to the affected binary/package instead of being ignored image-wide. That avoids hiding the same CVE ID if it shows up in a different component later.

🤖 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 @.trivyignore.yaml around lines 4 - 73, The ignores in .trivyignore.yaml are
currently image-wide, but this set should be narrowed to the affected artifacts
only. Update each vulnerability entry to use the supported paths and/or purls
fields so the CVEs are scoped to the specific binaries/packages mentioned in the
existing statements (kubectl, go-task, terraform, tflint, and rekor) instead of
applying globally. Keep the same CVE ids and expiry data, but attach the ignore
rules to the matching artifact identifiers so unrelated future occurrences are
still reported.

Comment on lines +27 to +59
resource "helm_release" "cloudflare_tunnel" {
depends_on = [kubernetes_namespace_v1.cloudflare_tunnel]

name = "cloudflare-tunnel"
repository = "https://cloudflare.github.io/helm-charts"
chart = "cloudflare-tunnel-remote"
version = var.cloudflare_tunnel_chart_version
namespace = kubernetes_namespace_v1.cloudflare_tunnel.metadata[0].name
timeout = 300
wait = true

set_sensitive = [
{
name = "cloudflare.tunnel_token"
value = var.cloudflare_tunnel_token
}
]

set = concat(
[
{
name = "replicaCount"
value = tostring(var.cloudflare_tunnel_replica_count)
}
],
var.cloudflare_tunnel_image_tag != "" ? [
{
name = "image.tag"
value = var.cloudflare_tunnel_image_tag
}
] : []
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Fail fast when the token is empty instead of deploying a broken tunnel.

var.cloudflare_tunnel_token defaults to "" in stage2/variables.tf with no cross-variable validation enforcing it when the module is enabled. If a user sets cloudflare_tunnel_enable = true without providing a token, this helm_release deploys successfully but cloudflared will crash-loop with an unclear error. A lifecycle.precondition here is a self-contained, version-agnostic guard (Terraform ≥1.2) that doesn't require cross-variable validation support.

🛡️ Proposed fix
 resource "helm_release" "cloudflare_tunnel" {
   depends_on = [kubernetes_namespace_v1.cloudflare_tunnel]
 
   name       = "cloudflare-tunnel"
   repository = "https://cloudflare.github.io/helm-charts"
   chart      = "cloudflare-tunnel-remote"
   version    = var.cloudflare_tunnel_chart_version
   namespace  = kubernetes_namespace_v1.cloudflare_tunnel.metadata[0].name
   timeout    = 300
   wait       = true
+
+  lifecycle {
+    precondition {
+      condition     = var.cloudflare_tunnel_token != ""
+      error_message = "cloudflare_tunnel_token must be set when the cloudflare-tunnel module is enabled."
+    }
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
resource "helm_release" "cloudflare_tunnel" {
depends_on = [kubernetes_namespace_v1.cloudflare_tunnel]
name = "cloudflare-tunnel"
repository = "https://cloudflare.github.io/helm-charts"
chart = "cloudflare-tunnel-remote"
version = var.cloudflare_tunnel_chart_version
namespace = kubernetes_namespace_v1.cloudflare_tunnel.metadata[0].name
timeout = 300
wait = true
set_sensitive = [
{
name = "cloudflare.tunnel_token"
value = var.cloudflare_tunnel_token
}
]
set = concat(
[
{
name = "replicaCount"
value = tostring(var.cloudflare_tunnel_replica_count)
}
],
var.cloudflare_tunnel_image_tag != "" ? [
{
name = "image.tag"
value = var.cloudflare_tunnel_image_tag
}
] : []
)
}
resource "helm_release" "cloudflare_tunnel" {
depends_on = [kubernetes_namespace_v1.cloudflare_tunnel]
name = "cloudflare-tunnel"
repository = "https://cloudflare.github.io/helm-charts"
chart = "cloudflare-tunnel-remote"
version = var.cloudflare_tunnel_chart_version
namespace = kubernetes_namespace_v1.cloudflare_tunnel.metadata[0].name
timeout = 300
wait = true
lifecycle {
precondition {
condition = var.cloudflare_tunnel_token != ""
error_message = "cloudflare_tunnel_token must be set when the cloudflare-tunnel module is enabled."
}
}
set_sensitive = [
{
name = "cloudflare.tunnel_token"
value = var.cloudflare_tunnel_token
}
]
set = concat(
[
{
name = "replicaCount"
value = tostring(var.cloudflare_tunnel_replica_count)
}
],
var.cloudflare_tunnel_image_tag != "" ? [
{
name = "image.tag"
value = var.cloudflare_tunnel_image_tag
}
] : []
)
}
🤖 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 `@stage2/cloudflare-tunnel/main.tf` around lines 27 - 59, The cloudflare_tunnel
helm_release allows an empty cloudflare_tunnel_token, which can let deployment
succeed while the tunnel later crash-loops. Add a lifecycle.precondition on the
helm_release "cloudflare_tunnel" resource that checks
var.cloudflare_tunnel_token is non-empty when the module is enabled, and surface
a clear error message so Terraform fails fast before applying. Use the existing
cloudflare_tunnel_token input and cloudflare_tunnel resource to keep the guard
self-contained.

Comment on lines +18 to +22
variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only, do NOT autoscale (downscaling breaks live connections)."
type = number
default = 2
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add validation to prevent replica_count of 0.

cloudflare_tunnel_replica_count feeds directly into the Helm chart's replicaCount (per stage2/cloudflare-tunnel/main.tf). A value of 0 would silently disable the tunnel connector, contradicting the "HA only" intent documented in the description.

♻️ Proposed validation
 variable "cloudflare_tunnel_replica_count" {
   description = "Number of cloudflared replicas. HA only, do NOT autoscale (downscaling breaks live connections)."
   type        = number
   default     = 2
+
+  validation {
+    condition     = var.cloudflare_tunnel_replica_count >= 1
+    error_message = "cloudflare_tunnel_replica_count must be at least 1."
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only, do NOT autoscale (downscaling breaks live connections)."
type = number
default = 2
}
variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only, do NOT autoscale (downscaling breaks live connections)."
type = number
default = 2
validation {
condition = var.cloudflare_tunnel_replica_count >= 1
error_message = "cloudflare_tunnel_replica_count must be at least 1."
}
}
🤖 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 `@stage2/cloudflare-tunnel/variables.tf` around lines 18 - 22, Add validation
to the cloudflare_tunnel_replica_count variable so it cannot be set to 0, since
that value would disable the tunnel connector. Update the variable block in
variables.tf to enforce a minimum of 1, and keep the constraint aligned with how
cloudflare_tunnel_replica_count is passed through
stage2/cloudflare-tunnel/main.tf into the Helm chart replicaCount.

Comment thread stage2/variables.tf
Comment on lines +802 to +831
variable "cloudflare_tunnel_enable" {
description = "Deploy the remotely-managed Cloudflare Tunnel connector (cloudflared) into the cluster."
type = bool
default = false
}

variable "cloudflare_tunnel_token" {
description = "Cloudflare Tunnel token (sensitive). Not self-generated; Cloudflare issues it per tunnel. Get it: dashboard > Zero Trust > Networks > Tunnels > Create a tunnel > cloudflared > name it > Save; on the install screen copy the value after --token (the eyJ... string)."
type = string
sensitive = true
default = ""
}

variable "cloudflare_tunnel_chart_version" {
description = "cloudflare-tunnel-remote Helm chart version. Pinned per repo convention. Reference: helm show chart cloudflare/cloudflare-tunnel-remote"
type = string
default = "0.1.2" # empty would resolve to latest chart and defeat pinning
}

variable "cloudflare_tunnel_image_tag" {
description = "cloudflared image tag to pin. Empty uses the chart default. Reference: https://github.com/cloudflare/cloudflared/releases"
type = string
default = ""
}

variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only; do not autoscale (downscaling breaks live connections)."
type = number
default = 2
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add validation blocks to the new variables.

None of the five new variables (cloudflare_tunnel_enable, cloudflare_tunnel_token, cloudflare_tunnel_chart_version, cloudflare_tunnel_image_tag, cloudflare_tunnel_replica_count) include a validation block. As per coding guidelines, stage2/variables.tf should "Include type, description, default, and validation when adding variables to stage2/variables.tf". At minimum, cloudflare_tunnel_chart_version should reject empty strings (an empty version defeats pinning, per its own description) and cloudflare_tunnel_replica_count should enforce >= 1.

♻️ Example validation additions
 variable "cloudflare_tunnel_chart_version" {
   description = "cloudflare-tunnel-remote Helm chart version. Pinned per repo convention. Reference: helm show chart cloudflare/cloudflare-tunnel-remote"
   type        = string
   default     = "0.1.2" # empty would resolve to latest chart and defeat pinning
+
+  validation {
+    condition     = length(trimspace(var.cloudflare_tunnel_chart_version)) > 0
+    error_message = "cloudflare_tunnel_chart_version must not be empty."
+  }
 }
 
 variable "cloudflare_tunnel_replica_count" {
   description = "Number of cloudflared replicas. HA only; do not autoscale (downscaling breaks live connections)."
   type        = number
   default     = 2
+
+  validation {
+    condition     = var.cloudflare_tunnel_replica_count >= 1
+    error_message = "cloudflare_tunnel_replica_count must be at least 1."
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
variable "cloudflare_tunnel_enable" {
description = "Deploy the remotely-managed Cloudflare Tunnel connector (cloudflared) into the cluster."
type = bool
default = false
}
variable "cloudflare_tunnel_token" {
description = "Cloudflare Tunnel token (sensitive). Not self-generated; Cloudflare issues it per tunnel. Get it: dashboard > Zero Trust > Networks > Tunnels > Create a tunnel > cloudflared > name it > Save; on the install screen copy the value after --token (the eyJ... string)."
type = string
sensitive = true
default = ""
}
variable "cloudflare_tunnel_chart_version" {
description = "cloudflare-tunnel-remote Helm chart version. Pinned per repo convention. Reference: helm show chart cloudflare/cloudflare-tunnel-remote"
type = string
default = "0.1.2" # empty would resolve to latest chart and defeat pinning
}
variable "cloudflare_tunnel_image_tag" {
description = "cloudflared image tag to pin. Empty uses the chart default. Reference: https://github.com/cloudflare/cloudflared/releases"
type = string
default = ""
}
variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only; do not autoscale (downscaling breaks live connections)."
type = number
default = 2
}
variable "cloudflare_tunnel_enable" {
description = "Deploy the remotely-managed Cloudflare Tunnel connector (cloudflared) into the cluster."
type = bool
default = false
}
variable "cloudflare_tunnel_token" {
description = "Cloudflare Tunnel token (sensitive). Not self-generated; Cloudflare issues it per tunnel. Get it: dashboard > Zero Trust > Networks > Tunnels > Create a tunnel > cloudflared > name it > Save; on the install screen copy the value after --token (the eyJ... string)."
type = string
sensitive = true
default = ""
}
variable "cloudflare_tunnel_chart_version" {
description = "cloudflare-tunnel-remote Helm chart version. Pinned per repo convention. Reference: helm show chart cloudflare/cloudflare-tunnel-remote"
type = string
default = "0.1.2" # empty would resolve to latest chart and defeat pinning
validation {
condition = length(trimspace(var.cloudflare_tunnel_chart_version)) > 0
error_message = "cloudflare_tunnel_chart_version must not be empty."
}
}
variable "cloudflare_tunnel_image_tag" {
description = "cloudflared image tag to pin. Empty uses the chart default. Reference: https://github.com/cloudflare/cloudflared/releases"
type = string
default = ""
}
variable "cloudflare_tunnel_replica_count" {
description = "Number of cloudflared replicas. HA only; do not autoscale (downscaling breaks live connections)."
type = number
default = 2
validation {
condition = var.cloudflare_tunnel_replica_count >= 1
error_message = "cloudflare_tunnel_replica_count must be at least 1."
}
}
🤖 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 `@stage2/variables.tf` around lines 802 - 831, Add validation blocks to the new
Cloudflare Tunnel variables in variables.tf to match the stage2 variable
guidelines. Update each of cloudflare_tunnel_enable, cloudflare_tunnel_token,
cloudflare_tunnel_chart_version, cloudflare_tunnel_image_tag, and
cloudflare_tunnel_replica_count with appropriate validation, and make sure
cloudflare_tunnel_chart_version rejects empty strings while
cloudflare_tunnel_replica_count requires a value of at least 1. Keep the checks
close to the variable definitions so they’re easy to find and maintain.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant