From 2214ab5a187b8c7da0cbfa417c90eb7611e33809 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Mon, 30 Oct 2023 17:46:04 -0400 Subject: [PATCH 01/11] Add sub-functions to ResourceAdmin Add Drafted sub-functions to Resource Admin for testing. Signed-off-by: Elijah Swift --- pyracf/resource/resource_admin.py | 191 ++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index 13b9467e..2dd0c09c 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -216,6 +216,197 @@ def get_my_access(self, resource: str, class_name: str) -> Union[str, bytes, Non profile = self.extract(resource, class_name, profile_only=True) return self._get_field(profile, "base", "yourAccess") + # ============================================================================ + # Class Administration + # ============================================================================ + def add_resource_class( + self, class_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new general resource class.""" + return self.add(resource=class_name, class_name="CDT", traits=traits) + + def alter_resource_class( + self, class_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing general resource class.""" + return self.alter(resource=class_name, class_name="CDT", traits=traits) + + def extract_resource_class(self, class_name: str) -> Union[dict, bytes]: + """Extract the attributes of a general resource class.""" + profile = self.extract( + resource=class_name, class_name="CDT", segments=["CDTINFO"] + ) + return profile["cdtinfo"] + + def delete_resource_class(self, class_name: str) -> Union[dict, bytes]: + """Delete a general resource class.""" + return self.delete(resource=class_name, class_name="CDT") + + # ============================================================================ + # Started Task Administration + # ============================================================================ + def add_started_task( + self, started_task_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new started task profile.""" + return self.add(resource=started_task_name, class_name="STARTED", traits=traits) + + def alter_started_task( + self, started_task_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing started task profile.""" + return self.alter( + resource=started_task_name, class_name="STARTED", traits=traits + ) + + def extract_started_task(self, started_task_name: str) -> Union[dict, bytes]: + """Extract the attributes of a started task profile.""" + profile = self.extract( + resource=started_task_name, class_name="STARTED", segments=["STDATA"] + ) + return profile["stdata"] + + def delete_started_task(self, started_task_name: str) -> Union[dict, bytes]: + """Delete a started task profile.""" + return self.delete(resource=started_task_name, class_name="STARTED") + + # ============================================================================ + # Custom Field Administration + # ============================================================================ + def add_custom_field( + self, custom_field_name: str, custom_field_type: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new custom field.""" + full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" + return self.add(resource=full_profile_name, class_name="CFIELD", traits=traits) + + def alter_custom_field( + self, custom_field_name: str, custom_field_type: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing custom field.""" + full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" + return self.alter( + resource=full_profile_name, class_name="CFIELD", traits=traits + ) + + def extract_custom_field( + self, custom_field_name: str, custom_field_type: str + ) -> Union[dict, bytes]: + """Extract the attributes of a custom field.""" + full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" + profile = self.extract( + resource=full_profile_name, class_name="CFIELD", segments=["CFDEF"] + ) + return profile["cfdef"] + + def delete_custom_field( + self, custom_field_name: str, custom_field_type: str + ) -> Union[dict, bytes]: + """Delete a custom field.""" + full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" + return self.delete(resource=full_profile_name, class_name="CFIELD") + + # ============================================================================ + # Kerberos Realm Administration + # ============================================================================ + def add_kerberos_realm( + self, kerberos_realm_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new kerberos realm profile.""" + return self.add(resource=kerberos_realm_name, class_name="REALM", traits=traits) + + def alter_kerberos_realm( + self, kerberos_realm_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing kerberos realm profile.""" + return self.alter( + resource=kerberos_realm_name, class_name="REALM", traits=traits + ) + + def extract_kerberos_realm(self, kerberos_realm_name: str) -> Union[dict, bytes]: + """Extract the attributes of a kerberos realm profile.""" + profile = self.extract( + resource=kerberos_realm_name, class_name="REALM", segments=["KERB"] + ) + return profile["kerb"] + + def delete_kerberos_realm(self, kerberos_realm_name: str) -> Union[dict, bytes]: + """Delete a kerberos realm profile.""" + return self.delete(resource=kerberos_realm_name, class_name="REALM") + + # ============================================================================ + # Signed Program Administration + # ============================================================================ + def add_signed_program( + self, signed_program_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new signed program profile.""" + if traits["sigver:library"]: + traits["base:member"] = traits["sigver:library"] + del traits["sigver:library"] + return self.add( + resource=signed_program_name, class_name="PROGRAM", traits=traits + ) + + def alter_signed_program( + self, signed_program_name: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing signed program profile.""" + if traits["sigver:library"]: + traits["base:member"] = traits["sigver:library"] + del traits["sigver:library"] + return self.alter( + resource=signed_program_name, class_name="PROGRAM", traits=traits + ) + + def extract_signed_program(self, signed_program_name: str) -> Union[dict, bytes]: + """Extract the attributes of a signed program profile.""" + profile = self.extract( + resource=signed_program_name, class_name="PROGRAM", segments=["SIGVER"] + ) + profile["sigver"]["library"] = profile["base"].get("member") + return profile["sigver"] + + def delete_signed_program(self, signed_program_name: str) -> Union[dict, bytes]: + """Delete a signed program profile.""" + return self.delete(resource=signed_program_name, class_name="PROGRAM") + + # ============================================================================ + # APPC Session Administration + # ============================================================================ + def add_appc_session( + self, net_id: str, local_lu: str, partner_lu: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Create a new APPC session profile.""" + full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" + return self.add(resource=full_profile_name, class_name="APPCLU", traits=traits) + + def alter_appc_session( + self, net_id: str, local_lu: str, partner_lu: str, traits: dict = {} + ) -> Union[dict, bytes]: + """Alter an existing APPC session profile.""" + full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" + return self.alter( + resource=full_profile_name, class_name="APPCLU", traits=traits + ) + + def extract_appc_session( + self, net_id: str, local_lu: str, partner_lu: str + ) -> Union[dict, bytes]: + """Extract the attributes of a APPC session profile.""" + full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" + profile = self.extract( + resource=full_profile_name, class_name="APPCLU", segments=["SESSION"] + ) + return profile["session"] + + def delete_appc_session( + self, net_id: str, local_lu: str, partner_lu: str + ) -> Union[dict, bytes]: + """Delete a APPC session.""" + full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" + return self.delete(resource=full_profile_name, class_name="APPCLU") + # ============================================================================ # Base Functions # ============================================================================ From c743a9a1861e081ba6048c027e5ffaa1bac33b00 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 09:20:28 -0400 Subject: [PATCH 02/11] Bug Fixes And Testing -Fix bug in Resource and Dataset Add/Alter errors that would allow generic profiles to cause issues -Test CFDEF MXLENGTH in case of typo in doc -Drive GenerateRequestOnly to faster output in Alter functions. Signed-off-by: Elijah Swift --- pyracf/data_set/data_set_admin.py | 24 ++++++++++++------- pyracf/group/group_admin.py | 5 ++++ pyracf/resource/resource_admin.py | 38 +++++++++++++++++++------------ 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/pyracf/data_set/data_set_admin.py b/pyracf/data_set/data_set_admin.py index 9c5c3520..52f6e7bf 100644 --- a/pyracf/data_set/data_set_admin.py +++ b/pyracf/data_set/data_set_admin.py @@ -110,15 +110,16 @@ def add( self._build_xml_segments(data_set_request) return self._make_request(data_set_request) try: - self.extract(data_set, volume=volume, generic=generic) + profile = self.extract(data_set, volume=volume, generic=generic, profile_only=True) + if self._get_field(profile, "base", "name") == data_set.lower(): + raise AddOperationError(data_set, self._profile_type) except SecurityRequestError as exception: if not exception.contains_error_message(self._profile_type, "ICH35003I"): raise exception - self._build_segment_dictionaries(traits) - data_set_request = DataSetRequest(data_set, "set", volume, generic) - self._build_xml_segments(data_set_request) - return self._make_request(data_set_request) - raise AddOperationError(data_set, self._profile_type) + self._build_segment_dictionaries(traits) + data_set_request = DataSetRequest(data_set, "set", volume, generic) + self._build_xml_segments(data_set_request) + return self._make_request(data_set_request) def alter( self, @@ -127,11 +128,18 @@ def alter( volume: Union[str, None] = None, generic: bool = False, ) -> Union[dict, bytes]: + """Alter an existing data set profile.""" + if self._generate_requests_only: + self._build_segment_dictionaries(traits) + data_set_request = DataSetRequest(data_set, "set", volume, generic) + self._build_xml_segments(data_set_request, alter=True) + return self._make_request(data_set_request, irrsmo00_precheck=True) try: - self.extract(data_set) + profile = self.extract(data_set, volume=volume, generic=generic, profile_only=True) except SecurityRequestError: raise AlterOperationError(data_set, self._profile_type) - """Alter an existing data set profile.""" + if not self._get_field(profile, "base", "name") == data_set.lower(): + raise AlterOperationError(data_set, self._profile_type) self._build_segment_dictionaries(traits) data_set_request = DataSetRequest(data_set, "set", volume, generic) self._build_xml_segments(data_set_request, alter=True) diff --git a/pyracf/group/group_admin.py b/pyracf/group/group_admin.py index f144ce7f..daaf0ec6 100644 --- a/pyracf/group/group_admin.py +++ b/pyracf/group/group_admin.py @@ -140,6 +140,11 @@ def add(self, group: str, traits: dict = {}) -> Union[dict, bytes]: def alter(self, group: str, traits: dict) -> Union[dict, bytes]: """Alter an existing group.""" + if self._generate_requests_only: + self._build_segment_dictionaries(traits) + group_request = GroupRequest(group, "set") + self._build_xml_segments(group_request, alter=True) + return self._make_request(group_request, irrsmo00_precheck=True) try: self.extract(group) except SecurityRequestError: diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index 2dd0c09c..14f62e2b 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -65,7 +65,7 @@ def __init__( "cdtinfo:key_qualifiers": "keyqual", "cdtinfo:manditory_access_control_processing": "macprocessing", "cdtinfo:max_length": "maxlenx", - "cdtinfo:max_length_racroute": "maxlength", + "cdtinfo:max_length_entityx": "maxlength", "cdtinfo:member_class_name": "member", "cdtinfo:operations": "operations", "cdtinfo:valid_other_characters": "other", @@ -83,7 +83,7 @@ def __init__( "cfdef:list_heading_text": "listhead", "cfdef:mixed_case_allowed": "mixed", "cfdef:min_numeric_value": "minvalue", - "cfdef:max_field_length": "maxlength", + "cfdef:max_field_length": "mxlength", "cfdef:max_numeric_value": "maxvalue", "cfdef:valid_other_characters": "other", "cfdef:validation_rexx_exec": "racf:cfvalrx", @@ -234,7 +234,7 @@ def alter_resource_class( def extract_resource_class(self, class_name: str) -> Union[dict, bytes]: """Extract the attributes of a general resource class.""" profile = self.extract( - resource=class_name, class_name="CDT", segments=["CDTINFO"] + resource=class_name, class_name="CDT", segments=["cdtinfo"], profile_only=True ) return profile["cdtinfo"] @@ -262,7 +262,7 @@ def alter_started_task( def extract_started_task(self, started_task_name: str) -> Union[dict, bytes]: """Extract the attributes of a started task profile.""" profile = self.extract( - resource=started_task_name, class_name="STARTED", segments=["STDATA"] + resource=started_task_name, class_name="STARTED", segments=["stdata"], profile_only=True ) return profile["stdata"] @@ -295,7 +295,7 @@ def extract_custom_field( """Extract the attributes of a custom field.""" full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" profile = self.extract( - resource=full_profile_name, class_name="CFIELD", segments=["CFDEF"] + resource=full_profile_name, class_name="CFIELD", segments=["cfdef"], profile_only=True ) return profile["cfdef"] @@ -326,7 +326,7 @@ def alter_kerberos_realm( def extract_kerberos_realm(self, kerberos_realm_name: str) -> Union[dict, bytes]: """Extract the attributes of a kerberos realm profile.""" profile = self.extract( - resource=kerberos_realm_name, class_name="REALM", segments=["KERB"] + resource=kerberos_realm_name, class_name="REALM", segments=["kerb"], profile_only=True ) return profile["kerb"] @@ -362,7 +362,7 @@ def alter_signed_program( def extract_signed_program(self, signed_program_name: str) -> Union[dict, bytes]: """Extract the attributes of a signed program profile.""" profile = self.extract( - resource=signed_program_name, class_name="PROGRAM", segments=["SIGVER"] + resource=signed_program_name, class_name="PROGRAM", segments=["sigver"], profile_only=True ) profile["sigver"]["library"] = profile["base"].get("member") return profile["sigver"] @@ -396,7 +396,7 @@ def extract_appc_session( """Extract the attributes of a APPC session profile.""" full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" profile = self.extract( - resource=full_profile_name, class_name="APPCLU", segments=["SESSION"] + resource=full_profile_name, class_name="APPCLU", segments=["session"], profile_only=True ) return profile["session"] @@ -420,22 +420,30 @@ def add( self._build_xml_segments(profile_request) return self._make_request(profile_request) try: - self.extract(resource, class_name) + profile = self.extract(resource, class_name, profile_only=True) + if self._get_field(profile, "base", "name") == resource.lower(): + raise AddOperationError(resource, class_name) except SecurityRequestError as exception: if not exception.contains_error_message(self._profile_type, "ICH13003I"): raise exception - self._build_segment_dictionaries(traits) - profile_request = ResourceRequest(resource, class_name, "set") - self._build_xml_segments(profile_request) - return self._make_request(profile_request) - raise AddOperationError(resource, class_name) + self._build_segment_dictionaries(traits) + profile_request = ResourceRequest(resource, class_name, "set") + self._build_xml_segments(profile_request) + return self._make_request(profile_request) def alter(self, resource: str, class_name: str, traits: dict) -> Union[dict, bytes]: """Alter an existing general resource profile.""" + if self._generate_requests_only: + self._build_segment_dictionaries(traits) + profile_request = ResourceRequest(resource, class_name, "set") + self._build_xml_segments(profile_request, alter=True) + return self._make_request(profile_request, irrsmo00_precheck=True) try: - self.extract(resource, class_name) + profile = self.extract(resource, class_name, profile_only=True) except SecurityRequestError: raise AlterOperationError(resource, class_name) + if not self._get_field(profile, "base", "name") == resource.lower(): + raise AlterOperationError(resource, class_name) self._build_segment_dictionaries(traits) profile_request = ResourceRequest(resource, class_name, "set") self._build_xml_segments(profile_request, alter=True) From dc1cfdf58ec2cc6ba67653f28738c317ed5106b6 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 12:17:55 -0400 Subject: [PATCH 03/11] Bug Fix and Formatting Translate null characters to blanks when not preceded by ">" to prevent premature string termination. Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 11 +++++++++++ pyracf/data_set/data_set_admin.py | 8 ++++++-- pyracf/resource/resource_admin.py | 30 ++++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index 3845e412..b06dcfa5 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -55,6 +55,17 @@ static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) rsp ); + int i; + for (i = 1; i < rsp_len; i++){ + if (rsp[i] == 0) { + if (rsp[i-1] == '>') { + break; + } + else { + rsp[i] = ' '; + } + } + } return Py_BuildValue("y", rsp); } diff --git a/pyracf/data_set/data_set_admin.py b/pyracf/data_set/data_set_admin.py index 52f6e7bf..41edc281 100644 --- a/pyracf/data_set/data_set_admin.py +++ b/pyracf/data_set/data_set_admin.py @@ -110,7 +110,9 @@ def add( self._build_xml_segments(data_set_request) return self._make_request(data_set_request) try: - profile = self.extract(data_set, volume=volume, generic=generic, profile_only=True) + profile = self.extract( + data_set, volume=volume, generic=generic, profile_only=True + ) if self._get_field(profile, "base", "name") == data_set.lower(): raise AddOperationError(data_set, self._profile_type) except SecurityRequestError as exception: @@ -135,7 +137,9 @@ def alter( self._build_xml_segments(data_set_request, alter=True) return self._make_request(data_set_request, irrsmo00_precheck=True) try: - profile = self.extract(data_set, volume=volume, generic=generic, profile_only=True) + profile = self.extract( + data_set, volume=volume, generic=generic, profile_only=True + ) except SecurityRequestError: raise AlterOperationError(data_set, self._profile_type) if not self._get_field(profile, "base", "name") == data_set.lower(): diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index 14f62e2b..bdf0a161 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -234,7 +234,10 @@ def alter_resource_class( def extract_resource_class(self, class_name: str) -> Union[dict, bytes]: """Extract the attributes of a general resource class.""" profile = self.extract( - resource=class_name, class_name="CDT", segments=["cdtinfo"], profile_only=True + resource=class_name, + class_name="CDT", + segments=["cdtinfo"], + profile_only=True, ) return profile["cdtinfo"] @@ -262,7 +265,10 @@ def alter_started_task( def extract_started_task(self, started_task_name: str) -> Union[dict, bytes]: """Extract the attributes of a started task profile.""" profile = self.extract( - resource=started_task_name, class_name="STARTED", segments=["stdata"], profile_only=True + resource=started_task_name, + class_name="STARTED", + segments=["stdata"], + profile_only=True, ) return profile["stdata"] @@ -295,7 +301,10 @@ def extract_custom_field( """Extract the attributes of a custom field.""" full_profile_name = f"{custom_field_type}.csdata.{custom_field_name}" profile = self.extract( - resource=full_profile_name, class_name="CFIELD", segments=["cfdef"], profile_only=True + resource=full_profile_name, + class_name="CFIELD", + segments=["cfdef"], + profile_only=True, ) return profile["cfdef"] @@ -326,7 +335,10 @@ def alter_kerberos_realm( def extract_kerberos_realm(self, kerberos_realm_name: str) -> Union[dict, bytes]: """Extract the attributes of a kerberos realm profile.""" profile = self.extract( - resource=kerberos_realm_name, class_name="REALM", segments=["kerb"], profile_only=True + resource=kerberos_realm_name, + class_name="REALM", + segments=["kerb"], + profile_only=True, ) return profile["kerb"] @@ -362,7 +374,10 @@ def alter_signed_program( def extract_signed_program(self, signed_program_name: str) -> Union[dict, bytes]: """Extract the attributes of a signed program profile.""" profile = self.extract( - resource=signed_program_name, class_name="PROGRAM", segments=["sigver"], profile_only=True + resource=signed_program_name, + class_name="PROGRAM", + segments=["sigver"], + profile_only=True, ) profile["sigver"]["library"] = profile["base"].get("member") return profile["sigver"] @@ -396,7 +411,10 @@ def extract_appc_session( """Extract the attributes of a APPC session profile.""" full_profile_name = f"{net_id}.{local_lu}.{partner_lu}" profile = self.extract( - resource=full_profile_name, class_name="APPCLU", segments=["session"], profile_only=True + resource=full_profile_name, + class_name="APPCLU", + segments=["session"], + profile_only=True, ) return profile["session"] From 0227bf82eb2cfe983cc7fa20c10a88abbcf6a43d Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 13:35:45 -0400 Subject: [PATCH 04/11] Correct Workaround Algorithm Made it codepage agnostic: Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index b06dcfa5..80dac171 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -30,7 +30,7 @@ static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) VarStr_T userid = { 0, {0}}; unsigned int alet = 0; unsigned int acee = 0; - char rsp[BUFFER_SIZE+1]; + unsigned char rsp[BUFFER_SIZE+1]; memset(rsp, 0, BUFFER_SIZE); unsigned int saf_rc=0, racf_rc=0, racf_rsn=0; unsigned int num_parms=17, fn=1, opts = input_opts, rsp_len = sizeof(rsp)-1; @@ -55,14 +55,13 @@ static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) rsp ); - int i; - for (i = 1; i < rsp_len; i++){ + for (int i = 1; i < rsp_len; i++){ if (rsp[i] == 0) { - if (rsp[i-1] == '>') { + if (rsp[i-1] == 0x6E) { break; } else { - rsp[i] = ' '; + rsp[i] = 0x40; } } } From 8890a5d307c312b86ed2abb71b62f2d43e47bcd5 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 15:50:33 -0400 Subject: [PATCH 05/11] Mapping Extract Functions Mapping Extract fucntions Cleaning up c code Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 24 ++++++++------ pyracf/resource/resource_admin.py | 54 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index 80dac171..1ed849a2 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -13,6 +13,19 @@ typedef struct { char str[8]; } VarStr_T; +static char* null_byte_fix(char* string) { + for (int i = 1; i < rsp_len; i++){ + if (rsp[i] == 0) { + if (rsp[i-1] == 0x6E) { + break; + } + else { + rsp[i] = 0x40; + } + } + } +} + static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) { const unsigned int xml_len; const unsigned int input_opts; @@ -55,16 +68,7 @@ static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) rsp ); - for (int i = 1; i < rsp_len; i++){ - if (rsp[i] == 0) { - if (rsp[i-1] == 0x6E) { - break; - } - else { - rsp[i] = 0x40; - } - } - } + rsp = null_byte_fix(rsp); return Py_BuildValue("y", rsp); } diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index bdf0a161..7f556a1b 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -180,6 +180,60 @@ def __init__( "tme:roles": "racf:roles", }, } + self._extracted_key_value_pair_segment_traits_map = { + "cdtinfo": { + "case": "caseAllowed", + "defaultrc": "defaultRacrouteReturnCode", + "first": "validFirstCharacters", + "generic": "generic", + "genlist": "genlist", + "grouping": "groupingClassName", + "keyqual": "keyQualifiers", + "macprocessing": "manditoryAccessControlProcessing", + "maxlenx": "maxLength", + "maxlength": "maxLengthEntityx", + "member": "memberClassName", + "operations": "operations", + "other": "validOtherCharacters", + "posit": "positNumber", + "profilesallowed": "profilesAllowed", + "raclist": "raclistAllowed", + "signal": "sendEnfSignalOnProfileCreation", + "seclabelrequired": "securityLabelRequired", + "defaultuacc": "defaultUniversalAccess", + }, + "cfdef": { + "type": "customFieldDataType", + "first": "validFirstCharacters", + "help": "helpText", + "listhead": "listHeadingText", + "mixed": "mixedCaseAllowed", + "minvalue": "minNumericValue", + "mxlength": "maxFieldLength", + "maxvalue": "maxNumericValue", + "other": "validOtherCharacters", + "cfvalrx": "validationRexxExec", + }, + "kerb": { + "checkaddrs": "validateAddresses", + "deftktlife": "defaultTicketLife", + "encrypt": "encryptionAlgorithms", + "kerbname": "realmName", + "maxtktlf": "maxTicketLife", + "mintklife": "minTicketLife", + }, + "session": { + "convsec": "securityCheckingLevel", + "interval": "sessionKeyInterval", + "lock": "locked", + "sesskey": "sessionKey", + }, + "sigver": { + "failload": "failProgramLoadCondition", + "sigaudit": "logSignatureVerificationEvents", + "sigrequired": "signatureRequired", + }, + } super().__init__( "resource", debug=debug, From 3b9d1d5fe5b6771efca7e33d61925eb152b7700c Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 16:18:10 -0400 Subject: [PATCH 06/11] Fix issues with c code Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index 1ed849a2..c8037e80 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -13,14 +13,14 @@ typedef struct { char str[8]; } VarStr_T; -static char* null_byte_fix(char* string) { - for (int i = 1; i < rsp_len; i++){ - if (rsp[i] == 0) { - if (rsp[i-1] == 0x6E) { +void null_byte_fix(char* str, unsigned int str_len) { + for (int i = 1; i < str_len; i++){ + if (str[i] == 0) { + if (str[i-1] == 0x6E) { break; } else { - rsp[i] = 0x40; + str[i] = 0x40; } } } @@ -68,7 +68,7 @@ static PyObject* call_irrsmo00(PyObject* self, PyObject* args, PyObject *kwargs) rsp ); - rsp = null_byte_fix(rsp); + null_byte_fix(rsp,rsp_len); return Py_BuildValue("y", rsp); } From 3b34ca37fee1cafdc7c7edeba7e99737565a15b6 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Wed, 1 Nov 2023 23:17:43 -0400 Subject: [PATCH 07/11] Add Unit Testing for Sub Functions Add Unit Testing for Sub Functions Further optimize c code --- pyracf/common/irrsmo00.c | 2 +- pyracf/resource/resource_admin.py | 10 +- .../add_appc_session_request.xml | 3 + .../add_custom_field_request.xml | 3 + .../add_kerberos_realm_request.xml | 3 + .../add_resource_class_request.xml | 17 ++ .../add_signed_program_request.xml | 3 + .../add_started_task_request.xml | 3 + .../alter_appc_session_request.xml | 7 + .../alter_custom_field_request.xml | 9 + .../alter_kerberos_realm_request.xml | 7 + .../alter_resource_class_request.xml | 11 ++ .../alter_signed_program_request.xml | 7 + .../alter_started_task_request.xml | 7 + .../delete_appc_session_request.xml | 3 + .../delete_custom_field_request.xml | 3 + .../delete_kerberos_realm_request.xml | 3 + .../delete_resource_class_request.xml | 3 + .../delete_signed_program_request.xml | 3 + .../delete_started_task_request.xml | 3 + ...act_resource_result_base_cdtinfo_error.xml | 14 ++ ...t_resource_result_base_cdtinfo_success.xml | 58 ++++++ ...tract_resource_result_base_cfdef_error.xml | 14 ++ ...act_resource_result_base_cfdef_success.xml | 47 +++++ ...t_resource_result_base_generic_success.xml | 36 ++++ ...xtract_resource_result_base_kerb_error.xml | 14 ++ ...ract_resource_result_base_kerb_success.xml | 41 ++++ ...act_resource_result_base_session_error.xml | 14 ++ ...t_resource_result_base_session_success.xml | 41 ++++ ...ract_resource_result_base_sigver_error.xml | 14 ++ ...ct_resource_result_base_sigver_success.xml | 50 +++++ ...ract_resource_result_base_stdata_error.xml | 14 ++ ...ct_resource_result_base_stdata_success.xml | 44 +++++ tests/resource/test_resource_constants.py | 187 ++++++++++++++++++ tests/resource/test_resource_result_parser.py | 36 ++++ .../test_resource_sub_function_extracts.py | 170 ++++++++++++++++ .../test_resource_sub_function_requests.py | 163 +++++++++++++++ tests/test_runner.py | 8 + 38 files changed, 1069 insertions(+), 6 deletions(-) create mode 100644 tests/resource/resource_request_samples/add_appc_session_request.xml create mode 100644 tests/resource/resource_request_samples/add_custom_field_request.xml create mode 100644 tests/resource/resource_request_samples/add_kerberos_realm_request.xml create mode 100644 tests/resource/resource_request_samples/add_resource_class_request.xml create mode 100644 tests/resource/resource_request_samples/add_signed_program_request.xml create mode 100644 tests/resource/resource_request_samples/add_started_task_request.xml create mode 100644 tests/resource/resource_request_samples/alter_appc_session_request.xml create mode 100644 tests/resource/resource_request_samples/alter_custom_field_request.xml create mode 100644 tests/resource/resource_request_samples/alter_kerberos_realm_request.xml create mode 100644 tests/resource/resource_request_samples/alter_resource_class_request.xml create mode 100644 tests/resource/resource_request_samples/alter_signed_program_request.xml create mode 100644 tests/resource/resource_request_samples/alter_started_task_request.xml create mode 100644 tests/resource/resource_request_samples/delete_appc_session_request.xml create mode 100644 tests/resource/resource_request_samples/delete_custom_field_request.xml create mode 100644 tests/resource/resource_request_samples/delete_kerberos_realm_request.xml create mode 100644 tests/resource/resource_request_samples/delete_resource_class_request.xml create mode 100644 tests/resource/resource_request_samples/delete_signed_program_request.xml create mode 100644 tests/resource/resource_request_samples/delete_started_task_request.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_cfdef_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_cfdef_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_generic_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_kerb_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_kerb_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_session_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_session_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_sigver_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_sigver_success.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_stdata_error.xml create mode 100644 tests/resource/resource_result_samples/extract_resource_result_base_stdata_success.xml create mode 100644 tests/resource/test_resource_sub_function_extracts.py create mode 100644 tests/resource/test_resource_sub_function_requests.py diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index c8037e80..e4c901b3 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -17,7 +17,7 @@ void null_byte_fix(char* str, unsigned int str_len) { for (int i = 1; i < str_len; i++){ if (str[i] == 0) { if (str[i-1] == 0x6E) { - break; + return; } else { str[i] = 0x40; diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index 7f556a1b..b62fb5be 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -187,8 +187,8 @@ def __init__( "first": "validFirstCharacters", "generic": "generic", "genlist": "genlist", - "grouping": "groupingClassName", - "keyqual": "keyQualifiers", + "group": "groupingClassName", + "keyqualifiers": "keyQualifiers", "macprocessing": "manditoryAccessControlProcessing", "maxlenx": "maxLength", "maxlength": "maxLengthEntityx", @@ -199,7 +199,7 @@ def __init__( "profilesallowed": "profilesAllowed", "raclist": "raclistAllowed", "signal": "sendEnfSignalOnProfileCreation", - "seclabelrequired": "securityLabelRequired", + "seclabelsrequired": "securityLabelsRequired", "defaultuacc": "defaultUniversalAccess", }, "cfdef": { @@ -407,7 +407,7 @@ def add_signed_program( self, signed_program_name: str, traits: dict = {} ) -> Union[dict, bytes]: """Create a new signed program profile.""" - if traits["sigver:library"]: + if "sigver:library" in traits: traits["base:member"] = traits["sigver:library"] del traits["sigver:library"] return self.add( @@ -418,7 +418,7 @@ def alter_signed_program( self, signed_program_name: str, traits: dict = {} ) -> Union[dict, bytes]: """Alter an existing signed program profile.""" - if traits["sigver:library"]: + if "sigver:library" in traits: traits["base:member"] = traits["sigver:library"] del traits["sigver:library"] return self.alter( diff --git a/tests/resource/resource_request_samples/add_appc_session_request.xml b/tests/resource/resource_request_samples/add_appc_session_request.xml new file mode 100644 index 00000000..7e8c87cf --- /dev/null +++ b/tests/resource/resource_request_samples/add_appc_session_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/add_custom_field_request.xml b/tests/resource/resource_request_samples/add_custom_field_request.xml new file mode 100644 index 00000000..454fdabd --- /dev/null +++ b/tests/resource/resource_request_samples/add_custom_field_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/add_kerberos_realm_request.xml b/tests/resource/resource_request_samples/add_kerberos_realm_request.xml new file mode 100644 index 00000000..5ae3d3aa --- /dev/null +++ b/tests/resource/resource_request_samples/add_kerberos_realm_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/add_resource_class_request.xml b/tests/resource/resource_request_samples/add_resource_class_request.xml new file mode 100644 index 00000000..0e02bab1 --- /dev/null +++ b/tests/resource/resource_request_samples/add_resource_class_request.xml @@ -0,0 +1,17 @@ + + + + UPPER + ALPHA + ALPHA NUMERIC + 246 + 246 + 0 + YES + 200 + 8 + NONE + ALLOWED + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/add_signed_program_request.xml b/tests/resource/resource_request_samples/add_signed_program_request.xml new file mode 100644 index 00000000..05a507b9 --- /dev/null +++ b/tests/resource/resource_request_samples/add_signed_program_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/add_started_task_request.xml b/tests/resource/resource_request_samples/add_started_task_request.xml new file mode 100644 index 00000000..c069b086 --- /dev/null +++ b/tests/resource/resource_request_samples/add_started_task_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_appc_session_request.xml b/tests/resource/resource_request_samples/alter_appc_session_request.xml new file mode 100644 index 00000000..b972bcee --- /dev/null +++ b/tests/resource/resource_request_samples/alter_appc_session_request.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_custom_field_request.xml b/tests/resource/resource_request_samples/alter_custom_field_request.xml new file mode 100644 index 00000000..974d407b --- /dev/null +++ b/tests/resource/resource_request_samples/alter_custom_field_request.xml @@ -0,0 +1,9 @@ + + + + Favorite TV Show + ALPHA + ALPHA + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_kerberos_realm_request.xml b/tests/resource/resource_request_samples/alter_kerberos_realm_request.xml new file mode 100644 index 00000000..199ae979 --- /dev/null +++ b/tests/resource/resource_request_samples/alter_kerberos_realm_request.xml @@ -0,0 +1,7 @@ + + + + AES128 + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_resource_class_request.xml b/tests/resource/resource_request_samples/alter_resource_class_request.xml new file mode 100644 index 00000000..532cbe0b --- /dev/null +++ b/tests/resource/resource_request_samples/alter_resource_class_request.xml @@ -0,0 +1,11 @@ + + + + ALPHA NUMERIC + ALPHA + NO + 4 + READ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_signed_program_request.xml b/tests/resource/resource_request_samples/alter_signed_program_request.xml new file mode 100644 index 00000000..35a63047 --- /dev/null +++ b/tests/resource/resource_request_samples/alter_signed_program_request.xml @@ -0,0 +1,7 @@ + + + + SUCCESS + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/alter_started_task_request.xml b/tests/resource/resource_request_samples/alter_started_task_request.xml new file mode 100644 index 00000000..97c9289e --- /dev/null +++ b/tests/resource/resource_request_samples/alter_started_task_request.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_appc_session_request.xml b/tests/resource/resource_request_samples/delete_appc_session_request.xml new file mode 100644 index 00000000..896d662e --- /dev/null +++ b/tests/resource/resource_request_samples/delete_appc_session_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_custom_field_request.xml b/tests/resource/resource_request_samples/delete_custom_field_request.xml new file mode 100644 index 00000000..ab75dbfb --- /dev/null +++ b/tests/resource/resource_request_samples/delete_custom_field_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_kerberos_realm_request.xml b/tests/resource/resource_request_samples/delete_kerberos_realm_request.xml new file mode 100644 index 00000000..b0e6a124 --- /dev/null +++ b/tests/resource/resource_request_samples/delete_kerberos_realm_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_resource_class_request.xml b/tests/resource/resource_request_samples/delete_resource_class_request.xml new file mode 100644 index 00000000..c5fe1627 --- /dev/null +++ b/tests/resource/resource_request_samples/delete_resource_class_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_signed_program_request.xml b/tests/resource/resource_request_samples/delete_signed_program_request.xml new file mode 100644 index 00000000..838b1074 --- /dev/null +++ b/tests/resource/resource_request_samples/delete_signed_program_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_request_samples/delete_started_task_request.xml b/tests/resource/resource_request_samples/delete_started_task_request.xml new file mode 100644 index 00000000..7956543b --- /dev/null +++ b/tests/resource/resource_request_samples/delete_started_task_request.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_error.xml new file mode 100644 index 00000000..b7162734 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST CDT (SHELCITY) CDTINFO + ICH13003I TESTING NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_success.xml new file mode 100644 index 00000000..bebced95 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_cdtinfo_success.xml @@ -0,0 +1,58 @@ + + + + + 0 + 0 + 0 + RLIST CDT (SHELCITY) CDTINFO + CLASS NAME + ----- ---- + CDT SHELCITY + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE ALTER NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + CDTINFO INFORMATION + ------------------- + CASE = UPPER + DEFAULTRC = 008 + DEFAULTUACC = NONE + FIRST = ALPHA + GENLIST = DISALLOWED + GENERIC = ALLOWED + GROUP = + KEYQUALIFIERS = 0000000000 + MACPROCESSING = NORMAL + MAXLENGTH = 246 + MAXLENX = 0000000246 + MEMBER = + OPERATIONS = NO + OTHER = ALPHA NUMERIC + POSIT = 0000000200 + PROFILESALLOWED = YES + RACLIST = ALLOWED + SECLABELSREQUIRED = NO + SIGNAL = NO + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_error.xml new file mode 100644 index 00000000..23e544ba --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST CFIELD (USER.CSDATA.TVSHOW) CFDEF + ICH13003I USER.CSDATA.TVSHOW NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_success.xml new file mode 100644 index 00000000..6808f253 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_cfdef_success.xml @@ -0,0 +1,47 @@ + + + + + 0 + 0 + 0 + RLIST CFIELD (USER.CSDATA.TVSHOW) CFDEF + CLASS NAME + ----- ---- + CFIELD USER.CSDATA.TVSHOW + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE ALTER NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + CFDEF INFORMATION + ----------------- + TYPE = CHAR + MAXLENGTH = NONE + MAXVALUE = NONE + MINVALUE = NONE + FIRST = ALPHA + OTHER = ALPHA + MIXED = NO + HELP = FAVORITE TV SHOW + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_generic_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_generic_success.xml new file mode 100644 index 00000000..26342807 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_generic_success.xml @@ -0,0 +1,36 @@ + + + + + 0 + 0 + 0 + RLIST ELIJTEST (TESTING) + CLASS NAME + ----- ---- + ELIJTEST TEST* + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT READ READ NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_kerb_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_kerb_error.xml new file mode 100644 index 00000000..aa45018f --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_kerb_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST REALM (TSTREALM) KERB + ICH13003I TSTREALM NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_kerb_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_kerb_success.xml new file mode 100644 index 00000000..3f83084d --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_kerb_success.xml @@ -0,0 +1,41 @@ + + + + + 0 + 0 + 0 + RLIST REALM (TSTREALM) KERB + CLASS NAME + ----- ---- + REALM TSTREALM + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE ALTER NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + KERB INFORMATION + ---------------- + KEY ENCRYPTION TYPE= DES DES3 DESD AES128 AES256 AES128SHA2 AES256SHA2 + CHECK ADDRESSES= NO + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_session_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_session_error.xml new file mode 100644 index 00000000..47dace61 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_session_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST APPCLU (TSTNET.TSTLOCLU.TSTPRTLU) SESSION + ICH13003I TSTNET.TSTLOCLU.TSTPRTLU NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_session_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_session_success.xml new file mode 100644 index 00000000..028679ec --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_session_success.xml @@ -0,0 +1,41 @@ + + + + + 0 + 0 + 0 + RLIST APPCLU (TSTNET.TSTLOCLU.TSTPRTLU) SESSION + CLASS NAME + ----- ---- + APPCLU TSTNET.TSTLOCLU.TSTPRTLU + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE ALTER NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + SESSION INFORMATION + ------------------- + SESSION KEY INTERVAL IS UNLIMITED + LOCKED + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_sigver_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_sigver_error.xml new file mode 100644 index 00000000..fd0d4b71 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_sigver_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST PROGRAM (TESTPRGM) SIGVER + ICH13003I TESTPRGM NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_sigver_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_sigver_success.xml new file mode 100644 index 00000000..44f27b64 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_sigver_success.xml @@ -0,0 +1,50 @@ + + + + + 0 + 0 + 0 + RLIST PROGRAM (TESTPRGM) SIGVER + CLASS NAME + ----- ---- + PROGRAM TESTPRGM + + MEMBER CLASS NAME + ------ ----- ---- + PMBR + + DATA SET NAME VOLSER PADS CHECKING + -------------------------------------------- ------ ------------- + NONE + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE ALTER NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + SIGVER INFORMATION + ------------------ + SIGREQUIRED = NO + FAILLOAD = NEVER + SIGAUDIT = SUCCESS + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_stdata_error.xml b/tests/resource/resource_result_samples/extract_resource_result_base_stdata_error.xml new file mode 100644 index 00000000..3c30b137 --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_stdata_error.xml @@ -0,0 +1,14 @@ + + + + + 8 + 16 + 4 + RLIST STARTED (TSTTSKEL) STDATA + ICH13003I TSTTSKEL NOT FOUND + + + 4 + 0 + \ No newline at end of file diff --git a/tests/resource/resource_result_samples/extract_resource_result_base_stdata_success.xml b/tests/resource/resource_result_samples/extract_resource_result_base_stdata_success.xml new file mode 100644 index 00000000..cf4d8f1c --- /dev/null +++ b/tests/resource/resource_result_samples/extract_resource_result_base_stdata_success.xml @@ -0,0 +1,44 @@ + + + + + 0 + 0 + 0 + RLIST STARTED (TSTTSKEL) STDATA + CLASS NAME + ----- ---- + STARTED TSTTSKEL + + LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING + ----- -------- ---------------- ----------- ------- + 00 ESWIFT NONE NONE NO + + INSTALLATION DATA + ----------------- + NONE + + APPLICATION DATA + ---------------- + NONE + + AUDITING + -------- + FAILURES(READ) + + NOTIFY + ------ + NO USER TO BE NOTIFIED + + STDATA INFORMATION + ------------------ + USER= + GROUP= + TRUSTED= YES + PRIVILEGED= NO + TRACE= NO + + + 0 + 0 + \ No newline at end of file diff --git a/tests/resource/test_resource_constants.py b/tests/resource/test_resource_constants.py index 4efa9571..f2e0712d 100644 --- a/tests/resource/test_resource_constants.py +++ b/tests/resource/test_resource_constants.py @@ -58,6 +58,9 @@ def get_sample(sample_file: str) -> Union[str, bytes]: TEST_EXTRACT_RESOURCE_RESULT_BAD_CLASS_ERROR_DICTIONARY = get_sample( "extract_resource_result_bad_class_error.json" ) +TEST_EXTRACT_RESOURCE_RESULT_BASE_GENERIC_SUCCESS_XML = get_sample( + "extract_resource_result_base_generic_success.xml" +) # Delete Resource TEST_DELETE_RESOURCE_RESULT_SUCCESS_XML = get_sample( @@ -118,3 +121,187 @@ def get_sample(sample_file: str) -> Union[str, bytes]: TEST_EXTRACT_RESOURCE_BASE_SUCCESS_LOG = get_sample("extract_resource_base_success.log") TEST_EXTRACT_RESOURCE_BASE_ERROR_LOG = get_sample("extract_resource_base_error.log") + +# ============================================================================ +# Class Administration +# ============================================================================ + +TEST_ADD_RESOURCE_CLASS_REQUEST_XML = get_sample("add_resource_class_request.xml") +TEST_ALTER_RESOURCE_CLASS_REQUEST_XML = get_sample("alter_resource_class_request.xml") +TEST_DELETE_RESOURCE_CLASS_REQUEST_XML = get_sample("delete_resource_class_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_CDTINFO_SUCCESS_XML = get_sample( + "extract_resource_result_base_cdtinfo_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_CDTINFO_ERROR_XML = get_sample( + "extract_resource_result_base_cdtinfo_error.xml" +) + +TEST_EXTRACT_RESOURCE_CLASS_PROFILE = { + "caseAllowed": "upper", + "defaultRacrouteReturnCode": 8, + "defaultUniversalAccess": None, + "validFirstCharacters": "alpha", + "genlist": "disallowed", + "generic": "allowed", + "groupingClassName": "", + "keyQualifiers": 0, + "manditoryAccessControlProcessing": "normal", + "maxLength": 246, + "maxLengthEntityx": 246, + "memberClassName": "", + "operations": None, + "validOtherCharacters": ["alpha", "numeric"], + "positNumber": 200, + "profilesAllowed": "yes", + "raclistAllowed": "allowed", + "securityLabelsRequired": None, + "sendEnfSignalOnProfileCreation": None, +} + + +TEST_ADD_RESOURCE_CLASS_REQUEST_TRAITS = { + "cdtinfo:case_allowed": "UPPER", + "cdtinfo:valid_first_characters": "ALPHA", + "cdtinfo:valid_other_characters": ["ALPHA", "NUMERIC"], + "cdtinfo:max_length": 246, + "cdtinfo:max_length_entityx": 246, + "cdtinfo:key_qualifiers": 0, + "cdtinfo:profiles_allowed": "YES", + "cdtinfo:posit_number": 200, + "cdtinfo:default_racroute_return_code": 8, + "cdtinfo:default_universal_access": "NONE", + "cdtinfo:raclist_allowed": "ALLOWED", +} + +TEST_ALTER_RESOURCE_CLASS_REQUEST_TRAITS = { + "cdtinfo:valid_first_characters": ["ALPHA", "NUMERIC"], + "cdtinfo:valid_other_characters": ["ALPHA"], + "cdtinfo:profiles_allowed": "NO", + "cdtinfo:default_racroute_return_code": 4, + "cdtinfo:default_universal_access": "READ", +} + +# ============================================================================ +# Custom Field Administration +# ============================================================================ + +TEST_ADD_CUSTOM_FIELD_REQUEST_XML = get_sample("add_custom_field_request.xml") +TEST_ALTER_CUSTOM_FIELD_REQUEST_XML = get_sample("alter_custom_field_request.xml") +TEST_DELETE_CUSTOM_FIELD_REQUEST_XML = get_sample("delete_custom_field_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_CFDEF_SUCCESS_XML = get_sample( + "extract_resource_result_base_cfdef_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_CFDEF_ERROR_XML = get_sample( + "extract_resource_result_base_cfdef_error.xml" +) + +TEST_EXTRACT_CUSTOM_FIELD_PROFILE = { + "customFieldDataType": "char", + "maxlength": None, + "maxNumericValue": None, + "minNumericValue": None, + "validFirstCharacters": "alpha", + "validOtherCharacters": "alpha", + "mixedCaseAllowed": None, + "helpText": ["favorite", "tv", "show"], +} + +TEST_ALTER_CUSTOM_FIELD_REQUEST_TRAITS = { + "cfdef:help_text": "Favorite TV Show", + "cfdef:valid_first_characters": "ALPHA", + "cfdef:valid_other_characters": "ALPHA", +} + +# ============================================================================ +# Started Task Administration +# ============================================================================ + +TEST_ADD_STARTED_TASK_REQUEST_XML = get_sample("add_started_task_request.xml") +TEST_ALTER_STARTED_TASK_REQUEST_XML = get_sample("alter_started_task_request.xml") +TEST_DELETE_STARTED_TASK_REQUEST_XML = get_sample("delete_started_task_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_STDATA_SUCCESS_XML = get_sample( + "extract_resource_result_base_stdata_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_STDATA_ERROR_XML = get_sample( + "extract_resource_result_base_stdata_error.xml" +) + +TEST_EXTRACT_STARTED_TASK_PROFILE = { + "user": "", + "group": "", + "trusted": "yes", + "privileged": None, + "trace": None, +} + +# ============================================================================ +# Kerberos Realm Administration +# ============================================================================ + +TEST_ADD_KERBEROS_REALM_REQUEST_XML = get_sample("add_kerberos_realm_request.xml") +TEST_ALTER_KERBEROS_REALM_REQUEST_XML = get_sample("alter_kerberos_realm_request.xml") +TEST_DELETE_KERBEROS_REALM_REQUEST_XML = get_sample("delete_kerberos_realm_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_KERB_SUCCESS_XML = get_sample( + "extract_resource_result_base_kerb_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_KERB_ERROR_XML = get_sample( + "extract_resource_result_base_kerb_error.xml" +) + +TEST_EXTRACT_KERBEROS_REALM_PROFILE = { + "keyEncryptionType": [ + "des", + "des3", + "desd", + "aes128", + "aes256", + "aes128sha2", + "aes256sha2", + ], + "checkAddresses": None, +} + +# ============================================================================ +# Signed Program Administration +# ============================================================================ + +TEST_ADD_SIGNED_PROGRAM_REQUEST_XML = get_sample("add_signed_program_request.xml") +TEST_ALTER_SIGNED_PROGRAM_REQUEST_XML = get_sample("alter_signed_program_request.xml") +TEST_DELETE_SIGNED_PROGRAM_REQUEST_XML = get_sample("delete_signed_program_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_SIGVER_SUCCESS_XML = get_sample( + "extract_resource_result_base_sigver_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_SIGVER_ERROR_XML = get_sample( + "extract_resource_result_base_sigver_error.xml" +) + +TEST_EXTRACT_SIGNED_PROGRAM_PROFILE = { + "signatureRequired": None, + "failProgramLoadCondition": "never", + "logSignatureVerificationEvents": "success", + "library": None, +} + +# ============================================================================ +# APPC Session Administration +# ============================================================================ + +TEST_ADD_APPC_SESSION_REQUEST_XML = get_sample("add_appc_session_request.xml") +TEST_ALTER_APPC_SESSION_REQUEST_XML = get_sample("alter_appc_session_request.xml") +TEST_DELETE_APPC_SESSION_REQUEST_XML = get_sample("delete_appc_session_request.xml") + +TEST_EXTRACT_RESOURCE_RESULT_BASE_SESSION_SUCCESS_XML = get_sample( + "extract_resource_result_base_session_success.xml" +) +TEST_EXTRACT_RESOURCE_RESULT_BASE_SESSION_ERROR_XML = get_sample( + "extract_resource_result_base_session_error.xml" +) + +# This segment requires additional logic that is not currently implemented. +# This will not be documented and the rest marked experimental +TEST_EXTRACT_APPC_SESSION_PROFILE = {} diff --git a/tests/resource/test_resource_result_parser.py b/tests/resource/test_resource_result_parser.py index 8c830103..525366ee 100644 --- a/tests/resource/test_resource_result_parser.py +++ b/tests/resource/test_resource_result_parser.py @@ -63,6 +63,19 @@ def test_resource_admin_throws_error_on_add_existing_profile( + f"'{profile_name}' already exists as a profile in the '{class_name}' class.", ) + def test_resource_admin_avoids_error_on_add_covered_profile( + self, + call_racf_mock: Mock, + ): + call_racf_mock.side_effect = [ + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_GENERIC_SUCCESS_XML, + TestResourceConstants.TEST_ADD_RESOURCE_RESULT_SUCCESS_XML, + ] + self.assertEqual( + self.resource_admin.add("TESTING", "ELIJTEST"), + TestResourceConstants.TEST_ADD_RESOURCE_RESULT_SUCCESS_DICTIONARY, + ) + # Error: bad Entity Name ELIXTEST def test_resource_admin_can_parse_add_resource_error_xml( self, @@ -122,6 +135,29 @@ def test_resource_admin_throws_error_on_alter_new_profile( + f"'{profile_name}' does not exist as a profile in the '{class_name}' class.", ) + def test_resource_admin_throws_error_on_alter_covered_profile( + self, + call_racf_mock: Mock, + ): + profile_name = "TESTING" + class_name = "ELIJTEST" + call_racf_mock.side_effect = [ + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_GENERIC_SUCCESS_XML, + TestResourceConstants.TEST_ALTER_RESOURCE_RESULT_SUCCESS_XML, + ] + with self.assertRaises(AlterOperationError) as exception: + self.resource_admin.alter( + profile_name, + class_name, + traits=TestResourceConstants.TEST_ALTER_RESOURCE_REQUEST_TRAITS, + ) + self.assertEqual( + exception.exception.message, + "Refusing to make security request to IRRSMO00." + + "\n\nTarget profile " + + f"'{profile_name}' does not exist as a profile in the '{class_name}' class.", + ) + # Error: bad Universal Access ALL def test_resource_admin_can_parse_alter_resource_error_xml( self, diff --git a/tests/resource/test_resource_sub_function_extracts.py b/tests/resource/test_resource_sub_function_extracts.py new file mode 100644 index 00000000..e68b46c0 --- /dev/null +++ b/tests/resource/test_resource_sub_function_extracts.py @@ -0,0 +1,170 @@ +"""Test general resource profile setter functions.""" + +import unittest +from unittest.mock import Mock, patch + +import __init__ + +import tests.resource.test_resource_constants as TestResourceConstants +from pyracf import ResourceAdmin, SecurityRequestError +from pyracf.common.irrsmo00 import IRRSMO00 + +# Resolves F401 +__init__ + + +@patch("pyracf.common.irrsmo00.IRRSMO00.call_racf") +class TestResourceSubFunctionExtracts(unittest.TestCase): + maxDiff = None + IRRSMO00.__init__ = Mock(return_value=None) + resource_admin = ResourceAdmin() + + # ============================================================================ + # Class Administration + # ============================================================================ + def test_resource_admin_extract_resource_class_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_CDTINFO_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_resource_class("SHELCITY"), + TestResourceConstants.TEST_EXTRACT_RESOURCE_CLASS_PROFILE, + ) + + def test_resource_admin_extract_resource_class_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_CDTINFO_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_resource_class("SHELCITY") + + # ============================================================================ + # Started Task Administration + # ============================================================================ + def test_resource_admin_build_extract_started_task_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_STDATA_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_started_task("TSTTSKEL"), + TestResourceConstants.TEST_EXTRACT_STARTED_TASK_PROFILE, + ) + + def test_resource_admin_build_extract_started_task_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_STDATA_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_started_task("TSTTSKEL") + + # ============================================================================ + # Custom Field Administration + # ============================================================================ + def test_resource_admin_build_extract_custom_field_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_CFDEF_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_custom_field("TVSHOW", "user"), + TestResourceConstants.TEST_EXTRACT_CUSTOM_FIELD_PROFILE, + ) + + def test_resource_admin_build_extract_custom_field_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_CFDEF_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_custom_field("TVSHOW", "user") + + # ============================================================================ + # Kerberos Realm Administration + # ============================================================================ + def test_resource_admin_build_extract_kerberos_realm_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_KERB_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_kerberos_realm("TSTREALM"), + TestResourceConstants.TEST_EXTRACT_KERBEROS_REALM_PROFILE, + ) + + def test_resource_admin_build_extract_kerberos_realm_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_KERB_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_kerberos_realm("TSTREALM") + + # ============================================================================ + # Signed Program Administration + # ============================================================================ + def test_resource_admin_build_extract_signed_program_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_SIGVER_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_signed_program("TESTPRGM"), + TestResourceConstants.TEST_EXTRACT_SIGNED_PROGRAM_PROFILE, + ) + + def test_resource_admin_build_extract_signed_program_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_SIGVER_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_signed_program("TESTPRGM") + + # ============================================================================ + # APPC Session Administration + # ============================================================================ + def test_resource_admin_build_extract_appc_session_returns_valid_on_success( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_SESSION_SUCCESS_XML + ) + self.assertEqual( + self.resource_admin.extract_appc_session("TSTNET", "TSTLOCLU", "TSTPRTLU"), + TestResourceConstants.TEST_EXTRACT_APPC_SESSION_PROFILE, + ) + + def test_resource_admin_build_extract_appc_session_raises_exception_when_extract_fails( + self, + call_racf_mock: Mock, + ): + call_racf_mock.return_value = ( + TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_SESSION_ERROR_XML + ) + with self.assertRaises(SecurityRequestError): + self.resource_admin.extract_appc_session("TSTNET", "TSTLOCLU", "TSTPRTLU") diff --git a/tests/resource/test_resource_sub_function_requests.py b/tests/resource/test_resource_sub_function_requests.py new file mode 100644 index 00000000..cfd48189 --- /dev/null +++ b/tests/resource/test_resource_sub_function_requests.py @@ -0,0 +1,163 @@ +"""Test general resource profile setter functions.""" + +import unittest +from unittest.mock import Mock + +import __init__ + +import tests.resource.test_resource_constants as TestResourceConstants +from pyracf import ResourceAdmin +from pyracf.common.irrsmo00 import IRRSMO00 + +# Resolves F401 +__init__ + + +class TestResourceSubFunctionRequests(unittest.TestCase): + maxDiff = None + IRRSMO00.__init__ = Mock(return_value=None) + resource_admin = ResourceAdmin(generate_requests_only=True) + + # ============================================================================ + # Class Administration + # ============================================================================ + def test_resource_admin_build_add_resource_class_request(self): + result = self.resource_admin.add_resource_class( + "SHELCITY", TestResourceConstants.TEST_ADD_RESOURCE_CLASS_REQUEST_TRAITS + ) + self.assertEqual( + result, TestResourceConstants.TEST_ADD_RESOURCE_CLASS_REQUEST_XML + ) + + def test_resource_admin_build_alter_resource_class_request(self): + result = self.resource_admin.alter_resource_class( + "SHELCITY", TestResourceConstants.TEST_ALTER_RESOURCE_CLASS_REQUEST_TRAITS + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_RESOURCE_CLASS_REQUEST_XML + ) + + def test_resource_admin_build_delete_resource_class_request(self): + result = self.resource_admin.delete_resource_class("SHELCITY") + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_RESOURCE_CLASS_REQUEST_XML + ) + + # ============================================================================ + # Started Task Administration + # ============================================================================ + def test_resource_admin_build_add_started_task_request(self): + result = self.resource_admin.add_started_task("TSTTSKEL") + self.assertEqual( + result, TestResourceConstants.TEST_ADD_STARTED_TASK_REQUEST_XML + ) + + def test_resource_admin_build_alter_started_task_request(self): + result = self.resource_admin.alter_started_task( + "TSTTSKEL", {"stdata:trusted": True} + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_STARTED_TASK_REQUEST_XML + ) + + def test_resource_admin_build_delete_started_task_request(self): + result = self.resource_admin.delete_started_task("TSTTSKEL") + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_STARTED_TASK_REQUEST_XML + ) + + # ============================================================================ + # Custom Field Administration + # ============================================================================ + def test_resource_admin_build_add_custom_field_request(self): + result = self.resource_admin.add_custom_field("TVSHOW", "user") + self.assertEqual( + result, TestResourceConstants.TEST_ADD_CUSTOM_FIELD_REQUEST_XML + ) + + def test_resource_admin_build_alter_custom_field_request(self): + result = self.resource_admin.alter_custom_field( + "TVSHOW", + "user", + traits=TestResourceConstants.TEST_ALTER_CUSTOM_FIELD_REQUEST_TRAITS, + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_CUSTOM_FIELD_REQUEST_XML + ) + + def test_resource_admin_build_delete_custom_field_request(self): + result = self.resource_admin.delete_custom_field("TVSHOW", "user") + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_CUSTOM_FIELD_REQUEST_XML + ) + + # ============================================================================ + # Kerberos Realm Administration + # ============================================================================ + def test_resource_admin_build_add_kerberos_realm_request(self): + result = self.resource_admin.add_kerberos_realm("TSTREALM") + self.assertEqual( + result, TestResourceConstants.TEST_ADD_KERBEROS_REALM_REQUEST_XML + ) + + def test_resource_admin_build_alter_kerberos_realm_request(self): + result = self.resource_admin.alter_kerberos_realm( + "TSTREALM", traits={"kerb:encryption_algorithms": "AES128"} + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_KERBEROS_REALM_REQUEST_XML + ) + + def test_resource_admin_build_delete_kerberos_realm_request(self): + result = self.resource_admin.delete_kerberos_realm("TSTREALM") + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_KERBEROS_REALM_REQUEST_XML + ) + + # ============================================================================ + # Signed Program Administration + # ============================================================================ + def test_resource_admin_build_add_signed_program_request(self): + result = self.resource_admin.add_signed_program("TESTPRGM") + self.assertEqual( + result, TestResourceConstants.TEST_ADD_SIGNED_PROGRAM_REQUEST_XML + ) + + def test_resource_admin_build_alter_signed_program_request(self): + result = self.resource_admin.alter_signed_program( + "TESTPRGM", traits={"sigver:log_signature_verification_events": "SUCCESS"} + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_SIGNED_PROGRAM_REQUEST_XML + ) + + def test_resource_admin_build_delete_signed_program_request(self): + result = self.resource_admin.delete_signed_program("TESTPRGM") + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_SIGNED_PROGRAM_REQUEST_XML + ) + + # ============================================================================ + # APPC Session Administration + # ============================================================================ + def test_resource_admin_build_add_appc_session_request(self): + result = self.resource_admin.add_appc_session("TSTNET", "TSTLOCLU", "TSTPRTLU") + self.assertEqual( + result, TestResourceConstants.TEST_ADD_APPC_SESSION_REQUEST_XML + ) + + def test_resource_admin_build_alter_appc_session_request(self): + result = self.resource_admin.alter_appc_session( + "TSTNET", "TSTLOCLU", "TSTPRTLU", traits={"session:locked": True} + ) + self.assertEqual( + result, TestResourceConstants.TEST_ALTER_APPC_SESSION_REQUEST_XML + ) + + def test_resource_admin_build_delete_appc_session_request(self): + result = self.resource_admin.delete_appc_session( + "TSTNET", "TSTLOCLU", "TSTPRTLU" + ) + self.assertEqual( + result, TestResourceConstants.TEST_DELETE_APPC_SESSION_REQUEST_XML + ) diff --git a/tests/test_runner.py b/tests/test_runner.py index 8b240d9c..e0b1aab8 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -30,6 +30,12 @@ from tests.resource.test_resource_request_builder import TestResourceRequestBuilder from tests.resource.test_resource_result_parser import TestResourceResultParser from tests.resource.test_resource_setters import TestResourceSetters +from tests.resource.test_resource_sub_function_extracts import ( + TestResourceSubFunctionExtracts, +) +from tests.resource.test_resource_sub_function_requests import ( + TestResourceSubFunctionRequests, +) from tests.setropts.test_setropts_debug_logging import TestSetroptsDebugLogging from tests.setropts.test_setropts_getters import TestSetroptsGetters from tests.setropts.test_setropts_request_builder import TestSetroptsRequestBuilder @@ -68,6 +74,8 @@ def __test_suite() -> unittest.TestSuite: TestResourceGetters, TestResourceSetters, TestResourceDebugLogging, + TestResourceSubFunctionRequests, + TestResourceSubFunctionExtracts, TestGroupResultParser, TestGroupRequestBuilder, TestGroupGetters, From c53fdcc5f93aed5cc1c2eb149c1457a76737ec7a Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Thu, 2 Nov 2023 11:53:36 -0400 Subject: [PATCH 08/11] Comments and Name Changes Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 3 +++ pyracf/resource/resource_admin.py | 8 ++++---- tests/resource/test_resource_constants.py | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index e4c901b3..7eb336be 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -13,6 +13,9 @@ typedef struct { char str[8]; } VarStr_T; +// This function changes any null character not preceded by '>' to whitespace +// This works around an issue with IRRSMO00 treating whitespace as null characters +// which led to premature string termination void null_byte_fix(char* str, unsigned int str_len) { for (int i = 1; i < str_len; i++){ if (str[i] == 0) { diff --git a/pyracf/resource/resource_admin.py b/pyracf/resource/resource_admin.py index b62fb5be..9e0d5d4e 100644 --- a/pyracf/resource/resource_admin.py +++ b/pyracf/resource/resource_admin.py @@ -59,8 +59,8 @@ def __init__( "cdtinfo:case_allowed": "case", "cdtinfo:default_racroute_return_code": "defaultrc", "cdtinfo:valid_first_characters": "first", - "cdtinfo:generic": "generic", - "cdtinfo:genlist": "genlist", + "cdtinfo:generic_profile_checking": "racf:generic", + "cdtinfo:generic_profile_sharing": "racf:genlist", "cdtinfo:grouping_class_name": "grouping", "cdtinfo:key_qualifiers": "keyqual", "cdtinfo:manditory_access_control_processing": "macprocessing", @@ -185,8 +185,8 @@ def __init__( "case": "caseAllowed", "defaultrc": "defaultRacrouteReturnCode", "first": "validFirstCharacters", - "generic": "generic", - "genlist": "genlist", + "generic": "genericProfileChecking", + "genlist": "genericProfileSharing", "group": "groupingClassName", "keyqualifiers": "keyQualifiers", "macprocessing": "manditoryAccessControlProcessing", diff --git a/tests/resource/test_resource_constants.py b/tests/resource/test_resource_constants.py index f2e0712d..b23c189e 100644 --- a/tests/resource/test_resource_constants.py +++ b/tests/resource/test_resource_constants.py @@ -142,8 +142,8 @@ def get_sample(sample_file: str) -> Union[str, bytes]: "defaultRacrouteReturnCode": 8, "defaultUniversalAccess": None, "validFirstCharacters": "alpha", - "genlist": "disallowed", - "generic": "allowed", + "genericProfileSharing": "disallowed", + "genericProfileChecking": "allowed", "groupingClassName": "", "keyQualifiers": 0, "manditoryAccessControlProcessing": "normal", From c8deb71cc7f1f30d88cb99b77438e4df08081d72 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Thu, 2 Nov 2023 13:02:40 -0400 Subject: [PATCH 09/11] Change wording and naming Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 6 +++--- tests/resource/test_resource_sub_function_extracts.py | 2 +- tests/resource/test_resource_sub_function_requests.py | 2 +- tests/test_runner.py | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index 7eb336be..b22f6623 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -13,9 +13,9 @@ typedef struct { char str[8]; } VarStr_T; -// This function changes any null character not preceded by '>' to whitespace -// This works around an issue with IRRSMO00 treating whitespace as null characters -// which led to premature string termination +// This function changes any null character not preceded by '>' to a blank character. +// This works around an issue with our expectations of values in the response string +// returned from IRRSMO00 which led to premature string termination. void null_byte_fix(char* str, unsigned int str_len) { for (int i = 1; i < str_len; i++){ if (str[i] == 0) { diff --git a/tests/resource/test_resource_sub_function_extracts.py b/tests/resource/test_resource_sub_function_extracts.py index e68b46c0..2f4787aa 100644 --- a/tests/resource/test_resource_sub_function_extracts.py +++ b/tests/resource/test_resource_sub_function_extracts.py @@ -14,7 +14,7 @@ @patch("pyracf.common.irrsmo00.IRRSMO00.call_racf") -class TestResourceSubFunctionExtracts(unittest.TestCase): +class TestResourceSubfunctionExtracts(unittest.TestCase): maxDiff = None IRRSMO00.__init__ = Mock(return_value=None) resource_admin = ResourceAdmin() diff --git a/tests/resource/test_resource_sub_function_requests.py b/tests/resource/test_resource_sub_function_requests.py index cfd48189..e99d80a7 100644 --- a/tests/resource/test_resource_sub_function_requests.py +++ b/tests/resource/test_resource_sub_function_requests.py @@ -13,7 +13,7 @@ __init__ -class TestResourceSubFunctionRequests(unittest.TestCase): +class TestResourceSubfunctionRequests(unittest.TestCase): maxDiff = None IRRSMO00.__init__ = Mock(return_value=None) resource_admin = ResourceAdmin(generate_requests_only=True) diff --git a/tests/test_runner.py b/tests/test_runner.py index e0b1aab8..e06697a6 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -31,10 +31,10 @@ from tests.resource.test_resource_result_parser import TestResourceResultParser from tests.resource.test_resource_setters import TestResourceSetters from tests.resource.test_resource_sub_function_extracts import ( - TestResourceSubFunctionExtracts, + TestResourceSubfunctionExtracts, ) from tests.resource.test_resource_sub_function_requests import ( - TestResourceSubFunctionRequests, + TestResourceSubfunctionRequests, ) from tests.setropts.test_setropts_debug_logging import TestSetroptsDebugLogging from tests.setropts.test_setropts_getters import TestSetroptsGetters @@ -74,8 +74,8 @@ def __test_suite() -> unittest.TestSuite: TestResourceGetters, TestResourceSetters, TestResourceDebugLogging, - TestResourceSubFunctionRequests, - TestResourceSubFunctionExtracts, + TestResourceSubfunctionRequests, + TestResourceSubfunctionExtracts, TestGroupResultParser, TestGroupRequestBuilder, TestGroupGetters, From f66964d96a5202c1c6eaebb0dd46ba64b0eeb219 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Thu, 2 Nov 2023 13:11:44 -0400 Subject: [PATCH 10/11] Add Dataset Covered Profile Testing Signed-off-by: Elijah Swift --- tests/data_set/test_data_set_result_parser.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/data_set/test_data_set_result_parser.py b/tests/data_set/test_data_set_result_parser.py index 27c0070b..c4417d35 100644 --- a/tests/data_set/test_data_set_result_parser.py +++ b/tests/data_set/test_data_set_result_parser.py @@ -65,6 +65,22 @@ def test_data_set_admin_thows_error_on_add_existing_data_set_profile( + f"'{self.data_set_admin._profile_type}' profile.", ) + def test_dataset_admin_avoids_error_on_add_covered_profile( + self, + call_racf_mock: Mock, + ): + call_racf_mock.side_effect = [ + TestDataSetConstants.TEST_EXTRACT_DATA_SET_RESULT_GENERIC_BASE_ONLY_SUCCESS_XML, + TestDataSetConstants.TEST_ADD_DATA_SET_RESULT_SUCCESS_XML, + ] + self.assertEqual( + self.data_set_admin.add( + "ESWIFT.TEST.T1136242.P3020470", + traits=TestDataSetConstants.TEST_ADD_DATA_SET_REQUEST_TRAITS, + ), + TestDataSetConstants.TEST_ADD_DATA_SET_RESULT_SUCCESS_DICTIONARY, + ) + # Error in command, ESWIFTTESTT1136242P3020470 is not a valid DATASET def test_data_set_admin_can_parse_add_data_set_error_xml( self, @@ -125,6 +141,28 @@ def test_data_set_admin_thows_error_on_alter_new_data_set_profile( + f"'{self.data_set_admin._profile_type}' profile.", ) + def test_dataset_admin_throws_error_on_alter_covered_profile( + self, + call_racf_mock: Mock, + ): + profile_name = "ESWIFT.TEST.T1136242.P3020470" + call_racf_mock.side_effect = [ + TestDataSetConstants.TEST_EXTRACT_DATA_SET_RESULT_GENERIC_BASE_ONLY_SUCCESS_XML, + TestDataSetConstants.TEST_ALTER_DATA_SET_RESULT_SUCCESS_XML, + ] + with self.assertRaises(AlterOperationError) as exception: + self.data_set_admin.alter( + profile_name, + traits=TestDataSetConstants.TEST_ALTER_DATA_SET_REQUEST_TRAITS, + ) + self.assertEqual( + exception.exception.message, + "Refusing to make security request to IRRSMO00." + + "\n\nTarget profile " + + f"'{profile_name}' does not exist as a " + + f"'{self.data_set_admin._profile_type}' profile.", + ) + # Error in environment, ESWIFT.TEST.T1136242.P3020470 data set does not exist def test_data_set_admin_can_parse_alter_data_set_error_xml( self, From 1da9b13ff74ec4dfcb466f5973df8c79cf6749e3 Mon Sep 17 00:00:00 2001 From: Elijah Swift Date: Thu, 2 Nov 2023 13:14:38 -0400 Subject: [PATCH 11/11] Name and Doc Changes Signed-off-by: Elijah Swift --- pyracf/common/irrsmo00.c | 5 +++-- ...ion_extracts.py => test_resource_subfunction_extracts.py} | 0 ...ion_requests.py => test_resource_subfunction_requests.py} | 0 tests/test_runner.py | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) rename tests/resource/{test_resource_sub_function_extracts.py => test_resource_subfunction_extracts.py} (100%) rename tests/resource/{test_resource_sub_function_requests.py => test_resource_subfunction_requests.py} (100%) diff --git a/pyracf/common/irrsmo00.c b/pyracf/common/irrsmo00.c index b22f6623..2cff3cff 100644 --- a/pyracf/common/irrsmo00.c +++ b/pyracf/common/irrsmo00.c @@ -14,8 +14,9 @@ typedef struct { } VarStr_T; // This function changes any null character not preceded by '>' to a blank character. -// This works around an issue with our expectations of values in the response string -// returned from IRRSMO00 which led to premature string termination. +// This is a workaround for an issue where the profile data embedded in response xml +// returned by IRROSMO00 sometimes includes null characters instead of properly +// encoded text, which causes the returned xml to be truncated. void null_byte_fix(char* str, unsigned int str_len) { for (int i = 1; i < str_len; i++){ if (str[i] == 0) { diff --git a/tests/resource/test_resource_sub_function_extracts.py b/tests/resource/test_resource_subfunction_extracts.py similarity index 100% rename from tests/resource/test_resource_sub_function_extracts.py rename to tests/resource/test_resource_subfunction_extracts.py diff --git a/tests/resource/test_resource_sub_function_requests.py b/tests/resource/test_resource_subfunction_requests.py similarity index 100% rename from tests/resource/test_resource_sub_function_requests.py rename to tests/resource/test_resource_subfunction_requests.py diff --git a/tests/test_runner.py b/tests/test_runner.py index e06697a6..6253f828 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -30,10 +30,10 @@ from tests.resource.test_resource_request_builder import TestResourceRequestBuilder from tests.resource.test_resource_result_parser import TestResourceResultParser from tests.resource.test_resource_setters import TestResourceSetters -from tests.resource.test_resource_sub_function_extracts import ( +from tests.resource.test_resource_subfunction_extracts import ( TestResourceSubfunctionExtracts, ) -from tests.resource.test_resource_sub_function_requests import ( +from tests.resource.test_resource_subfunction_requests import ( TestResourceSubfunctionRequests, ) from tests.setropts.test_setropts_debug_logging import TestSetroptsDebugLogging