Skip to content

Commit

Permalink
Add templates on extract for resource and data set
Browse files Browse the repository at this point in the history
-Add resource_template mapping to resource extract function
-Add unit testing for resource_template
-Add data_set_template mapping to data_set extract function
-Add unit testing for data_set_template

Signed-off-by: Elijah Swift <elijah.swift@ibm.com>
  • Loading branch information
ElijahSwiftIBM committed Feb 19, 2024
1 parent 024da09 commit 6aeb064
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 29 deletions.
27 changes: 24 additions & 3 deletions pyracf/common/security_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ class SecurityAdmin:
"base:generic": "racf:generic",
}

__template_map = {
"base:warning": "base:warn_on_insufficient_access",
"base:erase": "base:erase_data_sets_on_delete",
"base:notify": "base:notify_userid",
"cdtinfo:security_labels_required": "cdtinfo:security_label_required",
"cfdef:maxlength": "cfdef:max_field_length",
"kerb:key_encryption_type": "kerb:encryption_algorithms",
"kerb:check_addresses": "kerb:validate_addresses",
}

_valid_segment_traits = {}
_extracted_key_value_pair_segment_traits_map = {}
_case_sensitive_extracted_values = []
Expand Down Expand Up @@ -235,7 +245,7 @@ def _validate_access_levels(
)
raise ValueError(value_error_text)

def _build_traits_from_audit_rules(self, audit_rules: dict) -> dict:
def _build_traits_from_audit_rules(self, audit_rules: dict = {}) -> dict:
traits = {}
if "success" in audit_rules:
traits[f"base:audit_{audit_rules['success']}"] = "success"
Expand Down Expand Up @@ -524,13 +534,17 @@ def _build_template(
if self._generate_requests_only:
# Allows this function to work with "self._generate_requests_only" mode.
return profile
template = {}
audit_rules = profile["base"].get("auditing", {})
template = self._build_traits_from_audit_rules(audit_rules)
for segment in profile.keys():
for trait in profile[segment].keys():
if (
f"{segment}:{self.__camel_case_to_snake_case(trait)}"
not in self._valid_segment_traits[segment]
):
template = self.__map_extract_to_template(
template, segment, trait, profile[segment][trait]
)
continue
template[f"{segment}:{self.__camel_case_to_snake_case(trait)}"] = (
profile[segment][trait]
Expand All @@ -539,7 +553,14 @@ def _build_template(
template[f"{segment}:{self.__camel_case_to_snake_case(trait)}"] = (
re.sub(r"20([0-9][0-9])", r"\1", profile[segment][trait])
)
print(template)
return template

def __map_extract_to_template(
self, template: dict, segment: str, trait: str, value: Union[str, List, int]
):
key = f"{segment}:{self.__camel_case_to_snake_case(trait)}"
if key in self.__template_map:
template[self.__template_map[key]] = value
return template

def _get_field(
Expand Down
13 changes: 11 additions & 2 deletions tests/data_set/test_data_set_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,23 @@ def get_sample(sample_file: str) -> Union[str, bytes]:
TEST_EXTRACT_DATA_SET_REQUEST_BASE_TRAITS = {
"datasetname": "ESWIFT.TEST.T1136242.P3020470"
}
# Extract Data Set
TEST_EXTRACT_DATA_SET_REQUEST_GENRIC_BASE_XML = get_sample(
"extract_data_set_request_generic_base.xml"
)
TEST_EXTRACT_DATA_SET_REQUEST_GENERIC_BASE_TRAITS = {
"datasetname": "ESWIFT.TEST.T1136242.*"
}
TEST_EXTRACT_DATA_SET_BASE_ONLY_TEMPLATE_TRAITS = {}
TEST_EXTRACT_DATA_SET_BASE_ONLY_TEMPLATE_TRAITS = {
"base:audit_read": "failure",
"base:level": 0,
"base:owner": "eswift",
"base:universal_access": "read",
"base:warn_on_insufficient_access": None,
"base:erase_data_sets_on_delete": None,
"base:notify_userid": None,
"base:volumes": ["usrat2"],
"base:installation_data": None,
}

# Delete Data Set
TEST_DELETE_DATA_SET_REQUEST_XML = get_sample("delete_data_set_request.xml")
Expand Down
24 changes: 13 additions & 11 deletions tests/data_set/test_data_set_result_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,16 @@ def test_data_set_admin_can_parse_delete_data_set_error_xml(
# Build Template Data Set Profile
# ============================================================================

# def test_data_set_admin_can_build_template_data_set_base_success_xml(
# self,
# call_racf_mock: Mock,
# ):
# call_racf_mock.return_value = (
# TestDataSetConstants.TEST_EXTRACT_DATA_SET_RESULT_BASE_ONLY_SUCCESS_XML
# )
# self.assertEqual(
# self.data_set_admin.extract("ESWIFT.TEST.T1136242.P3020470",data_set_template = True),
# TestDataSetConstants.TEST_EXTRACT_DATA_SET_BASE_ONLY_TEMPLATE_TRAITS,
# )
def test_data_set_admin_can_build_template_data_set_base_success_xml(
self,
call_racf_mock: Mock,
):
call_racf_mock.return_value = (
TestDataSetConstants.TEST_EXTRACT_DATA_SET_RESULT_BASE_ONLY_SUCCESS_XML
)
self.assertEqual(
self.data_set_admin.extract(
"ESWIFT.TEST.T1136242.P3020470", data_set_template=True
),
TestDataSetConstants.TEST_EXTRACT_DATA_SET_BASE_ONLY_TEMPLATE_TRAITS,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="IBM-1047"?>
<securityresult xmlns="http://www.ibm.com/systems/zos/saf/IRRSMO00Result1">
<resource name="TSTTSKEL" class="STARTED" operation="listdata" requestid="ResourceRequest">
<command>
<safreturncode>0</safreturncode>
<returncode>0</returncode>
<reasoncode>0</reasoncode>
<image>RLIST STARTED (TSTTSKEL) STDATA </image>
<message>CLASS NAME</message>
<message>----- ----</message>
<message>STARTED TSTTSKEL</message>
<message> </message>
<message>LEVEL OWNER UNIVERSAL ACCESS YOUR ACCESS WARNING</message>
<message>----- -------- ---------------- ----------- -------</message>
<message> 00 ESWIFT NONE NONE NO</message>
<message> </message>
<message>INSTALLATION DATA</message>
<message>-----------------</message>
<message>NONE</message>
<message> </message>
<message>APPLICATION DATA</message>
<message>----------------</message>
<message>NONE</message>
<message> </message>
<message>AUDITING</message>
<message>--------</message>
<message>FAILURES(READ)</message>
<message> </message>
<message>NOTIFY</message>
<message>------</message>
<message>NO USER TO BE NOTIFIED</message>
<message> </message>
<message>STDATA INFORMATION</message>
<message>------------------</message>
<message>USER=</message>
<message>GROUP=</message>
<message>TRUSTED= YES</message>
<message>PRIVILEGED= NO</message>
<message>TRACE= NO</message>
<message> </message>
<message>CDTINFO INFORMATION</message>
<message>-------------------</message>
<message>CASE = UPPER</message>
<message>DEFAULTRC = 008</message>
<message>DEFAULTUACC = NONE</message>
<message>FIRST = ALPHA</message>
<message>GENLIST = DISALLOWED</message>
<message>GENERIC = ALLOWED</message>
<message>GROUP = </message>
<message>KEYQUALIFIERS = 0000000000</message>
<message>MACPROCESSING = NORMAL</message>
<message>MAXLENGTH = 246</message>
<message>MAXLENX = 0000000246</message>
<message>MEMBER = </message>
<message>OPERATIONS = NO</message>
<message>OTHER = ALPHA NUMERIC</message>
<message>POSIT = 0000000200</message>
<message>PROFILESALLOWED = YES</message>
<message>RACLIST = ALLOWED</message>
<message>SECLABELSREQUIRED = NO</message>
<message>SIGNAL = NO</message>
<message> </message>
<message>CFDEF INFORMATION</message>
<message>-----------------</message>
<message>TYPE = CHAR</message>
<message>MAXLENGTH = NONE</message>
<message>MAXVALUE = NONE</message>
<message>MINVALUE = NONE</message>
<message>FIRST = ALPHA</message>
<message>OTHER = ALPHA</message>
<message>MIXED = NO</message>
<message>HELP = FAVORITE TV SHOW</message>
<message> </message>
<message>KERB INFORMATION</message>
<message>----------------</message>
<message>KEY ENCRYPTION TYPE= DES DES3 DESD AES128 AES256 AES128SHA2 AES256SHA2</message>
<message>CHECK ADDRESSES= NO</message>
<message> </message>
<message>SESSION INFORMATION</message>
<message>-------------------</message>
<message>SESSION KEY IS E3C5E2E3D2C5E800</message>
<message>SESSION KEY INTERVAL IS 00005 DAYS</message>
<message>LOCKED</message>
<message>CONVSEC= CONV</message>
<message> </message>
<message>SIGVER INFORMATION</message>
<message>------------------</message>
<message>SIGREQUIRED = NO</message>
<message>FAILLOAD = NEVER</message>
<message>SIGAUDIT = SUCCESS</message>
</command>
</resource>
<returncode>0</returncode>
<reasoncode>0</reasoncode>
</securityresult>
64 changes: 64 additions & 0 deletions tests/resource/test_resource_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,70 @@ def get_sample(sample_file: str) -> Union[str, bytes]:
TEST_EXTRACT_RESOURCE_RESULT_BASE_GENERIC_SUCCESS_XML = get_sample(
"extract_resource_result_base_generic_success.xml"
)
# Note: It is impractical that one profile would have data in all of these segments, but it does
# have value to test with this larger value.
TEST_EXTRACT_RESOURCE_RESULT_BASE_AND_SUBFUNCTIONS_SUCCESS_XML = get_sample(
"extract_resource_result_base_and_subfunctions_success.xml"
)
TEST_EXTRACT_RESOURCE_BASE_AND_SUBFUNCTIONS_TEMPLATE_TRAITS = {
"base:application_data": None,
"base:audit_read": "failure",
"base:installation_data": None,
"base:level": 0,
"base:notify_userid": None,
"base:owner": "eswift",
"base:universal_access": None,
"base:warn_on_insufficient_access": None,
"cdtinfo:case_allowed": "upper",
"cdtinfo:default_racroute_return_code": 8,
"cdtinfo:default_universal_access": None,
"cdtinfo:generic_profile_checking": "allowed",
"cdtinfo:generic_profile_sharing": "disallowed",
"cdtinfo:grouping_class_name": None,
"cdtinfo:key_qualifiers": 0,
"cdtinfo:manditory_access_control_processing": "normal",
"cdtinfo:max_length": 246,
"cdtinfo:max_length_entityx": 246,
"cdtinfo:member_class_name": None,
"cdtinfo:operations": None,
"cdtinfo:posit_number": 200,
"cdtinfo:profiles_allowed": "yes",
"cdtinfo:raclist_allowed": "allowed",
"cdtinfo:security_label_required": None,
"cdtinfo:send_enf_signal_on_profile_creation": None,
"cdtinfo:valid_first_characters": "alpha",
"cdtinfo:valid_other_characters": ["alpha", "numeric"],
"cfdef:custom_field_data_type": "char",
"cfdef:help_text": ["favorite", "tv", "show"],
"cfdef:max_field_length": None,
"cfdef:max_numeric_value": None,
"cfdef:min_numeric_value": None,
"cfdef:mixed_case_allowed": None,
"cfdef:valid_first_characters": "alpha",
"cfdef:valid_other_characters": "alpha",
"kerb:encryption_algorithms": [
"des",
"des3",
"desd",
"aes128",
"aes256",
"aes128sha2",
"aes256sha2",
],
"kerb:validate_addresses": None,
"session:locked": True,
"session:security_checking_level": "conv",
"session:session_key": "e3c5e2e3d2c5e800",
"session:session_key_interval": 5,
"sigver:fail_program_load_condition": "never",
"sigver:log_signature_verification_events": "success",
"sigver:signature_required": None,
"stdata:group": None,
"stdata:privileged": None,
"stdata:trace": None,
"stdata:trusted": "yes",
"stdata:user": None,
}

# Delete Resource
TEST_DELETE_RESOURCE_RESULT_SUCCESS_XML = get_sample(
Expand Down
29 changes: 16 additions & 13 deletions tests/resource/test_resource_result_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,16 +404,19 @@ def test_resource_admin_delete_can_check_for_unnecessary_refresh_xml(
# Build template general resource profile
# ============================================================================

# def test_group_admin_can_build_template_group_base_omvs_tso_revoke_resume_success_xml(
# self,
# call_racf_mock: Mock,
# ):
# call_racf_mock.return_value = (
# TestGroupConstants.TEST_EXTRACT_GROUP_RESULT_BASE_OMVS_SUCCESS_XML
# )
# self.assertEqual(
# self.group_admin.extract(
# "testgrp0", segments=["omvs"], group_template=True
# ),
# TestGroupConstants.TEST_EXTRACT_GROUP_BASE_OMVS_TEMPLATE_TRAITS,
# )
def test_resource_admin_can_build_template_resource_base_xml(
self,
call_racf_mock: Mock,
):
call_racf_mock.return_value = (
TestResourceConstants.TEST_EXTRACT_RESOURCE_RESULT_BASE_AND_SUBFUNCTIONS_SUCCESS_XML
)
self.assertEqual(
self.resource_admin.extract(
"TESTING",
"ELIJTEST",
segments=["cfdef", "cdtinfo", "kerb", "session", "sigver", "stdata"],
resource_template=True,
),
TestResourceConstants.TEST_EXTRACT_RESOURCE_BASE_AND_SUBFUNCTIONS_TEMPLATE_TRAITS,
)

0 comments on commit 6aeb064

Please sign in to comment.