8000 Add tls_auth_handler for push gateway · glagny/client_python@82eca8f · GitHub
[go: up one dir, main page]

Skip to content

Commit 82eca8f

Br 8000 owse files
committed
Add tls_auth_handler for push gateway
Support pushing metrics to a push gateway instance running with TLS Authentication. A user will need to provide the appropriate certificates to send to the server, and can specify additional parameters depending on their setup. Signed-off-by: Chris Marchbanks <csmarchbanks@gmail.com>
1 parent f17a836 commit 82eca8f

File tree

5 files changed

+154
-4
lines changed

5 files changed

+154
-4
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,24 @@ g.set_to_current_time()
471471
push_to_gateway('localhost:9091', job='batchA', registry=registry, handler=my_auth_handler)
472472
```
473473

474+
TLS Auth is also supported when using the push gateway with a special handler.
475+
476+
```python
477+
from prometheus_client import CollectorRegistry, Gauge, push_to_gateway
478+
from prometheus_client.exposition import tls_handler
479+
480+
481+
def my_auth_handler(url, method, timeout, headers, data):
482+
certfile = 'client-crt.pem'
483+
keyfile = 'client-key.pem'
484+
return tls_auth_handler(url, method, timeout, headers, data, certfile, keyfile)
485+
486+
registry = CollectorRegistry()
487+
g = Gauge('job_last_success_unixtime', 'Last time a batch job successfully finished', registry=registry)
488+
g.set_to_current_time()
489+
push_to_gateway('localhost:9091', job='batchA', registry=registry, handler=my_auth_handler)
490+
```
491+
474492
## Bridges
475493

476494
It is also possible to expose metrics to systems other than Prometheus.

prometheus_client/exposition.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
import os
66
import socket
77
from socketserver import ThreadingMixIn
8+
import ssl
89
import sys
910
import threading
10-
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple
11+
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
1112
from urllib.error import HTTPError
1213
from urllib.parse import parse_qs, quote_plus, urlparse
1314
from urllib.request import (
14-
build_opener, HTTPHandler, HTTPRedirectHandler, Request,
15+
BaseHandler, build_opener, HTTPHandler, HTTPRedirectHandler, HTTPSHandler,
16+
Request,
1517
)
1618
import warnings
1719
from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer
@@ -324,7 +326,7 @@ def _make_handler(
324326
timeout: Optional[float],
325327
headers: Sequence[Tuple[str, str]],
326328
data: bytes,
327-
base_handler: type,
329+
base_handler: Union[BaseHandler, type],
328330
) -> Callable[[], None]:
329331
def handle() -> None:
330332
request = Request(url, data=data)
@@ -399,6 +401,40 @@ def handle():
399401
return handle
400402

401403

404+
def tls_auth_handler(
405+
url: str,
406+
method: str,
407+
timeout: Optional[float],
408+
headers: List[Tuple[str, str]],
409+
data: bytes,
410+
certfile: str,
411+
keyfile: str,
412+
cafile: Optional[str] = None,
413+
protocol: int = ssl.PROTOCOL_TLS_CLIENT,
414+
insecure_skip_verify: bool = False,
415+
) -> Callable[[], None]:
416+
"""Handler that implements an HTTPS connection with TLS Auth.
417+
418+
The default protocol (ssl.PROTOCOL_TLS_CLIENT) will also enable
419+
ssl.CERT_REQUIRED and SSLContext.check_hostname by default. This can be
420+
disabled by setting insecure_skip_verify to True.
421+
422+
Both this handler and the TLS feature on pushgateay are experimental."""
423+
context = ssl.SSLContext(protocol=protocol)
424+
if cafile is not None:
425+
context.load_verify_locations(cafile)
426+
else:
427+
context.load_default_certs()
428+
429+
if insecure_skip_verify:
430+
context.check_hostname = False
431+
context.verify_mode = ssl.CERT_NONE
432+
433+
context.load_cert_chain(certfile=certfile, keyfile=keyfile)
434+
handler = HTTPSHandler(context=context)
435+
return _make_handler(url, method, timeout, headers, data, handler)
436+
437+
402438
def push_to_gateway(
403439
gateway: str,
404440
job: str,

tests/certs/cert.pem

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIFkzCCA3ugAwIBAgIUWhYKmrh+gF5pZ7Yqj41cWJ2pRzkwDQYJKoZIhvcNAQEL
3+
BQAwWTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4+
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MB4X
5+
DTIyMDkyMDE4NTQzOFoXDTIyMTAyMDE4NTQzOFowWTELMAkGA1UEBhMCVVMxEzAR
6+
BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
7+
IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
8+
MIICCgKCAgEAxs6v9c/bNtA0TjNOzSoIq2CQuBhjWt8nwVG7Ujn3JBSvC263foRq
9+
OG0oGhaFrbt4HrbikYeSo5u/0CDBfKBIr7nuWifpISUovNSm2EVgVL7YQhgPOSvb
10+
PiJhrflfkUBZWUlNf0EAcFOn29xSvw3ElDUtxqUql39RRXUah1JDIIJpFPENwbmB
11+
4jN5AoumdzSZde3S1xAXqoPf7gwxvsIgBKYGxRZs95DLx3HwesDAmRdmXcLShNZm
12+
RpUbIbomn4w3mf7S0QZ7H49/IHRghw61/TGKCX6ieJ8QTWwnBgo9EiwhhuTCVtFw
13+
IFhzQy5sP2b6mYkxQK4enYiHkTEHESdV9ipDoyZfE3G+WojEa65OYkrBFaZbuJ8q
14+
lBjRCA+pyXfxa40XkK4x3aibvdKeH1CGE+rYhxPYC6emu0Jk1wMO5TNff2Gv+eJv
15+
GEQXuyQPC5SmgSpy0tWwO9ReYmDU1++gbmFZc1QVB0GI/WxgF+PpBBEa8naFXxbe
16+
ZWG3Q6pFfrIJ3pbhb1lkTlk2zpJO2hTDUIBIn6pdVBbv+QAqCyu94gItfUxWWNL9
17+
SHT+dfyX4CtpF9R9m9VltoKqXKcVhnjkPc9wG03TBcJdCZT3e9sg8bSz09hwx+HO
18+
5x8RrLkqUd7PFznhX59k/xhXTSIdtdWEfrhPjy2L36o2bEEpPL70qfMCAwEAAaNT
19+
MFEwHQYDVR0OBBYEFJOiGRDrPKW5+qvVZzs+Yu8qPNJnMB8GA1UdIwQYMBaAFJOi
20+
GRDrPKW5+qvVZzs+Yu8qPNJnMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
21+
BQADggIBALbV73MLFz24tQpC8Ax6vh9okeuc5n2eVOk/ofe2A9DL16IeMyJo8QAG
22+
dK2j+mfZBvPfYYX/Uz596bOLauRKAsXm3ERmPW74nemLE4CiMhod2snIUMbSHrem
23+
6iFLIqGGosncoqHIPJej4sG+XLKsqw8zLzflUSsvNveaHEwt2PSZys37bExADbB5
24 F438 +
uj4JU+vEBhagZ6ieZ3hENn3Uj5c46kimXrEStD3chT2PWoLAS4Am6VJyXUtqXQZj
25+
1ef+S+6caCbldaJNfNEVU1jQliJpo0u+EfiF/DqU799xnnoW4D132AxiG0L1jPFr
26+
7GbIme6H2ZbNCZngf6eCbdsoHAGkQZpD3wYFHLmTFDCNmjMJteb3YFMNHyU5eh8C
27+
2bTp4D+pifgFRo3Mc23kuRXiIzyrhg/eOHl+Qi2V8BpXP/7bI27FZXglp9rzhP57
28+
YMfBeoOejRgRHJTeMPhBbEevQyqpb9ecZxpuGV77Pi3S5IA26fe3pZQCHRceufZr
29+
YKWLOCt2jZJ0y9KM4wdVg40yr6BVZqy2OPqDn64q0pAgMHG24XrxxuaFISjgPOgx
30+
bYhhTUG/4Dkb1BWhfEv4EwEf/uDxhHE8k6LoKk3Qb+aOzPr2PKGvW3yBHEFNSmKH
31+
x3SB8xxj/IOiA+em+TLtKd66gG0T0b8cPt037k+D3a0BqC9d2sVs
32+
-----END CERTIFICATE-----

tests/certs/key.pem

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-----BEGIN PRIVATE KEY-----
2+
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
51+
YdxZTB2pN96tqnBm8vyvi81Cdy/x
52+
-----END PRIVATE KEY-----

tests/test_exposition.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from http.server import BaseHTTPRequestHandler, HTTPServer
2+
import os
23
import threading
34
import time
45
import unittest
@@ -14,7 +15,7 @@
1415
from prometheus_client.core import GaugeHistogramMetricFamily, Timestamp
1516
from prometheus_client.exposition import (
1617
basic_auth_handler, choose_encoder, choose_formatter, default_handler,
17-
MetricsHandler, passthrough_redirect_handler,
18+
MetricsHandler, passthrough_redirect_handler, tls_auth_handler,
1819
)
1920
import prometheus_client.openmetrics.exposition as openmetrics
2021

@@ -343,6 +344,17 @@ def my_auth_handler(url, method, timeout, headers, data):
343344
self.assertEqual(self.requests[0][0].headers.get('content-type'), CONTENT_TYPE_LATEST)
344345
self.assertEqual(self.requests[0][1], b'# HELP g help\n# TYPE g gauge\ng 0.0\n')
345346

347+
def test_push_with_tls_auth_handler(self):
348+
def my_auth_handler(url, method, timeout, headers, data):
349+
certs_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'certs')
350+
return tls_auth_handler(url, method, timeout, headers, data, os.path.join(certs_dir, "cert.pem"), os.path.join(certs_dir, "key.pem"))
351+
352+
push_to_gateway(self.address, "my_job_with_tls_auth", self.registry, handler=my_auth_handler)
353+
self.assertEqual(self.requests[0][0].command, 'PUT')
354+
self.assertEqual(self.requests[0][0].path, '/metrics/job/my_job_with_tls_auth')
355+
self.assertEqual(self.requests[0][0].headers.get('content-type'), CONTENT_TYPE_LATEST)
356+
self.assertEqual(self.requests[0][1], b'# HELP g help\n# TYPE g gauge\ng 0.0\n')
357+
346358
def test_push_with_redirect_handler(self):
347359
def my_redirect_handler(url, method, timeout, headers, data):
348360
return passthrough_redirect_handler(url, method, timeout, headers, data)

0 commit comments

Comments
 (0)
0