diff options
author | Tim Bielawa <tbielawa@redhat.com> | 2017-01-13 10:38:41 -0800 |
---|---|---|
committer | Tim Bielawa <tbielawa@redhat.com> | 2017-01-17 08:58:56 -0800 |
commit | d7bf06b2c474120cb2e183d2c889662c1270bf04 (patch) | |
tree | 40520acf2adbd88fa1fe959f8de04676ffe2a0d3 | |
parent | 1236604d2ddd835ab8559cbf632481a8a21e9bea (diff) | |
download | openshift-d7bf06b2c474120cb2e183d2c889662c1270bf04.tar.gz openshift-d7bf06b2c474120cb2e183d2c889662c1270bf04.tar.bz2 openshift-d7bf06b2c474120cb2e183d2c889662c1270bf04.tar.xz openshift-d7bf06b2c474120cb2e183d2c889662c1270bf04.zip |
[Cert Expiry] Add serial numbers, include example PBs, docs
* Now includes cert serial numbers in JSON and HTML output
* Docs are updated with explicit usage instructions
* Each example playbook includes a link to the playbook and an example of how to run it
* A graphic and copy of an HTML report are now included
* Example JSON output has been updated
11 files changed, 911 insertions, 107 deletions
diff --git a/roles/openshift_certificate_expiry/README.md b/roles/openshift_certificate_expiry/README.md index a88470bdd..8f71b94ff 100644 --- a/roles/openshift_certificate_expiry/README.md +++ b/roles/openshift_certificate_expiry/README.md @@ -1,5 +1,4 @@ -OpenShift Certificate Expiration Checker -======================================== +# OpenShift Certificate Expiration Checker OpenShift certificate expiration checking. Be warned of certificates expiring within a configurable window of days, and notified of @@ -21,8 +20,7 @@ cluster. For best results run `ansible-playbook` with the `-v` option. -Role Variables --------------- +# Role Variables Core variables in this role: @@ -42,8 +40,64 @@ Optional report/result saving variables in this role: | `openshift_certificate_expiry_json_results_path` | `/tmp/cert-expiry-report.json` | The full path to save the json report as | -Example Playbook ----------------- +# Using this Role + +How to use the Certificate Expiration Checking Role. + +> **NOTE:** In the examples shown below, ensure you change **HOSTS** +> to the path of your inventory file. + +## Run with ansible-playbook + +Run one of the example playbooks using an inventory file +representative of your existing cluster. Some example playbooks are +included in this repo, or you can read on below after this example to +craft you own. + +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/easy-mode.yaml +``` + +Using the `easy-mode.yaml` playbook will produce: + +* Reports including healthy and unhealthy hosts +* A JSON report in `/tmp/` +* A stylized HTML report in `/tmp/` + + +## More Example Playbooks + +> **Note:** These Playbooks are available to run directly out of the +> [examples/playbooks/](examples/playbooks/) directory. + + +This example playbook is great if you're just wanting to **try the +role out**. This playbook enables HTML and JSON reports. The warning +window is set very large so you will almost always get results back. +All certificates (healthy or not) are included in the results: + +```yaml +--- +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + vars: + openshift_certificate_expiry_warning_days: 1500 + openshift_certificate_expiry_save_json_results: yes + openshift_certificate_expiry_generate_html_report: yes + openshift_certificate_expiry_show_all: yes + roles: + - role: openshift_certificate_expiry +``` + +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/easy-mode.yaml +``` + +> [View This Playbook](examples/playbooks/easy-mode.yaml) + +*** Default behavior: @@ -57,6 +111,16 @@ Default behavior: - role: openshift_certificate_expiry ``` +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/default.yaml +``` + + +> [View This Playbook](examples/playbooks/default.yaml) + +*** + + Generate HTML and JSON artifacts in their default paths: ```yaml @@ -72,6 +136,15 @@ Generate HTML and JSON artifacts in their default paths: - role: openshift_certificate_expiry ``` +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/html_and_json_default_paths.yaml +``` + + +> [View This Playbook](examples/playbooks/html_and_json_default_paths.yaml) + +*** + Change the expiration warning window to 1500 days (good for testing the module out): @@ -87,6 +160,15 @@ the module out): - role: openshift_certificate_expiry ``` +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/longer_warning_period.yaml +``` + + +> [View This Playbook](examples/playbooks/longer_warning_period.yaml) + +*** + Change the expiration warning window to 1500 days (good for testing the module out) and save the results as a JSON file: @@ -103,9 +185,31 @@ the module out) and save the results as a JSON file: - role: openshift_certificate_expiry ``` +``` +$ ansible-playbook -v -i HOSTS ./roles/openshift_certificate_expiry/examples/playbooks/longer-warning-period-json-results.yaml +``` + + +> [View This Playbook](examples/playbooks/longer-warning-period-json-results.yaml) + -JSON Output ------------ + +# Output Formats + +As noted above there are two ways to format your check report. In +`json` format for machine parsing, or as a stylized `html` page for +easy skimming. These options are shown below. + +## HTML Report + +![HTML Expiration Report](examples/cert-expiry-report-html.png) + +For an example of the HTML report you can browse, save +[examples/cert-expiry-report.html](examples/cert-expiry-report.html) +and then open the file in your browser. + + +## JSON Report There are two top-level keys in the saved JSON results, `data` and `summary`. @@ -122,85 +226,116 @@ certificates: * expiring within the configured warning window * already expired -The example below is abbreviated to save space: +For an example of the full JSON report, see [examples/cert-expiry-report.json](examples/cert-expiry-report.json). + +The example below is abbreviated to save space. ```json { - "data": { - "192.168.124.148": { - "etcd": [ - { - "cert_cn": "CN:etcd-signer@1474563722", - "days_remaining": 350, - "expiry": "2017-09-22 17:02:25", - "health": "warning", - "path": "/etc/etcd/ca.crt" - }, - ], - "kubeconfigs": [ - { - "cert_cn": "O:system:nodes, CN:system:node:m01.example.com", - "days_remaining": 715, - "expiry": "2018-09-22 17:08:57", - "health": "warning", - "path": "/etc/origin/node/system:node:m01.example.com.kubeconfig" - }, - { - "cert_cn": "O:system:cluster-admins, CN:system:admin", - "days_remaining": 715, - "expiry": "2018-09-22 17:04:40", - "health": "warning", - "path": "/etc/origin/master/admin.kubeconfig" - } - ], - "meta": { - "checked_at_time": "2016-10-07 15:26:47.608192", - "show_all": "True", - "warn_before_date": "2020-11-15 15:26:47.608192", - "warning_days": 1500 - }, - "ocp_certs": [ - { - "cert_cn": "CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:m01.example.com, DNS:openshift, DNS:openshift.default, DNS:openshift.default.svc, DNS:openshift.default.svc.cluster.local, DNS:172.30.0.1, DNS:192.168.124.148, IP Address:172.30.0.1, IP Address:192.168.124.148", - "days_remaining": 715, - "expiry": "2018-09-22 17:04:39", - "health": "warning", - "path": "/etc/origin/master/master.server.crt" - }, - { - "cert_cn": "CN:openshift-signer@1474563878", - "days_remaining": 1810, - "expiry": "2021-09-21 17:04:38", - "health": "ok", - "path": "/etc/origin/node/ca.crt" - } - ], - "registry": [ - { - "cert_cn": "CN:172.30.101.81, DNS:docker-registry-default.router.default.svc.cluster.local, DNS:docker-registry.default.svc.cluster.local, DNS:172.30.101.81, IP Address:172.30.101.81", - "days_remaining": 728, - "expiry": "2018-10-05 18:54:29", - "health": "warning", - "path": "/api/v1/namespaces/default/secrets/registry-certificates" - } - ], - "router": [ - { - "cert_cn": "CN:router.default.svc, DNS:router.default.svc, DNS:router.default.svc.cluster.local", - "days_remaining": 715, - "expiry": "2018-09-22 17:48:23", - "health": "warning", - "path": "/api/v1/namespaces/default/secrets/router-certs" - } - ] + "data": { + "m01.example.com": { + "etcd": [ + { + "cert_cn": "CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc,...", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:03", + "health": "warning", + "path": "/etc/origin/master/etcd.server.crt", + "serial": 7, + "serial_hex": "0x7" + } + ], + "kubeconfigs": [ + { + "cert_cn": "O:system:nodes, CN:system:node:m01.example.com", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:28", + "health": "warning", + "path": "/etc/origin/node/system:node:m01.example.com.kubeconfig", + "serial": 11, + "serial_hex": "0xb" } + ], + "meta": { + "checked_at_time": "2017-01-17 10:36:25.230920", + "show_all": "True", + "warn_before_date": "2021-02-25 10:36:25.230920", + "warning_days": 1500 + }, + "ocp_certs": [ + { + "cert_cn": "CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc,...", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:02", + "health": "warning", + "path": "/etc/origin/master/master.server.crt", + "serial": 4, + "serial_hex": "0x4" + } + ], + "registry": [ + { + "cert_cn": "CN:172.30.242.251, DNS:docker-registry-default.router.default.svc.cluster.local,...", + "days_remaining": 722, + "expiry": "2019-01-09 17:05:54", + "health": "warning", + "path": "/api/v1/namespaces/default/secrets/registry-certificates", + "serial": 13, + "serial_hex": "0xd" + } + ], + "router": [ + { + "cert_cn": "CN:router.default.svc, DNS:router.default.svc, DNS:router.default.svc.cluster.local", + "days_remaining": 722, + "expiry": "2019-01-09 17:05:46", + "health": "warning", + "path": "/api/v1/namespaces/default/secrets/router-certs", + "serial": 5050662940948454653, + "serial_hex": "0x46178f2f6b765cfd" + } + ] }, - "summary": { - "warning": 6, - "expired": 0, - "total": 7, - "ok": 1 + "n01.example.com": { + "etcd": [], + "kubeconfigs": [ + { + "cert_cn": "O:system:nodes, CN:system:node:n01.example.com", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:28", + "health": "warning", + "path": "/etc/origin/node/system:node:n01.example.com.kubeconfig", + "serial": 11, + "serial_hex": "0xb" + } + ], + "meta": { + "checked_at_time": "2017-01-17 10:36:25.217103", + "show_all": "True", + "warn_before_date": "2021-02-25 10:36:25.217103", + "warning_days": 1500 + }, + "ocp_certs": [ + { + "cert_cn": "CN:192.168.124.11, DNS:n01.example.com, DNS:192.168.124.11, IP Address:192.168.124.11", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:29", + "health": "warning", + "path": "/etc/origin/node/server.crt", + "serial": 12, + "serial_hex": "0xc" + } + ], + "registry": [], + "router": [] } + }, + "summary": { + "expired": 0, + "ok": 3, + "total": 15, + "warning": 12 + } } ``` @@ -233,24 +368,17 @@ $ jq '.summary.warning,.summary.expired' /tmp/cert-expiry-report.json ``` -Requirements ------------- - +# Requirements * None -Dependencies ------------- - +# Dependencies * None -License -------- - +# License Apache License, Version 2.0 -Author Information ------------------- +# Author Information Tim Bielawa (tbielawa@redhat.com) diff --git a/roles/openshift_certificate_expiry/examples/cert-expiry-report-html.png b/roles/openshift_certificate_expiry/examples/cert-expiry-report-html.png Binary files differnew file mode 100644 index 000000000..799131659 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/cert-expiry-report-html.png diff --git a/roles/openshift_certificate_expiry/examples/cert-expiry-report.html b/roles/openshift_certificate_expiry/examples/cert-expiry-report.html new file mode 100644 index 000000000..db03a5060 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/cert-expiry-report.html @@ -0,0 +1,396 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8" /> + <title>OCP Certificate Expiry Report</title> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /> + <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700" rel="stylesheet" /> + <style type="text/css"> + body { + font-family: 'Source Sans Pro', sans-serif; + margin-left: 50px; + margin-right: 50px; + margin-bottom: 20px; + padding-top: 70px; + } + table { + border-collapse: collapse; + margin-bottom: 20px; + } + table, th, td { + border: 1px solid black; + } + th, td { + padding: 5px; + } + .cert-kind { + margin-top: 5px; + margin-bottom: 5px; + } + footer { + font-size: small; + text-align: center; + } + tr.odd { + background-color: #f2f2f2; + } + </style> + </head> + <body> + <nav class="navbar navbar-default navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <a class="navbar-brand" href="#">OCP Certificate Expiry Report</a> + </div> + <div class="collapse navbar-collapse"> + <p class="navbar-text navbar-right"> + <button> + <a href="https://docs.openshift.com/container-platform/latest/install_config/redeploying_certificates.html" + target="_blank" + class="navbar-link"> + <i class="glyphicon glyphicon-book"></i> Redeploying Certificates + </a> + </button> + <button> + <a href="https://github.com/openshift/openshift-ansible/tree/master/roles/openshift_certificate_expiry" + target="_blank" + class="navbar-link"> + <i class="glyphicon glyphicon-book"></i> Expiry Role Documentation + </a> + </button> + </p> + </div> + </div> + </nav> + + <h1>m01.example.com</h1> + + <p> + Checked 12 total certificates. Expired/Warning/OK: 0/10/2. Warning window: 1500 days + </p> + <ul> + <li><b>Expirations checked at:</b> 2017-01-17 10:36:25.230920</li> + <li><b>Warn after date:</b> 2021-02-25 10:36:25.230920</li> + </ul> + + <table border="1" width="100%"> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">ocp_certs</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:m01.example.com, DNS:openshift, DNS:openshift.default, DNS:openshift.default.svc, DNS:openshift.default.svc.cluster.local, DNS:172.30.0.1, DNS:192.168.124.148, IP Address:172.30.0.1, IP Address:192.168.124.148</td> + <td><code>int(4)/hex(0x4)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:02</td> + <td>/etc/origin/master/master.server.crt</td> + </tr> + + <tr class="even"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:192.168.124.148, DNS:m01.example.com, DNS:192.168.124.148, IP Address:192.168.124.148</td> + <td><code>int(12)/hex(0xc)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:03:29</td> + <td>/etc/origin/node/server.crt</td> + </tr> + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-ok"></i></td> + <td style="width:33%">CN:openshift-signer@1483981200</td> + <td><code>int(1)/hex(0x1)</code></td> + <td>ok</td> + <td>1817</td> + <td>2022-01-08 17:00:01</td> + <td>/etc/origin/master/ca.crt</td> + </tr> + + <tr class="even"> + <td style="text-align:center"><i class="glyphicon glyphicon-ok"></i></td> + <td style="width:33%">CN:openshift-signer@1483981200</td> + <td><code>int(1)/hex(0x1)</code></td> + <td>ok</td> + <td>1817</td> + <td>2022-01-08 17:00:01</td> + <td>/etc/origin/node/ca.crt</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">etcd</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:m01.example.com, DNS:openshift, DNS:openshift.default, DNS:openshift.default.svc, DNS:openshift.default.svc.cluster.local, DNS:172.30.0.1, DNS:192.168.124.148, IP Address:172.30.0.1, IP Address:192.168.124.148</td> + <td><code>int(7)/hex(0x7)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:03</td> + <td>/etc/origin/master/etcd.server.crt</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">kubeconfigs</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:nodes, CN:system:node:m01.example.com</td> + <td><code>int(11)/hex(0xb)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:03:28</td> + <td>/etc/origin/node/system:node:m01.example.com.kubeconfig</td> + </tr> + + <tr class="even"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:cluster-admins, CN:system:admin</td> + <td><code>int(8)/hex(0x8)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:03</td> + <td>/etc/origin/master/admin.kubeconfig</td> + </tr> + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:masters, CN:system:openshift-master</td> + <td><code>int(3)/hex(0x3)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:02</td> + <td>/etc/origin/master/openshift-master.kubeconfig</td> + </tr> + + <tr class="even"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:routers, CN:system:openshift-router</td> + <td><code>int(9)/hex(0x9)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:03</td> + <td>/etc/origin/master/openshift-router.kubeconfig</td> + </tr> + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:registries, CN:system:openshift-registry</td> + <td><code>int(10)/hex(0xa)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:00:03</td> + <td>/etc/origin/master/openshift-registry.kubeconfig</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">router</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:router.default.svc, DNS:router.default.svc, DNS:router.default.svc.cluster.local</td> + <td><code>int(5050662940948454653)/hex(0x46178f2f6b765cfd)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:05:46</td> + <td>/api/v1/namespaces/default/secrets/router-certs</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">registry</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:172.30.242.251, DNS:docker-registry-default.router.default.svc.cluster.local, DNS:docker-registry.default.svc.cluster.local, DNS:172.30.242.251, IP Address:172.30.242.251</td> + <td><code>int(13)/hex(0xd)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:05:54</td> + <td>/api/v1/namespaces/default/secrets/registry-certificates</td> + </tr> + </table> + <hr /> + <h1>n01.example.com</h1> + + <p> + Checked 3 total certificates. Expired/Warning/OK: 0/2/1. Warning window: 1500 days + </p> + <ul> + <li><b>Expirations checked at:</b> 2017-01-17 10:36:25.217103</li> + <li><b>Warn after date:</b> 2021-02-25 10:36:25.217103</li> + </ul> + + <table border="1" width="100%"> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">ocp_certs</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">CN:192.168.124.11, DNS:n01.example.com, DNS:192.168.124.11, IP Address:192.168.124.11</td> + <td><code>int(12)/hex(0xc)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:03:29</td> + <td>/etc/origin/node/server.crt</td> + </tr> + + <tr class="even"> + <td style="text-align:center"><i class="glyphicon glyphicon-ok"></i></td> + <td style="width:33%">CN:openshift-signer@1483981200</td> + <td><code>int(1)/hex(0x1)</code></td> + <td>ok</td> + <td>1817</td> + <td>2022-01-08 17:00:01</td> + <td>/etc/origin/node/ca.crt</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">etcd</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">kubeconfigs</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + + <tr class="odd"> + <td style="text-align:center"><i class="glyphicon glyphicon-alert"></i></td> + <td style="width:33%">O:system:nodes, CN:system:node:n01.example.com</td> + <td><code>int(11)/hex(0xb)</code></td> + <td>warning</td> + <td>722</td> + <td>2019-01-09 17:03:28</td> + <td>/etc/origin/node/system:node:n01.example.com.kubeconfig</td> + </tr> + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">router</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + <tr> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">registry</h2></th> + </tr> + + <tr> + <th> </th> + <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> + <th>Health</th> + <th>Days Remaining</th> + <th>Expiration Date</th> + <th>Path</th> + </tr> + + </table> + <hr /> + + <footer> + <p> + Expiration report generated by + the <a href="https://github.com/openshift/openshift-ansible" + target="_blank">openshift-ansible</a> + <a href="https://github.com/openshift/openshift-ansible/tree/master/roles/openshift_certificate_expiry" + target="_blank">certificate expiry</a> role. + </p> + <p> + Status icons from bootstrap/glyphicon + </p> + </footer> + </body> +</html> diff --git a/roles/openshift_certificate_expiry/examples/cert-expiry-report.json b/roles/openshift_certificate_expiry/examples/cert-expiry-report.json new file mode 100644 index 000000000..8206e2842 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/cert-expiry-report.json @@ -0,0 +1,178 @@ +{ + "data": { + "m01.example.com": { + "etcd": [ + { + "cert_cn": "CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:m01.example.com, DNS:openshift, DNS:openshift.default, DNS:openshift.default.svc, DNS:openshift.default.svc.cluster.local, DNS:172.30.0.1, DNS:192.168.124.148, IP Address:172.30.0.1, IP Address:192.168.124.148", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:03", + "health": "warning", + "path": "/etc/origin/master/etcd.server.crt", + "serial": 7, + "serial_hex": "0x7" + } + ], + "kubeconfigs": [ + { + "cert_cn": "O:system:nodes, CN:system:node:m01.example.com", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:28", + "health": "warning", + "path": "/etc/origin/node/system:node:m01.example.com.kubeconfig", + "serial": 11, + "serial_hex": "0xb" + }, + { + "cert_cn": "O:system:cluster-admins, CN:system:admin", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:03", + "health": "warning", + "path": "/etc/origin/master/admin.kubeconfig", + "serial": 8, + "serial_hex": "0x8" + }, + { + "cert_cn": "O:system:masters, CN:system:openshift-master", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:02", + "health": "warning", + "path": "/etc/origin/master/openshift-master.kubeconfig", + "serial": 3, + "serial_hex": "0x3" + }, + { + "cert_cn": "O:system:routers, CN:system:openshift-router", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:03", + "health": "warning", + "path": "/etc/origin/master/openshift-router.kubeconfig", + "serial": 9, + "serial_hex": "0x9" + }, + { + "cert_cn": "O:system:registries, CN:system:openshift-registry", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:03", + "health": "warning", + "path": "/etc/origin/master/openshift-registry.kubeconfig", + "serial": 10, + "serial_hex": "0xa" + } + ], + "meta": { + "checked_at_time": "2017-01-17 10:36:25.230920", + "show_all": "True", + "warn_before_date": "2021-02-25 10:36:25.230920", + "warning_days": 1500 + }, + "ocp_certs": [ + { + "cert_cn": "CN:172.30.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:m01.example.com, DNS:openshift, DNS:openshift.default, DNS:openshift.default.svc, DNS:openshift.default.svc.cluster.local, DNS:172.30.0.1, DNS:192.168.124.148, IP Address:172.30.0.1, IP Address:192.168.124.148", + "days_remaining": 722, + "expiry": "2019-01-09 17:00:02", + "health": "warning", + "path": "/etc/origin/master/master.server.crt", + "serial": 4, + "serial_hex": "0x4" + }, + { + "cert_cn": "CN:192.168.124.148, DNS:m01.example.com, DNS:192.168.124.148, IP Address:192.168.124.148", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:29", + "health": "warning", + "path": "/etc/origin/node/server.crt", + "serial": 12, + "serial_hex": "0xc" + }, + { + "cert_cn": "CN:openshift-signer@1483981200", + "days_remaining": 1817, + "expiry": "2022-01-08 17:00:01", + "health": "ok", + "path": "/etc/origin/master/ca.crt", + "serial": 1, + "serial_hex": "0x1" + }, + { + "cert_cn": "CN:openshift-signer@1483981200", + "days_remaining": 1817, + "expiry": "2022-01-08 17:00:01", + "health": "ok", + "path": "/etc/origin/node/ca.crt", + "serial": 1, + "serial_hex": "0x1" + } + ], + "registry": [ + { + "cert_cn": "CN:172.30.242.251, DNS:docker-registry-default.router.default.svc.cluster.local, DNS:docker-registry.default.svc.cluster.local, DNS:172.30.242.251, IP Address:172.30.242.251", + "days_remaining": 722, + "expiry": "2019-01-09 17:05:54", + "health": "warning", + "path": "/api/v1/namespaces/default/secrets/registry-certificates", + "serial": 13, + "serial_hex": "0xd" + } + ], + "router": [ + { + "cert_cn": "CN:router.default.svc, DNS:router.default.svc, DNS:router.default.svc.cluster.local", + "days_remaining": 722, + "expiry": "2019-01-09 17:05:46", + "health": "warning", + "path": "/api/v1/namespaces/default/secrets/router-certs", + "serial": 5050662940948454653, + "serial_hex": "0x46178f2f6b765cfd" + } + ] + }, + "n01.example.com": { + "etcd": [], + "kubeconfigs": [ + { + "cert_cn": "O:system:nodes, CN:system:node:n01.example.com", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:28", + "health": "warning", + "path": "/etc/origin/node/system:node:n01.example.com.kubeconfig", + "serial": 11, + "serial_hex": "0xb" + } + ], + "meta": { + "checked_at_time": "2017-01-17 10:36:25.217103", + "show_all": "True", + "warn_before_date": "2021-02-25 10:36:25.217103", + "warning_days": 1500 + }, + "ocp_certs": [ + { + "cert_cn": "CN:192.168.124.11, DNS:n01.example.com, DNS:192.168.124.11, IP Address:192.168.124.11", + "days_remaining": 722, + "expiry": "2019-01-09 17:03:29", + "health": "warning", + "path": "/etc/origin/node/server.crt", + "serial": 12, + "serial_hex": "0xc" + }, + { + "cert_cn": "CN:openshift-signer@1483981200", + "days_remaining": 1817, + "expiry": "2022-01-08 17:00:01", + "health": "ok", + "path": "/etc/origin/node/ca.crt", + "serial": 1, + "serial_hex": "0x1" + } + ], + "registry": [], + "router": [] + } + }, + "summary": { + "expired": 0, + "ok": 3, + "total": 15, + "warning": 12 + } +} diff --git a/roles/openshift_certificate_expiry/examples/playbooks/default.yaml b/roles/openshift_certificate_expiry/examples/playbooks/default.yaml new file mode 100644 index 000000000..630135cae --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/playbooks/default.yaml @@ -0,0 +1,10 @@ +--- +# Default behavior, you will need to ensure you run ansible with the +# -v option to see report results: + +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + roles: + - role: openshift_certificate_expiry diff --git a/roles/openshift_certificate_expiry/examples/playbooks/easy-mode.yaml b/roles/openshift_certificate_expiry/examples/playbooks/easy-mode.yaml new file mode 100644 index 000000000..f322e7a51 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/playbooks/easy-mode.yaml @@ -0,0 +1,21 @@ +--- +# This example playbook is great if you're just wanting to try the +# role out. +# +# This example enables HTML and JSON reports +# +# The warning window is set very large so you will almost always get results back +# +# All certificates (healthy or not) are included in the results + +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + vars: + openshift_certificate_expiry_warning_days: 1500 + openshift_certificate_expiry_save_json_results: yes + openshift_certificate_expiry_generate_html_report: yes + openshift_certificate_expiry_show_all: yes + roles: + - role: openshift_certificate_expiry diff --git a/roles/openshift_certificate_expiry/examples/playbooks/html_and_json_default_paths.yaml b/roles/openshift_certificate_expiry/examples/playbooks/html_and_json_default_paths.yaml new file mode 100644 index 000000000..d80cb6ff4 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/playbooks/html_and_json_default_paths.yaml @@ -0,0 +1,12 @@ +--- +# Generate HTML and JSON artifacts in their default paths: + +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + vars: + openshift_certificate_expiry_generate_html_report: yes + openshift_certificate_expiry_save_json_results: yes + roles: + - role: openshift_certificate_expiry diff --git a/roles/openshift_certificate_expiry/examples/playbooks/longer-warning-period-json-results.yaml b/roles/openshift_certificate_expiry/examples/playbooks/longer-warning-period-json-results.yaml new file mode 100644 index 000000000..87a0f3be4 --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/playbooks/longer-warning-period-json-results.yaml @@ -0,0 +1,13 @@ +--- +# Change the expiration warning window to 1500 days (good for testing +# the module out) and save the results as a JSON file: + +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + vars: + openshift_certificate_expiry_warning_days: 1500 + openshift_certificate_expiry_save_json_results: yes + roles: + - role: openshift_certificate_expiry diff --git a/roles/openshift_certificate_expiry/examples/playbooks/longer_warning_period.yaml b/roles/openshift_certificate_expiry/examples/playbooks/longer_warning_period.yaml new file mode 100644 index 000000000..960457c4b --- /dev/null +++ b/roles/openshift_certificate_expiry/examples/playbooks/longer_warning_period.yaml @@ -0,0 +1,12 @@ +--- +# Change the expiration warning window to 1500 days (good for testing +# the module out): + +- name: Check cert expirys + hosts: nodes:masters:etcd + become: yes + gather_facts: no + vars: + openshift_certificate_expiry_warning_days: 1500 + roles: + - role: openshift_certificate_expiry diff --git a/roles/openshift_certificate_expiry/library/openshift_cert_expiry.py b/roles/openshift_certificate_expiry/library/openshift_cert_expiry.py index a474b36b0..85671b164 100644 --- a/roles/openshift_certificate_expiry/library/openshift_cert_expiry.py +++ b/roles/openshift_certificate_expiry/library/openshift_cert_expiry.py @@ -122,6 +122,8 @@ A 3-tuple of the form: (certificate_common_name, certificate_expiry_date, certif cert_loaded = OpenSSL.crypto.load_certificate( OpenSSL.crypto.FILETYPE_PEM, _cert_string) + cert_serial = cert_loaded.get_serial_number() + ###################################################################### # Read all possible names from the cert cert_subjects = [] @@ -178,7 +180,7 @@ A 3-tuple of the form: (certificate_common_name, certificate_expiry_date, certif time_remaining = cert_expiry_date - now - return (cert_subject, cert_expiry_date, time_remaining) + return (cert_subject, cert_expiry_date, time_remaining, cert_serial) def classify_cert(cert_meta, now, time_remaining, expire_window, cert_list): @@ -210,6 +212,7 @@ Return: cert_meta['health'] = 'ok' cert_meta['expiry'] = expiry_str + cert_meta['serial_hex'] = hex(int(cert_meta['serial'])) cert_list.append(cert_meta) return cert_list @@ -373,7 +376,10 @@ an OpenShift Container Platform cluster for _, v in cert_meta.items(): with open(v, 'r') as fp: cert = fp.read() - cert_subject, cert_expiry_date, time_remaining = load_and_handle_cert(cert, now) + (cert_subject, + cert_expiry_date, + time_remaining, + cert_serial) = load_and_handle_cert(cert, now) expire_check_result = { 'cert_cn': cert_subject, @@ -381,6 +387,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, ocp_certs) @@ -420,7 +427,8 @@ an OpenShift Container Platform cluster c = cfg['users'][0]['user']['client-certificate-data'] (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(c, now, base64decode=True) + time_remaining, + cert_serial) = load_and_handle_cert(c, now, base64decode=True) expire_check_result = { 'cert_cn': cert_subject, @@ -428,6 +436,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, kubeconfigs) @@ -448,7 +457,8 @@ an OpenShift Container Platform cluster c = cfg['users'][0]['user']['client-certificate-data'] (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(c, now, base64decode=True) + time_remaining, + cert_serial) = load_and_handle_cert(c, now, base64decode=True) expire_check_result = { 'cert_cn': cert_subject, @@ -456,6 +466,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, kubeconfigs) @@ -500,7 +511,8 @@ an OpenShift Container Platform cluster c = fp.read() (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(c, now) + time_remaining, + cert_serial) = load_and_handle_cert(c, now) expire_check_result = { 'cert_cn': cert_subject, @@ -508,6 +520,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, etcd_certs) @@ -537,7 +550,8 @@ an OpenShift Container Platform cluster with open(etcd_cert, 'r') as etcd_fp: (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(etcd_fp.read(), now) + time_remaining, + cert_serial) = load_and_handle_cert(etcd_fp.read(), now) expire_check_result = { 'cert_cn': cert_subject, @@ -545,6 +559,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, etcd_certs) @@ -581,7 +596,8 @@ an OpenShift Container Platform cluster else: (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(router_c, now, base64decode=True) + time_remaining, + cert_serial) = load_and_handle_cert(router_c, now, base64decode=True) expire_check_result = { 'cert_cn': cert_subject, @@ -589,6 +605,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, router_certs) @@ -610,7 +627,8 @@ an OpenShift Container Platform cluster else: (cert_subject, cert_expiry_date, - time_remaining) = load_and_handle_cert(registry_c, now, base64decode=True) + time_remaining, + cert_serial) = load_and_handle_cert(registry_c, now, base64decode=True) expire_check_result = { 'cert_cn': cert_subject, @@ -618,6 +636,7 @@ an OpenShift Container Platform cluster 'expiry': cert_expiry_date, 'days_remaining': time_remaining.days, 'health': None, + 'serial': cert_serial } classify_cert(expire_check_result, now, time_remaining, expire_window, registry_certs) diff --git a/roles/openshift_certificate_expiry/templates/cert-expiry-table.html.j2 b/roles/openshift_certificate_expiry/templates/cert-expiry-table.html.j2 index b05110336..1d4bb24e9 100644 --- a/roles/openshift_certificate_expiry/templates/cert-expiry-table.html.j2 +++ b/roles/openshift_certificate_expiry/templates/cert-expiry-table.html.j2 @@ -45,11 +45,20 @@ </div> <div class="collapse navbar-collapse"> <p class="navbar-text navbar-right"> - <a href="https://docs.openshift.com/container-platform/latest/install_config/redeploying_certificates.html" - target="_blank" - class="navbar-link"> - <i class="glyphicon glyphicon-book"></i> Redeploying Certificates - </a> + <button> + <a href="https://docs.openshift.com/container-platform/latest/install_config/redeploying_certificates.html" + target="_blank" + class="navbar-link"> + <i class="glyphicon glyphicon-book"></i> Redeploying Certificates + </a> + </button> + <button> + <a href="https://github.com/openshift/openshift-ansible/tree/master/roles/openshift_certificate_expiry" + target="_blank" + class="navbar-link"> + <i class="glyphicon glyphicon-book"></i> Expiry Role Documentation + </a> + </button> </p> </div> </div> @@ -71,12 +80,13 @@ {# These are hard-coded right now, but should be grabbed dynamically from the registered results #} {%- for kind in ['ocp_certs', 'etcd', 'kubeconfigs', 'router', 'registry'] -%} <tr> - <th colspan="6" style="text-align:center"><h2 class="cert-kind">{{ kind }}</h2></th> + <th colspan="7" style="text-align:center"><h2 class="cert-kind">{{ kind }}</h2></th> </tr> <tr> <th> </th> <th style="width:33%">Certificate Common/Alt Name(s)</th> + <td>Serial</th> <th>Health</th> <th>Days Remaining</th> <th>Expiration Date</th> @@ -98,6 +108,7 @@ <tr class="{{ loop.cycle('odd', 'even') }}"> <td style="text-align:center"><i class="{{ health_icon }}"></i></td> <td style="width:33%">{{ v.cert_cn }}</td> + <td><code>int({{ v.serial }})/hex({{ v.serial_hex }})</code></td> <td>{{ v.health }}</td> <td>{{ v.days_remaining }}</td> <td>{{ v.expiry }}</td> @@ -114,7 +125,11 @@ <footer> <p> - Expiration report generated by <a href="https://github.com/openshift/openshift-ansible" target="_blank">openshift-ansible</a> + Expiration report generated by + the <a href="https://github.com/openshift/openshift-ansible" + target="_blank">openshift-ansible</a> + <a href="https://github.com/openshift/openshift-ansible/tree/master/roles/openshift_certificate_expiry" + target="_blank">certificate expiry</a> role. </p> <p> Status icons from bootstrap/glyphicon |