Skip to content

Commit

Permalink
Merge pull request #200 from vladimir-pachnik/master
Browse files Browse the repository at this point in the history
FEATURE: Add SSL client cert auth
  • Loading branch information
jakubplichta authored Jun 4, 2022
2 parents 82adb88 + 6fafb37 commit 77f4cb4
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
11 changes: 11 additions & 0 deletions grafana_dashboards/client/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,14 @@ def __init__(self, host):
def make_request(self, uri, body=None):
response = requests.post('{0}{1}'.format(self._host, uri), json=body, auth=HTTPKerberosAuth(), verify=False)
return response.json()


class SSLAuthConnection(object):
def __init__(self, host, cert_bundle, debug=0):
logger.debug('Using SSL client cert from "%s" with host=%s', cert_bundle, host)
self._host = host
self._cert = cert_bundle

def make_request(self, uri, body=None):
response = requests.post('{0}{1}'.format(self._host, uri), json=body, cert=self._cert)
return response.json()
16 changes: 15 additions & 1 deletion grafana_dashboards/client/grafana.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
import logging
import os

from grafana_dashboards.client.connection import KerberosConnection, BearerAuthConnection, BasicAuthConnection
from grafana_dashboards.client.connection import (KerberosConnection,
BearerAuthConnection,
BasicAuthConnection,
SSLAuthConnection)
from grafana_dashboards.exporter import DashboardExporter

__author__ = 'Jakub Plichta <[email protected]>'
Expand All @@ -34,11 +37,22 @@ def __init__(self, **kwargs):
username = os.getenv('GRAFANA_USERNAME', kwargs.get('username'))
auth_token = os.getenv('GRAFANA_TOKEN', kwargs.get('token'))
use_kerberos = os.getenv('GRAFANA_USE_KERBEROS', kwargs.get('use_kerberos'))
client_crt = os.getenv('GRAFANA_SSL_CLIENT_CRT', kwargs.get('ssl_client_crt'))

if use_kerberos:
self._connection = KerberosConnection(self._host)
elif auth_token:
self._connection = BearerAuthConnection(auth_token, self._host)
elif client_crt:
client_key = os.getenv('GRAFANA_SSL_CLIENT_KEY', kwargs.get('ssl_client_key'))
derived_key_path = os.path.splitext(client_crt)[0] + '.key'
# pull the separate key also if not given explicitly and derived filename exists
if client_key or (not client_key and os.path.exists(derived_key_path)):
cert_bundle = (client_crt, client_key if client_key else derived_key_path)
# otherwise assume bundled PEM
else:
cert_bundle = client_crt
self._connection = SSLAuthConnection(self._host, cert_bundle)
else:
self._connection = BasicAuthConnection(username, password, self._host)

Expand Down
16 changes: 15 additions & 1 deletion tests/grafana_dashboards/client/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
from mock import MagicMock, patch
from requests_kerberos import HTTPKerberosAuth

from grafana_dashboards.client.connection import KerberosConnection, BasicAuthConnection, BearerAuthConnection
from grafana_dashboards.client.connection import (KerberosConnection,
BearerAuthConnection,
BasicAuthConnection,
SSLAuthConnection)

__author__ = 'Jakub Plichta <[email protected]>'

Expand Down Expand Up @@ -98,3 +101,14 @@ def test_connection_with_kerberos(post):
capture = Capture()
post.assert_called_with('https://host/uri', auth=capture, json={"it's": 'alive'}, verify=False)
assert isinstance(capture.value, HTTPKerberosAuth)


@patch('requests.post')
def test_connection_with_sslauth(post):
connection = SSLAuthConnection('https://host', ('/fake/cert'))

post().json.return_value = {'hello': 'world'}

assert connection.make_request('/uri', {'it\'s': 'alive'}) == {'hello': 'world'}

post.assert_called_with('https://host/uri', json={"it's": 'alive'}, cert='/fake/cert')
13 changes: 13 additions & 0 deletions tests/grafana_dashboards/client/test_grafana.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,16 @@ def test_grafana_with_kerberos():
# noinspection PyProtectedMember
exporter._connection.make_request.assert_called_once_with('/api/dashboards/db',
body)


def test_grafana_with_sslauth():
exporter = GrafanaExporter(host='host', ssl_client_crt='/file/fake')
exporter._connection = MagicMock()

dashboard_data = {'title': 'title', 'tags': []}
exporter.process_dashboard('project_name', 'dashboard_name', dashboard_data)

body = {'overwrite': True, 'dashboard': dashboard_data}
# noinspection PyProtectedMember
exporter._connection.make_request.assert_called_once_with('/api/dashboards/db',
body)

0 comments on commit 77f4cb4

Please sign in to comment.