This post will cover how to use Ansible to gather information from many NetApp ONTAP clusters using REST and generate a report of all server certificates.
Table of Contents
Intro
NetApp ONTAP uses different types of certificates to secure communications and data, and if you have a large number of systems – tracking the expiry dates can become a bit of a challenge.
These certificates include:
- Server certificates: These certificates are used to authenticate ONTAP servers to clients. They are installed on each cluster or SVM and are used to secure HTTPS connections.
- Client certificates: These certificates are used to authenticate clients to ONTAP servers. They can be used to secure SSH connections, API access, and other types of client-server communication.
- CA certificates: These certificates are used to sign other certificates. They are used to create a chain of trust that allows clients to verify the authenticity of server and client certificates.
- CA-signed certificates: These certificates are created and signed by an enterprise certificate authority. They are often used in production for cluster or SVM certificates.
- Self-signed certificates: These certificates are created and signed by the same entity. They are often used for testing or for small deployments where a CA is not necessary.
This post will focus on server certificates, both CA-issued and self-signed and detail a way to create and schedule an ONTAP certificate report using Jenkins/Ansible.
ONTAP Certificate Report
Normally a NetApp ONTAP cluster will have the following certificates: a cluster scope certificate which is most frequently used by the ONTAP System Manager and a svm scope self-signed certificate for each SVM (vserver). And depending on the number of clusters and SVMs, the total number of certificates can range from dozens to thousands of certificates.
The following report is one I have implemented for a number of customers and executed regularly by Jenkins. It uses the official NetApp ONTAP Collection collection netapp.ontap.
Variables
In our variables section we first define the list of our ONTAP clusters using ontap_clusters as well as the variables needed to send the ONTAP certificate report.
vars:
ontap_clusters:
- cluster1_hostname
- cluster2_hostname
ontap_fields: [common_name, serial_number, ca, type, expiry_time, scope]
certs: "{{ dict(certificate_info.results|json_query(certs_query)) }}"
certs_query: '[].[item, ontap_info."security/certificates".records]'
csv_file_path: /var/lib/jenkins/workspace/Infra-NetApp_certificates_report/netapp_certificate_details.csv
sender: sender@domain.com
recipient: recipient@domain.com
mailrelay: fqdn_of_mailrelay
template_vars:
subject: NetApp Storage Certificate Report
body: 'Attached is the list of certificates for all clusters (this includes both cluster and svm certificates). Please review and renew as needed.'
YAMLAdditionally, the three lines for ontap_fields, certs and certs_query are used to organize the data but more on that later.
Tasks
There are three ansible tasks in our playbook.
run ONTAP gather facts for certificate info with specified fields
The first playbook uses the module netapp.ontap.na_ontap_rest_info which gathers various information about ONTAP configuration using REST APIs. In our case, the focus is on security/certificates and only certain fields are stored in the certificate_info variable: common_name, serial_number, ca, type, expiry_time, scope.
- name: run ONTAP gather facts for certificate info with specified fields
netapp.ontap.na_ontap_rest_info:
hostname: "{{ item }}"
username: "{{ lookup('env', 'ontap_admin_usr') }}"
password: "{{ lookup('env', 'ontap_admin_pwd') }}"
use_rest: always
https: true
validate_certs: false
gather_subset:
- security/certificates
fields:
- 'common_name'
- 'serial_number'
- 'ca'
- 'type'
- 'expiry_time'
- 'scope'
parameters:
type: server
loop: "{{ ontap_clusters }}"
register: certificate_info
YAMLUnfortunately, the information required is rather lengthy (JSON) and not particularly easy to reason.
copy the results to CSV
For the purposes of this report, we will tidy up and export the results to CSV which we can later e-mail.
In the variable section above we had the following three lines. The first one simply defines the fields which will be our “CSV header”. The other two define what is known as a dictionary in abstract transformations:
ontap_fields: [common_name, serial_number, ca, type, expiry_time, scope]
certs: "{{ dict(certificate_info.results|json_query(certs_query)) }}"
certs_query: '[].[item, ontap_info."security/certificates".records]'
YAMLFinally, in our task, we define the header using “{{ ontap_fields|join(‘,’) }}” and then create a line for each certificate:
- name: copy the results to CSV
copy:
dest: "{{ csv_file_path }}"
content: |
{{ ontap_fields|join(',') }}
{% for cluster,certs in certs.items() %}
{% for cert in certs %}
{{ ontap_fields|map('extract', cert)|join(',') }}
{% endfor %}
{% endfor %}
YAMLsend the results by e-mail
The following is the simplest way to e-mail the contents of our report to the interested parties
- name: send the results by e-mail
mail:
host: "{{ mailrelay }}"
port: 25
subject: "{{ template_vars.subject }}"
body: "{{ template_vars.body }}"
from: "{{ sender }}"
to: "{{ recipient }}"
attach:
- "{{ csv_file_path }}"
delegate_to: localhost
YAMLFull Playbook code
---
- name: NetApp Certificate Expiry Reporting
hosts: localhost
gather_facts: no
collections:
- netapp.ontap
vars:
ontap_clusters:
- cluster1_hostname
- cluster2_hostname
ontap_fields: [common_name, serial_number, ca, type, expiry_time, scope]
certs: "{{ dict(certificate_info.results|json_query(certs_query)) }}"
certs_query: '[].[item, ontap_info."security/certificates".records]'
csv_file_path: /var/lib/jenkins/workspace/Infra-NetApp_certificates_report/netapp_certificate_details.csv
sender: sender@domain.com
recipient: recipient@domain.com
mailrelay: fqdn_of_mailrelay
template_vars:
subject: NetApp Storage Certificate Report
body: 'Attached is the list of certificates for all clusters (this includes both cluster and svm certificates). Please review and renew as needed.'
tasks:
- name: run ONTAP gather facts for certificate info with specified fields
netapp.ontap.na_ontap_rest_info:
hostname: "{{ item }}"
username: "{{ lookup('env', 'ontap_admin_usr') }}"
password: "{{ lookup('env', 'ontap_admin_pwd') }}"
use_rest: always
https: true
validate_certs: false
gather_subset:
- security/certificates
fields:
- 'common_name'
- 'serial_number'
- 'ca'
- 'type'
- 'expiry_time'
- 'scope'
parameters:
type: server
loop: "{{ ontap_clusters }}"
register: certificate_info
- name: copy the results to CSV
copy:
dest: "{{ csv_file_path }}"
content: |
{{ ontap_fields|join(',') }}
{% for cluster,certs in certs.items() %}
{% for cert in certs %}
{{ ontap_fields|map('extract', cert)|join(',') }}
{% endfor %}
{% endfor %}
- name: send the results by e-mail
mail:
host: "{{ mailrelay }}"
port: 25
subject: "{{ template_vars.subject }}"
body: "{{ template_vars.body }}"
from: "{{ sender }}"
to: "{{ recipient }}"
attach:
- "{{ csv_file_path }}"
delegate_to: localhost
YAML