linux-system-roles / certificate

Role for managing TLS/SSL certificate issuance and renewal
https://linux-system-roles.github.io/certificate/
MIT License
30 stars 20 forks source link

The role is not idempotent with Debian 12 #216

Open rjeffman opened 6 months ago

rjeffman commented 6 months ago

The certificate role is not idempotent using Debian 12 on both the controller and managed node.

For details, see discussion after https://github.com/linux-system-roles/certificate/issues/45#issuecomment-1894465030

Nihlus commented 4 months ago

After some more testing, it appears that the certificate is actually re-issued every time the role runs. The configuration I'm using looks like this:

certificate_requests:
  - name: '{{ ipa_certificate_name }}' # something like "HTTP"
    ca: ipa
    dns: '{{ inventory_hostname }}'
    ip: '{{ ansible_host }}'
    principal: '{{ ipa_certificate_principal }}/{{ inventory_hostname }}@{{ ipaserver_realm }}' # something like HTTP/myhost.mydomain.net@MYDOMAIN.NET
    owner: '{{ ipa_certificate_owner }}'
    group: '{{ ipa_certificate_group }}'
    mode: '{{ ipa_certificate_mode }}'
- name: ensure an IPA-issued certificate is present
  include_role:
    name: fedora.linux_system_roles.certificate
    apply:
      become: true

It's part of another role that wraps it up with outer configurable options, but that's the gist of the invocation. ipa-getcerts list also doesn't show the IP as part of the cert anywhere, but I'm not sure if that has anything to do with this issue.

Nihlus commented 4 months ago

Okay, I've had another crack at it and managed to narrow down the issue. Essentially:

  1. IPA does not issue certificates with an IP address in the SAN 1.1. This causes the certificate/csr comparison to fail if an IP is requested
  2. IPA always issues the Kerberos realm as the certificates organization 2.1. This causes the certificate/csr comparison to fail, since the subject does not match
  3. IPA always issues the certificate with key usage as Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment 3.1. This causes the certificate/csr comparison to fail, since the default key usage is Digital Signature, Key Encipherment
  4. key_size is not set in the CSR during A/B comparison in base.py's certificate proxy, but the certificate's key size is 4.1. This causes the certificate/csr comparison to fail, since the two keys are compared straight-across

The following workarounds can be applied to resolve the idempotency problems.

The issue with key_size can probably be resolved by accepting any value in the issued certificate if no specific key_size is requested in the CSR. The other are likely better suited as documentation in this repository under https://github.com/linux-system-roles/certificate?tab=readme-ov-file#using-freeipa-to-issue-a-certificate or someplace similar.

rjeffman commented 4 months ago

Thank you for your research on this issue.

Requesting a certificate with the same settings, twice, should no re-issue the certificate, at least, against the same version of IPA. It may be that recent versions of IPA have changed something that is affecting this role.

I've been in a medical leave, but will look at it in a couple of weeks (I'd say next week, but it will be hard, as I don't even have a Debian setup around).

Nihlus commented 4 months ago

Right - the issue is that IPA doesn't respect some settings and overrides them in the issued certificate (the organization and key usages, for example). As long as you know what you're going to get, you can set those options so they become part of the CSR and the comparison succeeds.

The only real bug here is the handling of key_size, which appears to be broken for the CSR, resulting in a falsy value being set in the cert_info structure. The other issues just need some documentation regarding IPAs overrides when issuing the actual certificate.