ysde / grafana-backup-tool

A Python-based application to backup Grafana settings by using the Grafana API
MIT License
877 stars 277 forks source link

Cannot provide path to CA bundle in SSL_VERIFY #233

Closed chriz-active closed 1 year ago

chriz-active commented 1 year ago

Goal

I want to provide and use my own certificate .pem-file.

Certificates in grafana-backup-tool

The used package handling certificates is called requests.

requests suggests, that you can provide the verify-argument in the following way:

verify – (optional) Either a boolean, in which case it controls whether we verify the server’s TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to True.

https://requests.readthedocs.io/en/latest/api/

Within grafana-backup-tool

In the grafana-backup-tool it seems that the SSL_VERIFY is used as requests-verify-argument

In https://github.com/ysde/grafana-backup-tool/blob/bedbf3d2d89b4343bf2452430bbaa739eb376d79/grafana_backup/grafanaSettings.py#L95

the SSL_VERIFY is converted to bool.

In case that this argument is not a bool, the tool crashes:

# grafana-backup save
Traceback (most recent call last):
  File "/usr/local/bin/grafana-backup", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/site-packages/grafana_backup/cli.py", line 49, in main
    settings = conf(default_config)
               ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/grafana_backup/grafanaSettings.py", line 95, in main
    VERIFY_SSL = json.loads(VERIFY_SSL.lower())  # convert environment variable string to bool
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Minimal example:

>>> import json
>>> json.loads("True".lower())
True
>>> json.loads("/etc/ssl/certs".lower())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Hacky workaround

The standard path where requests searches for certs in my alpine container:

      # >>> requests.certs.where()
      # '/usr/local/lib/python3.11/site-packages/certifi/cacert.pem'

The only way to provide my own certificate is, to overwrite this file.

acjohnson commented 1 year ago

234 is merged should be solved. Thanks!