Skip to content

ansibleguy/infra_pki

Repository files navigation

Public Key Infrastructure

Ansible Role - Public Key Infrastructure (PKI)

Role to provision and manage one or multiple PKI's on the target server.

Buy me a coffee

The EasyRSA script is used as 'backend' to simplify the automation process.

Molecule Test Status YamlLint Test Status PyLint Test Status Ansible-Lint Test Status Ansible Galaxy

Molecule Logs: Short, Full

Tested:

  • Debian 11

Install

# latest
ansible-galaxy role install git+https://github.com/ansibleguy/infra_pki

# from galaxy
ansible-galaxy install ansibleguy.infra_pki

# or to custom role-path
ansible-galaxy install ansibleguy.infra_pki --roles-path ./roles

# install dependencies
ansible-galaxy install -r requirements.yml

Functionality

  • Package installation

    • OpenSSL
  • Configuration

    • Usage of a group to allow read-only access to public-keys

    • Default config:

      • Paths:
        • PKI base: '/var/local/lib/pki'
        • Script: '/usr/local/sbin/easyrsa'
      • PKI user: 'pki'
      • Read-only group: 'pki_read'
      • EasyRSA vars:
        • Expiration:
          • Root-CA: 20 years
          • Sub-CA: 15 years
          • Certificates: 3 years
        • Digest:
          • Root-CA: sha512
          • Sub-CA/Certificates: sha256
        • Algorithm: rsa
        • Key size: 4096
      • Certificates:
        • Don't password-encrypt certificate private-keys
        • Export formats:
          • pkcs12 (private/.p12)
          • certificate chain (issued/.chain.crt)
    • Default opt-ins:

      • Adding dedicated PKI-user and read-only group
      • Saving CA/Sub-CA/Certificate passwords to files for easier automation
        • See the information below for alternatives
      • Installation and configuration of a Nginx webserver to server CRL's and CA-PublicKey's (not yet implemented)
    • Default opt-outs:

      • Purging of orphaned (existing but not configured) certificates
      • Encryption of certificate private-keys (non CA/Sub-CA)

Usage

You want a simple Ansible GUI? Check-out my Ansible WebUI

Config

Define the config as needed:

Example

You can find a more detailed example here: Example

Minimal setup

pki:
  crl_distribution:
    domain: 'crl.ansibleguy.net'

  instances:
    root:
      pwd_ca: !vault |
        $ANSIBLE_VAULT;1.1;AES256
        ...

      sub_cas:
        main:
          pwd_ca: !vault |
            $ANSIBLE_VAULT;1.1;AES256
            ...

          certs:
            server:  # server certificates
              ansibleguy_net:
                cn: 'AnsibleGuy Website'
                san:
                  dns: ['www.ansibleguy.net', 'ansibleguy.net']
                  ip: '135.181.170.217'
                  uri: 'https://www-ansibleguy.net'

            client:  # client certificates
              workstation1:
                cn: 'AnsibleGuy Workstation'

You might want to use 'ansible-vault' to encrypt your passwords:

ansible-vault encrypt_string

Execution

Run the playbook:

ansible-playbook -K -D -i inventory/hosts.yml playbook_pki.yml

There is also an 'entrypoint' for managing single certificates - that can be useful if they are automagically managed by other roles.

# to run it interactively
ansible-playbook -K -D -i inventory/hosts.yml playbook_single_cert.yml

There are also some useful tags available:

  • instances => skip basic tasks but process all PKI-instances (RootCA's)
  • subcas => skip basic and instance (RootCA) tasks but process all SubCA tasks
  • certs => only process task related to managing certificates
  • certs_create => create non-existent certificates
  • certs_renew => renew certificates that have the state 'renewed' set
  • certs_revoke => revoke certificates that have the state 'revoked' or 'absent' set

To debug errors - you can set the 'debug' variable at runtime:

# WARNING: Will log passwords!
ansible-playbook -K -D -i inventory/hosts.yml playbook.yml -e debug=yes

Note: --check mode is not supported by this role as it heavily depends on scripted command-tasks.


Info

  • Note: Most of the role's functionality can be opted in or out.

    For all available options - see the default-config located in the main defaults-file!

  • Info: To make sure the role config 'behaves' as expected - it tested by this role using molecule!

    Per example: The certificate-attributes, file- & directory-permissions & -ownership are checked after generating multiple certificates using multiple Root- & Sub-CA's.

    See Verification Tests

  • Warning: Not every setting/variable you provide will be checked for validity. Bad config might break the role!

  • Note: If you want to read more about PKI's and certificates:

    • The EasyRSA project has a nice documentation
    • For (x509) certificates check out the OpenSSL documentation.
    • If you want to read a good explanation of how 'keyUsage' and 'extendedKeyUsage' are to be used - check out this StackExchange answer: LINK
    • If you want to know how to manually create a PKI/SubCA's using EasyRSA - check out @QueuingKoala's clean example on how to do that: GitHub Gist
  • Warning: For gained security against CA-compromise you should:

    1. Make sure all your needed Sub-CA's are created by the role

    2. Copy the CA private-key (${path_base}/ca/private/ca.key) to an offline medium (keep redundancy in mind)

    3. Save the password you used to initialize the CA (not on the same medium)

    4. Remove the ca.key file from your Online-system using a 'secure-deletion' tool like 'shred':

      shred -vzu -n10 ca.key
  • Note: You have multiple options to supply the CA/Sub-CA/Certificate passwords:

    • if 'save_passwords' is set to true - the saved password will be retrieved after the CA is initialized
    • as inventory variable (ansible-vault encrypted to be decrypted at runtime)
    • --extra-vars at runtime
    • if no password was set, the role will prompt for one at runtime
  • Note: Certificate variables you set on:

    • global level will be inherited by all instances and their sub-ca's
    • instance-level will be inherited by its sub-ca's
    • specific config on instance/subca level will always override the inherited one
  • Note: You can find scripts for automated certificate-expiration monitoring that can be integrated with monitoring systems like Zabbix at files/usr/local/bin/monitoring.

  • Warning: The CRL-Distribution settings CANNOT BE CHANGED easily.

    All existing certificates would have to be re-generated once the settings are changed.

  • Note: The 'cert_expire' variable of the root-ca will set the runtime of the sub-ca's!

  • Note: Passwords used for CA/Sub-CA/Certificate encryption are checked for complexity rules:

    • min. 8 characters long
    • must contain
      • number
      • uppercase letter
      • lowercase letter
  • Note: Certificates states can be set to either:

    • 'present' or 'created' to make sure a certificate exists
    • 'absent' or 'revoked' to make sure a certificate does not exist
    • 'renewed' to renew a certificate