OPNsense Trust Certificates

This role manages SSL/TLS certificates on OPNsense via the Trust API.

Ansible Centreon DNS HTTPS JSON Navidrome OPNsense SSL

OPNsense Trust Certificates Role

Overview

This role manages SSL/TLS certificates on OPNsense via the Trust API. It provides full lifecycle management: creating new certificates signed by an existing OPNsense CA, reissuing certificates when configuration changes or they expire, and deleting certificates not defined in configuration. Certificate and private key files are saved locally for deployment to services.

Purpose

  • Certificate as Code: Define all certificates in version-controlled configuration
  • Automatic Creation: New certificates are created and signed by OPNsense CA
  • Automatic Reissue: Certificates are reissued when configuration changes or on expiry
  • Cleanup: Certificates not in configuration are automatically deleted
  • File Export: Certificate and private key files saved for deployment
  • Idempotent: Safe to run multiple times, only changes what’s needed
  • Secure: Private keys never appear in Ansible logs (no_log: true)

Requirements

  • Ansible 2.14 or higher
  • OPNsense firewall with API access enabled
  • API key and secret stored in Ansible Vault
  • Network connectivity to OPNsense (VLAN10)
  • An existing Certificate Authority configured in OPNsense
  • gather_facts: true in playbook (required for expiry check)

Role Variables

Required Variables

VariableRequiredDescription
vault_opnsense_bjoffrey_user_api_keyYesOPNsense API key (in vault)
vault_opnsense_bjoffrey_user_api_secretYesOPNsense API secret (in vault)
opnsense_trust_certificates_listYesList of certificate definitions (in vars file)

Optional Variables

VariableDefaultDescription
opnsense_trust_certificates_ca_nameOPNsense_CAName of the signing CA in OPNsense
opnsense_trust_certificates_validate_certstrueValidate SSL certificates for API calls
opnsense_trust_certificates_output_dir/home/bjoffrey/Documents/ansible/homelabDirectory for exported .crt/.key files

Default Certificate Settings

Applied to all certificates unless overridden per-certificate:

VariableDefaultDescription
key_type2048RSA key size
digestsha256Signature digest algorithm
cert_typeserver_certCertificate type
lifetime1200Certificate validity in days (~3.3 years)
private_key_locationfirewallWhere the private key is stored
countryFRSubject country
stateRhone-AlpesSubject state
cityLyonSubject city
organizationHomeSubject organization
organizationalunitHomeSubject organizational unit
emailadmin@example.comSubject email

Certificate Definition

Each certificate in opnsense_trust_certificates_list:

FieldRequiredDescription
descrYesCertificate description (used as identifier)
commonnameYesCertificate Common Name (CN)
altnames_dnsNoDNS Subject Alternative Names
altnames_ipNoIP Subject Alternative Names
altnames_uriNoURI Subject Alternative Names
altnames_emailNoEmail Subject Alternative Names
key_typeNoOverride default key type
digestNoOverride default digest
cert_typeNoOverride default cert type
lifetimeNoOverride default lifetime

Certificate Examples

Simple Certificate (Single DNS/IP)

- descr: "Navidrome"
  commonname: "server.homelab"
  altnames_dns: "server.homelab"
  altnames_ip: "192.168.x.x"

Certificate with Multiple SANs

- descr: "Centreon"
  commonname: "server.homelab"
  altnames_dns: |
    server.homelab
    server.homelab
  altnames_ip: |
    192.168.x.x
    192.168.x.x

Dependencies

This role has no dependencies on other Ansible roles.

Example Playbook

---
- name: Configure OPNsense Trust Certificates
  hosts: mint-vm
  gather_facts: true

  vars_files:
    - ../../roles/opnsense_trust_certificates/vars/certificates.yml

  tasks:
    - name: Manage SSL/TLS certificates
      ansible.builtin.include_role:
        name: opnsense_trust_certificates

What This Role Does

  1. Fetch CA list and look up CA by name to get refid
  2. Fetch existing certificates from OPNsense and build lookup by description
  3. Create new certificates that exist in config but not in OPNsense
    • Signs with the configured CA
    • Saves .crt and .key files locally
  4. Check existing certificates for reissue need:
    • Common name changed
    • DNS/IP/URI/email SANs changed
    • Certificate type, key type, or digest changed
    • Certificate expired (valid_to < current timestamp)
  5. Reissue certificates that need updating
    • Generates new certificate (keeps same private key)
    • Saves updated .crt and .key files locally
  6. Delete certificates not defined in configuration
  7. Display summary of created, reissued, and deleted certificates

Reissue Triggers

A certificate is reissued when any of these change:

FieldDescription
commonnameCertificate Common Name
altnames_dnsDNS Subject Alternative Names
altnames_ipIP Subject Alternative Names
altnames_uriURI Subject Alternative Names
altnames_emailEmail Subject Alternative Names
cert_typeCertificate type (server_cert, etc.)
key_typeKey type/size
digestSignature digest algorithm
expiredCertificate valid_to is in the past

Note: lifetime changes alone do NOT trigger reissue. The new lifetime is applied on the next reissue.

OPNsense API Endpoints

Search Certificates

GET /api/trust/cert/search
Authorization: Basic (API key:secret)

Returns all certificates with their properties.

Get Certificate Details

GET /api/trust/cert/get/{uuid}
Authorization: Basic (API key:secret)

Returns full certificate details including crt_payload and prv_payload.

Create Certificate

POST /api/trust/cert/add
Authorization: Basic (API key:secret)
Content-Type: application/json

Request body:

{
  "cert": {
    "action": "internal",
    "descr": "My Certificate",
    "caref": "ca-refid-here",
    "commonname": "server.homelab",
    "altnames_dns": "server.homelab",
    "altnames_ip": "192.168.x.x",
    "key_type": "2048",
    "digest": "sha256",
    "cert_type": "server_cert",
    "lifetime": "1200"
  }
}

Reissue Certificate

POST /api/trust/cert/set/{uuid}
Authorization: Basic (API key:secret)
Content-Type: application/json

Same body as create, but with "action": "reissue" and existing payloads included.

Delete Certificate

POST /api/trust/cert/del/{uuid}
Authorization: Basic (API key:secret)

Search Certificate Authorities

GET /api/trust/ca/search
Authorization: Basic (API key:secret)

Returns all CAs. The role uses refid (not uuid) as the caref when signing certificates.

File Output

Created and reissued certificates are saved to the output directory:

{output_dir}/{descr}.crt    # Certificate (PEM format)
{output_dir}/{descr}.key    # Private key (PEM format)

Spaces in descr are replaced with underscores. Files are created with mode 0600.

Example:

/home/bjoffrey/Documents/ansible/homelab/OPNsense_Web_UI.crt
/home/bjoffrey/Documents/ansible/homelab/OPNsense_Web_UI.key

Idempotency

Role is fully idempotent:

  1. First run: Creates all certificates, reports changes
  2. Subsequent runs:
    • Skips existing certificates with matching configuration
    • Only reissues if configuration changed or certificate expired
    • Only deletes certificates removed from config
    • Reports ok if no changes needed

Multiline SAN values (using YAML |) are normalized before comparison to avoid false positives from trailing whitespace.

Security Considerations

  • API Credentials: Stored in Ansible Vault
  • HTTPS: Uses SSL/TLS for API calls
  • no_log: Certificate and private key content never appears in Ansible output
  • File Permissions: Output files created with mode 0600
  • Private Keys: Exported keys should be handled securely
  • Certificate Validation: Enabled by default

Troubleshooting

Certificates reissued unnecessarily

Cause: Multiline SAN format mismatch between YAML and API response

Solution: The role normalizes multiline values (trim, split, sort, join) before comparing. If issues persist, verify the exact format returned by the API.

CA not found

Cause: opnsense_trust_certificates_ca_name doesn’t match any CA in OPNsense

Solution: Check CA names in OPNsense UI (System > Trust > Authorities) and update the variable.

Certificate files not created

Cause: Output directory doesn’t exist or wrong permissions

Solution: Ensure opnsense_trust_certificates_output_dir exists and is writable.

This role is often used with:

  • deploy_ssl_certificates: Deploy certificates to servers
  • opnsense_conf_backup: Backup OPNsense configuration
  • opnsense_dashboard: Dashboard shows certificate status widget

License

MIT

Author

Created for homelab infrastructure management.