diff --git a/plugins/puppet/puppetdb b/plugins/puppet/puppetdb index 7eb1352a..a4d55aa4 100755 --- a/plugins/puppet/puppetdb +++ b/plugins/puppet/puppetdb @@ -21,11 +21,33 @@ Plugin configuration parameters: Time in seconds (int) to wait for a result when querying the REST API. By default, wait for 2 seconds + * ca: + Path to the Certificate Authority used for verifying a cert received from + the PuppetDB server during an https connection. This can be useful if the + cert used by PuppetDB was signed by the puppetmaster's CA. This option is + not necessary if a plaintext connection is used (e.g. if pdburl starts + with 'http://'). + + * cert: + Path to the TLS certificate file used for establishing client + communication for an https connection. This option should be paired with + the `key` option. This option is not necessary if a plaintext connection + is used (e.g. if pdburl starts with 'http://'). + + * key: + Path to the TLS private key used for establishing client communication for + an https connection. This option should be paired with the `cert` option. + This option is not necessary if a plaintext connection is used (e.g. if + pdburl starts with 'http://'). + Example: [puppetdb] env.pdburl https://puppetdb.example.com:8080/metrics/v1/mbeans env.timeout 5 + env.ca /etc/puppetboard/ca.pem + env.cert /etc/puppetboard/client_cert.pem + env.key /etc/puppetboard/client_key.pem =head1 DEPENDENCIES @@ -54,14 +76,21 @@ class WrongStatusCode(Exception): pass -def rest_request(url, timeout): +def rest_request(url, timeout, ca, key_pair): """Make a GET request to URL. We expect a 200 response. This function will let exceptions from requests raise through to indicate request failure. If response code is not 200, it will raise a WrongStatusCode exception. """ headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'} - resp = requests.get(url, headers=headers, timeout=timeout) + + ssl_options = {} + if ca: + ssl_options['verify'] = ca + if key_pair: + ssl_options['cert'] = key_pair + + resp = requests.get(url, headers=headers, timeout=timeout, **ssl_options) if resp.status_code != 200: err = f"GET Request to '{url}' returned code {resp.status_code}; expected 200." # noqa: E501 raise WrongStatusCode(err) @@ -93,12 +122,12 @@ def config(): print("jvm_mem_used.draw AREA") -def fetch_field_values(mbeans_url, timeout): +def fetch_field_values(mbeans_url, timeout, ca, key_pair): """Get values from PuppetDB and print them out.""" memory_url = f"{mbeans_url}/java.lang:type=Memory" try: - mem_req = rest_request(memory_url, timeout) + mem_req = rest_request(memory_url, timeout, ca, key_pair) except Exception as e: print(f"HTTP Request did not complete successfully: {e}", file=sys.stderr) @@ -134,9 +163,31 @@ if __name__ == '__main__': print(f"Invalid value for timeout: {e}", file=sys.stderr) exit(1) + ca = os.environ.get('ca', None) + if ca: + if not os.path.exists(ca): + print(f"CA file '{ca}' not found.", file=sys.stderr) + exit(1) + + cert = os.environ.get('cert', None) + key = os.environ.get('key', None) + if cert or key: + if cert and key: + if not os.path.exists(cert): + print(f"Certificate file '{cert}' not found.", file=sys.stderr) + exit(1) + if not os.path.exists(key): + print(f"Key file '{key}' not found.", file=sys.stderr) + exit(1) + else: + print("Only one of 'cert' and 'key' supplied. " + "Both are needed for client authentication.", + file=sys.stderr) + exit(1) + if len(sys.argv) > 1 and sys.argv[1] == 'autoconf': try: - dummy = rest_request(mbeans_url, timeout) + dummy = rest_request(mbeans_url, timeout, ca, (cert, key)) except Exception as e: print(f"no ({e})") exit(0) @@ -148,4 +199,4 @@ if __name__ == '__main__': config() exit(0) - fetch_field_values(mbeans_url, timeout) + fetch_field_values(mbeans_url, timeout, ca, (cert, key))