Skip to content

Commit

Permalink
Refactor issuers configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Debakel Orakel committed Feb 6, 2025
1 parent 454ed90 commit af027cb
Show file tree
Hide file tree
Showing 17 changed files with 328 additions and 301 deletions.
4 changes: 0 additions & 4 deletions class/cert-manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ parameters:
- ${_base_directory}/component/main.jsonnet
input_type: jsonnet
output_path: cert-manager/
- input_paths:
- ${_base_directory}/component/issuers.jsonnet
input_type: jsonnet
output_path: cert-manager/
- input_paths:
- ${_base_directory}/component/helm/cert-manager.jsonnet
input_type: jsonnet
Expand Down
19 changes: 12 additions & 7 deletions class/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ parameters:
httpProxy: ''
httpsProxy: ''
noProxy: ''
email: test@syn.tools
certificateOwnerRef: false
recursiveNameservers: '1.1.1.1:53'
recursiveNameserversOnly: true
Expand All @@ -57,19 +58,23 @@ parameters:
secretKey: '?{vaultkv:${cluster:tenant}/${cluster:name}/exoscale/cert_webhook/s3_secret_key}'

acmeClients: {}
secrets: {}

letsencrypt_email: test@syn.tools
letsencrypt_clusterissuers:
staging: true
production: true
solvers:
nginx_http01:
http01:
ingress:
class: 'nginx'
cluster_issuers: {}

issuers: {}
clusterIssuers:
letsencrypt-staging:
solverRefs:
- nginx_http01
letsencrypt-production:
solverRefs:
- nginx_http01

alerts: {}
secrets: {}

resources:
cert_manager:
Expand Down
69 changes: 0 additions & 69 deletions component/issuers.jsonnet

This file was deleted.

124 changes: 124 additions & 0 deletions component/issuers.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// main template for certificates
local legacy = import 'legacy.libsonnet';
local cert = import 'lib/cert-manager.libsonnet';
local com = import 'lib/commodore.libjsonnet';
local kap = import 'lib/kapitan.libjsonnet';
local kube = import 'lib/kube.libjsonnet';
local inv = kap.inventory();

// The hiera parameters for the component
local params = inv.parameters.cert_manager;

// namespacedName decodes a namespaced name into a namespace and name
local namespacedName(string) = {
local namespaced = std.splitLimit(string, '/', 1),
namespace: if std.length(namespaced) > 1 then namespaced[0] else params.namespace,
name: if std.length(namespaced) > 1 then namespaced[1] else namespaced[0],
};

// Let's Encrypt convenience
local isLetsEncrypt(string) = std.member([ 'letsencrypt-staging', 'letsencrypt-production' ], string);
local letsEncryptServer(string) = if string == 'letsencrypt-staging' then 'https://acme-staging-v02.api.letsencrypt.org/directory'
else if string == 'letsencrypt-production' then 'https://acme-v02.api.letsencrypt.org/directory'
else '';

// Merge letsencrypt acme config if named letsencrypt
local patchLetsEncrypt(name) = {
[if isLetsEncrypt(name) then 'spec']: {
acme: {
email: legacy.email,
privateKeySecretRef: {
name: name,
},
server: letsEncryptServer(name),
},
},
};

// Merge solvers if solverRefs are defined
local patchSolverRefs(obj) = {
[if std.objectHas(obj, 'solverRefs') then 'spec']: {
acme: {
solvers: [
params.solvers[solver]
for solver in obj.solverRefs
if std.length(params.solvers[solver]) > 0
],
},
},
};

// Merge solvers if acmeClientRefs are defined
local patchAcmeClientRefs(obj) = {
[if std.objectHas(obj, 'acmeClientRefs') then 'spec']: {
acme: {
solvers: [
{
dns01: {
acmeDNS: {
accountSecretRef: {
key: 'acmedns.json',
name: '%s-client' % client,
},
host: params.acmeClients[client].api.endpoint,
},
},
[if std.objectHas(params.acmeClients[client], 'fqdns') then 'selector']: {
dnsNames: [
fqdn
for fqdn in params.acmeClients[client].fqdns
],
},
}
for client in obj.acmeClientRefs
if std.length(params.acmeClients[client]) > 0
],
},
},
};

// Merge keys metadata and spec if they exist
local patchSpec(obj) = {
[key]: obj[key]
for key in std.objectFields(obj)
if std.member([ 'metadata', 'spec' ], key)
};

// Consecutively apply patches to result of previous apply.
local process(obj, initManifest) = std.foldl(
// we use std.mergePatch here, because this way we don't need
// to make each patch object mergeable by suffixing all keys with a +.
function(manifest, patch) std.mergePatch(manifest, patch),
[
patchLetsEncrypt(initManifest.metadata.name),
patchAcmeClientRefs(obj),
patchSolverRefs(obj),
patchSpec(obj),
],
initManifest
);

local clusterIssuers = [
process(legacy.clusterIssuers[name], cert.clusterIssuer(name))
for name in std.objectFields(legacy.clusterIssuers)
if legacy.clusterIssuers[name] != null && std.length(legacy.clusterIssuers[name]) > 0
];

local issuers = [
process(
params.issuers[name],
cert.issuer(namespacedName(name).name) {
metadata+: {
namespace: namespacedName(name).namespace,
},
}
)
for name in std.objectFields(params.issuers)
if params.issuers[name] != null && std.length(params.issuers[name]) > 0
];

// Define outputs below
{
[if std.length(clusterIssuers) > 0 then '60_clusterissuer']: clusterIssuers,
[if std.length(issuers) > 0 then '60_issuer']: issuers,
}
5 changes: 5 additions & 0 deletions component/legacy.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ local params = inv.parameters.cert_manager;
fqdns: params.acme_dns_api.fqdns,
},
}) else {},

email: if std.objectHas(params, 'letsencrypt_email') then std.trace('Parameter `letsencrypt_email` is deprecated, please use `components.cert_manager.email`.', params.letsencrypt_email) else params.components.cert_manager.email,
clusterIssuers: params.clusterIssuers + com.makeMergeable(
if std.objectHas(params, 'cluster_issuers') then std.trace('Parameter `cluster_issuers` is deprecated, please use `clusterIssuers`,', params.cluster_issuers) else {},
),
}
1 change: 1 addition & 0 deletions component/main.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ local exoscaleSecret = kube.Secret('exoscale-secret') {
[if params.components.exoscale_webhook.enabled then '90_secrets_exoscale']: exoscaleSecret,
}
+ (import 'acme-dns.libsonnet')
+ (import 'issuers.libsonnet')
88 changes: 0 additions & 88 deletions component/upgrade.jsonnet

This file was deleted.

21 changes: 7 additions & 14 deletions docs/modules/ROOT/pages/how-tos/dns01.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,14 @@ This configuration creates a secret `acme-dns-client-name-client` with the acme-
----
parameters:
cert_manager:
solvers:
nginx_http01: null <1>
dns01:
acmeDNS:
host: https://acme-dns-api.example.com <2>
accountSecretRef: <3>
name: acme-dns-client-name-client <4>
key: acmedns.json
clusterIssuers:
letsencrypt-production:
~solverRefs: [] <1>
acmeClientRefs: <2>
- client-name
----
<1> Disable the default `nginx_http01` solver
<2> The HTTP API of the acme-dns instance.
This should match parameter `acme_dns_api.endpoint`.
<3> The account secret for the acme-dns instance.
Use the values shown here to use the client secret which is created by the configuration from the previous step.
<4> Generated name from the previous step
<2> Reference the acme-dns client from the previous step

. Compile and push the cluster catalog to apply your configuration.

Expand All @@ -73,7 +66,7 @@ Use the values shown here to use the client secret which is created by the confi
.Extract CNAME target from the acme-dns-client secret
[source,shell]
----
$ kubectl -n syn-cert-manager get secret acme-dns-client-name-client \
$ kubectl -n syn-cert-manager get secret client-name-client \
-ojsonpath='{.data.acmedns\.json}' | \
base64 -d | \
jq -r '[.[]][0].fulldomain'
Expand Down
Loading

0 comments on commit af027cb

Please sign in to comment.