Reorganise for the urllib3 > requests change

This commit is contained in:
benoit 2023-03-14 18:02:53 +01:00 committed by Benoit
parent 2443505ad6
commit 7eea4c94be
4 changed files with 47 additions and 93 deletions

View file

@ -24,9 +24,9 @@ Options:
services check the status of the cluster, therefore
it's better to give a list of all Patroni node
addresses. [default: http://127.0.0.1:8008]
--cert_file TEXT File with the client certificate.
--key_file TEXT File with the client key.
--ca_file TEXT The CA certificate.
--cert_file PATH File with the client certificate.
--key_file PATH File with the client key.
--ca_file PATH The CA certificate.
-v, --verbose Increase verbosity -v (info)/-vv (warning)/-vvv
(debug)
--version
@ -103,30 +103,13 @@ check_patroni -e https://10.20.199.3:8008 cluster_has_replica --warning 2: --cri
```
## SSL
Several option are available:
Several options are available:
* you have a self-signed certificate:
* the server's CA certificate is not available or trusted by the client system:
* `--ca_cert`: your certification chain `cat CA-certificate server-certificate > cabundle`
* you have a valid root certificate:
* you have a client certificate for authenticating with Patroni's REST API:
* `--cert_file`: your certificate or the concatenation of your certificate and private key
* `--key_file`: your private key (optional)
* `--ca_cert`: if your CA certificate is not installed on the server you can provide it here (optional)
* unsafe access: dont provide any info, you will get a warning as described below.
If you configuration is unsafe you might get warning message such as:
```
$ check_patroni -e https://p1:8008 cluster_node_count
/home/vagrant/.local/lib/python3.9/site-packages/urllib3/connectionpool.py:1045: InsecureRequestWarning: Unverified HTTPS request is being made to host 'p1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
warnings.warn(
CLUSTERNODECOUNT OK - members is 2 | members=2 role_leader=1 role_replica=1 state_running=2
```
After checking on the message, you can choose to ignore it by redirecting the
standart output to /dev/null:
```
$ check_patroni -e https://p1:8008 cluster_node_count 2>/dev/null
CLUSTERNODECOUNT OK - members is 2 | members=2 role_leader=1 role_replica=1 state_running=2
```
## Cluster services
@ -230,7 +213,7 @@ Usage: check_patroni cluster_node_count [OPTIONS]
Count the number of nodes in the cluster.
The state refers to the state of PostgreSQL. Possible values are:
* initalizing new cluster, initdb failed
* initializing new cluster, initdb failed
* running custom bootstrap script, custom bootstrap failed
* starting, start failed
* restarting, restart failed

View file

@ -100,19 +100,22 @@ def configure(ctx: click.Context, param: str, filename: str) -> None:
@click.option(
"--cert_file",
"cert_file",
type=str,
type=click.Path(exists=True),
default=None,
help="File with the client certificate.",
)
@click.option(
"--key_file",
"key_file",
type=str,
type=click.Path(exists=True),
default=None,
help="File with the client key.",
)
@click.option(
"--ca_file",
"ca_file",
type=str,
type=click.Path(exists=True),
default=None,
help="The CA certificate.",
)
@click.option(
@ -166,8 +169,14 @@ def main(
logging.basicConfig(format="%(levelname)s - %(message)s", level=logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG)
connection_info: ConnectionInfo
if cert_file is None and key_file is None:
connection_info = ConnectionInfo(endpoints, None, ca_file)
else:
connection_info = ConnectionInfo(endpoints, (cert_file, key_file), ca_file)
ctx.obj = Parameters(
ConnectionInfo(endpoints, cert_file, key_file, ca_file),
connection_info,
timeout,
verbose,
)

View file

@ -1,4 +1,5 @@
import logging
from urllib.parse import urlparse
import attr
import nagiosplugin
@ -17,8 +18,7 @@ class APIError(requests.exceptions.RequestException):
@attr.s(auto_attribs=True, frozen=True, slots=True)
class ConnectionInfo:
endpoints: List[str] = ["http://127.0.0.1:8008"]
cert_file: Optional[str] = None
key_file: Optional[str] = None
cert: Optional[Union[str, Tuple[str, str]]] = None
ca_cert: Optional[str] = None
@ -36,54 +36,33 @@ class PatroniResource(nagiosplugin.Resource):
def rest_api(self: "PatroniResource", service: str) -> Any:
"""Try to connect to all the provided endpoints for the requested service"""
for endpoint in self.conn_info.endpoints:
cert: Optional[Union[Tuple[str, str], str]] = None
verify: Optional[Union[str, bool]] = None
if urlparse(endpoint).scheme == "https":
if self.conn_info.cert is not None:
# we can have: a key + a cert or a single file with key and cert.
cert = self.conn_info.cert
if self.conn_info.ca_cert is not None:
verify = self.conn_info.ca_cert
_log.debug(
f"Trying to connect to {endpoint}/{service} with cert: {cert} verify: {verify}"
)
try:
cert: Optional[Union[Tuple[str, str], str]] = None
verify: Optional[Union[str, bool]] = None
if endpoint[:5] == "https":
if (
self.conn_info.cert_file is not None
and self.conn_info.key_file is not None # noqa W503
):
# we provide a certificate and a private key
cert = (self.conn_info.cert_file, self.conn_info.key_file)
elif (
self.conn_info.cert_file is not None
and self.conn_info.key_file is None # noqa W503
):
# we provide a pem file with the private key and the certificate
cert = self.conn_info.cert_file
if self.conn_info.ca_cert is not None:
# if cert is not None: this is the CA certificate
# otherwise this is a ca bundle with root certificate
# then some optional intermediate certificate and finally
# the cerver certificate to validate the certification chain
verify = self.conn_info.ca_cert
else:
if cert is None:
# if cert is None we want to bypass https verification,
# this is in secure and should be avoided for production use
verify = False
_log.debug(
f"Trying to connect to {endpoint}/{service} with cert: {cert} verify: {verify}"
)
r = requests.get(f"{endpoint}/{service}", verify=verify, cert=cert)
# The status code is already handled by urllib3
_log.debug(f"api call data: {r.text}")
if r.status_code != 200:
raise APIError(
f"Failed to connect to {endpoint}/{service} status code {r.status_code}"
)
return r.json()
except nagiosplugin.Timeout as e:
raise e
except Exception as e:
_log.debug(e)
continue
# The status code is already handled by urllib3
_log.debug(f"api call data: {r.text}")
if r.status_code != 200:
raise APIError(
f"Failed to connect to {endpoint}/{service} status code {r.status_code}"
)
return r.json()
raise nagiosplugin.CheckError("Connection failed for all provided endpoints")

View file

@ -87,30 +87,13 @@ check_patroni -e https://10.20.199.3:8008 cluster_has_replica --warning 2: --cri
```
## SSL
Several option are available:
Several options are available:
* you have a self-signed certificate:
* the server's CA certificate is not available or trusted by the client system:
* `--ca_cert`: your certification chain `cat CA-certificate server-certificate > cabundle`
* you have a valid root certificate:
* you have a client certificate for authenticating with Patroni's REST API:
* `--cert_file`: your certificate or the concatenation of your certificate and private key
* `--key_file`: your private key (optional)
* `--ca_cert`: if your CA certificate is not installed on the server you can provide it here (optional)
* unsafe access: dont provide any info, you will get a warning as described below.
If you configuration is unsafe you might get warning message such as:
```
$ check_patroni -e https://p1:8008 cluster_node_count
/home/vagrant/.local/lib/python3.9/site-packages/urllib3/connectionpool.py:1045: InsecureRequestWarning: Unverified HTTPS request is being made to host 'p1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
warnings.warn(
CLUSTERNODECOUNT OK - members is 2 | members=2 role_leader=1 role_replica=1 state_running=2
```
After checking on the message, you can choose to ignore it by redirecting the
standart output to /dev/null:
```
$ check_patroni -e https://p1:8008 cluster_node_count 2>/dev/null
CLUSTERNODECOUNT OK - members is 2 | members=2 role_leader=1 role_replica=1 state_running=2
```
_EOF_
readme