Related docs:
IDM CERT CAPABILITIES IDM VAULT PLUGIN AAP INTEGRATION DOCS MAP
eigenstate.ipa.cert requests, retrieves, and searches certificates from the
IdM CA directly from Ansible.
This reference covers:
IdM runs a full Dogtag CA. This plugin gives automation a direct interface to it without requiring certmonger on the target host or shell-out tasks for each service principal.
flowchart LR
ans["Ansible task or template"]
lookup["eigenstate.ipa.cert"]
krb["Kerberos ticket\nexisting, password-derived,\nor keytab-derived"]
ipa["ipalib cert APIs"]
ca["IdM CA\nDogtag PKI"]
out["Lookup return value\nPEM or base64, with metadata"]
ans --> lookup
lookup --> krb
krb --> ipa
ipa --> ca
ca --> out
The lookup calls the IdM Python client library directly through ipalib. No
external HTTP or REST call is made outside that stack. The CA backend is
Dogtag. The authentication layer is Kerberos.
The lookup always operates with a Kerberos credential cache.
It can get there in three ways:
ipaadmin_password:
kerberos_keytab:
[!IMPORTANT] The lookup plugin requires
python3-ipalibandpython3-ipaclienton the controller or execution environment. It also requireskrb5-workstationwhen a ticket must be acquired dynamically. The plugin warns if any input file (kerberos_keytab,csr_file) has permissions broader than0600.
TLS behavior:
verify: /path/to/ca.crt enables explicit certificate verificationverify first tries /etc/ipa/ca.crtipalibThe lookup supports three operations:
request:
terms to be one or more service principalscsr or csr_fileretrieve:
terms must be one or more serial numbers (decimal, hex 0x..., or int)find:
terms is ignoredrequest and retrieve are per-term and return a list of the same length as
terms. find is a single bulk call and returns however many the CA matches.
For operation='request', provide the CSR as one of:
csr:
csr_file:
These are mutually exclusive. Exactly one must be provided.
The CSR must be PEM-formatted. The plugin passes it to ipalib unchanged. The
subject CN in the CSR should match the principal being requested.
[!NOTE] When a single CSR is used with multiple principals in
terms, the same CSR is submitted for each principal. If each principal needs a distinct CSR, call the lookup once per principal.
Profile and CA override parameters for request:
profile:
caIPAserviceCert)ca:
ipa)add:
false)For operation='retrieve', each term must be a serial number. Accepted forms:
"12345""0x3039"12345The plugin normalizes all forms to an integer before calling cert_show.
For operation='find', all filter parameters are optional. Calling find
with no filters returns all certificates the principal has access to and emits a
warning. Useful filters:
principal:
subject:
valid_not_after_from:
valid_not_after_to:
revocation_reason:
exactly:
true, requires an exact subject match rather than substringCombining valid_not_after_from and valid_not_after_to creates an expiry
window. That is the primary pattern for pre-expiry maintenance plays.
Each certificate result carries a value field. Encoding controls its form:
pem:
-----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- wrapped at 64
characters per line.crt files or inlining a cert for a service configbase64:
Both encodings are derived from the base64 DER returned by ipalib. No
external cryptography dependency is required.
The default return shape is value: a plain list of certificate strings, one
per result.
Use result_format: record when the caller needs cert identity alongside the
value. Each element is then a dictionary:
name:
request), serial number string (for retrieve and find)value:
encoding:
pem or base64metadata:
Additional container shapes:
result_format: map:
{name: value}result_format: map_record:
{name: {name, value, encoding, metadata}}The mapping forms are useful when multiple principals or serials are requested in one call and the playbook must not depend on positional list ordering.
For operation='find', the key in map and map_record is the
serial_number string from the metadata. Serial numbers are unique per IdM CA
and unambiguous as a key.
Every record or map_record result includes a metadata dict with:
| Field | Type | Description |
|---|---|---|
serial_number |
int | CA-assigned serial number |
subject |
str | Certificate subject DN |
issuer |
str | Certificate issuer DN |
valid_not_before |
str | Validity start (ISO string from IdM) |
valid_not_after |
str | Validity end (ISO string from IdM) |
san |
list | Subject Alternative Names; may be empty |
revoked |
bool | Whether the certificate has been revoked |
revocation_reason |
int or None | Revocation reason code, or None if not revoked |
valid_not_after is the field to compare when building expiry-window plays.
Use result_format: map_record with operation='find' and
valid_not_after_to to retrieve a pre-indexed map of certificates expiring
before a given date.
Request a signed certificate for a service principal:
- ansible.builtin.set_fact:
api_cert: "{{ lookup('eigenstate.ipa.cert',
'HTTP/api.example.com@EXAMPLE.COM',
operation='request',
server='idm-01.example.com',
kerberos_keytab='/runner/env/ipa/admin.keytab',
csr_file='/runner/env/csr/api.example.com.csr',
verify='/etc/ipa/ca.crt') }}"
Retrieve an existing certificate by serial number:
- ansible.builtin.set_fact:
cert_pem: "{{ lookup('eigenstate.ipa.cert',
'12345',
operation='retrieve',
server='idm-01.example.com',
kerberos_keytab='/runner/env/ipa/admin.keytab',
verify='/etc/ipa/ca.crt') }}"
Find certificates expiring within a window:
- ansible.builtin.set_fact:
expiring_certs: "{{ lookup('eigenstate.ipa.cert',
operation='find',
server='idm-01.example.com',
kerberos_keytab='/runner/env/ipa/admin.keytab',
valid_not_after_from='2026-04-01',
valid_not_after_to='2026-06-30',
result_format='map_record',
verify='/etc/ipa/ca.crt') }}"
Request with full record including metadata:
- ansible.builtin.set_fact:
cert_record: "{{ lookup('eigenstate.ipa.cert',
'HTTP/web.example.com@EXAMPLE.COM',
operation='request',
server='idm-01.example.com',
ipaadmin_password=lookup('env', 'IPA_ADMIN_PASSWORD'),
csr=my_csr_pem_string,
profile='caIPAserviceCert',
result_format='record',
verify='/etc/ipa/ca.crt') }}"
Return the signed cert as base64 DER:
- ansible.builtin.set_fact:
cert_der: "{{ lookup('eigenstate.ipa.cert',
'HTTP/svc.example.com@EXAMPLE.COM',
operation='request',
server='idm-01.example.com',
kerberos_keytab='/runner/env/ipa/admin.keytab',
csr_file='/runner/env/csr/svc.csr',
encoding='base64',
verify='/etc/ipa/ca.crt') }}"
Common failure classes are:
ipalib libraries on the controller or EErequestadd=falseretrieve[!NOTE] A
requestfailure citing a subject mismatch usually means the CN or SAN in the CSR does not match the service principal name registered in IdM. Verify the principal withipa service-showbefore submitting.
[!CAUTION] The
add=trueparameter auto-creates the principal if it is missing. Use this only in controlled automation where principal namespace hygiene is managed at the play level. In shared environments, prefer requiring the principal to exist first.
Use IDM CERT CAPABILITIES when you need operator patterns rather than option-by-option reference: