From aecb80cd79363fdd23bc52c6296b5665d8d27842 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 00:03:45 +0530 Subject: [PATCH 01/22] Added support for sso server Signed-off-by: Vonteddu Chaithra --- docs/appendix.rst | 6 +- tests/end2end/test_sso_server_definition.py | 217 ++++++++++ .../zhmcclient/test_sso_server_definition.py | 389 ++++++++++++++++++ zhmcclient/__init__.py | 1 + zhmcclient/_console.py | 18 + zhmcclient/_sso_server_definition.py | 301 ++++++++++++++ zhmcclient/_utils.py | 3 + zhmcclient/mock/_hmc.py | 82 ++++ zhmcclient/mock/_session.py | 2 +- 9 files changed, 1017 insertions(+), 2 deletions(-) create mode 100644 tests/end2end/test_sso_server_definition.py create mode 100644 tests/unit/zhmcclient/test_sso_server_definition.py create mode 100644 zhmcclient/_sso_server_definition.py diff --git a/docs/appendix.rst b/docs/appendix.rst index 20365862..9e436fd1 100644 --- a/docs/appendix.rst +++ b/docs/appendix.rst @@ -400,7 +400,11 @@ Resources scoped to the HMC MFA Server Definition The information in an HMC about an MFA server that may be used for HMC user authorization purposes. - + + SSO Server Definition + The information in an HMC about an SSO server that may be used for + HMC user authorization purposes. + Password Rule A rule which HMC users need to follow when creating a HMC logon password. diff --git a/tests/end2end/test_sso_server_definition.py b/tests/end2end/test_sso_server_definition.py new file mode 100644 index 00000000..1e59db25 --- /dev/null +++ b/tests/end2end/test_sso_server_definition.py @@ -0,0 +1,217 @@ +# Copyright 2021 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +End2end tests for SSO server definitions (on CPCs in DPM mode). + +These tests do not change any existing SSO server definitions, but create, +modify and delete test SSO server definitions. +""" + + +import warnings +import pytest +from requests.packages import urllib3 + +import zhmcclient + +from .utils import skip_warn, pick_test_resources, TEST_PREFIX, \ + runtest_find_list, runtest_get_properties + +urllib3.disable_warnings() + +# Properties in minimalistic SSOServerDefinition objects (e.g. find_by_name()) +SSOSRVDEF_MINIMAL_PROPS = ['element-uri', 'name'] + +# Properties in SSOServerDefinition objects returned by list() without full +# props +SSOSRVDEF_LIST_PROPS = ['element-uri', 'name','type'] + +# Properties whose values can change between retrievals of SSOServerDefinition +# objects +SSOSRVDEF_VOLATILE_PROPS = [] + + +def test_ssosrvdef_find_list(hmc_session): + """ + Test list(), find(), findall(). + """ + client = zhmcclient.Client(hmc_session) + console = client.consoles.console + hd = hmc_session.hmc_definition + + api_version = client.query_api_version() + hmc_version = api_version['hmc-version'] + hmc_version_info = tuple(map(int, hmc_version.split('.'))) + if hmc_version_info < (2, 17, 0): + skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions") + + # Pick the SSO server definitions to test with + ssosrvdef_list = console.sso_server_definitions.list() + if not ssosrvdef_list: + skip_warn(f"No SSO server definitions defined on HMC {hd.host}") + ssosrvdef_list = pick_test_resources(ssosrvdef_list) + + for ssosrvdef in ssosrvdef_list: + print(f"Testing with SSO server definition {ssosrvdef.name!r}") + runtest_find_list( + hmc_session, console.sso_server_definitions, ssosrvdef.name, + 'name', 'element-uri', SSOSRVDEF_VOLATILE_PROPS, + SSOSRVDEF_MINIMAL_PROPS, SSOSRVDEF_LIST_PROPS) + + +def test_ssosrvdef_property(hmc_session): + """ + Test property related methods + """ + client = zhmcclient.Client(hmc_session) + console = client.consoles.console + hd = hmc_session.hmc_definition + + api_version = client.query_api_version() + hmc_version = api_version['hmc-version'] + hmc_version_info = tuple(map(int, hmc_version.split('.'))) + if hmc_version_info < (2, 17, 0): + skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions") + + # Pick the SSO server definitions to test with + ssosrvdef_list = console.sso_server_definitions.list() + if not ssosrvdef_list: + skip_warn(f"No SSO server definitions defined on HMC {hd.host}") + ssosrvdef_list = pick_test_resources(ssosrvdef_list) + + for ssosrvdef in ssosrvdef_list: + print(f"Testing with SSO server definition {ssosrvdef.name!r}") + + # Select a property that is not returned by list() + non_list_prop = 'description' + + runtest_get_properties(ssosrvdef.manager, non_list_prop) + + +def test_ssosrvdef_crud(hmc_session): + """ + Test create, read, update and delete a SSO server definition. + """ + client = zhmcclient.Client(hmc_session) + console = client.consoles.console + hd = hmc_session.hmc_definition + + api_version = client.query_api_version() + hmc_version = api_version['hmc-version'] + hmc_version_info = tuple(map(int, hmc_version.split('.'))) + if hmc_version_info < (2, 17, 0): + skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions") + + ssosrvdef_name = TEST_PREFIX + ' test_ssosrvdef_crud ssosrvdef1' + ssosrvdef_name_new = ssosrvdef_name + ' new' + + # Ensure a clean starting point for this test + try: + ssosrvdef = console.sso_server_definitions.find( + name=ssosrvdef_name) + except zhmcclient.NotFound: + pass + else: + warnings.warn( + "Deleting test SSO server definition from previous run: " + f"{ssosrvdef_name!r}", UserWarning) + ssosrvdef.delete() + + # Test creating the SSO server definition + + ssosrvdef_input_props = { + "authentication-page-servers":[ + { + "hostname-ipaddr":"images1.example.com", + "port":443 + }, + { + "hostname-ipaddr":"images2.example.com", + "port":80 + } + ], + "authentication-url":"https://sso1.example.com/auth", + "client-id":"sso1-123456", + "client-secret":"sso1-client-secret", + "description":"Primary SSO server", + "issuer-url":"https://sso1.example.com/issuer", + "jwks-url":"https://sso1.example.com/jwks", + "logout-sso-session-on-reauthentication-failure":true, + "logout-url":"https://sso1.example.com/logout", + "name":"SSO Server 1", + "token-url":"https://sso1.example.com/token", + "type":"oidc" + } + ssosrvdef_auto_props = { + 'logout-url': None, + 'logout-sso-session-on-reauthentication-failure': False, + } + + # The code to be tested + try: + ssosrvdef = console.sso_server_definitions.create( + ssosrvdef_input_props) + except zhmcclient.HTTPError as exc: + if exc.http_status == 403 and exc.reason == 1: + skip_warn(f"HMC userid {hd.userid!r} is not authorized for task " + f"'Manage Single Sign-On Servers' on HMC {hd.host}") + else: + raise + + for pn, exp_value in ssosrvdef_input_props.items(): + assert ssosrvdef.properties[pn] == exp_value, \ + f"Unexpected value for property {pn!r}" + ssosrvdef.pull_full_properties() + for pn, exp_value in ssosrvdef_input_props.items(): + assert ssosrvdef.properties[pn] == exp_value, \ + f"Unexpected value for property {pn!r}" + for pn, exp_value in ssosrvdef_auto_props.items(): + assert ssosrvdef.properties[pn] == exp_value, \ + f"Unexpected value for property {pn!r}" + + # Test updating a property of the SSO server definition + + new_desc = "Updated SSO server definition description." + + # The code to be tested + ssosrvdef.update_properties(dict(description=new_desc)) + + assert ssosrvdef.properties['description'] == new_desc + ssosrvdef.pull_full_properties() + assert ssosrvdef.properties['description'] == new_desc + + # Test that SSO server definitions cannot be renamed + + with pytest.raises(zhmcclient.HTTPError) as exc_info: + + # The code to be tested + ssosrvdef.update_properties(dict(name=ssosrvdef_name_new)) + + exc = exc_info.value + assert exc.http_status == 400 + assert exc.reason == 6 + with pytest.raises(zhmcclient.NotFound): + console.sso_server_definitions.find(name=ssosrvdef_name_new) + + # Test deleting the SSO server definition + + # The code to be tested + ssosrvdef.delete() + + with pytest.raises(zhmcclient.NotFound): + console.sso_server_definitions.find(name=ssosrvdef_name) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py new file mode 100644 index 00000000..3e0690f3 --- /dev/null +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -0,0 +1,389 @@ +# Copyright 2017,2021 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Unit tests for _sso_srv_def module. +""" + + +import re +import copy +import logging +import pytest + +from zhmcclient import Client, HTTPError, NotFound, SSOServerDefinition +from zhmcclient.mock import FakedSession +from tests.common.utils import assert_resources, assert_blanked_in_message + + +class TestSSOServerDefinition: + """All tests for the SSOServerDefinition and SSOServerDefinitionManager + classes.""" + + def setup_method(self): + """ + Setup that is called by pytest before each test method. + Set up a faked session, and add a faked Console without any + child resources. + """ + # pylint: disable=attribute-defined-outside-init + + self.session = FakedSession('fake-host', 'fake-hmc', '2.17.1', '1.8') + self.client = Client(self.session) + + self.faked_console = self.session.hmc.consoles.add({ + 'object-id': None, + # object-uri will be automatically set + 'parent': None, + 'class': 'console', + 'name': 'fake-console1', + 'description': 'Console #1', + }) + self.console = self.client.consoles.find(name=self.faked_console.name) + + def add_sso_srv_def(self, name): + """ + Add a faked SSOServerDefinition object to the faked Console + and return it. + """ + + faked_sso_srv_def = self.faked_console.sso_server_definitions.add({ + 'element-id': f'oid-{name}', + # element-uri will be automatically set + 'parent': '/api/console', + 'class': 'sso-server-definition', + 'name': name, + 'description': f'SSO Server Definition {name}', + "authentication-page-servers":[ + { + "hostname-ipaddr":"images1.example.com", + "port":443 + }, + { + "hostname-ipaddr":"images2.example.com", + "port":80 + } + ], + "authentication-url":"https://sso1.example.com/auth", + "client-id":"sso1-123456", + "element-uri":"/api/console/sso-server-definitions/c6a464c2-a211-11ef-bbc4-fa163e7cf285", + "issuer-url":"https://sso1.example.com/issuer", + "jwks-url":"https://sso1.example.com/jwks", + "logout-sso-session-on-reauthentication-failure":true, + "logout-url":"https://sso1.example.com/logoff", + "token-url":"https://sso1.example.com/token", + "type":"oidc" + }) + return faked_sso_srv_def + + def test_sso_srv_def_manager_repr(self): + """Test SSOServerDefinitionManager.__repr__().""" + + sso_srv_def_mgr = self.console.sso_server_definitions + + # Execute the code to be tested + repr_str = repr(sso_srv_def_mgr) + + repr_str = repr_str.replace('\n', '\\n') + # We check just the begin of the string: + assert re.match( + rf'^{sso_srv_def_mgr.__class__.__name__}\s+at\s+' + rf'0x{id(sso_srv_def_mgr):08x}\s+\(\\n.*', + repr_str) + + def test_sso_srv_def_manager_initial_attrs(self): + """Test initial attributes of SSOServerDefinitionManager.""" + + sso_srv_def_mgr = self.console.sso_server_definitions + + # Verify all public properties of the manager object + assert sso_srv_def_mgr.resource_class == SSOServerDefinition + assert sso_srv_def_mgr.class_name == 'sso-server-definition' + assert sso_srv_def_mgr.session is self.session + assert sso_srv_def_mgr.parent is self.console + assert sso_srv_def_mgr.console is self.console + + @pytest.mark.parametrize( + "full_properties_kwargs, prop_names", [ + (dict(full_properties=False), + ['element-uri', 'name','type']), + (dict(full_properties=True), + ['element-uri', 'name', 'type']), + ({}, # test default for full_properties (False) + ['element-uri', 'name','type']), + ] + ) + @pytest.mark.parametrize( + "filter_args, exp_names", [ + (None, + ['a', 'b']), + ({}, + ['a', 'b']), + ({'name': 'a'}, + ['a']), + ({'name': 'A'}, # SSO user definitions have case-insensitive names + ['a']), + ] + ) + def test_sso_srv_def_manager_list( + self, filter_args, exp_names, full_properties_kwargs, prop_names): + """Test SSOServerDefinitionManager.list().""" + + faked_sso_srv_def1 = self.add_sso_srv_def(name='a') + faked_sso_srv_def2 = self.add_sso_srv_def(name='b') + faked_sso_srv_defs = [faked_sso_srv_def1, faked_sso_srv_def2] + exp_faked_sso_srv_defs = [u for u in faked_sso_srv_defs + if u.name in exp_names] + sso_srv_def_mgr = self.console.sso_server_definitions + + # Execute the code to be tested + sso_srv_defs = sso_srv_def_mgr.list(filter_args=filter_args, + **full_properties_kwargs) + + assert_resources(sso_srv_defs, exp_faked_sso_srv_defs, prop_names) + + @pytest.mark.parametrize( + "input_props, exp_prop_names, exp_exc", [ + ({}, # props missing + None, + HTTPError({'http-status': 400, 'reason': 5})), + ({'description': 'fake description X'}, # props missing + None, + HTTPError({'http-status': 400, 'reason': 5})), + ({'description': 'fake description X', + 'name': 'a', + 'type': 'oidc', + 'client-secret': 'sso1-client-secret', + "issuer-url":"https://sso1.example.com/issuer", + 'authentication-url' :'https://sso1.example.com/auth', + 'token-url':'https://sso1.example.com/token', + "jwks-url":"https://sso1.example.com/jwks", + 'logout-url ':'https://sso1.example.com/logout'}, + ['element-uri', 'name', 'description'], + None), + ({'description': 'fake description X', + 'name': 'a', + 'type': 'oidc', + 'client-secret': 'sso1-client-secret', + "issuer-url":"https://sso1.example.com/issuer", + 'authentication-url' :'https://sso1.example.com/auth', + 'token-url':'https://sso1.example.com/token', + "jwks-url":"https://sso1.example.com/jwks", + 'logout-url ':'https://sso1.example.com/logout'}, + ['element-uri', 'name', 'client-secret'], + None), + ] + ) + def test_sso_srv_def_manager_create( + self, caplog, input_props, exp_prop_names, exp_exc): + """Test SSOServerDefinitionManager.create().""" + + logger_name = "zhmcclient.api" + caplog.set_level(logging.DEBUG, logger=logger_name) + + sso_srv_def_mgr = self.console.sso_server_definitions + + if exp_exc is not None: + + with pytest.raises(exp_exc.__class__) as exc_info: + + # Execute the code to be tested + sso_srv_def_mgr.create(properties=input_props) + + exc = exc_info.value + if isinstance(exp_exc, HTTPError): + assert exc.http_status == exp_exc.http_status + assert exc.reason == exp_exc.reason + + else: + + + # Execute the code to be tested. + sso_srv_def = sso_srv_def_mgr.create(properties=input_props) + + # Get its API call log record + call_record = caplog.records[-2] + + # Check the resource for consistency within itself + assert isinstance(sso_srv_def, SSOServerDefinition) + sso_srv_def_name = sso_srv_def.name + exp_sso_srv_def_name = sso_srv_def.properties['name'] + assert sso_srv_def_name == exp_sso_srv_def_name + sso_srv_def_uri = sso_srv_def.uri + exp_sso_srv_def_uri = sso_srv_def.properties['element-uri'] + assert sso_srv_def_uri == exp_sso_srv_def_uri + + # Check the properties against the expected names and values + for prop_name in exp_prop_names: + assert prop_name in sso_srv_def.properties + if prop_name in input_props: + value = sso_srv_def.properties[prop_name] + exp_value = input_props[prop_name] + assert value == exp_value + + # Verify the API call log record for blanked-out properties. + assert_blanked_in_message( + call_record.message, input_props, + ['client-secret']) + + def test_sso_srv_def_repr(self): + """Test SSOServerDefinition.__repr__().""" + + faked_sso_srv_def1 = self.add_sso_srv_def(name='a') + sso_srv_def1 = self.console.sso_server_definitions.find( + name=faked_sso_srv_def1.name) + + # Execute the code to be tested + repr_str = repr(sso_srv_def1) + + repr_str = repr_str.replace('\n', '\\n') + # We check just the begin of the string: + assert re.match( + rf'^{sso_srv_def1.__class__.__name__}\s+at\s+' + rf'0x{id(sso_srv_def1):08x}\s+\(\\n.*', + repr_str) + + @pytest.mark.parametrize( + "input_props, exp_exc", [ + ({'name': 'a'}, + None), + ({'name': 'b'}, + None), + ] + ) + def test_sso_srv_def_delete(self, input_props, exp_exc): + """Test SSOServerDefinition.delete().""" + + faked_sso_srv_def = self.add_sso_srv_def(name=input_props['name']) + + sso_srv_def_mgr = self.console.sso_server_definitions + sso_srv_def = sso_srv_def_mgr.find(name=faked_sso_srv_def.name) + + if exp_exc is not None: + + with pytest.raises(exp_exc.__class__) as exc_info: + + # Execute the code to be tested + sso_srv_def.delete() + + exc = exc_info.value + if isinstance(exp_exc, HTTPError): + assert exc.http_status == exp_exc.http_status + assert exc.reason == exp_exc.reason + + # Check that the SSO Server Definition still exists + sso_srv_def_mgr.find(name=faked_sso_srv_def.name) + + else: + + # Execute the code to be tested. + sso_srv_def.delete() + + # Check that the SSO Server Definition no longer exists + with pytest.raises(NotFound) as exc_info: + sso_srv_def_mgr.find(name=faked_sso_srv_def.name) + + def test_sso_delete_create_same(self): + """Test SSOServerDefinition.delete() followed by create() with same + name.""" + + sso_srv_def_name = 'faked_a' + + # Add the SSO Server Definition to be tested + self.add_sso_srv_def(name=sso_srv_def_name) + + # Input properties for a SSO Server Definition with the same name + sn_sso_srv_def_props = { + 'name': sso_srv_def_name, + 'description': 'SSO Server Definition with same name', + 'primary-hostname-ipaddr': '10.11.12.13', + 'search-distinguished-name': 'test{0}', + } + + sso_srv_def_mgr = self.console.sso_server_definitions + sso_srv_def = sso_srv_def_mgr.find(name=sso_srv_def_name) + + # Execute the deletion code to be tested + sso_srv_def.delete() + + # Check that the SSO Server Definition no longer exists + with pytest.raises(NotFound): + sso_srv_def_mgr.find(name=sso_srv_def_name) + + # Execute the creation code to be tested. + sso_srv_def_mgr.create(sn_sso_srv_def_props) + + # Check that the SSO Server Definition exists again under that name + sn_sso_srv_def = sso_srv_def_mgr.find(name=sso_srv_def_name) + description = sn_sso_srv_def.get_property('description') + assert description == sn_sso_srv_def_props['description'] + + @pytest.mark.parametrize( + "input_props", [ + {}, + {'description': 'New SSO Server Definition description'}, + {'client-secret': 'bla'}, + ] + ) + def test_sso_srv_def_update_properties(self, caplog, input_props): + """Test SSOServerDefinition.update_properties().""" + + logger_name = "zhmcclient.api" + caplog.set_level(logging.DEBUG, logger=logger_name) + + sso_srv_def_name = 'faked_a' + + # Add the SSO Server Definition to be tested + self.add_sso_srv_def(name=sso_srv_def_name) + + sso_srv_def_mgr = self.console.sso_server_definitions + sso_srv_def = sso_srv_def_mgr.find(name=sso_srv_def_name) + + sso_srv_def.pull_full_properties() + saved_properties = copy.deepcopy(sso_srv_def.properties) + + # Execute the code to be tested + sso_srv_def.update_properties(properties=input_props) + + # Get its API call log record + call_record = caplog.records[-2] + + # Verify that the resource object already reflects the property + # updates. + for prop_name in saved_properties: + if prop_name in input_props: + exp_prop_value = input_props[prop_name] + else: + exp_prop_value = saved_properties[prop_name] + assert prop_name in sso_srv_def.properties + prop_value = sso_srv_def.properties[prop_name] + assert prop_value == exp_prop_value, \ + f"Unexpected value for property {prop_name!r}" + + # Refresh the resource object and verify that the resource object + # still reflects the property updates. + sso_srv_def.pull_full_properties() + for prop_name in saved_properties: + if prop_name in input_props: + exp_prop_value = input_props[prop_name] + else: + exp_prop_value = saved_properties[prop_name] + assert prop_name in sso_srv_def.properties + prop_value = sso_srv_def.properties[prop_name] + assert prop_value == exp_prop_value + + # Verify the API call log record for blanked-out properties. + assert_blanked_in_message( + call_record.message, input_props, + ['client-secret']) diff --git a/zhmcclient/__init__.py b/zhmcclient/__init__.py index 4c97f65b..5a96489d 100644 --- a/zhmcclient/__init__.py +++ b/zhmcclient/__init__.py @@ -52,6 +52,7 @@ from ._task import * # noqa: F401 from ._ldap_server_definition import * # noqa: F401 from ._mfa_server_definition import * # noqa: F401 +from ._sso_server_definition import * # noqa: F401 from ._unmanaged_cpc import * # noqa: F401 from ._storage_group import * # noqa: F401 from ._storage_volume import * # noqa: F401 diff --git a/zhmcclient/_console.py b/zhmcclient/_console.py index eaf0cfac..81b622c7 100644 --- a/zhmcclient/_console.py +++ b/zhmcclient/_console.py @@ -37,6 +37,7 @@ from ._task import TaskManager from ._ldap_server_definition import LdapServerDefinitionManager from ._mfa_server_definition import MfaServerDefinitionManager +from ._sso_server_definition import SSOServerDefinitionManager from ._unmanaged_cpc import UnmanagedCpcManager from ._group import GroupManager from ._utils import get_api_features @@ -218,6 +219,7 @@ def __init__(self, manager, uri, name=None, properties=None): self._tasks = None self._ldap_server_definitions = None self._mfa_server_definitions = None + self._sso_server_definitions = None self._unmanaged_cpcs = None self._groups = None self._certificates = None @@ -337,6 +339,18 @@ def mfa_server_definitions(self): self._mfa_server_definitions = MfaServerDefinitionManager(self) return self._mfa_server_definitions + @property + def sso_server_definitions(self): + """ + :class:`~zhmcclient.SSOServerDefinitionManager`: Access to the + :term:`sso Server Definitions ` in this + Console. + """ + # We do here some lazy loading. + if not self._sso_server_definitions: + self._sso_server_definitions = SSOServerDefinitionManager(self) + return self._sso_server_definitions + @property def unmanaged_cpcs(self): """ @@ -1612,6 +1626,7 @@ def dump(self): "tasks": [...], "ldap_server_definitions": [...], "mfa_server_definitions": [...], + "sso_server_definitions": [...], "unmanaged_cpcs": [...], "storage_groups": [...], } @@ -1646,6 +1661,9 @@ def dump(self): mfa_server_definitions = self.mfa_server_definitions.dump() if mfa_server_definitions: resource_dict['mfa_server_definitions'] = mfa_server_definitions + sso_server_definitions = self.sso_server_definitions.dump() + if sso_server_definitions: + resource_dict['sso_server_definitions'] = sso_server_definitions storage_groups = self.storage_groups.dump() if storage_groups: resource_dict['storage_groups'] = storage_groups diff --git a/zhmcclient/_sso_server_definition.py b/zhmcclient/_sso_server_definition.py new file mode 100644 index 00000000..7062d241 --- /dev/null +++ b/zhmcclient/_sso_server_definition.py @@ -0,0 +1,301 @@ +# Copyright 2017,2021 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +A :term:`SSO Server Definition` resource represents a definition that contains +information about an SSO server that may be used for HMC user authentication +purposes.The SSO server support is added by the single sign-on feature +""" + + +import copy + +from ._manager import BaseManager +from ._resource import BaseResource +from ._logging import logged_api_call +from ._utils import RC_SSO_SERVER_DEFINITION + +__all__ = ['SSOServerDefinitionManager', 'SSOServerDefinition'] + + +class SSOServerDefinitionManager(BaseManager): + """ + Manager providing access to the :term:`SSO Server Definition` resources of + a HMC. + + Derived from :class:`~zhmcclient.BaseManager`; see there for common methods + and attributes. + + Objects of this class are not directly created by the user; they are + accessible via the following instance variable of a + :class:`~zhmcclient.Console` object: + + * :attr:`zhmcclient.Console.sso_server_definitions` + + HMC/SE version requirements: + + * HMC version == 2.17.0 + """ + + def __init__(self, console): + # This function should not go into the docs. + # Parameters: + # console (:class:`~zhmcclient.Console`): + # Console object representing the HMC. + + # Resource properties that are supported as filter query parameters. + # If the support for a resource property changes within the set of HMC + # versions that support this type of resource, this list must be set up + # for the version of the HMC this session is connected to. + # Because this resource has case-insensitive names, this list must + # contain the name property. + query_props = [ + 'name', + 'type', + 'additional-properties', + ] + + super().__init__( + resource_class=SSOServerDefinition, + class_name=RC_SSO_SERVER_DEFINITION, + session=console.manager.session, + parent=console, + base_uri='/api/console/sso-server-definitions', + oid_prop='element-id', + uri_prop='element-uri', + name_prop='name', + query_props=query_props, + case_insensitive_names=True) + + @property + def console(self): + """ + :class:`~zhmcclient.Console`: :term:`Console` defining the scope for + this manager. + """ + return self._parent + + @logged_api_call + def list(self, full_properties=False, filter_args=None): + """ + List the :term:`sso Server Definition` resources representing the + definitions of sso servers in this HMC. + + Any resource property may be specified in a filter argument. For + details about filter arguments, see :ref:`Filtering`. + + The listing of resources is handled in an optimized way: + + * If this manager is enabled for :ref:`auto-updating`, a locally + maintained resource list is used (which is automatically updated via + inventory notifications from the HMC) and the provided filter + arguments are applied. + + * Otherwise, if the filter arguments specify the resource name as a + single filter argument with a straight match string (i.e. without + regular expressions), an optimized lookup is performed based on a + locally maintained name-URI cache. + + * Otherwise, the HMC List operation is performed with the subset of the + provided filter arguments that can be handled on the HMC side and the + remaining filter arguments are applied on the client side on the list + result. + + HMC/SE version requirements: + + * HMC version == 2.17.0 + + Authorization requirements: + + * User-related-access permission to the SSO Server Definition objects + included in the result, or task permission to the "Manage Single Sign-On Servers" task. + + Parameters: + + full_properties (bool): + Controls whether the full set of resource properties should be + retrieved, vs. only the short set as returned by the list + operation. + + filter_args (dict): + Filter arguments that narrow the list of returned resources to + those that match the specified filter arguments. For details, see + :ref:`Filtering`. + + `None` causes no filtering to happen, i.e. all resources are + returned. + + Returns: + + : A list of :class:`~zhmcclient.SSOServerDefinition` objects. + + Raises: + + :exc:`~zhmcclient.HTTPError` + :exc:`~zhmcclient.ParseError` + :exc:`~zhmcclient.AuthError` + :exc:`~zhmcclient.ConnectionError` + :exc:`~zhmcclient.FilterConversionError` + """ + result_prop = 'sso-server-definitions' + list_uri = f'{self.console.uri}/sso-server-definitions' + return self._list_with_operation( + list_uri, result_prop, full_properties, filter_args, None) + + @logged_api_call(blanked_properties=['client-secret'], properties_pos=1) + def create(self, properties): + """ + Create a new SSO Server Definition in this HMC. + + HMC/SE version requirements: + + * HMC version == 2.17.0 + + Authorization requirements: + + * Task permission to the "Manage Single Sign-On Servers" task. + + Parameters: + + properties (dict): Initial property values. + Allowable properties are defined in section 'Request body contents' + in section 'Create SSO Server Definition' in the :term:`HMC API` + book. + + Returns: + + SSOServerDefinition: + The resource object for the new SSO Server Definition. + The object will have its 'object-uri' property set as returned by + the HMC, and will also have the input properties set. + + Raises: + + :exc:`~zhmcclient.HTTPError` + :exc:`~zhmcclient.ParseError` + :exc:`~zhmcclient.AuthError` + :exc:`~zhmcclient.ConnectionError` + """ + result = self.session.post( + self.console.uri + '/sso-server-definitions', body=properties) + # There should not be overlaps, but just in case there are, the + # returned props should overwrite the input props: + props = copy.deepcopy(properties) + props.update(result) + name = props.get(self._name_prop, None) + uri = props[self._uri_prop] + sso_server_definition = SSOServerDefinition(self, uri, name, props) + self._name_uri_cache.update(name, uri) + return sso_server_definition + + +class SSOServerDefinition(BaseResource): + """ + Representation of a :term:`SSO Server Definition`. + + Derived from :class:`~zhmcclient.BaseResource`; see there for common + methods and attributes. + + Objects of this class are not directly created by the user; they are + returned from creation or list functions on their manager object + (in this case, :class:`~zhmcclient.SSOServerDefinitionManager`). + + HMC/SE version requirements: + + * HMC version == 2.17.0 + """ + + def __init__(self, manager, uri, name=None, properties=None): + # This function should not go into the docs. + # manager (:class:`~zhmcclient.SSOServerDefinitionManager`): + # Manager object for this resource object. + # uri (string): + # Canonical URI path of the resource. + # name (string): + # Name of the resource. + # properties (dict): + # Properties to be set for this resource object. May be `None` or + # empty. + assert isinstance(manager, SSOServerDefinitionManager), ( + "Console init: Expected manager type " + f"{SSOServerDefinitionManager}, got {type(manager)}") + super().__init__( + manager, uri, name, properties) + + @logged_api_call + def delete(self): + """ + Delete this SSO Server Definition. + + HMC/SE version requirements: + + * HMC version == 2.17.0 + + Authorization requirements: + + * Task permission to the "Manage Single Sign-On Servers" task. + + Raises: + + :exc:`~zhmcclient.HTTPError` + :exc:`~zhmcclient.ParseError` + :exc:`~zhmcclient.AuthError` + :exc:`~zhmcclient.ConnectionError` + """ + # pylint: disable=protected-access + self.manager.session.delete(self.uri, resource=self) + self.manager._name_uri_cache.delete( + self.get_properties_local(self.manager._name_prop, None)) + self.cease_existence_local() + + @logged_api_call(blanked_properties=['client-secret'], properties_pos=1) + def update_properties(self, properties): + """ + Update writeable properties of this SSO Server Definitions. + + This method serializes with other methods that access or change + properties on the same Python object. + + HMC/SE version requirements: + + * HMC version == 2.17.0 + + Authorization requirements: + + * Task permission to the "Manage Single Sign-On Servers" task. + + Parameters: + + properties (dict): New values for the properties to be updated. + Properties not to be updated are omitted. + Allowable properties are the properties with qualifier (w) in + section 'Data model' in section 'SSO Server Definition object' in + the :term:`HMC API` book. + + Raises: + + :exc:`~zhmcclient.HTTPError` + :exc:`~zhmcclient.ParseError` + :exc:`~zhmcclient.AuthError` + :exc:`~zhmcclient.ConnectionError` + """ + # pylint: disable=protected-access + self.manager.session.post(self.uri, resource=self, body=properties) + + # The name of SSO Server Definitions cannot be updated. An attempt to + # do so should cause HTTPError to be raised in the POST above, so we + # assert that here, because we omit the extra code for handling name + # updates: + assert self.manager._name_prop not in properties + self.update_properties_local(copy.deepcopy(properties)) diff --git a/zhmcclient/_utils.py b/zhmcclient/_utils.py index 0ae9f5be..2f6bdc0c 100644 --- a/zhmcclient/_utils.py +++ b/zhmcclient/_utils.py @@ -77,6 +77,7 @@ RC_USER = 'user' RC_GROUP = 'group' RC_LDAP_SERVER_DEFINITION = 'ldap-server-definition' +RC_SSO_SERVER_DEFINITION = 'sso-server-definition' RC_MFA_SERVER_DEFINITION = 'mfa-server-definition' RC_HW_MESSAGE = 'hardware-message' @@ -102,6 +103,7 @@ RC_USER, RC_LDAP_SERVER_DEFINITION, RC_MFA_SERVER_DEFINITION, + RC_SSO_SERVER_DEFINITION, RC_CPC, # For unmanaged CPCs RC_PARTITION_LINK, ) @@ -144,6 +146,7 @@ RC_LOAD_ACTIVATION_PROFILE, RC_LDAP_SERVER_DEFINITION, RC_MFA_SERVER_DEFINITION, + RC_SSO_SERVER_DEFINITION, RC_LOGICAL_PARTITION, RC_CONSOLE, RC_CPC, diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 3880e626..e6ac618e 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -36,6 +36,7 @@ 'FakedPasswordRuleManager', 'FakedPasswordRule', 'FakedTaskManager', 'FakedTask', 'FakedLdapServerDefinitionManager', 'FakedLdapServerDefinition', + 'FakedSSOServerDefinitionManager', 'FakedSSOServerDefinition', 'FakedMfaServerDefinitionManager', 'FakedMfaServerDefinition', 'FakedActivationProfileManager', 'FakedActivationProfile', 'FakedAdapterManager', 'FakedAdapter', @@ -1149,6 +1150,8 @@ def __init__(self, manager, properties): hmc=manager.hmc, console=self) self._mfa_server_definitions = FakedMfaServerDefinitionManager( hmc=manager.hmc, console=self) + self._sso_server_definitions = FakedSSOServerDefinitionManager( + hmc=manager.hmc, console=self) self._unmanaged_cpcs = FakedUnmanagedCpcManager( hmc=manager.hmc, console=self) self._groups = FakedGroupManager(hmc=manager.hmc, console=self) @@ -1180,6 +1183,8 @@ def __repr__(self): f"{repr_manager(self.ldap_server_definitions, indent=2)}\n" " _mfa_server_definitions = " f"{repr_manager(self.mfa_server_definitions, indent=2)}\n" + " _sso_server_definitions = " + f"{repr_manager(self.sso_server_definitions, indent=2)}\n" " _unmanaged_cpcs = " f"{repr_manager(self.unmanaged_cpcs, indent=2)}\n" f" _groups = {repr_manager(self.groups, indent=2)}\n" @@ -1259,6 +1264,13 @@ def mfa_server_definitions(self): return self._mfa_server_definitions @property + def sso_server_definitions(self): + """ + :class:`~zhmcclient.mock.FakedSSOServerDefinitionManager`: Access to + the faked SSO Server Definition resources of this Console. + """ + return self._sso_server_definitions + @property def unmanaged_cpcs(self): """ :class:`~zhmcclient.mock.FakedUnmanagedCpcManager`: Access to the faked @@ -1782,6 +1794,76 @@ def __init__(self, manager, properties): properties=properties) +class FakedSSOServerDefinitionManager(FakedBaseManager): + """ + A manager for faked SSO Server Definition resources within a faked HMC + (see :class:`zhmcclient.mock.FakedHmc`). + Derived from :class:`zhmcclient.mock.FakedBaseManager`, see there for + common methods and attributes. + """ + + def __init__(self, hmc, console): + super().__init__( + hmc=hmc, + parent=console, + resource_class=FakedSSOServerDefinition, + base_uri=console.uri + '/sso-server-definitions', + oid_prop='element-id', + uri_prop='element-uri', + class_value='sso-server-definition', + name_prop='name', + case_insensitive_names=True) + + def add(self, properties): + # pylint: disable=useless-super-delegation + """ + Add a faked SSO Server Definition resource. + Parameters: + properties (dict): + Resource properties. + Special handling and requirements for certain properties: + * 'element-id' will be auto-generated with a unique value across + all instances of this resource type, if not specified. + * 'element-uri' will be auto-generated based upon the element ID, + if not specified. + * 'class' will be auto-generated to 'sso-server-definition', + if not specified. + * All of the other class-soecific resource properties will be set + to a default value consistent with the HMC data model. + Returns: + :class:`~zhmcclient.mock.FakedSSOServerDefinition`: The faked + SSOServerDefinition resource. + """ + new_lsd = super().add(properties) + + # Resource type specific default values + new_lsd.properties.setdefault('description', '') + new_lsd.properties.setdefault('authentication-url', 'https://sso1.example.com/auth') + new_lsd.properties.setdefault('type', 'oidc') + new_lsd.properties.setdefault('logout-sso-session-on-reauthentication-failure', + True) + new_lsd.properties.setdefault('logout-url','https://sso1.example.com/logout') + new_lsd.properties.setdefault('issuer-url', 'https://sso1.example.com/issuer') + new_lsd.properties.setdefault('jwks-url', 'https://sso1.example.com/jwks') + new_lsd.properties.setdefault('replication-overwrite-possible', False) + + + return new_lsd + + +class FakedSSOServerDefinition(FakedBaseResource): + """ + A faked SSO Server Definition resource within a faked HMC (see + :class:`zhmcclient.mock.FakedHmc`). + Derived from :class:`zhmcclient.mock.FakedBaseResource`, see there for + common methods and attributes. + """ + + def __init__(self, manager, properties): + super().__init__( + manager=manager, + properties=properties) + class FakedActivationProfileManager(FakedBaseManager): """ A manager for faked Activation Profile resources within a faked HMC (see diff --git a/zhmcclient/mock/_session.py b/zhmcclient/mock/_session.py index 52b7e811..b7608731 100644 --- a/zhmcclient/mock/_session.py +++ b/zhmcclient/mock/_session.py @@ -293,7 +293,7 @@ }, }, "LdapServerDefinition": { - "description": "An LPAP server definition on an HMC", + "description": "An LDAP server definition on an HMC", "type": "object", "additionalProperties": False, "required": [ From db173459270fb6f64586e873cef19290daa1e879 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 00:23:43 +0530 Subject: [PATCH 02/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- tests/end2end/test_sso_server_definition.py | 136 +++++---- .../zhmcclient/test_sso_server_definition.py | 268 +++++++++--------- zhmcclient/_console.py | 2 +- zhmcclient/_sso_server_definition.py | 3 +- zhmcclient/mock/_hmc.py | 17 +- 5 files changed, 228 insertions(+), 198 deletions(-) diff --git a/tests/end2end/test_sso_server_definition.py b/tests/end2end/test_sso_server_definition.py index 1e59db25..4a64d069 100644 --- a/tests/end2end/test_sso_server_definition.py +++ b/tests/end2end/test_sso_server_definition.py @@ -26,17 +26,22 @@ import zhmcclient -from .utils import skip_warn, pick_test_resources, TEST_PREFIX, \ - runtest_find_list, runtest_get_properties +from .utils import ( + skip_warn, + pick_test_resources, + TEST_PREFIX, + runtest_find_list, + runtest_get_properties, +) urllib3.disable_warnings() # Properties in minimalistic SSOServerDefinition objects (e.g. find_by_name()) -SSOSRVDEF_MINIMAL_PROPS = ['element-uri', 'name'] +SSOSRVDEF_MINIMAL_PROPS = ["element-uri", "name"] # Properties in SSOServerDefinition objects returned by list() without full # props -SSOSRVDEF_LIST_PROPS = ['element-uri', 'name','type'] +SSOSRVDEF_LIST_PROPS = ["element-uri", "name", "type"] # Properties whose values can change between retrievals of SSOServerDefinition # objects @@ -52,11 +57,13 @@ def test_ssosrvdef_find_list(hmc_session): hd = hmc_session.hmc_definition api_version = client.query_api_version() - hmc_version = api_version['hmc-version'] - hmc_version_info = tuple(map(int, hmc_version.split('.'))) + hmc_version = api_version["hmc-version"] + hmc_version_info = tuple(map(int, hmc_version.split("."))) if hmc_version_info < (2, 17, 0): - skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " - "support SSO server definitions") + skip_warn( + f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions" + ) # Pick the SSO server definitions to test with ssosrvdef_list = console.sso_server_definitions.list() @@ -67,9 +74,15 @@ def test_ssosrvdef_find_list(hmc_session): for ssosrvdef in ssosrvdef_list: print(f"Testing with SSO server definition {ssosrvdef.name!r}") runtest_find_list( - hmc_session, console.sso_server_definitions, ssosrvdef.name, - 'name', 'element-uri', SSOSRVDEF_VOLATILE_PROPS, - SSOSRVDEF_MINIMAL_PROPS, SSOSRVDEF_LIST_PROPS) + hmc_session, + console.sso_server_definitions, + ssosrvdef.name, + "name", + "element-uri", + SSOSRVDEF_VOLATILE_PROPS, + SSOSRVDEF_MINIMAL_PROPS, + SSOSRVDEF_LIST_PROPS, + ) def test_ssosrvdef_property(hmc_session): @@ -81,11 +94,13 @@ def test_ssosrvdef_property(hmc_session): hd = hmc_session.hmc_definition api_version = client.query_api_version() - hmc_version = api_version['hmc-version'] - hmc_version_info = tuple(map(int, hmc_version.split('.'))) + hmc_version = api_version["hmc-version"] + hmc_version_info = tuple(map(int, hmc_version.split("."))) if hmc_version_info < (2, 17, 0): - skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " - "support SSO server definitions") + skip_warn( + f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions" + ) # Pick the SSO server definitions to test with ssosrvdef_list = console.sso_server_definitions.list() @@ -97,7 +112,7 @@ def test_ssosrvdef_property(hmc_session): print(f"Testing with SSO server definition {ssosrvdef.name!r}") # Select a property that is not returned by list() - non_list_prop = 'description' + non_list_prop = "description" runtest_get_properties(ssosrvdef.manager, non_list_prop) @@ -111,78 +126,79 @@ def test_ssosrvdef_crud(hmc_session): hd = hmc_session.hmc_definition api_version = client.query_api_version() - hmc_version = api_version['hmc-version'] - hmc_version_info = tuple(map(int, hmc_version.split('.'))) + hmc_version = api_version["hmc-version"] + hmc_version_info = tuple(map(int, hmc_version.split("."))) if hmc_version_info < (2, 17, 0): - skip_warn(f"HMC {hd.host} of version {hmc_version} does not yet " - "support SSO server definitions") + skip_warn( + f"HMC {hd.host} of version {hmc_version} does not yet " + "support SSO server definitions" + ) - ssosrvdef_name = TEST_PREFIX + ' test_ssosrvdef_crud ssosrvdef1' - ssosrvdef_name_new = ssosrvdef_name + ' new' + ssosrvdef_name = TEST_PREFIX + " test_ssosrvdef_crud ssosrvdef1" + ssosrvdef_name_new = ssosrvdef_name + " new" # Ensure a clean starting point for this test try: - ssosrvdef = console.sso_server_definitions.find( - name=ssosrvdef_name) + ssosrvdef = console.sso_server_definitions.find(name=ssosrvdef_name) except zhmcclient.NotFound: pass else: warnings.warn( "Deleting test SSO server definition from previous run: " - f"{ssosrvdef_name!r}", UserWarning) + f"{ssosrvdef_name!r}", + UserWarning, + ) ssosrvdef.delete() # Test creating the SSO server definition ssosrvdef_input_props = { - "authentication-page-servers":[ - { - "hostname-ipaddr":"images1.example.com", - "port":443 - }, - { - "hostname-ipaddr":"images2.example.com", - "port":80 - } - ], - "authentication-url":"https://sso1.example.com/auth", - "client-id":"sso1-123456", - "client-secret":"sso1-client-secret", - "description":"Primary SSO server", - "issuer-url":"https://sso1.example.com/issuer", - "jwks-url":"https://sso1.example.com/jwks", - "logout-sso-session-on-reauthentication-failure":true, - "logout-url":"https://sso1.example.com/logout", - "name":"SSO Server 1", - "token-url":"https://sso1.example.com/token", - "type":"oidc" + "authentication-page-servers": [ + {"hostname-ipaddr": "images1.example.com", "port": 443}, + {"hostname-ipaddr": "images2.example.com", "port": 80}, + ], + "authentication-url": "https://sso1.example.com/auth", + "client-id": "sso1-123456", + "client-secret": "sso1-client-secret", + "description": "Primary SSO server", + "issuer-url": "https://sso1.example.com/issuer", + "jwks-url": "https://sso1.example.com/jwks", + "logout-sso-session-on-reauthentication-failure": true, + "logout-url": "https://sso1.example.com/logout", + "name": "SSO Server 1", + "token-url": "https://sso1.example.com/token", + "type": "oidc", } ssosrvdef_auto_props = { - 'logout-url': None, - 'logout-sso-session-on-reauthentication-failure': False, + "logout-url": None, + "logout-sso-session-on-reauthentication-failure": False, } # The code to be tested try: - ssosrvdef = console.sso_server_definitions.create( - ssosrvdef_input_props) + ssosrvdef = console.sso_server_definitions.create(ssosrvdef_input_props) except zhmcclient.HTTPError as exc: if exc.http_status == 403 and exc.reason == 1: - skip_warn(f"HMC userid {hd.userid!r} is not authorized for task " - f"'Manage Single Sign-On Servers' on HMC {hd.host}") + skip_warn( + f"HMC userid {hd.userid!r} is not authorized for task " + f"'Manage Single Sign-On Servers' on HMC {hd.host}" + ) else: raise for pn, exp_value in ssosrvdef_input_props.items(): - assert ssosrvdef.properties[pn] == exp_value, \ - f"Unexpected value for property {pn!r}" + assert ( + ssosrvdef.properties[pn] == exp_value + ), f"Unexpected value for property {pn!r}" ssosrvdef.pull_full_properties() for pn, exp_value in ssosrvdef_input_props.items(): - assert ssosrvdef.properties[pn] == exp_value, \ - f"Unexpected value for property {pn!r}" + assert ( + ssosrvdef.properties[pn] == exp_value + ), f"Unexpected value for property {pn!r}" for pn, exp_value in ssosrvdef_auto_props.items(): - assert ssosrvdef.properties[pn] == exp_value, \ - f"Unexpected value for property {pn!r}" + assert ( + ssosrvdef.properties[pn] == exp_value + ), f"Unexpected value for property {pn!r}" # Test updating a property of the SSO server definition @@ -191,9 +207,9 @@ def test_ssosrvdef_crud(hmc_session): # The code to be tested ssosrvdef.update_properties(dict(description=new_desc)) - assert ssosrvdef.properties['description'] == new_desc + assert ssosrvdef.properties["description"] == new_desc ssosrvdef.pull_full_properties() - assert ssosrvdef.properties['description'] == new_desc + assert ssosrvdef.properties["description"] == new_desc # Test that SSO server definitions cannot be renamed diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 3e0690f3..4b826413 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -39,17 +39,19 @@ def setup_method(self): """ # pylint: disable=attribute-defined-outside-init - self.session = FakedSession('fake-host', 'fake-hmc', '2.17.1', '1.8') + self.session = FakedSession("fake-host", "fake-hmc", "2.17.1", "1.8") self.client = Client(self.session) - self.faked_console = self.session.hmc.consoles.add({ - 'object-id': None, - # object-uri will be automatically set - 'parent': None, - 'class': 'console', - 'name': 'fake-console1', - 'description': 'Console #1', - }) + self.faked_console = self.session.hmc.consoles.add( + { + "object-id": None, + # object-uri will be automatically set + "parent": None, + "class": "console", + "name": "fake-console1", + "description": "Console #1", + } + ) self.console = self.client.consoles.find(name=self.faked_console.name) def add_sso_srv_def(self, name): @@ -58,33 +60,29 @@ def add_sso_srv_def(self, name): and return it. """ - faked_sso_srv_def = self.faked_console.sso_server_definitions.add({ - 'element-id': f'oid-{name}', - # element-uri will be automatically set - 'parent': '/api/console', - 'class': 'sso-server-definition', - 'name': name, - 'description': f'SSO Server Definition {name}', - "authentication-page-servers":[ + faked_sso_srv_def = self.faked_console.sso_server_definitions.add( { - "hostname-ipaddr":"images1.example.com", - "port":443 - }, - { - "hostname-ipaddr":"images2.example.com", - "port":80 + "element-id": f"oid-{name}", + # element-uri will be automatically set + "parent": "/api/console", + "class": "sso-server-definition", + "name": name, + "description": f"SSO Server Definition {name}", + "authentication-page-servers": [ + {"hostname-ipaddr": "images1.example.com", "port": 443}, + {"hostname-ipaddr": "images2.example.com", "port": 80}, + ], + "authentication-url": "https://sso1.example.com/auth", + "client-id": "sso1-123456", + "element-uri": "/api/console/sso-server-definitions/c6a464c2-a211-11ef-bbc4-fa163e7cf285", + "issuer-url": "https://sso1.example.com/issuer", + "jwks-url": "https://sso1.example.com/jwks", + "logout-sso-session-on-reauthentication-failure": true, + "logout-url": "https://sso1.example.com/logoff", + "token-url": "https://sso1.example.com/token", + "type": "oidc", } - ], - "authentication-url":"https://sso1.example.com/auth", - "client-id":"sso1-123456", - "element-uri":"/api/console/sso-server-definitions/c6a464c2-a211-11ef-bbc4-fa163e7cf285", - "issuer-url":"https://sso1.example.com/issuer", - "jwks-url":"https://sso1.example.com/jwks", - "logout-sso-session-on-reauthentication-failure":true, - "logout-url":"https://sso1.example.com/logoff", - "token-url":"https://sso1.example.com/token", - "type":"oidc" - }) + ) return faked_sso_srv_def def test_sso_srv_def_manager_repr(self): @@ -95,12 +93,13 @@ def test_sso_srv_def_manager_repr(self): # Execute the code to be tested repr_str = repr(sso_srv_def_mgr) - repr_str = repr_str.replace('\n', '\\n') + repr_str = repr_str.replace("\n", "\\n") # We check just the begin of the string: assert re.match( - rf'^{sso_srv_def_mgr.__class__.__name__}\s+at\s+' - rf'0x{id(sso_srv_def_mgr):08x}\s+\(\\n.*', - repr_str) + rf"^{sso_srv_def_mgr.__class__.__name__}\s+at\s+" + rf"0x{id(sso_srv_def_mgr):08x}\s+\(\\n.*", + repr_str, + ) def test_sso_srv_def_manager_initial_attrs(self): """Test initial attributes of SSOServerDefinitionManager.""" @@ -109,84 +108,93 @@ def test_sso_srv_def_manager_initial_attrs(self): # Verify all public properties of the manager object assert sso_srv_def_mgr.resource_class == SSOServerDefinition - assert sso_srv_def_mgr.class_name == 'sso-server-definition' + assert sso_srv_def_mgr.class_name == "sso-server-definition" assert sso_srv_def_mgr.session is self.session assert sso_srv_def_mgr.parent is self.console assert sso_srv_def_mgr.console is self.console @pytest.mark.parametrize( - "full_properties_kwargs, prop_names", [ - (dict(full_properties=False), - ['element-uri', 'name','type']), - (dict(full_properties=True), - ['element-uri', 'name', 'type']), - ({}, # test default for full_properties (False) - ['element-uri', 'name','type']), - ] + "full_properties_kwargs, prop_names", + [ + (dict(full_properties=False), ["element-uri", "name", "type"]), + (dict(full_properties=True), ["element-uri", "name", "type"]), + ( + {}, # test default for full_properties (False) + ["element-uri", "name", "type"], + ), + ], ) @pytest.mark.parametrize( - "filter_args, exp_names", [ - (None, - ['a', 'b']), - ({}, - ['a', 'b']), - ({'name': 'a'}, - ['a']), - ({'name': 'A'}, # SSO user definitions have case-insensitive names - ['a']), - ] + "filter_args, exp_names", + [ + (None, ["a", "b"]), + ({}, ["a", "b"]), + ({"name": "a"}, ["a"]), + ({"name": "A"}, ["a"]), # SSO user definitions have case-insensitive names + ], ) def test_sso_srv_def_manager_list( - self, filter_args, exp_names, full_properties_kwargs, prop_names): + self, filter_args, exp_names, full_properties_kwargs, prop_names + ): """Test SSOServerDefinitionManager.list().""" - faked_sso_srv_def1 = self.add_sso_srv_def(name='a') - faked_sso_srv_def2 = self.add_sso_srv_def(name='b') + faked_sso_srv_def1 = self.add_sso_srv_def(name="a") + faked_sso_srv_def2 = self.add_sso_srv_def(name="b") faked_sso_srv_defs = [faked_sso_srv_def1, faked_sso_srv_def2] - exp_faked_sso_srv_defs = [u for u in faked_sso_srv_defs - if u.name in exp_names] + exp_faked_sso_srv_defs = [u for u in faked_sso_srv_defs if u.name in exp_names] sso_srv_def_mgr = self.console.sso_server_definitions # Execute the code to be tested - sso_srv_defs = sso_srv_def_mgr.list(filter_args=filter_args, - **full_properties_kwargs) + sso_srv_defs = sso_srv_def_mgr.list( + filter_args=filter_args, **full_properties_kwargs + ) assert_resources(sso_srv_defs, exp_faked_sso_srv_defs, prop_names) @pytest.mark.parametrize( - "input_props, exp_prop_names, exp_exc", [ - ({}, # props missing - None, - HTTPError({'http-status': 400, 'reason': 5})), - ({'description': 'fake description X'}, # props missing - None, - HTTPError({'http-status': 400, 'reason': 5})), - ({'description': 'fake description X', - 'name': 'a', - 'type': 'oidc', - 'client-secret': 'sso1-client-secret', - "issuer-url":"https://sso1.example.com/issuer", - 'authentication-url' :'https://sso1.example.com/auth', - 'token-url':'https://sso1.example.com/token', - "jwks-url":"https://sso1.example.com/jwks", - 'logout-url ':'https://sso1.example.com/logout'}, - ['element-uri', 'name', 'description'], - None), - ({'description': 'fake description X', - 'name': 'a', - 'type': 'oidc', - 'client-secret': 'sso1-client-secret', - "issuer-url":"https://sso1.example.com/issuer", - 'authentication-url' :'https://sso1.example.com/auth', - 'token-url':'https://sso1.example.com/token', - "jwks-url":"https://sso1.example.com/jwks", - 'logout-url ':'https://sso1.example.com/logout'}, - ['element-uri', 'name', 'client-secret'], - None), - ] + "input_props, exp_prop_names, exp_exc", + [ + ({}, None, HTTPError({"http-status": 400, "reason": 5})), # props missing + ( + {"description": "fake description X"}, # props missing + None, + HTTPError({"http-status": 400, "reason": 5}), + ), + ( + { + "description": "fake description X", + "name": "a", + "type": "oidc", + "client-secret": "sso1-client-secret", + "issuer-url": "https://sso1.example.com/issuer", + "authentication-url": "https://sso1.example.com/auth", + "token-url": "https://sso1.example.com/token", + "jwks-url": "https://sso1.example.com/jwks", + "logout-url ": "https://sso1.example.com/logout", + }, + ["element-uri", "name", "description"], + None, + ), + ( + { + "description": "fake description X", + "name": "a", + "type": "oidc", + "client-secret": "sso1-client-secret", + "issuer-url": "https://sso1.example.com/issuer", + "authentication-url": "https://sso1.example.com/auth", + "token-url": "https://sso1.example.com/token", + "jwks-url": "https://sso1.example.com/jwks", + "logout-url ": "https://sso1.example.com/logout", + }, + ["element-uri", "name", "client-secret"], + None, + ), + ], ) def test_sso_srv_def_manager_create( - self, caplog, input_props, exp_prop_names, exp_exc): + self, caplog, input_props, exp_prop_names, exp_exc + ): """Test SSOServerDefinitionManager.create().""" logger_name = "zhmcclient.api" @@ -208,7 +216,6 @@ def test_sso_srv_def_manager_create( else: - # Execute the code to be tested. sso_srv_def = sso_srv_def_mgr.create(properties=input_props) @@ -218,10 +225,10 @@ def test_sso_srv_def_manager_create( # Check the resource for consistency within itself assert isinstance(sso_srv_def, SSOServerDefinition) sso_srv_def_name = sso_srv_def.name - exp_sso_srv_def_name = sso_srv_def.properties['name'] + exp_sso_srv_def_name = sso_srv_def.properties["name"] assert sso_srv_def_name == exp_sso_srv_def_name sso_srv_def_uri = sso_srv_def.uri - exp_sso_srv_def_uri = sso_srv_def.properties['element-uri'] + exp_sso_srv_def_uri = sso_srv_def.properties["element-uri"] assert sso_srv_def_uri == exp_sso_srv_def_uri # Check the properties against the expected names and values @@ -234,38 +241,39 @@ def test_sso_srv_def_manager_create( # Verify the API call log record for blanked-out properties. assert_blanked_in_message( - call_record.message, input_props, - ['client-secret']) + call_record.message, input_props, ["client-secret"] + ) def test_sso_srv_def_repr(self): """Test SSOServerDefinition.__repr__().""" - faked_sso_srv_def1 = self.add_sso_srv_def(name='a') + faked_sso_srv_def1 = self.add_sso_srv_def(name="a") sso_srv_def1 = self.console.sso_server_definitions.find( - name=faked_sso_srv_def1.name) + name=faked_sso_srv_def1.name + ) # Execute the code to be tested repr_str = repr(sso_srv_def1) - repr_str = repr_str.replace('\n', '\\n') + repr_str = repr_str.replace("\n", "\\n") # We check just the begin of the string: assert re.match( - rf'^{sso_srv_def1.__class__.__name__}\s+at\s+' - rf'0x{id(sso_srv_def1):08x}\s+\(\\n.*', - repr_str) + rf"^{sso_srv_def1.__class__.__name__}\s+at\s+" + rf"0x{id(sso_srv_def1):08x}\s+\(\\n.*", + repr_str, + ) @pytest.mark.parametrize( - "input_props, exp_exc", [ - ({'name': 'a'}, - None), - ({'name': 'b'}, - None), - ] + "input_props, exp_exc", + [ + ({"name": "a"}, None), + ({"name": "b"}, None), + ], ) def test_sso_srv_def_delete(self, input_props, exp_exc): """Test SSOServerDefinition.delete().""" - faked_sso_srv_def = self.add_sso_srv_def(name=input_props['name']) + faked_sso_srv_def = self.add_sso_srv_def(name=input_props["name"]) sso_srv_def_mgr = self.console.sso_server_definitions sso_srv_def = sso_srv_def_mgr.find(name=faked_sso_srv_def.name) @@ -298,17 +306,17 @@ def test_sso_delete_create_same(self): """Test SSOServerDefinition.delete() followed by create() with same name.""" - sso_srv_def_name = 'faked_a' + sso_srv_def_name = "faked_a" # Add the SSO Server Definition to be tested self.add_sso_srv_def(name=sso_srv_def_name) # Input properties for a SSO Server Definition with the same name sn_sso_srv_def_props = { - 'name': sso_srv_def_name, - 'description': 'SSO Server Definition with same name', - 'primary-hostname-ipaddr': '10.11.12.13', - 'search-distinguished-name': 'test{0}', + "name": sso_srv_def_name, + "description": "SSO Server Definition with same name", + "primary-hostname-ipaddr": "10.11.12.13", + "search-distinguished-name": "test{0}", } sso_srv_def_mgr = self.console.sso_server_definitions @@ -326,15 +334,16 @@ def test_sso_delete_create_same(self): # Check that the SSO Server Definition exists again under that name sn_sso_srv_def = sso_srv_def_mgr.find(name=sso_srv_def_name) - description = sn_sso_srv_def.get_property('description') - assert description == sn_sso_srv_def_props['description'] + description = sn_sso_srv_def.get_property("description") + assert description == sn_sso_srv_def_props["description"] @pytest.mark.parametrize( - "input_props", [ + "input_props", + [ {}, - {'description': 'New SSO Server Definition description'}, - {'client-secret': 'bla'}, - ] + {"description": "New SSO Server Definition description"}, + {"client-secret": "bla"}, + ], ) def test_sso_srv_def_update_properties(self, caplog, input_props): """Test SSOServerDefinition.update_properties().""" @@ -342,7 +351,7 @@ def test_sso_srv_def_update_properties(self, caplog, input_props): logger_name = "zhmcclient.api" caplog.set_level(logging.DEBUG, logger=logger_name) - sso_srv_def_name = 'faked_a' + sso_srv_def_name = "faked_a" # Add the SSO Server Definition to be tested self.add_sso_srv_def(name=sso_srv_def_name) @@ -368,8 +377,9 @@ def test_sso_srv_def_update_properties(self, caplog, input_props): exp_prop_value = saved_properties[prop_name] assert prop_name in sso_srv_def.properties prop_value = sso_srv_def.properties[prop_name] - assert prop_value == exp_prop_value, \ - f"Unexpected value for property {prop_name!r}" + assert ( + prop_value == exp_prop_value + ), f"Unexpected value for property {prop_name!r}" # Refresh the resource object and verify that the resource object # still reflects the property updates. @@ -384,6 +394,4 @@ def test_sso_srv_def_update_properties(self, caplog, input_props): assert prop_value == exp_prop_value # Verify the API call log record for blanked-out properties. - assert_blanked_in_message( - call_record.message, input_props, - ['client-secret']) + assert_blanked_in_message(call_record.message, input_props, ["client-secret"]) diff --git a/zhmcclient/_console.py b/zhmcclient/_console.py index 81b622c7..9dcf96db 100644 --- a/zhmcclient/_console.py +++ b/zhmcclient/_console.py @@ -350,7 +350,7 @@ def sso_server_definitions(self): if not self._sso_server_definitions: self._sso_server_definitions = SSOServerDefinitionManager(self) return self._sso_server_definitions - + @property def unmanaged_cpcs(self): """ diff --git a/zhmcclient/_sso_server_definition.py b/zhmcclient/_sso_server_definition.py index 7062d241..aeda8d61 100644 --- a/zhmcclient/_sso_server_definition.py +++ b/zhmcclient/_sso_server_definition.py @@ -119,7 +119,8 @@ def list(self, full_properties=False, filter_args=None): Authorization requirements: * User-related-access permission to the SSO Server Definition objects - included in the result, or task permission to the "Manage Single Sign-On Servers" task. + included in the result, or task permission to the "Manage Single + Sign-On Servers" task. Parameters: diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index e6ac618e..7418206f 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1270,6 +1270,7 @@ def sso_server_definitions(self): the faked SSO Server Definition resources of this Console. """ return self._sso_server_definitions + @property def unmanaged_cpcs(self): """ @@ -1838,16 +1839,19 @@ def add(self, properties): # Resource type specific default values new_lsd.properties.setdefault('description', '') - new_lsd.properties.setdefault('authentication-url', 'https://sso1.example.com/auth') + new_lsd.properties.setdefault('authentication-url', + 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') - new_lsd.properties.setdefault('logout-sso-session-on-reauthentication-failure', + new_lsd.properties.setdefault('logout-sso-session-on-reauthentication-failure', True) - new_lsd.properties.setdefault('logout-url','https://sso1.example.com/logout') - new_lsd.properties.setdefault('issuer-url', 'https://sso1.example.com/issuer') - new_lsd.properties.setdefault('jwks-url', 'https://sso1.example.com/jwks') + new_lsd.properties.setdefault('logout-url', + 'https://sso1.example.com/logout') + new_lsd.properties.setdefault('issuer-url', + 'https://sso1.example.com/issuer') + new_lsd.properties.setdefault('jwks-url', + 'https://sso1.example.com/jwks') new_lsd.properties.setdefault('replication-overwrite-possible', False) - return new_lsd @@ -1864,6 +1868,7 @@ def __init__(self, manager, properties): manager=manager, properties=properties) + class FakedActivationProfileManager(FakedBaseManager): """ A manager for faked Activation Profile resources within a faked HMC (see From 8e7c8c64199f91c94de76d8f1df0327c634fb6f9 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 00:48:43 +0530 Subject: [PATCH 03/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- tests/end2end/test_sso_server_definition.py | 2 +- .../zhmcclient/test_sso_server_definition.py | 16 ++++++++++------ zhmcclient/_sso_server_definition.py | 2 +- zhmcclient/mock/_hmc.py | 13 +++++++------ 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tests/end2end/test_sso_server_definition.py b/tests/end2end/test_sso_server_definition.py index 4a64d069..b2c7b42e 100644 --- a/tests/end2end/test_sso_server_definition.py +++ b/tests/end2end/test_sso_server_definition.py @@ -163,7 +163,7 @@ def test_ssosrvdef_crud(hmc_session): "description": "Primary SSO server", "issuer-url": "https://sso1.example.com/issuer", "jwks-url": "https://sso1.example.com/jwks", - "logout-sso-session-on-reauthentication-failure": true, + "logout-sso-session-on-reauthentication-failure": True, "logout-url": "https://sso1.example.com/logout", "name": "SSO Server 1", "token-url": "https://sso1.example.com/token", diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 4b826413..e277cc72 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -74,10 +74,10 @@ def add_sso_srv_def(self, name): ], "authentication-url": "https://sso1.example.com/auth", "client-id": "sso1-123456", - "element-uri": "/api/console/sso-server-definitions/c6a464c2-a211-11ef-bbc4-fa163e7cf285", + "element-uri": "/api/console/sso-server-definitions/c42-211", "issuer-url": "https://sso1.example.com/issuer", "jwks-url": "https://sso1.example.com/jwks", - "logout-sso-session-on-reauthentication-failure": true, + "logout-sso-session-on-reauthentication-failure": True, "logout-url": "https://sso1.example.com/logoff", "token-url": "https://sso1.example.com/token", "type": "oidc", @@ -130,7 +130,7 @@ def test_sso_srv_def_manager_initial_attrs(self): (None, ["a", "b"]), ({}, ["a", "b"]), ({"name": "a"}, ["a"]), - ({"name": "A"}, ["a"]), # SSO user definitions have case-insensitive names + ({"name": "A"}, ["a"]), # SSO user have case-insensitive names ], ) def test_sso_srv_def_manager_list( @@ -141,7 +141,8 @@ def test_sso_srv_def_manager_list( faked_sso_srv_def1 = self.add_sso_srv_def(name="a") faked_sso_srv_def2 = self.add_sso_srv_def(name="b") faked_sso_srv_defs = [faked_sso_srv_def1, faked_sso_srv_def2] - exp_faked_sso_srv_defs = [u for u in faked_sso_srv_defs if u.name in exp_names] + exp_faked_sso_srv_defs = [u for u in faked_sso_srv_defs + if u.name in exp_names] sso_srv_def_mgr = self.console.sso_server_definitions # Execute the code to be tested @@ -154,7 +155,9 @@ def test_sso_srv_def_manager_list( @pytest.mark.parametrize( "input_props, exp_prop_names, exp_exc", [ - ({}, None, HTTPError({"http-status": 400, "reason": 5})), # props missing + ({}, # props missing + None, + HTTPError({"http-status": 400, "reason": 5})), ( {"description": "fake description X"}, # props missing None, @@ -394,4 +397,5 @@ def test_sso_srv_def_update_properties(self, caplog, input_props): assert prop_value == exp_prop_value # Verify the API call log record for blanked-out properties. - assert_blanked_in_message(call_record.message, input_props, ["client-secret"]) + assert_blanked_in_message(call_record.message, input_props, + ["client-secret"]) diff --git a/zhmcclient/_sso_server_definition.py b/zhmcclient/_sso_server_definition.py index aeda8d61..bf7104b5 100644 --- a/zhmcclient/_sso_server_definition.py +++ b/zhmcclient/_sso_server_definition.py @@ -119,7 +119,7 @@ def list(self, full_properties=False, filter_args=None): Authorization requirements: * User-related-access permission to the SSO Server Definition objects - included in the result, or task permission to the "Manage Single + included in the result, or task permission to the "Manage Single Sign-On Servers" task. Parameters: diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 7418206f..44840bba 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1270,7 +1270,7 @@ def sso_server_definitions(self): the faked SSO Server Definition resources of this Console. """ return self._sso_server_definitions - + @property def unmanaged_cpcs(self): """ @@ -1839,16 +1839,17 @@ def add(self, properties): # Resource type specific default values new_lsd.properties.setdefault('description', '') - new_lsd.properties.setdefault('authentication-url', + new_lsd.properties.setdefault('authentication-url', 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') - new_lsd.properties.setdefault('logout-sso-session-on-reauthentication-failure', + new_lsd.properties.setdefault( + 'logout-sso-session-on-reauthentication-failure', True) - new_lsd.properties.setdefault('logout-url', + new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') - new_lsd.properties.setdefault('issuer-url', + new_lsd.properties.setdefault('issuer-url', 'https://sso1.example.com/issuer') - new_lsd.properties.setdefault('jwks-url', + new_lsd.properties.setdefault('jwks-url', 'https://sso1.example.com/jwks') new_lsd.properties.setdefault('replication-overwrite-possible', False) From ef52d1927684bc8b327d2a514383276737862633 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 00:56:49 +0530 Subject: [PATCH 04/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 2 +- zhmcclient/mock/_hmc.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index e277cc72..cb574311 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -397,5 +397,5 @@ def test_sso_srv_def_update_properties(self, caplog, input_props): assert prop_value == exp_prop_value # Verify the API call log record for blanked-out properties. - assert_blanked_in_message(call_record.message, input_props, + assert_blanked_in_message(call_record.message, input_props, ["client-secret"]) diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 44840bba..461c4410 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1843,8 +1843,8 @@ def add(self, properties): 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') new_lsd.properties.setdefault( - 'logout-sso-session-on-reauthentication-failure', - True) + 'logout-sso-session-on-reauthentication-failure', True + ) new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') new_lsd.properties.setdefault('issuer-url', From c99d5bd893640af933075f9706d2d7caced3fda0 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 01:00:43 +0530 Subject: [PATCH 05/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_hmc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 461c4410..38719c76 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1844,7 +1844,7 @@ def add(self, properties): new_lsd.properties.setdefault('type', 'oidc') new_lsd.properties.setdefault( 'logout-sso-session-on-reauthentication-failure', True - ) + ) new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') new_lsd.properties.setdefault('issuer-url', From 20919ab0558b216558a6dde94e709f9769345bfe Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 01:07:09 +0530 Subject: [PATCH 06/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_hmc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 38719c76..8a8e0c39 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1843,7 +1843,7 @@ def add(self, properties): 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') new_lsd.properties.setdefault( - 'logout-sso-session-on-reauthentication-failure', True + 'logout-sso-session-on-reauthentication-failure', True ) new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') From ed33f3c8fed16d250b7efe1da9367b3515ba1d53 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 01:12:47 +0530 Subject: [PATCH 07/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_hmc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index 8a8e0c39..d8f600f3 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1843,7 +1843,7 @@ def add(self, properties): 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') new_lsd.properties.setdefault( - 'logout-sso-session-on-reauthentication-failure', True + 'logout-sso-session-on-reauthentication-failure', True ) new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') From f15ab8f89c6f81811b5376728fbf0c845f2ba968 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Tue, 25 Nov 2025 01:15:43 +0530 Subject: [PATCH 08/22] Fixed run check issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_hmc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zhmcclient/mock/_hmc.py b/zhmcclient/mock/_hmc.py index d8f600f3..64122950 100644 --- a/zhmcclient/mock/_hmc.py +++ b/zhmcclient/mock/_hmc.py @@ -1843,7 +1843,7 @@ def add(self, properties): 'https://sso1.example.com/auth') new_lsd.properties.setdefault('type', 'oidc') new_lsd.properties.setdefault( - 'logout-sso-session-on-reauthentication-failure', True + 'logout-sso-session-on-reauthentication-failure', True ) new_lsd.properties.setdefault('logout-url', 'https://sso1.example.com/logout') From 8a8c39d26587eaf32d6665dab123c36a26f83a2a Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Thu, 27 Nov 2025 12:05:21 +0530 Subject: [PATCH 09/22] Fixed unit test issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/mock/test_session.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/unit/zhmcclient/mock/test_session.py b/tests/unit/zhmcclient/mock/test_session.py index 30025c9f..ad5821f5 100644 --- a/tests/unit/zhmcclient/mock/test_session.py +++ b/tests/unit/zhmcclient/mock/test_session.py @@ -90,6 +90,14 @@ }, }, ], + 'sso_server_definitions': [ + { + 'properties': { + 'element-id': 'sso1', + 'name': 'SSO server definition 1', + }, + }, + ], 'unmanaged_cpcs': [ { 'properties': { From 8cf43d697ff49a2474bcd24be0d6df798bab3bb2 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Thu, 27 Nov 2025 12:39:56 +0530 Subject: [PATCH 10/22] Fixed unit test issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_session.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/zhmcclient/mock/_session.py b/zhmcclient/mock/_session.py index b7608731..dd575191 100644 --- a/zhmcclient/mock/_session.py +++ b/zhmcclient/mock/_session.py @@ -204,6 +204,13 @@ "$ref": "#/definitions/LdapServerDefinition" }, }, + "sso_server_definitions": { + "description": "The SSO server definitions on this HMC", + "type": "array", + "items": { + "$ref": "#/definitions/SSOServerDefinition" + }, + }, "unmanaged_cpcs": { "description": "The unmanaged CPCs discovered by this HMC", "type": "array", @@ -305,6 +312,19 @@ }, }, }, + "SSOServerDefinition": { + "description": "An SSO server definition on an HMC", + "type": "object", + "additionalProperties": False, + "required": [ + "properties", + ], + "properties": { + "properties": { + "$ref": "#/definitions/Properties" + }, + }, + }, "UnmanagedCpc": { "description": "An unmanaged CPC discovered by an HMC", "type": "object", From 5a45cc5041e2bf85cb04ad4b4848feb5c2f2b644 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Thu, 27 Nov 2025 15:50:01 +0530 Subject: [PATCH 11/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- docs/resources.rst | 20 +++++++++++++++++++ .../zhmcclient/test_sso_server_definition.py | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/resources.rst b/docs/resources.rst index 78bc847e..35672d84 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -576,6 +576,26 @@ LDAP Server Definition :autosummary: :autosummary-inherited-members: :special-members: __str__ + + +.. _`SSO Server Definition`: + +SSO Server Definition +---------------------- + +.. automodule:: zhmcclient._sso_server_definition + +.. autoclass:: zhmcclient.SSOServerDefinitionManager + :members: + :autosummary: + :autosummary-inherited-members: + :special-members: __str__ + +.. autoclass:: zhmcclient.SSOServerDefinition + :members: + :autosummary: + :autosummary-inherited-members: + :special-members: __str__ .. _`MFA Server Definition`: diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index cb574311..4ba94026 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -39,7 +39,7 @@ def setup_method(self): """ # pylint: disable=attribute-defined-outside-init - self.session = FakedSession("fake-host", "fake-hmc", "2.17.1", "1.8") + self.session = FakedSession("fake-host", "fake-hmc", "2.14.1", "1.8") self.client = Client(self.session) self.faked_console = self.session.hmc.consoles.add( From 4e3c57f118426cb5e5b64a03735438fcd2889ec3 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 13:46:04 +0530 Subject: [PATCH 12/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- docs/mocksupport.rst | 6 ++++++ tests/unit/zhmcclient/test_sso_server_definition.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/mocksupport.rst b/docs/mocksupport.rst index 8c553f6f..f9ec1c91 100644 --- a/docs/mocksupport.rst +++ b/docs/mocksupport.rst @@ -221,6 +221,12 @@ Faked HMC .. autoclass:: zhmcclient.mock.FakedLdapServerDefinition :members: +.. autoclass:: zhmcclient.mock.FakedSSOServerDefinitionManager + :members: + +.. autoclass:: zhmcclient.mock.FakedSSOServerDefinition + :members: + .. autoclass:: zhmcclient.mock.FakedLparManager :members: diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 4ba94026..cb574311 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -39,7 +39,7 @@ def setup_method(self): """ # pylint: disable=attribute-defined-outside-init - self.session = FakedSession("fake-host", "fake-hmc", "2.14.1", "1.8") + self.session = FakedSession("fake-host", "fake-hmc", "2.17.1", "1.8") self.client = Client(self.session) self.faked_console = self.session.hmc.consoles.add( From b928df3d7468f354a48ed679f6fba4d56fafd06e Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 15:19:32 +0530 Subject: [PATCH 13/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/_sso_server_definition.py | 2 - zhmcclient/mock/_urihandler.py | 95 ++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/zhmcclient/_sso_server_definition.py b/zhmcclient/_sso_server_definition.py index bf7104b5..80283153 100644 --- a/zhmcclient/_sso_server_definition.py +++ b/zhmcclient/_sso_server_definition.py @@ -62,8 +62,6 @@ def __init__(self, console): # contain the name property. query_props = [ 'name', - 'type', - 'additional-properties', ] super().__init__( diff --git a/zhmcclient/mock/_urihandler.py b/zhmcclient/mock/_urihandler.py index 9c1f15b9..b326bb95 100644 --- a/zhmcclient/mock/_urihandler.py +++ b/zhmcclient/mock/_urihandler.py @@ -1900,6 +1900,96 @@ def post(method, hmc, uri, uri_parms, body, logon_required, mfa.update(body) +class SSOServerDefinitionsHandler: + """ + Handler class for HTTP methods on set of SSOServerDefinition resources. + """ + + valid_query_parms_get = ['name'] + + returned_props = ['element-uri', 'name','type'] + + @classmethod + def get(cls, method, hmc, uri, uri_parms, logon_required): + # pylint: disable=unused-argument + """Operation: List SSO Server Definitions.""" + uri, query_parms = parse_query_parms(method, uri) + check_invalid_query_parms( + method, uri, query_parms, cls.valid_query_parms_get) + filter_args = query_parms + + try: + console = hmc.consoles.lookup_by_oid(None) + except KeyError: + new_exc = InvalidResourceError(method, uri) + new_exc.__cause__ = None + raise new_exc # zhmcclient.mock.InvalidResourceError + result_sso_srv_defs = [] + for sso_srv_def in console.sso_server_definitions.list(filter_args): + result_sso_srv_def = {} + for prop in cls.returned_props: + result_sso_srv_def[prop] = \ + sso_srv_def.properties.get(prop) + result_sso_srv_defs.append(result_sso_srv_def) + return {'sso-server-definitions': result_sso_srv_defs} + + @staticmethod + def post(method, hmc, uri, uri_parms, body, logon_required, + wait_for_completion): + # pylint: disable=unused-argument + """Operation: Create SSO Server Definition.""" + assert wait_for_completion is True # synchronous operation + try: + console = hmc.consoles.lookup_by_oid(None) + except KeyError: + new_exc = InvalidResourceError(method, uri) + new_exc.__cause__ = None + raise new_exc # zhmcclient.mock.InvalidResourceError + check_required_fields(method, uri, body, + ['name', 'type','client-id','client-secret', + 'issuer-url','authentication-url','token-url', + 'jwks-url']) + new_sso_srv_def = console.sso_server_definitions.add(body) + return {'element-uri': new_sso_srv_def.uri} + + +class SSOServerDefinitionHandler(GenericGetPropertiesHandler, + GenericDeleteHandler): + """ + Handler class for HTTP methods on single SSOServerDefinition resource. + """ + + @staticmethod + def post(method, hmc, uri, uri_parms, body, logon_required, + wait_for_completion): + # pylint: disable=unused-argument + """Operation: Update SSOServerDefinition Properties.""" + try: + sso = hmc.lookup_by_uri(uri) + except KeyError: + new_exc = InvalidResourceError(method, uri) + new_exc.__cause__ = None + raise new_exc # zhmcclient.mock.InvalidResourceError + # Check whether requested properties are modifiable + check_writable( + method, uri, body, + [ + 'name', + 'description', + 'client-id', + 'client-secret', + 'issuer-url', + 'authentication-url', + 'token-url', + 'jwks-url', + 'logout-url', + 'logout-sso-session-on-reauthentication-failure', + 'authentication-page-servers', + + ]) + sso.update(body) + + class ConsoleHwMessagesHandler: """ Handler class for HTTP methods on set of Console HwMessage resources. @@ -6627,6 +6717,11 @@ def post(method, hmc, uri, uri_parms, body, logon_required, (r'/api/console/mfa-server-definitions/([^?/]+)(?:\?(.*))?', MfaServerDefinitionHandler), + (r'/api/console/sso-server-definitions(?:\?(.*))?', + SSOServerDefinitionsHandler), + (r'/api/console/sso-server-definitions/([^?/]+)(?:\?(.*))?', + SSOServerDefinitionHandler), + (r'/api/console/hardware-messages(?:\?(.*))?', ConsoleHwMessagesHandler), (r'/api/console/hardware-messages/([^?/]+)(?:\?(.*))?', From 94d677b0d18362703edee908c59abf4608afb0dd Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 15:25:27 +0530 Subject: [PATCH 14/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_urihandler.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zhmcclient/mock/_urihandler.py b/zhmcclient/mock/_urihandler.py index b326bb95..5390e446 100644 --- a/zhmcclient/mock/_urihandler.py +++ b/zhmcclient/mock/_urihandler.py @@ -1907,7 +1907,7 @@ class SSOServerDefinitionsHandler: valid_query_parms_get = ['name'] - returned_props = ['element-uri', 'name','type'] + returned_props = ['element-uri', 'name', 'type'] @classmethod def get(cls, method, hmc, uri, uri_parms, logon_required): @@ -1946,8 +1946,8 @@ def post(method, hmc, uri, uri_parms, body, logon_required, new_exc.__cause__ = None raise new_exc # zhmcclient.mock.InvalidResourceError check_required_fields(method, uri, body, - ['name', 'type','client-id','client-secret', - 'issuer-url','authentication-url','token-url', + ['name', 'type', 'client-id', 'client-secret', + 'issuer-url', 'authentication-url', 'token-url', 'jwks-url']) new_sso_srv_def = console.sso_server_definitions.add(body) return {'element-uri': new_sso_srv_def.uri} @@ -1984,12 +1984,11 @@ def post(method, hmc, uri, uri_parms, body, logon_required, 'jwks-url', 'logout-url', 'logout-sso-session-on-reauthentication-failure', - 'authentication-page-servers', - + 'authentication-page-servers', ]) - sso.update(body) - + sso.update(body) + class ConsoleHwMessagesHandler: """ Handler class for HTTP methods on set of Console HwMessage resources. From bb1dd82dc3407376012c7bc2022e1363818bf3a0 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 15:35:23 +0530 Subject: [PATCH 15/22] Fixed Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_urihandler.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zhmcclient/mock/_urihandler.py b/zhmcclient/mock/_urihandler.py index 5390e446..5f3db35d 100644 --- a/zhmcclient/mock/_urihandler.py +++ b/zhmcclient/mock/_urihandler.py @@ -1984,11 +1984,11 @@ def post(method, hmc, uri, uri_parms, body, logon_required, 'jwks-url', 'logout-url', 'logout-sso-session-on-reauthentication-failure', - 'authentication-page-servers', + 'authentication-page-servers', ]) - sso.update(body) - - + sso.update(body) + + class ConsoleHwMessagesHandler: """ Handler class for HTTP methods on set of Console HwMessage resources. @@ -6720,7 +6720,7 @@ def post(method, hmc, uri, uri_parms, body, logon_required, SSOServerDefinitionsHandler), (r'/api/console/sso-server-definitions/([^?/]+)(?:\?(.*))?', SSOServerDefinitionHandler), - + (r'/api/console/hardware-messages(?:\?(.*))?', ConsoleHwMessagesHandler), (r'/api/console/hardware-messages/([^?/]+)(?:\?(.*))?', From caa626b7cdc0f7d8794c1536dc3794e6ab527a8d Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 15:39:29 +0530 Subject: [PATCH 16/22] Fixed Signed-off-by: Vonteddu Chaithra --- zhmcclient/mock/_urihandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zhmcclient/mock/_urihandler.py b/zhmcclient/mock/_urihandler.py index 5f3db35d..7eb8d802 100644 --- a/zhmcclient/mock/_urihandler.py +++ b/zhmcclient/mock/_urihandler.py @@ -1987,7 +1987,7 @@ def post(method, hmc, uri, uri_parms, body, logon_required, 'authentication-page-servers', ]) sso.update(body) - + class ConsoleHwMessagesHandler: """ From eb14d015e8cb53c4423dc6d45d917b785204a994 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 16:12:33 +0530 Subject: [PATCH 17/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index cb574311..75804c5d 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -165,9 +165,9 @@ def test_sso_srv_def_manager_list( ), ( { - "description": "fake description X", - "name": "a", + "name": "t", "type": "oidc", + "client-id": "sso1-123456", "client-secret": "sso1-client-secret", "issuer-url": "https://sso1.example.com/issuer", "authentication-url": "https://sso1.example.com/auth", @@ -184,6 +184,7 @@ def test_sso_srv_def_manager_list( "name": "a", "type": "oidc", "client-secret": "sso1-client-secret", + "client-id": "sso1-123456", "issuer-url": "https://sso1.example.com/issuer", "authentication-url": "https://sso1.example.com/auth", "token-url": "https://sso1.example.com/token", From 84c5929ac8a33e224aab8cfb83ad0e3e3eff59fe Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 16:26:22 +0530 Subject: [PATCH 18/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 75804c5d..2fa920d9 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -165,6 +165,7 @@ def test_sso_srv_def_manager_list( ), ( { + "description": "fake description X", "name": "t", "type": "oidc", "client-id": "sso1-123456", @@ -180,8 +181,7 @@ def test_sso_srv_def_manager_list( ), ( { - "description": "fake description X", - "name": "a", + "name": "t", "type": "oidc", "client-secret": "sso1-client-secret", "client-id": "sso1-123456", From 46cc88fbd91b24ec56511bd62ac2953571344187 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 16:40:10 +0530 Subject: [PATCH 19/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 2fa920d9..f4ce88e4 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -166,7 +166,7 @@ def test_sso_srv_def_manager_list( ( { "description": "fake description X", - "name": "t", + "name": "a", "type": "oidc", "client-id": "sso1-123456", "client-secret": "sso1-client-secret", @@ -181,7 +181,7 @@ def test_sso_srv_def_manager_list( ), ( { - "name": "t", + "name": "a", "type": "oidc", "client-secret": "sso1-client-secret", "client-id": "sso1-123456", From 4e377c033c81633b2bcbba53de0e285662a086b5 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 17:15:07 +0530 Subject: [PATCH 20/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index f4ce88e4..9359cb7b 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -74,7 +74,7 @@ def add_sso_srv_def(self, name): ], "authentication-url": "https://sso1.example.com/auth", "client-id": "sso1-123456", - "element-uri": "/api/console/sso-server-definitions/c42-211", + "element-uri": "/api/console/sso-server-definitions/{name}", "issuer-url": "https://sso1.example.com/issuer", "jwks-url": "https://sso1.example.com/jwks", "logout-sso-session-on-reauthentication-failure": True, From 4a2b5e7e73465619962d97235d455cce0b6949fa Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 17:25:47 +0530 Subject: [PATCH 21/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 9359cb7b..53507fea 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -74,7 +74,7 @@ def add_sso_srv_def(self, name): ], "authentication-url": "https://sso1.example.com/auth", "client-id": "sso1-123456", - "element-uri": "/api/console/sso-server-definitions/{name}", + "element-uri": f"/api/console/sso-server-definitions/{name}", "issuer-url": "https://sso1.example.com/issuer", "jwks-url": "https://sso1.example.com/jwks", "logout-sso-session-on-reauthentication-failure": True, From 16f13b37d7277e42a0f036c3a540b84f112dfbd1 Mon Sep 17 00:00:00 2001 From: Vonteddu Chaithra Date: Sat, 29 Nov 2025 17:37:43 +0530 Subject: [PATCH 22/22] Fixed issues Signed-off-by: Vonteddu Chaithra --- tests/unit/zhmcclient/test_sso_server_definition.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/unit/zhmcclient/test_sso_server_definition.py b/tests/unit/zhmcclient/test_sso_server_definition.py index 53507fea..66c95aea 100644 --- a/tests/unit/zhmcclient/test_sso_server_definition.py +++ b/tests/unit/zhmcclient/test_sso_server_definition.py @@ -319,8 +319,14 @@ def test_sso_delete_create_same(self): sn_sso_srv_def_props = { "name": sso_srv_def_name, "description": "SSO Server Definition with same name", - "primary-hostname-ipaddr": "10.11.12.13", - "search-distinguished-name": "test{0}", + "type": "oidc", + "client-secret": "sso1-client-secret", + "client-id": "sso1-123456", + "issuer-url": "https://sso1.example.com/issuer", + "authentication-url": "https://sso1.example.com/auth", + "token-url": "https://sso1.example.com/token", + "jwks-url": "https://sso1.example.com/jwks", + "logout-url ": "https://sso1.example.com/logout", } sso_srv_def_mgr = self.console.sso_server_definitions