Skip to content

Commit c51ee3d

Browse files
committed
Seemingly working delegated wildcard cert generation
1 parent e786f95 commit c51ee3d

File tree

4 files changed

+116
-52
lines changed

4 files changed

+116
-52
lines changed

.terraform.lock.hcl

Lines changed: 22 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

certificates.tf

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
1-
# Dummy cert (copying from fixed .it cert for now) to bootstrap
2-
# httptoolkit.tech and get the gateway running.
3-
resource "kubernetes_secret_v1" "cert_httptoolkit_tech_bootstrap" {
1+
resource "kubernetes_namespace_v1" "certificates" {
42
metadata {
5-
name = "cert-httptoolkit-tech"
6-
namespace = "gateway"
7-
}
8-
9-
type = "kubernetes.io/tls"
10-
11-
data = {
12-
"tls.crt" = var.httptoolk_it_tls_cert
13-
"tls.key" = var.httptoolk_it_tls_key
14-
}
15-
16-
lifecycle {
17-
ignore_changes = [data, metadata]
3+
name = "certificates"
184
}
195
}
206

@@ -24,7 +10,7 @@ resource "helm_release" "cert_manager" {
2410
repository = "oci://quay.io/jetstack/charts"
2511
chart = "cert-manager"
2612
version = "v1.19.2"
27-
namespace = "cert-manager"
13+
namespace = "certificates"
2814
create_namespace = true
2915
wait = true
3016

@@ -44,7 +30,8 @@ resource "kubectl_manifest" "letsencrypt_prod" {
4430
apiVersion = "cert-manager.io/v1"
4531
kind = "ClusterIssuer"
4632
metadata = {
47-
name = "letsencrypt-prod"
33+
name = "letsencrypt-prod"
34+
namespace = "certificates"
4835
}
4936
spec = {
5037
acme = {
@@ -55,36 +42,41 @@ resource "kubectl_manifest" "letsencrypt_prod" {
5542
}
5643
solvers = [
5744
{
58-
http01 = {
59-
gatewayHTTPRoute = {
60-
parentRefs = [
61-
{
62-
name = "primary-gateway"
63-
namespace = "gateway"
64-
kind = "Gateway"
65-
},
66-
{
67-
name = "secondary-gateway"
68-
namespace = "gateway"
69-
kind = "Gateway"
70-
}
71-
]
45+
# All ACME is delegated via CNAMEs to acme-dns.httptoolkit.tech:
46+
dns01 = {
47+
cnameStrategy = "Follow"
48+
webhook = {
49+
groupName = "acme.scaleway.com"
50+
solverName = "scaleway"
51+
config = {
52+
zone = "acme-dns.httptoolkit.tech"
53+
projectId = var.project_id
54+
}
7255
}
7356
}
57+
selector = {
58+
dnsNames = [
59+
"httptoolkit.tech",
60+
"*.httptoolkit.tech"
61+
]
62+
}
7463
}
7564
]
7665
}
7766
}
7867
})
7968

80-
depends_on = [helm_release.cert_manager]
69+
depends_on = [
70+
helm_release.cert_manager,
71+
helm_release.cert_manager_scaleway_webhook
72+
]
8173
}
8274

83-
# Set up our two certificates
75+
# Manually set up the TLS cert for *.e.httptoolk.it, for now:
8476
resource "kubernetes_secret_v1" "cert_httptoolk_it" {
8577
metadata {
8678
name = "cert-httptoolk-it"
87-
namespace = "gateway"
79+
namespace = "certificates"
8880
}
8981

9082
type = "kubernetes.io/tls"
@@ -97,25 +89,68 @@ resource "kubernetes_secret_v1" "cert_httptoolk_it" {
9789
depends_on = [helm_release.envoy_gateway]
9890
}
9991

100-
resource "kubectl_manifest" "cert_httptoolkit_tech" {
92+
# We create a new app & API key for cert manager to automate our DNS:
93+
resource "scaleway_iam_application" "acme_dns_bot" {
94+
name = "acme-dns-bot"
95+
description = "Automated bot for Cert Manager DNS challenges"
96+
}
97+
98+
resource "scaleway_iam_policy" "acme_dns_bot_policy" {
99+
name = "acme-dns-bot-policy"
100+
application_id = scaleway_iam_application.acme_dns_bot.id
101+
102+
rule {
103+
project_ids = [var.project_id]
104+
permission_set_names = ["DomainsDNSFullAccess"]
105+
}
106+
}
107+
108+
resource "scaleway_iam_api_key" "acme_dns_key" {
109+
application_id = scaleway_iam_application.acme_dns_bot.id
110+
description = "Key for Cert Manager ACME DNS challenges"
111+
}
112+
113+
resource "helm_release" "cert_manager_scaleway_webhook" {
114+
name = "scaleway-webhook"
115+
repository = "https://helm.scw.cloud"
116+
chart = "scaleway-certmanager-webhook"
117+
namespace = "certificates"
118+
119+
depends_on = [helm_release.cert_manager]
120+
121+
values = [
122+
yamlencode({
123+
certManager = {
124+
namespace = "certificates"
125+
serviceAccountName = "cert-manager"
126+
}
127+
128+
secret = {
129+
accessKey = scaleway_iam_api_key.acme_dns_key.access_key
130+
secretKey = scaleway_iam_api_key.acme_dns_key.secret_key
131+
}
132+
})
133+
]
134+
}
135+
136+
resource "kubectl_manifest" "cert_wildcard_httptoolkit_tech" {
101137
yaml_body = yamlencode({
102138
apiVersion = "cert-manager.io/v1"
103139
kind = "Certificate"
104140
metadata = {
105-
name = "cert-httptoolkit-tech"
106-
namespace = "gateway"
141+
name = "cert-wildcard-httptoolkit-tech"
142+
namespace = "certificates"
107143
}
108144
spec = {
109-
secretName = "cert-httptoolkit-tech"
145+
secretName = "cert-wildcard-httptoolkit-tech"
110146
issuerRef = {
111147
name = "letsencrypt-prod"
112148
kind = "ClusterIssuer"
113149
}
114150
commonName = "httptoolkit.tech"
115151
dnsNames = [
116152
"httptoolkit.tech",
117-
"public-endpoint.httptoolkit.tech",
118-
"accounts-api.httptoolkit.tech"
153+
"*.httptoolkit.tech"
119154
]
120155
}
121156
})

gateway.tf

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
resource "kubernetes_namespace_v1" "this" {
2-
metadata {
3-
name = "gateway"
4-
}
5-
}
6-
71
# Install the Gateway API CRDs (n.b. standard, not experimental)
82
data "http" "gateway_api_crds" {
93
url = "https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml"
@@ -22,6 +16,12 @@ resource "kubectl_manifest" "gateway_api_crds" {
2216
}
2317

2418
# Set up the gateways themselves:
19+
resource "kubernetes_namespace_v1" "gateway" {
20+
metadata {
21+
name = "gateway"
22+
}
23+
}
24+
2525
resource "helm_release" "envoy_gateway" {
2626
name = "envoy-gateway"
2727
repository = "oci://docker.io/envoyproxy"
@@ -74,7 +74,7 @@ locals {
7474
}
7575
tls = {
7676
mode = "Terminate"
77-
certificateRefs = [{ kind = "Secret", name = "cert-httptoolk-it" }]
77+
certificateRefs = [{ kind = "Secret", namespace = "certificates", name = "cert-httptoolk-it" }]
7878
}
7979
},
8080
// TLS termination but then raw TCP passthrough for the endpoint admin:
@@ -86,7 +86,7 @@ locals {
8686
allowedRoutes = { namespaces = { from = "All" } }
8787
tls = {
8888
mode = "Terminate"
89-
certificateRefs = [{ kind = "Secret", name = "cert-httptoolkit-tech" }]
89+
certificateRefs = [{ kind = "Secret", namespace = "certificates", name = "cert-wildcard-httptoolkit-tech" }]
9090
}
9191
},
9292
// Normal HTTPS for all other httptoolkit.tech sites:
@@ -98,7 +98,7 @@ locals {
9898
allowedRoutes = { namespaces = { from = "All" } }
9999
tls = {
100100
mode = "Terminate"
101-
certificateRefs = [{ kind = "Secret", name = "cert-httptoolkit-tech" }]
101+
certificateRefs = [{ kind = "Secret", namespace = "certificates", name = "cert-wildcard-httptoolkit-tech" }]
102102
}
103103
}
104104
]

providers.tf

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ terraform {
1919
}
2020
kubectl = {
2121
source = "gavinbunney/kubectl"
22-
version = ">= 1.19.0"
22+
version = "~> 1.19"
23+
}
24+
acme = {
25+
source = "vancluever/acme"
26+
version = "~> 2.40"
2327
}
2428
}
2529
}
@@ -51,4 +55,8 @@ provider "kubectl" {
5155
token = scaleway_k8s_cluster.main.kubeconfig[0].token
5256
cluster_ca_certificate = base64decode(scaleway_k8s_cluster.main.kubeconfig[0].cluster_ca_certificate)
5357
load_config_file = false
58+
}
59+
60+
provider "acme" {
61+
server_url = "https://acme-v02.api.letsencrypt.org/directory"
5462
}

0 commit comments

Comments
 (0)