Skip to content

Commit

Permalink
Certificate verification, part 2
Browse files Browse the repository at this point in the history
Details:

* Changed default to verify the HMC certificate.

* Documented how the REQUESTS_CA_BUNDLE and CURL_CA_BUNDLE env vars are
  used.

* Other documentation improvements in the HMC certificate section.

Signed-off-by: Andreas Maier <[email protected]>
  • Loading branch information
andy-maier committed May 19, 2021
1 parent 5cc3f18 commit 9a30f28
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 39 deletions.
7 changes: 3 additions & 4 deletions docs/appendix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,16 @@ The root cause is that the HMC is set up to use a self-signed certificate
and the client has used ``verify_cert=True`` in the :class:`zhmcclient.Session`
initialization, which is the default. That causes the client to use the
Python 'certifi' package for verification of the server certificate and the
'certifi' package rejects self-signed certificates. The 'certifi' package
uses the certificates from the
'certifi' package provides the CA certificates from the
`Mozilla Included CA Certificate List <https://wiki.mozilla.org/CA/Included_Certificates>`_
for verifying the server certificate.
which does not include the self-signed certificate.

The issue can be temporarily circumvented by specifying ``verify_cert=False``,
which disables the verification of the server certificate. Since that makes
the connection vulnerable to man-in-the-middle attacks, it should be done
only as a temporary circumvention.

The solution is to have your HMC administrator obtain a proper CA-verifyable
The solution is to have your HMC administrator obtain a CA-verifiable
certificate and to install that in the HMC.

See also the :ref:`Security` section.
Expand Down
11 changes: 9 additions & 2 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Released: not yet
are now raised as a new exception 'NotificationParseError'. Both new
exceptions are based on a new base exception 'NotificationError'. (issue #770)

* By default, the zhmcclient now verifies the HMC certificate using the
CA certificates in the Python 'certifi' package. This can be controlled with
a new 'verify_cert' init parameter to the 'zhmcclient.Session' class. (issue #779)

**Deprecations:**

**Bug fixes:**
Expand All @@ -51,14 +55,17 @@ Released: not yet
**Enhancements:**

* Added a 'verify_cert' init parameter to the 'zhmcclient.Session' class to
enable verificatin of the server certificate presented by the HMC during
SSL/TLS handshake.
enable verification of the server certificate presented by the HMC during
SSL/TLS handshake. By default, the certificate is validated against
the CA certificates provided in the Python 'certifi' package. (issue #779)

* Docs: Added a section "Security" to the documentation that describes security
related aspects in the communication between the zhmcclient and the HMC.
(related to issue #779)

* Docs: Added a section "Troubleshooting" to appendix of the documentation that
currently lists two cases of communication related issues.
(related to issue #779)

**Cleanup:**

Expand Down
89 changes: 67 additions & 22 deletions docs/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ This section contains information about the security of the communication
between the 'zhmcclient' client and the HMC.


.. _`HMC Web Services API`:

HMC Web Services API
--------------------

Expand Down Expand Up @@ -53,33 +55,74 @@ You can display the OpenSSL version used by Python using this command:
$ python -c "import ssl; print(ssl.OPENSSL_VERSION)"
OpenSSL 1.1.1i 8 Dec 2020
Server certificate
^^^^^^^^^^^^^^^^^^
By default, the HMC is configured with a self-signed certificate at its
Web Services API. Self-signed certificates are rejected by the 'certifi' package.
The HMC should be configured to use a proper CA-verifyable certificate. This
can be done in the HMC task "Certificate Management".
See also the :term:`HMC Security` book and Chapter 3 "Invoking API operations"
in the :term:`HMC API` book.
.. _`HMC certificate`:

HMC certificate
^^^^^^^^^^^^^^^

By default, the HMC is configured with a self-signed certificate. That is the
X.509 certificate presented by the HMC as the server certificate during SSL/TLS
handshake at its Web Services API.

Starting with version 0.31, the zhmcclient will reject self-signed certificates
by default.

The HMC should be configured to use a CA-verifiable certificate. This can be
done in the HMC task "Certificate Management". See also the :term:`HMC Security`
book and Chapter 3 "Invoking API operations" in the :term:`HMC API` book.

Starting with version 0.31, the zhmcclient provides a control knob for the
verification of the HMC certificate via the ``verify_cert`` init parameter of
the :class:`zhmcclient.Session` class. That init parameter can be set to:

* `False`: Do not verify the HMC certificate. Not verifying the HMC certificate
means the zhmcclient will not detect hostname mismatches, expired
certificates, revoked certificates, or otherwise invalid certificates. Since
this mode makes the connection vulnerable to man-in-the-middle attacks, it
is insecure and should not be used in production environments.

The 'zhmcclient' package provides a control knob for the verification of the
server certificate presented by the HMC during SSL/TLS handshake via the
``verify_cert`` init parameter of the :class:`zhmcclient.Session` class, which
can be set to:
* `True` (default): Verify the HMC certificate using the CA certificates from
the first of these locations:

* `False`: Do not verify the server certificate. Since that makes
the connection vulnerable to man-in-the-middle attacks, it should not be
used in production environments.
- The file or directory in the ``REQUESTS_CA_BUNDLE`` env.var, if set
- The file or directory in the ``CURL_CA_BUNDLE`` env.var, if set
- The `Python 'certifi' package <https://pypi.org/project/certifi/>`_
(which contains the
`Mozilla Included CA Certificate List <https://wiki.mozilla.org/CA/Included_Certificates>`_).

* `True`: Verify the server certificate using the certificates provided by the
`Python 'certifi' package <https://pypi.org/project/certifi/>`_,
which are the certificates in the
`Mozilla Included CA Certificate List <https://wiki.mozilla.org/CA/Included_Certificates>`_.
* :term:`string`: Path name of a certificate file or directory. Verify the HMC
certificate using the CA certificates in that file or directory.

* :term:`string`: Path name of a CA_BUNDLE certificate file or directory to be
used for verifying the server certificate. For details, see
`SSL Cert Verification <https://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification>`_.
If a certificate file is specified (using any of the ways listed above), that
file must be in PEM format and must contain all CA certificates that are
supposed to be used. Usually they are in the order from leaf to root, but
that is not a hard requirement. The single certificates are concatenated
in the file.

If a certificate directory is specified (using any of the ways listed above),
it must contain PEM files with all CA certificates that are supposed to be used,
and copies of the PEM files or symbolic links to them in the hashed format
created by the OpenSSL command ``c_rehash``.

An X.509 certificate in PEM format is base64-encoded, begins with the line
``-----BEGIN CERTIFICATE-----``, and ends with the line
``-----END CERTIFICATE-----``.
More information about the PEM format is for example on this
`www.ssl.com page <https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions>`_
or in this `serverfault.com answer <https://serverfault.com/a/9717/330351>`_.

Since the zhmcclient package uses the 'requests' package for the communication
with the Web Services API of the HMC, the behavior described above actually
comes from the 'requests' package. Unfortunately, its documentation about
certificate verification is somewhat brief, see
`SSL Cert Verification <https://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification>`_.

Note that setting the ``REQUESTS_CA_BUNDLE`` or ``CURL_CA_BUNDLE`` environment
variables influences other programs that use these variables, too.


.. _`Cipher suites`:

Cipher suites
^^^^^^^^^^^^^
Expand Down Expand Up @@ -130,6 +173,8 @@ Brief expansion of the output field names used by this command:
* Mac = Message Authentication Code


.. _`HMC Web Services API notifications`:

HMC Web Services API notifications
----------------------------------

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/zhmcclient/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
ClientAuthError, DEFAULT_HMC_PORT

# Default value for the 'verify_cert' parameter of the Session class:
DEFAULT_VERIFY_CERT = False
DEFAULT_VERIFY_CERT = True


# TODO: Test Session.get() in all variations (including errors)
Expand Down
30 changes: 20 additions & 10 deletions zhmcclient/_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ class Session(object):

def __init__(self, host, userid=None, password=None, session_id=None,
get_password=None, retry_timeout_config=None,
port=DEFAULT_HMC_PORT, verify_cert=False):
port=DEFAULT_HMC_PORT, verify_cert=True):
# pylint: disable=line-too-long
"""
Creating a session object will not immediately cause a logon to be
Expand Down Expand Up @@ -358,18 +358,28 @@ def __init__(self, host, userid=None, password=None, session_id=None,
Controls whether and how the client verifies the server certificate
presented by the HMC during SSL/TLS handshake:
* `False`: Do not verify the server certificate. Since that makes
the connection vulnerable to man-in-the-middle attacks, it should
not be used in production environments.
* `False`: Do not verify the HMC certificate. Not verifying the HMC
certificate means the zhmcclient will not detect hostname
mismatches, expired certificates, revoked certificates, or
otherwise invalid certificates. Since this mode makes the
connection vulnerable to man-in-the-middle attacks, it is insecure
and should not be used in production environments.
* `True`: Verify the server certificate using the certificates
in the
`Mozilla Included CA Certificate List <https://wiki.mozilla.org/CA/Included_Certificates>`_.
* `True`: Verify the HMC certificate using the CA certificates from
the first of these locations:
* :term:`string`: Path name of a CA_BUNDLE certificate file or
directory to be used for verifying the server certificate.
- The file or directory in the REQUESTS_CA_BUNDLE env.var, if set
- The file or directory in the CURL_CA_BUNDLE env.var, if set
- The Python 'certifi' package (which contains the
`Mozilla Included CA Certificate List <https://wiki.mozilla.org/CA/Included_Certificates>`_).
For details, see the :ref:`Security` section.
* :term:`string`: Path name of a certificate file or directory.
Verify the HMC certificate using the CA certificates in that file
or directory.
For details, see the :ref:`HMC certificate` section.
*Added in version 0.31*
""" # noqa: E501
# pylint: enable=line-too-long

Expand Down

0 comments on commit 9a30f28

Please sign in to comment.