From bb02f48d9a9ed3548ae065ecffa3d9f34237c442 Mon Sep 17 00:00:00 2001 From: Shahab Dogar Date: Tue, 15 Jul 2025 09:45:47 +0500 Subject: [PATCH] feat: CDKTF | migrate cert manager to cdktf --- cert-manager/cert-manager.yaml | 52 ------------- cert-manager/index.ts | 133 +++++++++++++++++++++++++++++++++ helm/helmfile.yaml | 10 --- main.ts | 15 ++++ postgres/index.ts | 3 +- 5 files changed, 150 insertions(+), 63 deletions(-) delete mode 100644 cert-manager/cert-manager.yaml create mode 100644 cert-manager/index.ts diff --git a/cert-manager/cert-manager.yaml b/cert-manager/cert-manager.yaml deleted file mode 100644 index 58b34f0..0000000 --- a/cert-manager/cert-manager.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: ca-issuer - namespace: cert-manager -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: selfsigned-ca - namespace: cert-manager -spec: - isCA: true - commonName: "Shahab Dogar" - secretName: root-secret - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: ca-issuer - kind: ClusterIssuer - group: cert-manager.io ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: cluster-issuer - namespace: cert-manager -spec: - ca: - secretName: root-secret ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: cloudflare-issuer - namespace: cert-manager -spec: - acme: - email: shahab@dogar.dev - server: https://acme-v02.api.letsencrypt.org/directory - privateKeySecretRef: - name: cloudflare-cluster-issuer-account-key - solvers: - - dns01: - cloudflare: - apiTokenSecretRef: - name: cloudflare-token - key: credential diff --git a/cert-manager/index.ts b/cert-manager/index.ts new file mode 100644 index 0000000..9c16ffb --- /dev/null +++ b/cert-manager/index.ts @@ -0,0 +1,133 @@ +import * as fs from "fs"; +import { HelmProvider } from "@cdktf/provider-helm/lib/provider"; +import { Release } from "@cdktf/provider-helm/lib/release"; +import { Construct } from "constructs"; +import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider"; +import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest"; + +type CertManagerOptions = { + providers: { + kubernetes: KubernetesProvider; + helm: HelmProvider; + }; + version: string; + name: string; + namespace: string; + certManagerApiVersion: string; +}; + +export class CertManager extends Construct { + constructor(scope: Construct, id: string, options: CertManagerOptions) { + super(scope, id); + + const { helm, kubernetes } = options.providers; + const { certManagerApiVersion } = options; + + new Release(this, id, { + provider: helm, + name: options.name, + namespace: options.namespace, + version: options.version, + repository: "https://charts.jetstack.io", + chart: "cert-manager", + createNamespace: true, + values: [ + fs.readFileSync("helm/values/cert-manager.values.yaml", { + encoding: "utf8", + }), + ], + }); + + // Self-signed ClusterIssuer for initial CA + new Manifest(this, "ca-issuer", { + provider: kubernetes, + manifest: { + apiVersion: certManagerApiVersion, + kind: "ClusterIssuer", + metadata: { + name: "ca-issuer", + }, + spec: { + selfSigned: {}, + }, + }, + }); + + // Self-signed CA Certificate + new Manifest(this, "selfsigned-ca", { + provider: kubernetes, + manifest: { + apiVersion: certManagerApiVersion, + kind: "Certificate", + metadata: { + name: "selfsigned-ca", + namespace: options.namespace, + }, + spec: { + isCA: true, + commonName: "Shahab Dogar", + secretName: "root-secret", + privateKey: { + algorithm: "ECDSA", + size: 256, + }, + issuerRef: { + name: "ca-issuer", + kind: "ClusterIssuer", + group: "cert-manager.io", + }, + }, + }, + }); + + // CA-based ClusterIssuer + new Manifest(this, "cluster-issuer", { + provider: kubernetes, + manifest: { + apiVersion: certManagerApiVersion, + kind: "ClusterIssuer", + metadata: { + name: "cluster-issuer", + }, + spec: { + ca: { + secretName: "root-secret", + }, + }, + }, + }); + + // Cloudflare ACME ClusterIssuer + new Manifest(this, "cloudflare-issuer", { + provider: kubernetes, + manifest: { + apiVersion: certManagerApiVersion, + kind: "ClusterIssuer", + metadata: { + name: "cloudflare-issuer", + }, + spec: { + acme: { + email: "shahab@dogar.dev", + server: "https://acme-v02.api.letsencrypt.org/directory", + privateKeySecretRef: { + name: "cloudflare-cluster-issuer-account-key", + }, + solvers: [ + { + dns01: { + cloudflare: { + apiTokenSecretRef: { + name: "cloudflare-token", + key: "credential", + }, + }, + }, + }, + ], + }, + }, + }, + }); + } +} diff --git a/helm/helmfile.yaml b/helm/helmfile.yaml index 4be19b8..d30d425 100644 --- a/helm/helmfile.yaml +++ b/helm/helmfile.yaml @@ -7,8 +7,6 @@ repositories: url: https://kubernetes.github.io/ingress-nginx - name: bitnami url: https://charts.bitnami.com/bitnami - - name: jetstack - url: https://charts.jetstack.io - name: prometheus-community url: https://prometheus-community.github.io/helm-charts --- @@ -51,14 +49,6 @@ releases: values: - ./values/memcached.values.yaml - # Cert Manager - - name: cert-manager - namespace: cert-manager - chart: jetstack/cert-manager - version: 1.15.3 - values: - - ./values/cert-manager.values.yaml - # Prometheus Operator - name: prometheus-operator namespace: prometheus-system diff --git a/main.ts b/main.ts index 859e7ad..804b462 100644 --- a/main.ts +++ b/main.ts @@ -11,6 +11,7 @@ import { PostgresCluster } from "./postgres"; import { Longhorn } from "./longhorn"; import { AuthentikServer } from "./authentik"; import { RedisCluster } from "./redis"; +import { CertManager } from "./cert-manager"; dotenv.config(); @@ -35,6 +36,8 @@ class Homelab extends TerraformStack { }, }); + const certManagerApiVersion = "cert-manager.io/v1"; + new Longhorn(this, "longhorn", { namespace: "longhorn-system", name: "longhorn", @@ -45,7 +48,19 @@ class Homelab extends TerraformStack { }, }); + new CertManager(this, "cert-manager", { + certManagerApiVersion, + name: "cert-manager", + namespace: "cert-manager", + version: "1.15.3", + providers: { + kubernetes, + helm, + }, + }); + new PostgresCluster(this, "postgres-cluster", { + certManagerApiVersion, name: "postgres-cluster", namespace: "postgres-system", providers: { diff --git a/postgres/index.ts b/postgres/index.ts index ff54914..a0b9b19 100644 --- a/postgres/index.ts +++ b/postgres/index.ts @@ -15,6 +15,7 @@ type PostgresClusterOptions = { users: string[]; primaryUser: string; initSecretName: string; + certManagerApiVersion: string; }; export class PostgresCluster extends Construct { @@ -31,7 +32,7 @@ export class PostgresCluster extends Construct { namespace: options.namespace, }); - const certManagerApiVersion = "cert-manager.io/v1"; + const { certManagerApiVersion } = options; const certNames = { server: "postgres-server-cert",