Add support for user defined HTTP header to Patroni REST API response (#1645)

Close #1644
This commit is contained in:
Yogesh Sharma
2020-08-26 17:37:02 +02:00
committed by GitHub
parent 35c3fd37a1
commit 62463db5e2
5 changed files with 34 additions and 1 deletions
+2
View File
@@ -143,6 +143,8 @@ REST API
- **PATRONI\_RESTAPI\_KEYFILE**: Specifies the file with the secret key in the PEM format.
- **PATRONI\_RESTAPI\_CAFILE**: Specifies the file with the CA_BUNDLE with certificates of trusted CAs to use while verifying client certs.
- **PATRONI\_RESTAPI\_VERIFY\_CLIENT**: ``none`` (default), ``optional`` or ``required``. When ``none`` REST API will not check client certificates. When ``required`` client certificates are required for all REST API calls. When ``optional`` client certificates are required for all unsafe REST API endpoints. When ``required`` is used, then client authentication succeeds, if the certificate signature verification succeeds. For ``optional`` the client cert will only be checked for ``PUT``, ``POST``, ``PATCH``, and ``DELETE`` requests.
- **PATRONI\_RESTAPI\_HTTP\_EXTRA\_HEADERS**: (optional) HTTP headers let the REST API server pass additional information with an HTTP response.
- **PATRONI\_RESTAPI\_HTTPS\_EXTRA\_HEADERS**: (optional) HTTPS headers let the REST API server pass additional information with an HTTP response when TLS is enabled. This will also pass additional information set in ``http_extra_headers``.
CTL
---
+22
View File
@@ -272,6 +272,28 @@ REST API
- **keyfile**: (optional): Specifies the file with the secret key in the PEM format.
- **cafile**: (optional): Specifies the file with the CA_BUNDLE with certificates of trusted CAs to use while verifying client certs.
- **verify\_client**: (optional): ``none`` (default), ``optional`` or ``required``. When ``none`` REST API will not check client certificates. When ``required`` client certificates are required for all REST API calls. When ``optional`` client certificates are required for all unsafe REST API endpoints. When ``required`` is used, then client authentication succeeds, if the certificate signature verification succeeds. For ``optional`` the client cert will only be checked for ``PUT``, ``POST``, ``PATCH``, and ``DELETE`` requests.
- **http\_extra\_headers**: (optional): HTTP headers let the REST API server pass additional information with an HTTP response.
- **https\_extra\_headers**: (optional): HTTPS headers let the REST API server pass additional information with an HTTP response when TLS is enabled. This will also pass additional information set in ``http_extra_headers``.
Here is an example of both **http_extra_headers** and **https_extra_headers**:
.. code:: YAML
restapi:
listen: <listen>
connect_address: <connect_address>
authentication:
username: <username>
password: <password>
http_extra_headers:
'X-Frame-Options': 'SAMEORIGIN'
'X-XSS-Protection': '1; mode=block'
'X-Content-Type-Options': 'nosniff'
cafile: <ca file>
certfile: <cert>
keyfile: <key>
https_extra_headers:
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'
.. _patronictl_settings:
+6
View File
@@ -38,6 +38,8 @@ class RestApiHandler(BaseHTTPRequestHandler):
headers['Content-Type'] = content_type
for name, value in headers.items():
self.send_header(name, value)
for name, value in self.server.patroni.api.http_extra_headers.items():
self.send_header(name, value)
self.end_headers()
self.wfile.write(body.encode('utf-8'))
@@ -533,6 +535,7 @@ class RestApiServer(ThreadingMixIn, HTTPServer, Thread):
self.patroni = patroni
self.__listen = None
self.__ssl_options = None
self.http_extra_headers = {}
self.reload_config(config)
self.daemon = True
@@ -667,6 +670,9 @@ class RestApiServer(ThreadingMixIn, HTTPServer, Thread):
ssl_options = {n: config[n] for n in ('certfile', 'keyfile', 'cafile') if n in config}
self.http_extra_headers = config.get('http_extra_headers') or {}
self.http_extra_headers.update(ssl_options.get('certfile') and config.get('https_extra_headers') or {})
if isinstance(config.get('verify_client'), six.string_types):
ssl_options['verify_client'] = config['verify_client'].lower()
+2 -1
View File
@@ -244,7 +244,8 @@ class Config(object):
if value:
ret[section][param] = value
_set_section_values('restapi', ['listen', 'connect_address', 'certfile', 'keyfile', 'cafile', 'verify_client'])
_set_section_values('restapi', ['listen', 'connect_address', 'certfile', 'keyfile', 'cafile', 'verify_client',
'http_extra_headers', 'https_extra_headers'])
_set_section_values('ctl', ['insecure', 'cacert', 'certfile', 'keyfile'])
_set_section_values('postgresql', ['listen', 'connect_address', 'config_dir', 'data_dir', 'pgpass', 'bin_dir'])
_set_section_values('log', ['level', 'traceback_level', 'format', 'dateformat', 'max_queue_size',
+2
View File
@@ -120,6 +120,8 @@ class MockPatroni(object):
logger = MockLogger()
tags = {}
version = '0.00'
api = Mock()
api.http_extra_headers = {}
noloadbalance = PropertyMock(return_value=False)
scheduled_restart = {'schedule': future_restart_time,
'postmaster_start_time': postgresql.postmaster_start_time()}