tls-certificates: Library design¶
The TLS Certificates interface allows charms to request TLS certificates without sharing their private key.
This library began life as a port of tls_certificates_interface.tls_certificates v4.22.
What the library does for you¶
When a charm uses TLSCertificatesRequiresV4, the library:
Generates an RSA-2048 private key by default on first use and stores it in a Juju secret owned by the requiring charm. Requirers can select RSA-3072, RSA-4096, ECDSA P-256, or ECDSA P-384 with the
key_algorithmandkey_sizeconstructor arguments.Builds a CSR from the
CertificateRequestAttributesyou supply and writes it to relation data.Receives the signed certificate from the provider and emits a
certificate_availableevent.Tracks certificate expiry and triggers renewal automatically (see below).
Because the library generates the private key, upgrading a charm that previously managed its own key will cause one certificate rotation: the library generates a new key, the previous CSR no longer matches, and a new certificate is issued. If you need to retain a specific key — for example, to avoid that rotation — you can pass it to TLSCertificatesRequiresV4 at instantiation time.
How automatic renewals work¶
The library renews certificates without any code in the requirer charm:
When the requirer receives a certificate from the provider, it stores the certificate in a Juju secret with an expiry set ahead of the certificate’s own expiry.
A
certificate_availableevent is emitted, prompting the requiring charm to write the certificate where its workload expects it.When the Juju secret expires, the library removes the old CSR from the relation data, deletes the secret, generates a new CSR, and writes the new CSR to the relation data.
The provider reads the new CSR, issues a new certificate, and writes it to relation data.
The requirer reads the new certificate, stores it in a fresh Juju secret, and re-emits
certificate_available.
The requiring charm only ever has to handle certificate_available; the rest is managed by the library.
Private key handling¶
The library never transmits the requirer’s private key over the relation. Only CSRs and the resulting certificates cross the relation; the private key stays inside the requiring charm’s data.
Storage at rest¶
The library stores the private key in a Juju secret owned by the requiring charm. Only the charm itself and a Juju administrator can read the secret. For details of the secret backend Juju uses, see the Juju documentation on secret backends.
Key generation¶
Private keys use RSA-2048 by default. A requirer can choose another algorithm with the
KeyAlgorithm enum:
|
Supported |
Default |
|---|---|---|
|
2048, 3072, 4096 |
2048 |
|
256 (P-256), 384 (P-384) |
256 |
from charmlibs.interfaces.tls_certificates import KeyAlgorithm
self.certificates = TLSCertificatesRequiresV4(
charm=self,
relationship_name="certificates",
certificate_requests=[CertificateRequestAttributes(common_name="example.com")],
key_algorithm=KeyAlgorithm.ECDSA,
key_size=384, # optional; omit to use P-256
)
Plain strings ("rsa", "ecdsa") are also accepted. An unsupported algorithm or size raises
TLSCertificatesError when the object is created.
The selected algorithm and size apply when the library first generates a key, or when
regenerate_private_key is called. Existing persisted keys are kept, and normal certificate
renewal reuses the current key. This means changing the configuration of a deployed charm doesn’t
rotate its key by itself. PrivateKey has read-only algorithm and key_size properties, so the
charm can detect a mismatch and rotate the key itself. The tutorial shows how.
Signature hash¶
The library chooses the signature hash from the signing key: SHA-384 for ECDSA P-384 keys and SHA-256 for all other keys. This applies to CSRs, issued certificates and self-signed CAs. For issued certificates, the hash depends on the CA’s key, not the subject’s key.
Key usage for ECDSA certificates¶
An EC key can’t be used for RSA-style key encipherment. When the library issues a non-CA
certificate for an EC CSR that doesn’t request a KeyUsage extension, it adds a critical
KeyUsage(digital_signature=True). This applies to any EC CSR, including CSRs that weren’t
created by this library. A KeyUsage extension requested in the CSR is kept as-is. CA
certificates always get key_cert_sign and crl_sign.
Out of scope: Ed25519¶
Ed25519 isn’t supported. It needs a different signing call (no separate hash) and PKCS#8 key serialization, and support for it varies across certificate providers and TLS consumers. It can be added later if a deployment needs it end to end.
Key labelling and multiple integrations¶
When a requirer charm participates in more than one tls-certificates integration, the library stores one private key per relation. The Juju secret labels include both the unit number and the relation name, so each integration gets its own key and certificate without collisions.
Manual key rotation¶
Charm authors can rotate the private key by calling the regenerate_private_key method, which generates a new private key, removes the old certificate requests, and sends new ones to the TLS provider.