Bootstrap FreeKB - Ansible - Get SSL certificates from a URL
Ansible - Get SSL certificates from a URL

Updated:   |  Ansible articles

If you are not familiar with modules, check out Ansible - Getting Started with Modules.

Let's say https://www.example.com uses a certificate chain consisting of a root CA, and intermediate CA, and a server certificate to create a secured connection. 

community.crypto.get_certificate can be used to get the SSL certificate being presented by a URL. 

---
- hosts: localhost
  tasks:
  - name: get the server certificate being presented by https://www.example.com
    community.crypto.get_certificate:
      host: www.example.com
      port: 443
    register: server_cert
    
  - ansible.builtin.debug:
      var: server_cert
...

 

Running this playbook should return something like this.

ok: [localhost] => {
    "server_cert": {
        "cert": "-----BEGIN CERTIFICATE-----\nMII...9NFcE=\n-----END CERTIFICATE-----\n",
        "changed": false,
        "deprecations": [
            {
                "collection_name": "community.crypto",
                "msg": "The default value `false` for asn1_base64 is deprecated and will change to `true` in community.crypto 3.0.0. If you need this value, it is best to set the value explicitly and adjust your roles/playbooks to use `asn1_base64=true` as soon as possible",
                "version": "3.0.0"
            }
        ],
        "expired": false,
        "extensions": [],
        "failed": false,
        "issuer": {
            "CN": "RootCA",
            "DC": "example"
        },
        "not_after": "20250717143450Z",
        "not_before": "20240717143450Z",
        "serial_number": 123456789012123456789012123456789012123456789012123456789012,
        "signature_algorithm": "sha256WithRSAEncryption",
        "subject": {
            "C": "US",
            "CN": "www.example.com",
            "L": "Guam",
            "O": "Acme",
            "ST": "California"
        },
        "version": 2
    }
}

 

By default, only the server certificate will be returned. get_certificate_chain can be used to return the full certificate chain, the root CA, the intermediate CA, and the server certificate.

I am not exactly sure which version of the community.crypto collection added get_certificate_chain. If you are using an older version of the community.crypto collection, such as version 2.18.0, you will need to update the community.crypto collection to a recent version, such as version 2.26.3. Check out my article FreeKB - Ansible - Install a collection using the ansible-galaxy collection install command.

---
- hosts: localhost
  tasks:
  - name: get the server certificate being presented by https://www.example.com
    community.crypto.get_certificate:
      host: www.example.com
      port: 443
      get_certificate_chain: true
    register: ssl_chain
    
  - ansible.builtin.debug:
      var: ssl_chain
...

 

Almost always, you are going to want to do something with the certificate data, such as determine when the certificate expires, or to base64 encode the certificate data. 

  1. Use ansible.bulitin.file to create an empty file
  2. Use ansible.builtin.lineinfile to append each line of the certificate data to the file
  3. Use ansible.builtin.shell to get the certificate subject
  4. Use ansible.builtin.shell to base64 encode the certificate data
  5. Use ansible.bulitin.file to delete the file
---
- hosts: localhost
  tasks:
  - name: get the server certificate being presented by https://www.example.com
    community.crypto.get_certificate:
      host: www.example.com
      port: 443
      get_certificate_chain: true
    register: ssl_chain
    
  - ansible.builtin.debug:
      var: ssl_chain

  - block:      
    - name: touch /tmp/my.pem
      ansible.builtin.file:
        path: /tmp/my.pem
        state: touch
      
    - name: append certificate_chain.verified_chain[0] to /tmp/my.pem
      ansible.builtin.lineinfile:
        path: /tmp/my.pem
        line: "{{ item }}"
      with_items: "{{ certificate_chain.verified_chain[0].split('\n') }}"
      when: item != ''
    
    - name: register SSL certificate subject
      ansible.builtin.shell: cat /tmp/my.pem | openssl x509 -subject -noout
      register: subject

    - ansible.builtin.debug:
        var: subject

    - block:
      - name: base64 encode /tmp/my.pem
        ansible.builtin.shell: cat /tmp/my.pem | base64 | xargs | sed 's| ||g'
        register: base64_encode

      - name: set_fact intermediateCA
        ansible.builtin.set_fact:
          intermediateCA: "{{ base64_encode.stdout }}"

      when: subject.stdout == "subject=DC = com, DC = example, CN = IntermediateCA"

    - block:
      - name: base64 encode /tmp/my.pem
        ansible.builtin.shell: cat /tmp/my.pem | base64 | xargs | sed 's| ||g'
        register: base64_encode

      - name: set_fact rootCA
        ansible.builtin.set_fact:
          rootCA: "{{ base64_encode.stdout }}"

      when: subject.stdout == "subject=CN = rootCA"

  always:
  - name: always delete /tmp/my.pem
    ansible.builtin.file:
      path: /tmp/my.pem
      state: absent
            
...

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter ed0d88 in the box below so that we can be sure you are a human.