From 9feef4232d378151f52cc56f9d0fe2711b745559 Mon Sep 17 00:00:00 2001 From: Jorge Saffe Date: Fri, 25 Aug 2023 17:21:02 -0400 Subject: [PATCH] sw-manager fails with SSL and CA Cert provided. When sw-manager is used through a secure connection (https enabled) either with the remote CLI or within the cluster via the public interface, the operation fails if the Certificate Authority's cert is not included among the system's trusted CAs. The sw-manager client lacks implemented methods for referencing a local Certificate Authority Cert during calls. Therefore, if the CA is not among the system's trusted CAs, all calls made by sw-manager's CLI will fail since authentication in Keystone will also fail. Other CLIs like fm or platform allow referencing a CA Cert via the "REQUESTS_CA_BUNDLE" environment variable. The fix involves loading, if defined, the CA Cert referenced by such an environment variable, and adjusting SSL calls to verify connections using the provided CA Cert. Test Plan: PASS Fresh Install SX Env PASS Source openrc.sh file (internal interface). PASS sw-manager patch-strategy show PASS Enable secure mode (https) PASS Download OpenStack RC File from Horizon. PASS Source RC file inside cluster (public interface). PASS Set REQUESTS_CA_BUNDLE with CA-Cert path. PASS sw-manager patch-strategy show PASS Enable secure mode (https) PASS Download OpenStack RC File from Horizon. PASS Install remote CLI (custom container with changes) PASS Source downloaded RC file PASS Set REQUESTS_CA_BUNDLE with CA-Cert path. PASS sw-manager patch-strategy show Closes-bug: 2033561 Change-Id: If5b70714cde09bd8c329b976a8148daee9001415 Signed-off-by: Jorge Saffe --- nfv/nfv-client/nfv_client/openstack/openstack.py | 8 +++++--- nfv/nfv-client/nfv_client/openstack/rest_api.py | 8 ++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/nfv/nfv-client/nfv_client/openstack/openstack.py b/nfv/nfv-client/nfv_client/openstack/openstack.py index bb22ead4..7e8606cc 100755 --- a/nfv/nfv-client/nfv_client/openstack/openstack.py +++ b/nfv/nfv-client/nfv_client/openstack/openstack.py @@ -1,9 +1,10 @@ # -# Copyright (c) 2016-2022 Wind River Systems, Inc. +# Copyright (c) 2016-2023 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # import json +import os from six.moves import urllib from nfv_client.openstack.objects import Token @@ -25,6 +26,7 @@ class OpenStackServiceTypes(object): SERVICE = OpenStackServices() SERVICE_TYPE = OpenStackServiceTypes() +CAFILE = os.environ.get('REQUESTS_CA_BUNDLE') def get_token(auth_uri, project_name, project_domain_name, username, password, @@ -34,7 +36,7 @@ def get_token(auth_uri, project_name, project_domain_name, username, password, """ try: # handle auth_uri re-direct (300) - urllib.request.urlopen(auth_uri) + urllib.request.urlopen(auth_uri, cafile=CAFILE) except urllib.error.HTTPError as e: if e.code == 300: auth_uri = e.headers['location'] @@ -70,7 +72,7 @@ def get_token(auth_uri, project_name, project_domain_name, username, password, request_info.data = payload.encode() - request = urllib.request.urlopen(request_info, timeout=30) + request = urllib.request.urlopen(request_info, timeout=30, cafile=CAFILE) # Identity API v3 returns token id in X-Subject-Token # response header. token_id = request.headers.get('X-Subject-Token') diff --git a/nfv/nfv-client/nfv_client/openstack/rest_api.py b/nfv/nfv-client/nfv_client/openstack/rest_api.py index df373adb..1c461bb2 100755 --- a/nfv/nfv-client/nfv_client/openstack/rest_api.py +++ b/nfv/nfv-client/nfv_client/openstack/rest_api.py @@ -1,12 +1,15 @@ # -# Copyright (c) 2016-2022 Wind River Systems, Inc. +# Copyright (c) 2016-2023 Wind River Systems, Inc. # # SPDX-License-Identifier: Apache-2.0 # import json +import os from six.moves import http_client as httplib from six.moves import urllib +CAFILE = os.environ.get('REQUESTS_CA_BUNDLE') + def request(token_id, method, api_cmd, api_cmd_headers=None, api_cmd_payload=None, timeout_in_secs=40): @@ -35,7 +38,8 @@ def request(token_id, method, api_cmd, api_cmd_headers=None, request_info.data = api_cmd_payload.encode() url_request = urllib.request.urlopen(request_info, - timeout=timeout_in_secs) + timeout=timeout_in_secs, + cafile=CAFILE) headers = list() # list of tuples for key, value in url_request.info().items():