Let's Encrypt DNS-01 (WIP)
If using a HTTP-challenge is not an option, it is possible to use DNS-challenges.
TL;DR
POST to https://acme-server.it.helsinki.fi/register from the internal network, create a DNS-record where the cname is the full domain + '.' from the HTTP-response and the name is _acme-challenge.domain (without .helsinki.fi). Then create a Secret in Kubernetes that has the information from the HTTP-response in json-form, then refer to that in your issuer.
Long form
This instruction will split off at the end, depending on if you want to do TLS-termination yourself or if the certificate is used by a OpenShift Route. But the start is the same for both
- Get credentials
- Create a DNS-entry
Outside Kubernetes
Credentials
The credentials can be self provisioned by posting to https://acme-server.it.helsinki.fi/register from the university's internal network.
#response edited for clarity, later referred to as "HTTP_RESPONSE"
{
"username":"0774057d-7a72-4f97-ba90-d54466c401de",
"password":"<redacted>",
"fulldomain":"50c47584-51b5-42bc-b33f-565421af03ad.acme.it.helsinki.fi",
"subdomain":"50c47584-51b5-42bc-b33f-565421af03ad",
"allowfrom":[]
}
DNS-entry
Create DNS entry, where the CNAME is the fulldomain from the earlier HTTP_RESPONSE and the FQDN is the name starting with _acme-challenge. It might take up to 15 minutes for the DNS-entry to populate to all servers.
dig +short @8.8.8.8 _acme-challenge.acme-dns.web.helsinki.fi
50c47584-51b5-42bc-b33f-565421af03ad.acme.it.helsinki.fi.
Kubernetes
- Create a file called acmedns.json from the contents of HTTP_RESPONSE
- Create a Secret from the acmedns.json file
- Create an Issuer that references the Secret
- Diverging paths:
- Ingress/Route
- (Create DNS-record for your FQDN)
- Create Ingress
- Handling TLS-termination
- (Create DNS-record for your FQDN)
- Create a Certificate
- Create a passthrough Route
- Mount the Secret that the Certificate creates in your Pod
- Ingress/Route
Creating the Secret
echo '{ "acme-dns.web.helsinki.fi": {HTTP_RESPONSE}' > acmedns.json
# Create a Secret from acmedns.json
oc create secret generic <secret-name> -n <namespace> --from-file=acmedns.json=acmedns.json
Create Issuer
The normal info about Issuer/Certificate/CertificateRequest objects apply, as seen here:
kind: Issuer
metadata:
name: letsencrypt-staging
namespace: <namespace>
spec:
acme:
email: <email>
privateKeySecretRef:
name: letsencrypt-staging-acme-key
server: https://acme-staging-v02.api.letsencrypt.org/directory
solvers:
- dns01:
acmeDNS:
accountSecretRef:
key: acmedns.json
name: <secret-name>
host: https://acme-server.it.helsinki.fi
Ingress/Route
Create an Ingress that mentions the Issuer
apiVersion: networking.k8s.io/v1
metadata:
name: acme-dns-web-helsinki-fi-staging
namespace: <namespace>
annotations:
cert-manager.io/issuer: letsencrypt-staging
spec:
ingressClassName: openshift-default
tls:
- hosts:
- <FQDN>
secretName: FQN-cert-staging #change periods "." into dashes "-"
rules:
- host: <FQDN>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: <service-name>
port:
number: <port>
After a while, you can check that the Certificate and CertificateRequest objects are fine, e.g. If you created a CNAME for your FQDN, you can also try accessing it using a browser. Note that sometimes clearing cookies or using incognito mode is required to see the new certificate in a browser.
NAME READY SECRET AGE
acme-dns-web-helsinki-fi-cert True acme-dns-web-helsinki-fi-cert 19m
oc get certificaterequest -n namespace
NAME APPROVED DENIED READY ISSUER REQUESTER AGE
acme-dns-web-helsinki-fi-cert-1 True True letsencrypt-staging system:serviceaccount:cert-manager:cert-manager 19m
Handling TLS-termination
If you want to create a passthrough type Route and need the TLS secret for your application, a Certificate object is required
kind: Certificate
metadata:
name: acme-dns-web-helsinki-fi-staging
namespace: <namespace>
spec:
dnsNames:
- acme-dns.web.helsinki.fi
issuerRef:
group: cert-manager.io
kind: Issuer
name: letsencrypt-staging
secretName: acme-dns-web-helsinki-fi-staging-cert
usages:
- digital signature
- key encipherment
You can then create a Passthrough Route and then have your Pod mount the Secret defined in spec.secretName.