Open depuits opened 1 year ago
There should be a way to just regenerate the existing certificate, instead of having to delete the certificate then re-create the certificate, and re-associate it to everything. Since I assume in the schema each certificate has a primary key that everything else just points to the PK, this would seem the easiest.
We have the same issue with our letsenrypt certificate. How can a renewal done automatically? Delete, recreate and the reassociate to all providers (we have quite a lot) cannot be the idea.
Just hit the same snag with our SAML providers, quite a lot of work to go throug everything and update a certificate. Seems like there should be a better way to do this automatically.
This also affects external certificates .
The certificate in my Kubernetes cluster was correctly updated by cert-manager and the new certificate files were mounted to authentik in the /certs folder. Authentik was still using the old (expired) certificate.
After I deleted the certificate in the authentik UI and restarted authentik, the certificate was re-imported again. So it seems that authentik does not check if the certificate has changed in the filesystem - it keeps using the old values until manually deleted.
There is a certificate discovery task under System Tasks that can be run, but best I can tell it's completely broken (at least for k8s setups) and the workaround is to use the import_certificate command.
import_certificate does work, but that means I've got to manually mount the files because Certificate secrets mounted are not named in a way that is compatible with Authentik and then I also have to have a cron running to keep them up to date within the container. Imagine a deployment at any kind of scale would be extremely hard to manage and the current state of this issue is creating a ton of unnecessary work for users.
@BeryJu Is there any plan to address this so that at least the certificate discovery task can function as intended? Even that would be a huge step forward from having to make a cron around import_certificate. This seems like a feature that should work out of the box
So the biggest problem here is that whilst you can overwrite the local /certs/domainname/ with the newer chains, the Import isn't setup to overwrite the current data in DB.
IE Below is a failure reported by the certificate_discovery task. It looks like the job should be changed to a IF EXISTS check before INSERT, otherwise UPDATE.
File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py", line 1067, in _save_table results = self._do_insert( ^^^^^^^^^^^^^^^^ File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py", line 1108, in _do_insert return manager._insert( ^^^^^^^^^^^^^^^^ File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/manager.py", line 87, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/ak-root/venv/lib/python3.12/site-packages/django_prometheus/db/common.py", line 69, in execute return super().execute(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/ak-root/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 732, in execute raise ex.with_traceback(None) django.db.utils.IntegrityError: duplicate key value violates unique constraint "authentik_crypto_certificatekeypair_name_719603a4_uniq" DETAIL: Key (name)=(DOMAIN.CO.UK) already exists.
@BeryJu Can this issue be changed to BUG tag?
It breaks automatic deployments, and induces unnecessary downtime having to rebuild the Providers using Certificates.
what is the current designed idea in how to renew this certificate?
as a quickfix: could we have the option for a longer valid self signed certificate until there is a better solution to rotate?
You could use the following doc until a renew option is available
renew_cert.py:
#!/usr/bin/env python3
#
# pip3 install -U --user --break-system-packages cryptography
#
import os
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from datetime import datetime, timedelta
def load_certificate(cert_path):
with open(cert_path, "rb") as cert_file:
cert_data = cert_file.read()
return x509.load_pem_x509_certificate(cert_data, default_backend())
def renew_certificate(cert, private_key, days=3650):
# Create a new certificate builder
builder = x509.CertificateBuilder()
# Copy attributes from the existing certificate
builder = builder.subject_name(cert.subject)
builder = builder.issuer_name(cert.issuer)
builder = builder.not_valid_before(cert.not_valid_before_utc)
builder = builder.not_valid_after(cert.not_valid_before_utc + timedelta(days=days))
builder = builder.serial_number(cert.serial_number)
builder = builder.public_key(cert.public_key())
# Add extensions
for ext in cert.extensions:
builder = builder.add_extension(ext.value, ext.critical)
# Sign the new certificate with the existing private key
new_cert = builder.sign(private_key, hashes.SHA256(), default_backend())
return new_cert
def save_certificate(cert, output_path):
with open(output_path, "wb") as cert_file:
cert_file.write(cert.public_bytes(encoding=serialization.Encoding.PEM))
def main():
cert_path = "authentik Self-signed Certificate_certificate.pem" # Path to your existing certificate
private_key_path = "authentik Self-signed Certificate_private_key.pem" # Path to your existing private key
output_cert_path = "authentik Self-signed Certificate_certificate_new.pem" # Path to save the new certificate
# Load existing certificate and private key
cert = load_certificate(cert_path)
with open(private_key_path, "rb") as key_file:
private_key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend())
# Renew the certificate
new_cert = renew_certificate(cert, private_key)
# Save the new certificate
save_certificate(new_cert, output_cert_path)
print(f"New certificate saved to {output_cert_path}")
if __name__ == "__main__":
main()
Go to https://authentik.example.com/if/admin/#/crypto/certificates
Expand "authentik Self-signed Certificate"
Click on "Download Certificate"
Click on "Download Private key"
mv ~/Downloads/authentik\ Self-signed\ Certificate_*.pem .
pip3 install -U --user --break-system-packages cryptography
cat <<'EOF'> renew_cert.py
...
--- 8< --- paste the renew_cert.py code here --- 8< ---
...
EOF
chmod +x renew_cert.py
./renew_cert.py
New certificate saved to authentik Self-signed Certificate_certificate_new.pem
diff -Naur \
<(openssl x509 -in 'authentik Self-signed Certificate_certificate.pem' -noout -text) \
<(openssl x509 -in 'authentik Self-signed Certificate_certificate_new.pem' -noout -text)
Go to https://authentik.example.com/if/admin/#/crypto/certificates
Edit (Actions) "authentik Self-signed Certificate"
Rename "authentik Self-signed Certificate" to "authentik Self-signed Certificate [OLD]"
Click on "Update"
Click on "Create"
Type "authentik Self-signed Certificate" in "Name"
Paste the content of 'authentik Self-signed Certificate_certificate_new.pem' in "Certificate"
Paste the content of 'authentik Self-signed Certificate_private_key.pem' in "Private Key"
Click on "Create"
Go to https://authentik.example.com/if/admin/#/core/providers
Edit (Actions) every single line with "Type" equal to "OAuth2/OpenID Provider" or "SAML Provider"
- For OAuth2/OpenID Provider: Change the "Signing Key" in Protocol settings to "authentik Self-signed Certificate"
- For SAML Provider: Change the "Signing Certificate" in "Advanced protocol settings" to "authentik Self-signed Certificate"
Click on "Update"
Add the new certificate to all your Apps...
N.B. Before doing all this, I tried to renew it via Authentik API but is not easy via the shell to import authentik and keep the same private key. https://raw.githubusercontent.com/goauthentik/authentik/refs/heads/main/authentik/core/tests/utils.py https://raw.githubusercontent.com/goauthentik/authentik/refs/heads/main/authentik/crypto/apps.py https://raw.githubusercontent.com/goauthentik/authentik/refs/heads/main/authentik/crypto/builder.py
Describe your question/ The default authentik Self-signed Certificate has expired and the one I've created to use with ldap will expire soon. The documentation doesn't mention what the correct way to renew this is. Should these be deleted and then be replaced by newly generated ones or is there a way to renew these?
Relevant infos i.e. Version of other software you're using, specifics of your setup
Screenshots If applicable, add screenshots to help explain your problem.
Logs Output of docker-compose logs or kubectl logs respectively
Version and Deployment (please complete the following information):
Additional context Add any other context about the problem here.