From 70d0ed3456a435c27f7664c855fbd7a8a7fec4a8 Mon Sep 17 00:00:00 2001 From: ember ana Date: Fri, 27 Mar 2026 13:47:36 +0100 Subject: [PATCH] crypto: improve discovery for mounted k8s TLS Secrets (#17636) Co-authored-by: Marc 'risson' Schmitt --- authentik/crypto/tasks.py | 11 ++++++----- authentik/crypto/tests.py | 15 +++++++++++++++ website/docs/sys-mgmt/certificates.md | 7 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/authentik/crypto/tasks.py b/authentik/crypto/tasks.py index daf104b01a..8476cdc3e5 100644 --- a/authentik/crypto/tasks.py +++ b/authentik/crypto/tasks.py @@ -114,15 +114,16 @@ def certificate_discovery(): discovered = 0 for file in glob(CONFIG.get("cert_discovery_dir") + "/**", recursive=True): path = Path(file) - if not path.exists(): - continue - if path.is_dir(): + if not path.exists() or path.is_dir(): continue # For certbot setups, we want to ignore archive. if "archive" in file: continue - # Support certbot's directory structure - if path.name in ["fullchain.pem", "privkey.pem"]: + # Handle additionalOutputFormats from cert-manager gracefully + if path.name in ["ca.crt", "tls-combined.pem", "key.der"]: + continue + # Support certbot & kubernetes.io/tls directory structure + if path.name in ["fullchain.pem", "privkey.pem", "tls.crt", "tls.key"]: cert_name = path.parent.name else: cert_name = path.name.replace(path.suffix, "") diff --git a/authentik/crypto/tests.py b/authentik/crypto/tests.py index 110aa695d3..e5f35e9f90 100644 --- a/authentik/crypto/tests.py +++ b/authentik/crypto/tests.py @@ -355,6 +355,16 @@ class TestCrypto(APITestCase): subject_alt_names=[], validity_days=3, ) + + name3 = generate_id() + builder3 = CertificateBuilder(name3) + with self.assertRaises(ValueError): + builder3.save() + builder3.build( + subject_alt_names=[], + validity_days=3, + ) + with TemporaryDirectory() as temp_dir: with open(f"{temp_dir}/foo.pem", "w+", encoding="utf-8") as _cert: _cert.write(builder.certificate) @@ -365,6 +375,8 @@ class TestCrypto(APITestCase): _cert.write(builder2.certificate) with open(f"{temp_dir}/foo.bar/privkey.pem", "w+", encoding="utf-8") as _key: _key.write(builder2.private_key) + with open(f"{temp_dir}/tls-combined.pem", "w+", encoding="utf-8") as _cert: + _cert.write(builder3.certificate) with CONFIG.patch("cert_discovery_dir", temp_dir): certificate_discovery.send() keypair: CertificateKeyPair = CertificateKeyPair.objects.filter( @@ -376,6 +388,9 @@ class TestCrypto(APITestCase): self.assertTrue( CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % "foo.bar").exists() ) + self.assertFalse( + CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % "tls-combined").exists() + ) def test_discovery_updating_same_private_key(self): """Test certificate discovery updating certs with matching private keys""" diff --git a/website/docs/sys-mgmt/certificates.md b/website/docs/sys-mgmt/certificates.md index 21d280085f..0bc0978595 100644 --- a/website/docs/sys-mgmt/certificates.md +++ b/website/docs/sys-mgmt/certificates.md @@ -104,6 +104,9 @@ authentik uses the following rules to import certificates: - **Certbot convention**: Files named `fullchain.pem` or `privkey.pem` will use their parent folder's name - Files in paths containing `archive` are ignored (to better support certbot setups) +- **[Kubernetes TLS Secrets](https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod)**: Files named `tls.crt` or `tls.key` will use their parent folder's name + - Files named `tls-combined.pem`, `ca.crt`, or `key.der` are ignored (to better support [cert-manager setups](https://cert-manager.io/docs/usage/certificate/#additional-certificate-output-formats)) + - **Flexible organization**: Files can use any directory structure and extension #### Directory structure example @@ -119,6 +122,10 @@ certs/ ├── foo.bar │ ├── fullchain.pem │ └── privkey.pem +├── foo.baz +│ ├── key.der +│ ├── tls.crt +│ └── tls.key ├── foo.key └── foo.pem ```