From 274ce1380dfdec8bf4c3ec0e20f9a06cf765e862 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Sun, 22 Oct 2023 16:00:08 -0400 Subject: [PATCH] Add resource sub-functions as function groups Added Function Groups for: Custom general resource class admin Custom Security Database Field admin APPC Session Admin Kerberos Realm Admin Signed Program Admin Started Task Admin Unit testing and doc still to come. Signed-off-by: Elijah Swift --- pyracf/class/class_admin.py | 122 ++++++++++++++++++ pyracf/class/class_request.py | 16 +++ pyracf/custom_field/custom_field_admin.py | 112 ++++++++++++++++ pyracf/custom_field/custom_field_request.py | 17 +++ pyracf/data_set/data_set_request.py | 2 +- pyracf/program/program_admin.py | 107 +++++++++++++++ pyracf/program/program_request.py | 16 +++ pyracf/realm/realm_admin.py | 111 ++++++++++++++++ pyracf/realm/realm_request.py | 16 +++ pyracf/resource/resource_admin.py | 2 +- pyracf/session/session_admin.py | 107 +++++++++++++++ pyracf/session/session_request.py | 18 +++ pyracf/started_task/started_task_admin.py | 108 ++++++++++++++++ pyracf/started_task/started_task_request.py | 16 +++ .../add_data_set_error.log | 6 +- .../add_data_set_success.log | 6 +- .../extract_data_set_base_error.log | 6 +- .../extract_data_set_base_success.log | 8 +- .../add_data_set_request.xml | 2 +- .../add_data_set_request_generic.xml | 2 +- .../alter_data_set_request.xml | 2 +- .../data_set_set_universal_access.xml | 2 +- .../delete_data_set_request.xml | 2 +- .../extract_data_set_request_base.xml | 2 +- .../extract_data_set_request_generic_base.xml | 2 +- .../add_data_set_result_error.json | 2 +- .../add_data_set_result_error.xml | 2 +- .../add_data_set_result_generic_success.json | 2 +- .../add_data_set_result_generic_success.xml | 2 +- .../add_data_set_result_success.json | 2 +- .../add_data_set_result_success.xml | 2 +- .../alter_data_set_result_error.json | 2 +- .../alter_data_set_result_error.xml | 2 +- .../alter_data_set_result_success.json | 2 +- .../alter_data_set_result_success.xml | 2 +- .../delete_data_set_result_error.json | 2 +- .../delete_data_set_result_error.xml | 2 +- .../delete_data_set_result_success.json | 2 +- .../delete_data_set_result_success.xml | 2 +- .../extract_data_set_result_base_error.json | 2 +- .../extract_data_set_result_base_error.xml | 2 +- .../extract_data_set_result_base_success.json | 2 +- .../extract_data_set_result_base_success.xml | 2 +- ..._data_set_result_generic_base_success.json | 2 +- ...t_data_set_result_generic_base_success.xml | 2 +- 45 files changed, 808 insertions(+), 42 deletions(-) create mode 100644 pyracf/class/class_admin.py create mode 100644 pyracf/class/class_request.py create mode 100644 pyracf/custom_field/custom_field_admin.py create mode 100644 pyracf/custom_field/custom_field_request.py create mode 100644 pyracf/program/program_admin.py create mode 100644 pyracf/program/program_request.py create mode 100644 pyracf/realm/realm_admin.py create mode 100644 pyracf/realm/realm_request.py create mode 100644 pyracf/session/session_admin.py create mode 100644 pyracf/session/session_request.py create mode 100644 pyracf/started_task/started_task_admin.py create mode 100644 pyracf/started_task/started_task_request.py diff --git a/pyracf/class/class_admin.py b/pyracf/class/class_admin.py new file mode 100644 index 00000000..b5a60b58 --- /dev/null +++ b/pyracf/class/class_admin.py @@ -0,0 +1,122 @@ +"""Custom General Resource Class Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .class_request import ClassRequest + + +class ClassAdmin(SecurityAdmin): + """Custom General Resource Class Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "cdtinfo:cdtcase": "case", + "cdtinfo:cdtdftrc": "defaultrc", + "cdtinfo:cdtfirst": "first", + "cdtinfo:cdtgen": "generic", + "cdtinfo:cdtgenl": "genlist", + "cdtinfo:cdtgroup": "grouping", + "cdtinfo:cdtkeyql": "keyqual", + "cdtinfo:cdtmac": "macprocessing", + "cdtinfo:cdtmaxln": "maxlenx", + "cdtinfo:cdtmaxlx": "maxlength", + "cdtinfo:cdtmembr": "member", + "cdtinfo:cdtoper": "operations", + "cdtinfo:cdtother": "other", + "cdtinfo:cdtposit": "posit", + "cdtinfo:cdtprfal": "profilesallowed", + "cdtinfo:cdtracl": "raclist", + "cdtinfo:cdtsigl": "signal", + "cdtinfo:cdtslreq": "seclabelrequired", + "cdtinfo:cdtuacc": "defaultuacc", + }, + } + super().__init__( + "class", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, class_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new custom general resource class.""" + self._build_segment_dictionaries(traits) + class_request = ClassRequest(class_name, "set") + self._build_xml_segments(class_request) + return self._make_request(class_request) + + def alter( + self, class_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing custom general resource class.""" + self._build_segment_dictionaries(traits) + class_request = ClassRequest(class_name, "set") + self._build_xml_segments(class_request, alter=True) + return self._make_request(class_request, irrsmo00_precheck=True) + + def extract( + self, class_name: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general class profile.""" + self._build_bool_segment_dictionaries(segments) + class_request = ClassRequest(class_name, "listdata") + self._build_xml_segments(class_request, extract=True) + result = self._extract_and_check_result(class_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, class_name: str) -> Union[dict, bytes]: + """Delete a general class profile.""" + class_request = ClassRequest(class_name, "del") + return self._make_request(class_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["class"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["class"]["commands"][0]["messages"] + result["securityResult"]["class"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/class/class_request.py b/pyracf/class/class_request.py new file mode 100644 index 00000000..21b825e2 --- /dev/null +++ b/pyracf/class/class_request.py @@ -0,0 +1,16 @@ +"""Custom General Resource Class Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class ClassRequest(SecurityRequest): + """Custom General Resource Class Administration Request Builder.""" + + def __init__(self, classname: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "customclass" + self._security_definition.attrib = { + "name": classname, + "operation": operation, + "requestid": "ClassRequest", + } diff --git a/pyracf/custom_field/custom_field_admin.py b/pyracf/custom_field/custom_field_admin.py new file mode 100644 index 00000000..7727f7b8 --- /dev/null +++ b/pyracf/custom_field/custom_field_admin.py @@ -0,0 +1,112 @@ +"""Custom Security Database Field Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .custom_field_request import CustomFieldRequest + + +class CustomFieldAdmin(SecurityAdmin): + """Custom Security Database Field Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "cfdef:cffirst": "first", + "cfdef:cfhelp": "help", + "cfdef:cflist": "listhead", + "cfdef:cfmixed": "mixed", + "cfdef:cfmnval": "minvalue", + "cfdef:cfmxlen": "maxlength", + "cfdef:cfmxval": "other", + "cfdef:cfother": "other", + "cfdef:cfvalrx": "racf:cfvalrx", + }, + } + super().__init__( + "custom_field", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, custom_field: str, field_type: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general custom_field profile.""" + self._build_segment_dictionaries(traits) + custom_field_request = CustomFieldRequest(custom_field, field_type, "set") + self._build_xml_segments(custom_field_request) + return self._make_request(custom_field_request) + + def alter( + self, custom_field: str, field_type: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general custom_field profile.""" + self._build_segment_dictionaries(traits) + custom_field_request = CustomFieldRequest(custom_field, field_type, "set") + self._build_xml_segments(custom_field_request, alter=True) + return self._make_request(custom_field_request, irrsmo00_precheck=True) + + def extract( + self, custom_field: str, field_type: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general custom_field profile.""" + self._build_bool_segment_dictionaries(segments) + custom_field_request = CustomFieldRequest(custom_field, field_type, "listdata") + self._build_xml_segments(custom_field_request, extract=True) + result = self._extract_and_check_result(custom_field_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, custom_field: str, field_type: str) -> Union[dict, bytes]: + """Delete a general custom_field profile.""" + custom_field_request = CustomFieldRequest(custom_field, field_type, "del") + return self._make_request(custom_field_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["custom_field"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["custom_field"]["commands"][0]["messages"] + result["securityResult"]["custom_field"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/custom_field/custom_field_request.py b/pyracf/custom_field/custom_field_request.py new file mode 100644 index 00000000..23e8844d --- /dev/null +++ b/pyracf/custom_field/custom_field_request.py @@ -0,0 +1,17 @@ +"""Custom Security Database Field Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class CustomFieldRequest(SecurityRequest): + """Custom Security Database Field Administration Request Builder.""" + + def __init__(self, custom_field_name: str, custom_field_type: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "customfield" + self._security_definition.attrib = { + "name": custom_field_name, + "type": custom_field_type, + "operation": operation, + "requestid": "CustomFieldRequest", + } diff --git a/pyracf/data_set/data_set_request.py b/pyracf/data_set/data_set_request.py index 2215299f..18c008e8 100644 --- a/pyracf/data_set/data_set_request.py +++ b/pyracf/data_set/data_set_request.py @@ -22,7 +22,7 @@ def __init__( "operation": operation, "generic": generic, "volume": volume, - "requestid": "DatasetRequest", + "requestid": "DataSetRequest", } ) if volume == "": diff --git a/pyracf/program/program_admin.py b/pyracf/program/program_admin.py new file mode 100644 index 00000000..3c56a1df --- /dev/null +++ b/pyracf/program/program_admin.py @@ -0,0 +1,107 @@ +"""Signed Program Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .program_request import ProgramRequest + + +class ProgramAdmin(SecurityAdmin): + """Signed Program Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "sigver:failload": "failload", + "sigver:sigaudit": "sigaudit", + "sigver:sigreqd": "sigrequired", + "sigver:library": "library", + }, + } + super().__init__( + "program", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, program_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general program profile.""" + self._build_segment_dictionaries(traits) + program_request = ProgramRequest(program_name, "set") + self._build_xml_segments(program_request) + return self._make_request(program_request) + + def alter( + self, program_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general program profile.""" + self._build_segment_dictionaries(traits) + program_request = ProgramRequest(program_name, "set") + self._build_xml_segments(program_request, alter=True) + return self._make_request(program_request, irrsmo00_precheck=True) + + def extract( + self, program_name: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general program profile.""" + self._build_bool_segment_dictionaries(segments) + program_request = ProgramRequest(program_name, "listdata") + self._build_xml_segments(program_request, extract=True) + result = self._extract_and_check_result(program_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, program_name: str) -> Union[dict, bytes]: + """Delete a general program profile.""" + program_request = ProgramRequest(program_name, "del") + return self._make_request(program_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["program"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["program"]["commands"][0]["messages"] + result["securityResult"]["program"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/program/program_request.py b/pyracf/program/program_request.py new file mode 100644 index 00000000..356d8c4e --- /dev/null +++ b/pyracf/program/program_request.py @@ -0,0 +1,16 @@ +"""Signed Program Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class ProgramRequest(SecurityRequest): + """Signed Program Administration Request Builder.""" + + def __init__(self, programname: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "signedprogram" + self._security_definition.attrib = { + "name": programname, + "operation": operation, + "requestid": "ProgramRequest", + } diff --git a/pyracf/realm/realm_admin.py b/pyracf/realm/realm_admin.py new file mode 100644 index 00000000..b905fe72 --- /dev/null +++ b/pyracf/realm/realm_admin.py @@ -0,0 +1,111 @@ +"""Kerberos Realm Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .realm_request import RealmRequest + + +class RealmAdmin(SecurityAdmin): + """Kerberos Resaurce Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "kerb:chkaddrs": "checkaddrs", + "kerb:deftktlf": "deftktlife", + "kerb:encrypt": "encrypt", + "kerb:kerbname": "kerbname", + "kerb:keyvers": "racf:keyvers", + "kerb:maxtktlf": "maxtktlf", + "kerb:mintktlf": "mintklife", + "kerb:password": "password", + }, + } + super().__init__( + "realm", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, realm_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general realm profile.""" + self._build_segment_dictionaries(traits) + realm_request = RealmRequest(realm_name, "set") + self._build_xml_segments(realm_request) + return self._make_request(realm_request) + + def alter( + self, realm_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general realm profile.""" + self._build_segment_dictionaries(traits) + realm_request = RealmRequest(realm_name, "set") + self._build_xml_segments(realm_request, alter=True) + return self._make_request(realm_request, irrsmo00_precheck=True) + + def extract( + self, realm_name: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general realm profile.""" + self._build_bool_segment_dictionaries(segments) + realm_request = RealmRequest(realm_name, "listdata") + self._build_xml_segments(realm_request, extract=True) + result = self._extract_and_check_result(realm_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, realm_name: str) -> Union[dict, bytes]: + """Delete a general realm profile.""" + realm_request = RealmRequest(realm_name, "del") + return self._make_request(realm_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["realm"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["realm"]["commands"][0]["messages"] + result["securityResult"]["realm"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/realm/realm_request.py b/pyracf/realm/realm_request.py new file mode 100644 index 00000000..72dfbfc1 --- /dev/null +++ b/pyracf/realm/realm_request.py @@ -0,0 +1,16 @@ +"""Kerberos Realm Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class RealmRequest(SecurityRequest): + """Kerberos Realm Administration Request Builder.""" + + def __init__(self, realmname: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "kerberosrealm" + self._security_definition.attrib = { + "name": realmname, + "operation": operation, + "requestid": "RealmRequest", + } diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index bae65a7b..76f0789b 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -8,7 +8,7 @@ class ResourceAdmin(SecurityAdmin): - """General Resaurce Profile Administration.""" + """General Resource Profile Administration.""" def __init__( self, diff --git a/pyracf/session/session_admin.py b/pyracf/session/session_admin.py new file mode 100644 index 00000000..e8627fd2 --- /dev/null +++ b/pyracf/session/session_admin.py @@ -0,0 +1,107 @@ +"""APPC Session Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .session_request import SessionRequest + + +class SessionAdmin(SecurityAdmin): + """APPC Session Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "session:convsec": "racf:convsec", + "session:interval": "racf:interval", + "session:lock": "racf:lock", + "session:sesskey": "racf:sesskey", + }, + } + super().__init__( + "session", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, session_id: str, local_lu: str, partner_lu: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general session profile.""" + self._build_segment_dictionaries(traits) + session_request = SessionRequest(session_id, local_lu, partner_lu, "set") + self._build_xml_segments(session_request) + return self._make_request(session_request) + + def alter( + self, session_id: str, local_lu: str, partner_lu: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general session profile.""" + self._build_segment_dictionaries(traits) + session_request = SessionRequest(session_id, local_lu, partner_lu, "set") + self._build_xml_segments(session_request, alter=True) + return self._make_request(session_request, irrsmo00_precheck=True) + + def extract( + self, session_id: str, local_lu: str, partner_lu: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general session profile.""" + self._build_bool_segment_dictionaries(segments) + session_request = SessionRequest(session_id, local_lu, partner_lu, "listdata") + self._build_xml_segments(session_request, extract=True) + result = self._extract_and_check_result(session_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, session_id: str, local_lu: str, partner_lu: str) -> Union[dict, bytes]: + """Delete a general session profile.""" + session_request = SessionRequest(session_id, local_lu, partner_lu, "del") + return self._make_request(session_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["session"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["session"]["commands"][0]["messages"] + result["securityResult"]["session"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/session/session_request.py b/pyracf/session/session_request.py new file mode 100644 index 00000000..67151b92 --- /dev/null +++ b/pyracf/session/session_request.py @@ -0,0 +1,18 @@ +"""APPC Session Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class SessionRequest(SecurityRequest): + """APPC Session Administration Request Builder.""" + + def __init__(self, net_id: str, local_lu_name: str, partner_lu_name: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "appcsession" + self._security_definition.attrib = { + "netid": net_id, + "locallu": local_lu_name, + "partnerlu": partner_lu_name, + "operation": operation, + "requestid": "SessionRequest", + } diff --git a/pyracf/started_task/started_task_admin.py b/pyracf/started_task/started_task_admin.py new file mode 100644 index 00000000..f5ad4a8b --- /dev/null +++ b/pyracf/started_task/started_task_admin.py @@ -0,0 +1,108 @@ +"""Started Task Administration.""" + +from typing import List, Union + +from pyracf.common.security_admin import SecurityAdmin + +from .started_task_request import StartedTaskRequest + + +class Started_taskAdmin(SecurityAdmin): + """Started Task Administration.""" + + def __init__( + self, + debug: bool = False, + generate_requests_only: bool = False, + update_existing_segment_traits: Union[dict, None] = None, + replace_existing_segment_traits: Union[dict, None] = None, + additional_secret_traits: Union[List[str], None] = None, + ) -> None: + self._valid_segment_traits = { + "base": { + "ssigon:group": "racf:group", + "ssigon:privlege": "racf:privlege", + "ssigon:trace": "racf:trace", + "ssigon:trusted": "racf:trusted", + "ssigon:user": "racf:user", + }, + } + super().__init__( + "started_task", + debug=debug, + generate_requests_only=generate_requests_only, + update_existing_segment_traits=update_existing_segment_traits, + replace_existing_segment_traits=replace_existing_segment_traits, + additional_secret_traits=additional_secret_traits, + ) + + # ============================================================================ + # Base Functions + # ============================================================================ + def add( + self, started_task_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general started_task profile.""" + self._build_segment_dictionaries(traits) + started_task_request = StartedTaskRequest(started_task_name, "set") + self._build_xml_segments(started_task_request) + return self._make_request(started_task_request) + + def alter( + self, started_task_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general started_task profile.""" + self._build_segment_dictionaries(traits) + started_task_request = StartedTaskRequest(started_task_name, "set") + self._build_xml_segments(started_task_request, alter=True) + return self._make_request(started_task_request, irrsmo00_precheck=True) + + def extract( + self, started_task_name: str, segments={}, profile_only: bool = False + ) -> Union[dict, bytes]: + """Extract a general started_task profile.""" + self._build_bool_segment_dictionaries(segments) + started_task_request = StartedTaskRequest(started_task_name, "listdata") + self._build_xml_segments(started_task_request, extract=True) + result = self._extract_and_check_result(started_task_request) + if profile_only: + return self._get_profile(result) + return result + + def delete(self, started_task_name: str) -> Union[dict, bytes]: + """Delete a general started_task profile.""" + started_task_request = StartedTaskRequest(started_task_name, "del") + return self._make_request(started_task_request) + + # ============================================================================ + # Private/Protected Utility Functions + # ============================================================================ + def _format_profile(self, result: dict) -> None: + """Format profile extract data into a dictionary.""" + messages = result["securityResult"]["started_task"]["commands"][0]["messages"] + indexes = [ + i + for i in range(len(messages) - 1) + if messages[i] and "CLASS NAME" in messages[i] + ] + indexes.append(len(messages)) + profiles = [] + for i in range(len(indexes) - 1): + profile = self._format_profile_generic( + messages[indexes[i] : indexes[i + 1]] + ) + # Post processing + if "(g)" in profile["base"].get("name"): + profile["base"]["generic"] = True + profile["base"]["name"] = self._cast_from_str( + profile["base"].get("name")[0] + ) + else: + profile["base"]["generic"] = False + + if profile["base"].get("notify") == [None, "user", "to", "be", "notified"]: + profile["base"]["notify"] = None + profiles.append(profile) + + del result["securityResult"]["started_task"]["commands"][0]["messages"] + result["securityResult"]["started_task"]["commands"][0]["profiles"] = profiles diff --git a/pyracf/started_task/started_task_request.py b/pyracf/started_task/started_task_request.py new file mode 100644 index 00000000..b232827a --- /dev/null +++ b/pyracf/started_task/started_task_request.py @@ -0,0 +1,16 @@ +"""Started Task Administration Request Builder.""" + +from pyracf.common.security_request import SecurityRequest + + +class StartedTaskRequest(SecurityRequest): + """Started Task Administration Request Builder.""" + + def __init__(self, started_task_name: str, operation: str) -> None: + super().__init__() + self._security_definition.tag = "started_tasl" + self._security_definition.attrib = { + "name": started_task_name, + "operation": operation, + "requestid": "Started_taslRequest", + } diff --git a/tests/data_set/data_set_log_samples/add_data_set_error.log b/tests/data_set/data_set_log_samples/add_data_set_error.log index 24b52aed..6450d1ad 100644 --- a/tests/data_set/data_set_log_samples/add_data_set_error.log +++ b/tests/data_set/data_set_log_samples/add_data_set_error.log @@ -24,7 +24,7 @@ - + None eswift @@ -40,7 +40,7 @@ - + 8 16 @@ -72,7 +72,7 @@ "name": "ESWIFF.TEST.T1136242.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_log_samples/add_data_set_success.log b/tests/data_set/data_set_log_samples/add_data_set_success.log index 47501b50..d2e46d7e 100644 --- a/tests/data_set/data_set_log_samples/add_data_set_success.log +++ b/tests/data_set/data_set_log_samples/add_data_set_success.log @@ -24,7 +24,7 @@ - + None eswift @@ -40,7 +40,7 @@ - + 0 0 @@ -70,7 +70,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_log_samples/extract_data_set_base_error.log b/tests/data_set/data_set_log_samples/extract_data_set_base_error.log index 2e791411..27997545 100644 --- a/tests/data_set/data_set_log_samples/extract_data_set_base_error.log +++ b/tests/data_set/data_set_log_samples/extract_data_set_base_error.log @@ -13,7 +13,7 @@ - + @@ -24,7 +24,7 @@ - + 8 16 @@ -49,7 +49,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_log_samples/extract_data_set_base_success.log b/tests/data_set/data_set_log_samples/extract_data_set_base_success.log index 68c4fd2f..8df30256 100644 --- a/tests/data_set/data_set_log_samples/extract_data_set_base_success.log +++ b/tests/data_set/data_set_log_samples/extract_data_set_base_success.log @@ -13,7 +13,7 @@ - + @@ -24,7 +24,7 @@ - + 0 0 @@ -71,7 +71,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, @@ -123,7 +123,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_request_samples/add_data_set_request.xml b/tests/data_set/data_set_request_samples/add_data_set_request.xml index d9f6d341..cba71bdd 100644 --- a/tests/data_set/data_set_request_samples/add_data_set_request.xml +++ b/tests/data_set/data_set_request_samples/add_data_set_request.xml @@ -1,5 +1,5 @@ - + None eswift diff --git a/tests/data_set/data_set_request_samples/add_data_set_request_generic.xml b/tests/data_set/data_set_request_samples/add_data_set_request_generic.xml index 7f26f505..4399f2ba 100644 --- a/tests/data_set/data_set_request_samples/add_data_set_request_generic.xml +++ b/tests/data_set/data_set_request_samples/add_data_set_request_generic.xml @@ -1,5 +1,5 @@ - + None eswift diff --git a/tests/data_set/data_set_request_samples/alter_data_set_request.xml b/tests/data_set/data_set_request_samples/alter_data_set_request.xml index 56ee0648..1749a91b 100644 --- a/tests/data_set/data_set_request_samples/alter_data_set_request.xml +++ b/tests/data_set/data_set_request_samples/alter_data_set_request.xml @@ -1,5 +1,5 @@ - + Read eswift diff --git a/tests/data_set/data_set_request_samples/data_set_set_universal_access.xml b/tests/data_set/data_set_request_samples/data_set_set_universal_access.xml index 2dae3946..86e6027d 100644 --- a/tests/data_set/data_set_request_samples/data_set_set_universal_access.xml +++ b/tests/data_set/data_set_request_samples/data_set_set_universal_access.xml @@ -1,5 +1,5 @@ - + ALTER diff --git a/tests/data_set/data_set_request_samples/delete_data_set_request.xml b/tests/data_set/data_set_request_samples/delete_data_set_request.xml index c281e06a..0f341033 100644 --- a/tests/data_set/data_set_request_samples/delete_data_set_request.xml +++ b/tests/data_set/data_set_request_samples/delete_data_set_request.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/tests/data_set/data_set_request_samples/extract_data_set_request_base.xml b/tests/data_set/data_set_request_samples/extract_data_set_request_base.xml index 2bb6e1e3..d82718f1 100644 --- a/tests/data_set/data_set_request_samples/extract_data_set_request_base.xml +++ b/tests/data_set/data_set_request_samples/extract_data_set_request_base.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/tests/data_set/data_set_request_samples/extract_data_set_request_generic_base.xml b/tests/data_set/data_set_request_samples/extract_data_set_request_generic_base.xml index 42141e41..d038dc6c 100644 --- a/tests/data_set/data_set_request_samples/extract_data_set_request_generic_base.xml +++ b/tests/data_set/data_set_request_samples/extract_data_set_request_generic_base.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_error.json b/tests/data_set/data_set_result_samples/add_data_set_result_error.json index 263aefe9..77204460 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_error.json +++ b/tests/data_set/data_set_result_samples/add_data_set_result_error.json @@ -4,7 +4,7 @@ "name": "ESWIFF.TEST.T1136242.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_error.xml b/tests/data_set/data_set_result_samples/add_data_set_result_error.xml index dd9ba686..9810eb42 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_error.xml +++ b/tests/data_set/data_set_result_samples/add_data_set_result_error.xml @@ -1,6 +1,6 @@ - + 8 16 diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.json b/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.json index f3c48657..e596e153 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.json +++ b/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.json @@ -4,7 +4,7 @@ "generic": "yes", "name": "ESWIFT.TEST.T1136242.*", "operation": "set", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.xml b/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.xml index 44a70bdf..30de3c41 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.xml +++ b/tests/data_set/data_set_result_samples/add_data_set_result_generic_success.xml @@ -1,6 +1,6 @@ - + 0 0 diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_success.json b/tests/data_set/data_set_result_samples/add_data_set_result_success.json index 78dfe698..29f25a25 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_success.json +++ b/tests/data_set/data_set_result_samples/add_data_set_result_success.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_result_samples/add_data_set_result_success.xml b/tests/data_set/data_set_result_samples/add_data_set_result_success.xml index 15a80604..bd87be0d 100644 --- a/tests/data_set/data_set_result_samples/add_data_set_result_success.xml +++ b/tests/data_set/data_set_result_samples/add_data_set_result_success.xml @@ -1,6 +1,6 @@ - + 0 0 diff --git a/tests/data_set/data_set_result_samples/alter_data_set_result_error.json b/tests/data_set/data_set_result_samples/alter_data_set_result_error.json index d4ddbf7f..9d745ed3 100644 --- a/tests/data_set/data_set_result_samples/alter_data_set_result_error.json +++ b/tests/data_set/data_set_result_samples/alter_data_set_result_error.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T113622.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_result_samples/alter_data_set_result_error.xml b/tests/data_set/data_set_result_samples/alter_data_set_result_error.xml index 4e0b947a..e88c9bbd 100644 --- a/tests/data_set/data_set_result_samples/alter_data_set_result_error.xml +++ b/tests/data_set/data_set_result_samples/alter_data_set_result_error.xml @@ -1,6 +1,6 @@ - + 8 16 diff --git a/tests/data_set/data_set_result_samples/alter_data_set_result_success.json b/tests/data_set/data_set_result_samples/alter_data_set_result_success.json index 58e5faf2..06910c28 100644 --- a/tests/data_set/data_set_result_samples/alter_data_set_result_success.json +++ b/tests/data_set/data_set_result_samples/alter_data_set_result_success.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "set", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "info": [ "Definition exists. Add command skipped due to precheck option" ], diff --git a/tests/data_set/data_set_result_samples/alter_data_set_result_success.xml b/tests/data_set/data_set_result_samples/alter_data_set_result_success.xml index c9d1661d..8f239bb5 100644 --- a/tests/data_set/data_set_result_samples/alter_data_set_result_success.xml +++ b/tests/data_set/data_set_result_samples/alter_data_set_result_success.xml @@ -1,6 +1,6 @@ - + Definition exists. Add command skipped due to precheck option 0 diff --git a/tests/data_set/data_set_result_samples/delete_data_set_result_error.json b/tests/data_set/data_set_result_samples/delete_data_set_result_error.json index d17658da..6e8446c9 100644 --- a/tests/data_set/data_set_result_samples/delete_data_set_result_error.json +++ b/tests/data_set/data_set_result_samples/delete_data_set_result_error.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "del", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_result_samples/delete_data_set_result_error.xml b/tests/data_set/data_set_result_samples/delete_data_set_result_error.xml index ad257028..7895a891 100644 --- a/tests/data_set/data_set_result_samples/delete_data_set_result_error.xml +++ b/tests/data_set/data_set_result_samples/delete_data_set_result_error.xml @@ -1,6 +1,6 @@ - + 8 16 diff --git a/tests/data_set/data_set_result_samples/delete_data_set_result_success.json b/tests/data_set/data_set_result_samples/delete_data_set_result_success.json index 0af42c0e..1d874a48 100644 --- a/tests/data_set/data_set_result_samples/delete_data_set_result_success.json +++ b/tests/data_set/data_set_result_samples/delete_data_set_result_success.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "del", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_result_samples/delete_data_set_result_success.xml b/tests/data_set/data_set_result_samples/delete_data_set_result_success.xml index 555d62c0..b36df7d5 100644 --- a/tests/data_set/data_set_result_samples/delete_data_set_result_success.xml +++ b/tests/data_set/data_set_result_samples/delete_data_set_result_success.xml @@ -1,6 +1,6 @@ - + 0 0 diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.json b/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.json index cdee6661..6c4e216e 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.json +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 8, diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.xml b/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.xml index 4bf80728..87ad9315 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.xml +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_base_error.xml @@ -1,6 +1,6 @@ - + 8 16 diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.json b/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.json index 5165ab4c..5a9a976d 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.json +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.P3020470", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.xml b/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.xml index c6805e36..075c037f 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.xml +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_base_success.xml @@ -1,6 +1,6 @@ - + 0 0 diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.json b/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.json index 28daeab4..77c25c61 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.json +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.json @@ -4,7 +4,7 @@ "name": "ESWIFT.TEST.T1136242.*", "operation": "listdata", "generic": "no", - "requestId": "DatasetRequest", + "requestId": "DataSetRequest", "commands": [ { "safReturnCode": 0, diff --git a/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.xml b/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.xml index 4f24f358..b3a4ef46 100644 --- a/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.xml +++ b/tests/data_set/data_set_result_samples/extract_data_set_result_generic_base_success.xml @@ -1,6 +1,6 @@ - + 0 0