diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7525cc960..c6c370a6a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,7 +6,7 @@ ### Check List - [ ] New functionality includes testing. - - [ ] All tests pass for Python 3.9+ & 3.9+(`$ tox`). + - [ ] All tests pass for Python 3.12+ (`$ tox`). - [ ] New functionality has been documented in the README if applicable. - [ ] New functionality has been thoroughly documented in the examples (please include helpful comments). - [ ] New endpoints supported are updated in the endpoints-support.md file. diff --git a/.github/workflows/dockerimage.yml b/.github/workflows/dockerimage.yml index 82800f6a0..ceb4886f5 100644 --- a/.github/workflows/dockerimage.yml +++ b/.github/workflows/dockerimage.yml @@ -18,7 +18,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.x' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 561deac2f..af90bd5ef 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -8,7 +8,7 @@ jobs: name: Run tox (${{ matrix.python_version }}) strategy: matrix: - python_version: [3.9] + python_version: [3.12] runs-on: ubuntu-latest steps: @@ -24,6 +24,17 @@ jobs: python -m pip install --upgrade pip pip install tox + - name: Display Python SSL runtime details + run: | + python -c "import ssl; print('Python SSL:', ssl.OPENSSL_VERSION)" + + - name: Display OpenSSL providers and PQC algorithms + run: | + openssl version + openssl list -providers || true + openssl list -public-key-algorithms | grep -i mldsa || true + openssl list -public-key-algorithms | grep -i mlkem || true + - name: Run tox tests run: tox @@ -33,7 +44,7 @@ jobs: coverage xml - name: Deploy to GitHub Pages - if: success() + if: success() && matrix.python_version == '3.12' uses: crazy-max/ghaction-github-pages@v2 with: target_branch: gh-pages diff --git a/CHANGELOG.md b/CHANGELOG.md index d7f9aead6..0549a55bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# Unreleased +#### Notes +- Updated HTTPS client context from TLS 1.2 pinning to TLS client mode with TLS 1.3 minimum. +- Added explicit trust-all hostname handling for non-verified SSL mode. +- Updated unit tests to validate TLS client protocol and TLS 1.3 minimum. +- Updated SCMB example to remove TLS 1.2 pinning. +- Updated Docker base image to Python 3.12 Bookworm and refreshed CI/tox matrix for Python 3.12 coverage. +- Added README guidance for OpenSSL runtime and PQC validation commands. + # 11.30.0 #### Notes Extends Support Of The Sdk To Oneview Rest Api Version 8600 (Oneview V11.30.0) diff --git a/Dockerfile b/Dockerfile index 29a324e57..91e7cf013 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim-bullseye +FROM python:3.12-slim-bookworm ARG http_proxy ARG https_proxy @@ -20,9 +20,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update -y && \ RUN python -m pip install --upgrade pip -RUN pip install future==0.18.2 - - RUN pip install hpeOneView diff --git a/README.md b/README.md index 18215c5a3..b3ee33bc1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,26 @@ HPE OneView makes it simple to deploy and manage today’s complex hybrid cloud infrastructure. HPE OneView can help you transform your data center to software-defined, and it supports HPE’s broad portfolio of servers, storage, and networking solutions, ensuring the simple and automated management of your hybrid infrastructure. Software-defined intelligence enables a template-driven approach for deploying, provisioning, updating, and integrating compute, storage, and networking infrastructure. -The HPE OneView Python library provides a pure Python interface to the HPE OneView REST APIs. It depends on the [Python-Future](http://python-future.org/index.html) library to provide Python 2/3 compatibility. +The HPE OneView Python library provides a pure Python interface to the HPE OneView REST APIs. + +## TLS and PQC Requirements + +For PQC-ready TLS negotiation, use an environment where Python is linked to a PQC-capable OpenSSL runtime. + +- Minimum Python runtime: 3.12+ +- Minimum OpenSSL runtime for PQC paths: 3.2+ with OQS provider, or 3.5+ with native PQC support +- TLS requirement for PQC handshake: TLS 1.3 + +To verify runtime capabilities: + +```bash +python -c "import ssl; print(ssl.OPENSSL_VERSION)" +openssl list -providers +openssl list -public-key-algorithms | grep -i mldsa +openssl list -public-key-algorithms | grep -i mlkem +``` + +Note: Do not pin ciphers or groups in the SDK; rely on OpenSSL defaults so hybrid PQC groups can be negotiated by the TLS stack. You can find the latest supported HPE OneView Python SDK [here](https://github.com/HewlettPackard/oneview-python/releases/latest) diff --git a/examples/scmb/scmb.py b/examples/scmb/scmb.py index 5d4834a49..232e852d6 100755 --- a/examples/scmb/scmb.py +++ b/examples/scmb/scmb.py @@ -91,7 +91,7 @@ def recv(host, route): 'certfile': 'client.pem', 'keyfile': 'key.pem', 'cert_reqs': ssl.CERT_NONE, - 'ssl_version': ssl.PROTOCOL_TLSv1_2, + 'ssl_version': ssl.PROTOCOL_TLS_CLIENT, 'server_side': False}) # Checking whether the file is present or not diff --git a/hpeOneView/__init__.py b/hpeOneView/__init__.py index 362d68807..95c86f28c 100644 --- a/hpeOneView/__init__.py +++ b/hpeOneView/__init__.py @@ -39,15 +39,9 @@ import warnings PYTHON_VERSION = sys.version_info[:3] -PY2 = (PYTHON_VERSION[0] == 2) -if PY2: - if PYTHON_VERSION < (2, 7, 9): - warning_message = 'Running unsupported Python version: %s, unexpected errors might occur.' - warning_message += ' Use of Python v2.7.9+ is advised.' - warnings.warn(warning_message % '.'.join(map(str, PYTHON_VERSION)), Warning) -elif PYTHON_VERSION < (3, 4): +if PYTHON_VERSION < (3, 12): warning_message = 'Running unsupported Python version> %s, unexpected errors might occur.' - warning_message += ' Use of Python v3.4+ is advised.' + warning_message += ' Use of Python v3.12+ is advised.' warnings.warn(warning_message % '.'.join(map(str, PYTHON_VERSION)), Warning) from hpeOneView.connection import * diff --git a/hpeOneView/connection.py b/hpeOneView/connection.py index 15f244cfd..7506817b1 100644 --- a/hpeOneView/connection.py +++ b/hpeOneView/connection.py @@ -226,7 +226,8 @@ def __handle_download_error(self, resp, conn): raise HPEOneViewException(body) def get_connection(self): - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.minimum_version = ssl.TLSVersion.TLSv1_3 if self._sslTrustAll is False: context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(self._sslTrustedBundle) @@ -241,6 +242,7 @@ def get_connection(self): timeout=self._timeout) conn.set_tunnel(self._host, 443) else: + context.check_hostname = False context.verify_mode = ssl.CERT_NONE if self._doProxy is False: conn = http.client.HTTPSConnection(self._host, diff --git a/setup.py b/setup.py index 0b361e1cc..2bfea4c9e 100644 --- a/setup.py +++ b/setup.py @@ -28,6 +28,7 @@ author_email='pdl-oneview-sdk@hpe.com', license='Apache', packages=find_packages(exclude=['examples*', 'tests*']), + python_requires='>=3.12', keywords=['oneview', 'hpe'], long_description_content_type="text/markdown", install_requires=['future>=0.15.2', 'docutils<0.18']) diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py index 343249ce5..3e4a3f1d8 100644 --- a/tests/unit/test_connection.py +++ b/tests/unit/test_connection.py @@ -1065,7 +1065,8 @@ def test_get_connection_ssl_trust_all(self): self.assertEqual(conn.host, '127.0.0.1') self.assertEqual(conn.port, 443) - self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLSv1_2) + self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLS_CLIENT) + self.assertEqual(conn._context.minimum_version, ssl.TLSVersion.TLSv1_3) def test_get_connection_ssl_trust_all_with_proxy(self): @@ -1075,7 +1076,8 @@ def test_get_connection_ssl_trust_all_with_proxy(self): self.assertEqual(conn.host, '10.0.0.1') self.assertEqual(conn.port, 3128) - self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLSv1_2) + self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLS_CLIENT) + self.assertEqual(conn._context.minimum_version, ssl.TLSVersion.TLSv1_3) @patch.object(ssl.SSLContext, 'load_verify_locations') def test_get_connection_trusted_ssl_bundle_with_proxy(self, mock_lvl): @@ -1087,7 +1089,8 @@ def test_get_connection_trusted_ssl_bundle_with_proxy(self, mock_lvl): self.assertEqual(conn.host, '10.0.0.1') self.assertEqual(conn.port, 3128) - self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLSv1_2) + self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLS_CLIENT) + self.assertEqual(conn._context.minimum_version, ssl.TLSVersion.TLSv1_3) @patch.object(ssl.SSLContext, 'load_verify_locations') def test_get_connection_trusted_ssl_bundle(self, mock_lvl): @@ -1098,7 +1101,8 @@ def test_get_connection_trusted_ssl_bundle(self, mock_lvl): self.assertEqual(conn.host, '127.0.0.1') self.assertEqual(conn.port, 443) - self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLSv1_2) + self.assertEqual(conn._context.protocol, ssl.PROTOCOL_TLS_CLIENT) + self.assertEqual(conn._context.minimum_version, ssl.TLSVersion.TLSv1_3) if __name__ == '__main__': diff --git a/tox.ini b/tox.ini index cdb0bd9d0..77c87bf14 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ [tox] -envlist = docs, py34, py36, py39-coverage, py39-flake8 +envlist = docs, py312-coverage, py312-flake8 skip_missing_interpreters = true [flake8] @@ -23,9 +23,9 @@ deps = commands = {envpython} -m unittest discover -[testenv:py39-coverage] +[testenv:py312-coverage] basepython = - python3.9 + python3.12 passenv = TRAVIS, TRAVIS_JOB_ID, TRAVIS_BRANCH deps = -r{toxinidir}/test_requirements.txt @@ -36,16 +36,16 @@ commands = coverage run --source=hpeOneView -m unittest discover - coveralls -[testenv:py39-flake8] +[testenv:py312-flake8] basepython = - python3.9 + python3.12 deps = flake8 commands = flake8 {posargs} hpeOneView/ tests/ examples/ [testenv:docs] -basepython=python3.9 +basepython=python3.12 deps= sphinx sphinx_rtd_theme