diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/README.md b/security/security-design/shared-assets/oci-security-health-check-standard/README.md index b72639240..332ab42e8 100644 --- a/security/security-design/shared-assets/oci-security-health-check-standard/README.md +++ b/security/security-design/shared-assets/oci-security-health-check-standard/README.md @@ -2,7 +2,7 @@ Owner: Olaf Heimburger -Version: 250722 (cis_report.py version 3.0.1) for CIS OCI Foundation Benchmark 3.0.0 +Version: 251104 (cis_report.py version 3.1.0) for CIS OCI Foundation Benchmark 3.0.0 # Introduction ![Flyer](./files/resources/OCI_Security_Health_Check_Standard.png) @@ -57,22 +57,22 @@ See the *OCI Security Health Check - Standard Edition* in action and watch the [ Before running the *OCI Security Health Check - Standard Edition* you should download and verify it. - - Download the latest distribution [oci-security-health-check-standard-250722.zip](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip). + - Download the latest distribution [oci-security-health-check-standard-251104.zip](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip). - Download the respective checksum file: - - [oci-security-health-check-standard-250722.sha512](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512). - - [oci-security-health-check-standard-250722.sha512256](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512256). + - [oci-security-health-check-standard-251104.sha512](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512). + - [oci-security-health-check-standard-251104.sha512256](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512256). - Verify the integrity of the distribution. Both files must be in the same directory (for example, in your downloads directory). On MacOS: ``` cd - shasum -a 512256 -c oci-security-health-check-standard-250722.sha512256 + shasum -a 512256 -c oci-security-health-check-standard-251104.sha512256 ``` On Linux (including Cloud Shell): ``` cd - sha512sum -c oci-security-health-check-standard-250722.sha512 + sha512sum -c oci-security-health-check-standard-251104.sha512 ``` **Reject the downloaded file if the check fails!** @@ -85,10 +85,10 @@ In OCI Cloud Shell you can do a short cut without downloading the files mentione 2. Open Cloud Shell 3. Run these commands in your Cloud Shell: ``` - wget -q https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip - wget -q https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512 - sha512sum -c oci-security-health-check-standard-250722.sha512 - unzip -q oci-security-health-check-standard-250722.zip + wget -q https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip + wget -q https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512 + sha512sum -c oci-security-health-check-standard-251104.sha512 + unzip -q oci-security-health-check-standard-251104.zip ``` ## Prepare the OCI Tenancy diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/README.md b/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/README.md index 0c1bfb930..dea8b8f3d 100644 --- a/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/README.md +++ b/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/README.md @@ -2,7 +2,7 @@ Owner: Olaf Heimburger -Version: 250722 (cis_report.py version 3.0.1) for CIS OCI Foundation Benchmark 3.0.0 +Version: 251104 (cis_report.py version 3.1.0) for CIS OCI Foundation Benchmark 3.0.0 ## When to use this asset? @@ -47,22 +47,22 @@ Tested on **OCI Cloud Shell** with **Public network**, **Oracle Linux**, **MacOS Before running the *OCI Security Health Check - Standard Edition* you should download and verify it. - - Download the latest distribution [oci-security-health-check-standard-250722.zip](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip). + - Download the latest distribution [oci-security-health-check-standard-251104.zip](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip). - Download the respective checksum file: - - [oci-security-health-check-standard-250722.sha512](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512). - - [oci-security-health-check-standard-250722.sha512256](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512256). + - [oci-security-health-check-standard-251104.sha512](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512). + - [oci-security-health-check-standard-251104.sha512256](https://github.com/oracle-devrel/technology-engineering/raw/main/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512256). - Verify the integrity of the distribution. Both files must be in the same directory (for example, in your downloads directory). On MacOS: ``` cd - shasum -a 512256 -c oci-security-health-check-standard-250722.sha512256 + shasum -a 512256 -c oci-security-health-check-standard-251104.sha512256 ``` On Linux (including Cloud Shell): ``` cd - sha512sum -c oci-security-health-check-standard-250722.sha512 + sha512sum -c oci-security-health-check-standard-251104.sha512 ``` **Reject the downloaded file when the check fails!** @@ -225,7 +225,7 @@ allow group 'Default'/'grp-auditors' to inspect vcns in compartment = 14: @@ -4069,6 +4196,7 @@ def __report_cis_analyze_tenancy_data(self): self.cis_foundations_benchmark_3_0['1.5']['Total'] = self.__identity_domains self.cis_foundations_benchmark_3_0['1.6']['Total'] = self.__identity_domains + def __cis_check_users(self): # 1.7 Check - Local Users w/o MFA for user in self.__users: if not(user['is_federated']) and user['can_use_console_password'] and not (user['is_mfa_activated']) and user['lifecycle_state']: @@ -4089,6 +4217,7 @@ def __report_cis_analyze_tenancy_data(self): "user_name": user['name'], "user_id": user['id'], "key_id": key['id'], + "domain_deeplink": user['domain_deeplink'], 'fingerprint': key['fingerprint'], # 'inactive_status': key['inactive_status'], # 'lifecycle_state': key['lifecycle_state'], @@ -4112,6 +4241,7 @@ def __report_cis_analyze_tenancy_data(self): "user_id": user['id'], "id": key['id'], 'display_name': key['display_name'], + "domain_deeplink": user['domain_deeplink'], # 'inactive_status': key['inactive_status'], # 'lifecycle_state': key['lifecycle_state'], 'time_created': key['time_created'], @@ -4134,10 +4264,11 @@ def __report_cis_analyze_tenancy_data(self): "user_name": user['name'], "user_id": user['id'], "id": key['id'], + "domain_deeplink": user['domain_deeplink'], "description": key['description'], # "inactive_status": key['inactive_status'], # "lifecycle_state": key['lifecycle_state'], - "time_created": key['time_created'], + "time_created": key['time_created'] # "time_expires": key['time_expires'], # "token": key['token'] } @@ -4148,7 +4279,7 @@ def __report_cis_analyze_tenancy_data(self): # CIS Total 1.10 Adding - Keys to CIS Total self.cis_foundations_benchmark_3_0['1.10']['Total'].append( key) - # CIS 1.11 Check - Old DB Password + # CIS 1.11 Check - Old DB Password #__iso_time_format1 = "%Y-%m-%dT%H:%M:%S.%fZ" for user in self.__users: if user['database_passwords']: @@ -4160,8 +4291,9 @@ def __report_cis_analyze_tenancy_data(self): "user_name": user['name'], "user_id": user['id'], "id": key['ocid'], + "domain_deeplink": user['domain_deeplink'], "description": key['description'], - "time_created": key['time_created'], + "time_created": key['time_created'] # "expires-on": key['expires_on'] } @@ -4186,7 +4318,7 @@ def __report_cis_analyze_tenancy_data(self): # CIS 1.13 Check - This check is complete uses email verification # Iterating through all users to see if they have API Keys and if they are active users for user in self.__users: - if user['external_identifier'] is None and user['lifecycle_state'] and not (user['email_verified']): + if not (user['is_federated'] and user['lifecycle_state']) and user['external_identifier'] is None and user['lifecycle_state'] and not user['email_verified']: self.cis_foundations_benchmark_3_0['1.13']['Status'] = False self.cis_foundations_benchmark_3_0['1.13']['Findings'].append( user) @@ -4194,54 +4326,6 @@ def __report_cis_analyze_tenancy_data(self): # CIS Total 1.13 Adding - All IAM Users for to CIS Total self.cis_foundations_benchmark_3_0['1.13']['Total'] = self.__users - # CIS 1.14 Check - Ensure Dynamic Groups are used for OCI instances, OCI Cloud Databases and OCI Function to access OCI resources - # Iterating through all dynamic groups ensure there are some for fnfunc, instance or autonomous. Using reverse logic so starts as a false - for dynamic_group in self.__dynamic_groups: - if any(oci_resource.upper() in str(dynamic_group['matching_rule'].upper()) for oci_resource in self.cis_iam_checks['1.14']['resources']): - self.cis_foundations_benchmark_3_0['1.14']['Status'] = True - else: - self.cis_foundations_benchmark_3_0['1.14']['Findings'].append( - dynamic_group) - # Clearing finding - if self.cis_foundations_benchmark_3_0['1.14']['Status']: - self.cis_foundations_benchmark_3_0['1.14']['Findings'] = [] - - # CIS Total 1.14 Adding - All Dynamic Groups for to CIS Total - self.cis_foundations_benchmark_3_0['1.14']['Total'] = self.__dynamic_groups - - # CIS 1.15 Check - Ensure storage service-level admins cannot delete resources they manage. - # Iterating through all policies - for policy in self.__policies: - if policy['name'].lower() not in ['tenant admin policy', 'psm-root-policy']: - for statement in policy['statements']: - for resource in self.cis_iam_checks['1.15']: - if "allow group".upper() in statement.upper() and "to manage ".upper() in statement.upper() and resource.upper() in statement.upper(): - split_statement = statement.split("where") - if len(split_statement) == 2: - clean_where_clause = split_statement[1].upper().replace(" ", "").replace("'", "") - if all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15'][resource]) and \ - not(all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15-storage-admin'][resource])): - debug("__report_cis_analyze_tenancy_data CIS 1.15 no permissions to delete storage: " + str(policy['name'])) - pass - # Checking if this is the Storage admin with allowed - elif all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15-storage-admin'][resource]) and \ - not(all(permission.upper() in clean_where_clause for permission in self.cis_iam_checks['1.15'][resource])): - debug("__report_cis_analyze_tenancy_data CIS 1.15 storage admin policy is: " + str(policy['name'])) - pass - else: - self.cis_foundations_benchmark_3_0['1.15']['Findings'].append(policy) - debug("__report_cis_analyze_tenancy_data CIS 1.15 else policy is\n: " + str(policy['name'])) - - else: - self.cis_foundations_benchmark_3_0['1.15']['Findings'].append(policy) - - if self.cis_foundations_benchmark_3_0['1.15']['Findings']: - self.cis_foundations_benchmark_3_0['1.15']['Status'] = False - else: - self.cis_foundations_benchmark_3_0['1.15']['Status'] = True - - # CIS Total 1.15 Adding - All IAM Policies for to CIS Total - self.cis_foundations_benchmark_3_0['1.15']['Total'] = self.__policies # CIS 1.16 Check - Users with API Keys over 45 days @@ -4249,14 +4333,14 @@ def __report_cis_analyze_tenancy_data(self): login_over_45_days = None api_key_over_45_days = None - if user['lifecycle_state']: # and not(user['is_federated']) and user['can_use_console_password']: - debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Login Over 45 days is: {login_over_45_days}') + if user['lifecycle_state'] and user['can_use_console_password'] and not(user['is_federated']): #and user['can_use_console_password']: if user['last_successful_login_date']: last_successful_login_date = user['last_successful_login_date'].split(".")[0] if self.local_user_time_max_datetime > datetime.datetime.strptime(last_successful_login_date, self.__iso_time_format): login_over_45_days = True debug(f"__report_cis_analyze_tenancy_data CIS 1.16 Last login is {user['last_successful_login_date']} and max login is {self.local_user_time_max_datetime}") else: + debug(f"__report_cis_analyze_tenancy_data CIS 1.16 Last login is {user['last_successful_login_date']} and max login is {self.local_user_time_max_datetime}") login_over_45_days = False else: debug("__report_cis_analyze_tenancy_data CIS 1.16 No Last login") @@ -4266,20 +4350,16 @@ def __report_cis_analyze_tenancy_data(self): debug("__report_cis_analyze_tenancy_data CIS 1.16 INACTIVE USE") login_over_45_days = False - if user['api_keys']: - debug("__report_cis_analyze_tenancy_data CIS 1.16 API Key Check") - for api_key in user['api_keys']: - if api_key['apikey_used_in_45_days']: - api_key_over_45_days = True - else: - debug("__report_cis_analyze_tenancy_data CIS 1.16 API Key used in under 45 days") - api_key_over_45_days = True - # else: - # api_key_over_45_days = False - - debug(f"__report_cis_analyze_tenancy_data CIS 1.16 User: {user['id']}") - debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Over Login Over 45: {login_over_45_days}') - debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Over API Key Over 45: {api_key_over_45_days}') + if user['api_keys'] and user['lifecycle_state']: + print("__report_cis_analyze_tenancy_data CIS 1.16 API Key Check") + api_key_over_45_days = not(all(key.get('apikey_used_in_45_days', False) for key in user['api_keys'])) + else: + api_key_over_45_days = False + + debug(f"__report_cis_analyze_tenancy_data CIS 1.16 User: {user['name']}") + debug(f"__report_cis_analyze_tenancy_data CIS 1.16 Domain: {user['domain_deeplink']}") + debug(f'__report_cis_analyze_tenancy_data CIS 1.16 Login Over 45: {login_over_45_days}') + debug(f'__report_cis_analyze_tenancy_data CIS 1.16 API Key Over 45: {api_key_over_45_days}') if login_over_45_days or api_key_over_45_days: finding = user.copy() finding['login_over_45_days'] = login_over_45_days @@ -4291,7 +4371,7 @@ def __report_cis_analyze_tenancy_data(self): else: self.cis_foundations_benchmark_3_0['1.16']['Status'] = True - # CIS Total 1.15 Adding - All IAM Policies for to CIS Total + # CIS Total 1.16 Adding - All IAM Policies for to CIS Total self.cis_foundations_benchmark_3_0['1.16']['Total'] = self.__users @@ -4307,8 +4387,25 @@ def __report_cis_analyze_tenancy_data(self): self.cis_foundations_benchmark_3_0['1.17']['Status'] = True # CIS Total 1.17 Adding - All IAM Policies for to CIS Total self.cis_foundations_benchmark_3_0['1.17']['Total'] = self.__users + + def __cis_check_dynamic_groups(self): + # CIS 1.14 Check - Ensure Dynamic Groups are used for OCI instances, OCI Cloud Databases and OCI Function to access OCI resources + # Iterating through all dynamic groups ensure there are some for fnfunc, instance or autonomous. Using reverse logic so starts as a false + for dynamic_group in self.__dynamic_groups: + if any(oci_resource.upper() in str(dynamic_group['matching_rule'].upper()) for oci_resource in self.cis_iam_checks['1.14']['resources']): + self.cis_foundations_benchmark_3_0['1.14']['Status'] = True + else: + self.cis_foundations_benchmark_3_0['1.14']['Findings'].append( + dynamic_group) + # Clearing finding + if self.cis_foundations_benchmark_3_0['1.14']['Status']: + self.cis_foundations_benchmark_3_0['1.14']['Findings'] = [] + + # CIS Total 1.14 Adding - All Dynamic Groups for to CIS Total + self.cis_foundations_benchmark_3_0['1.14']['Total'] = self.__dynamic_groups - # CIS 2.1, 2.2, & 2.5 Check - Security List Ingress from 0.0.0.0/0 on ports 22, 3389 + def __cis_check_network_security(self): + # CIS 2.1, 2.2 Check - Security List Ingress from 0.0.0.0/0 on ports 22, 3389 for sl in self.__network_security_lists: for irule in sl['ingress_security_rules']: if irule['source'] == "0.0.0.0/0" and irule['protocol'] == '6': @@ -4392,7 +4489,7 @@ def __report_cis_analyze_tenancy_data(self): self.cis_foundations_benchmark_3_0['2.4']['Findings'].append(nsg) break - # CIS Total 2.2 & 2.4 Adding - All NSGs Instances to CIS Total + # CIS Total 2.3 & 2.4 Adding - All NSGs Instances to CIS Total self.cis_foundations_benchmark_3_0['2.3']['Total'] = self.__network_security_groups self.cis_foundations_benchmark_3_0['2.4']['Total'] = self.__network_security_groups @@ -4434,40 +4531,36 @@ def __report_cis_analyze_tenancy_data(self): if autonomous_database['lifecycle_state'] not in [ oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_TERMINATED, oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_TERMINATING, oci.database.models.AutonomousDatabaseSummary.LIFECYCLE_STATE_UNAVAILABLE ]: if not (autonomous_database['whitelisted_ips']) and not (autonomous_database['subnet_id']): self.cis_foundations_benchmark_3_0['2.8']['Status'] = False - self.cis_foundations_benchmark_3_0['2.8']['Findings'].append( - autonomous_database) + self.cis_foundations_benchmark_3_0['2.8']['Findings'].append(autonomous_database) elif autonomous_database['whitelisted_ips']: for value in autonomous_database['whitelisted_ips']: - if '0.0.0.0/0' in str(autonomous_database['whitelisted_ips']): + if '0.0.0.0/0' in str(value): self.cis_foundations_benchmark_3_0['2.8']['Status'] = False - self.cis_foundations_benchmark_3_0['2.8']['Findings'].append( - autonomous_database) + self.cis_foundations_benchmark_3_0['2.8']['Findings'].append(autonomous_database) # CIS Total 2.8 Adding - All ADBs to CIS Total self.cis_foundations_benchmark_3_0['2.8']['Total'] = self.__autonomous_databases - # From CIS 2.0 CIS 4.1 Check - Ensure Audit log retention == 365 - Only checking in home region - # if self.__audit_retention_period >= 365: - # self.cis_foundations_benchmark_3_0['4.1']['Status'] = True - + def __cis_check_compute_instances(self): for instance in self.__Instance: - # CIS Check 3.1 Metadata Service v2 Enabled - if instance['instance_options'] is None or not(instance['instance_options']['are_legacy_imds_endpoints_disabled']): - debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't disable IMDSv1") - self.cis_foundations_benchmark_3_0['3.1']['Status'] = False - self.cis_foundations_benchmark_3_0['3.1']['Findings'].append(instance) - - # CIS Check 3.2 Secure Boot enabled - if instance['platform_config'] is None or not(instance['platform_config']['is_secure_boot_enabled']): - debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable secure boot") - self.cis_foundations_benchmark_3_0['3.2']['Status'] = False - self.cis_foundations_benchmark_3_0['3.2']['Findings'].append(instance) - - # CIS Check 3.3 Encryption in Transit enabled - if instance['launch_options'] is None or not(instance['launch_options']['is_pv_encryption_in_transit_enabled']): - debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable encryption in transit") - self.cis_foundations_benchmark_3_0['3.3']['Status'] = False - self.cis_foundations_benchmark_3_0['3.3']['Findings'].append(instance) + if instance['lifecycle_state'] not in ["TERMINATED","TERMINATING"]: + # CIS Check 3.1 Metadata Service v2 Enabled + if instance['instance_options'] is None or not(instance['instance_options']['are_legacy_imds_endpoints_disabled']): + debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't disable IMDSv1") + self.cis_foundations_benchmark_3_0['3.1']['Status'] = False + self.cis_foundations_benchmark_3_0['3.1']['Findings'].append(instance) + + # CIS Check 3.2 Secure Boot enabled + if instance['platform_config'] is None or not(instance['platform_config']['is_secure_boot_enabled']): + debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable secure boot") + self.cis_foundations_benchmark_3_0['3.2']['Status'] = False + self.cis_foundations_benchmark_3_0['3.2']['Findings'].append(instance) + + # CIS Check 3.3 Encryption in Transit enabled + if instance['launch_options'] is None or not(instance['launch_options']['is_pv_encryption_in_transit_enabled']): + debug(f"__report_cis_analyze_tenancy_data {instance['display_name']} doesn't enable encryption in transit") + self.cis_foundations_benchmark_3_0['3.3']['Status'] = False + self.cis_foundations_benchmark_3_0['3.3']['Findings'].append(instance) # CIS Total 3.1 Adding - All Instances to CIS Total self.cis_foundations_benchmark_3_0['3.1']['Total'] = self.__Instance @@ -4476,6 +4569,7 @@ def __report_cis_analyze_tenancy_data(self): # CIS Total 3.3 Adding - All Instances to CIS Total self.cis_foundations_benchmark_3_0['3.3']['Total'] = self.__Instance + def __cis_check_tagging_and_monitoring(self): # CIS Check 4.1 - Check for Default Tags in Root Compartment # Iterate through tags looking for ${iam.principal.name} for tag in self.__tag_defaults: @@ -4657,6 +4751,7 @@ def __report_cis_analyze_tenancy_data(self): # CIS Check 4.17 Total - Adding All Buckets to total self.cis_foundations_benchmark_3_0['4.17']['Total'] = self.__buckets + def __cis_check_storage(self): # CIS Section 5.1 Bucket Checks # Generating list of buckets names for bucket in self.__buckets: @@ -4704,7 +4799,7 @@ def __report_cis_analyze_tenancy_data(self): boot_volume) self.cis_foundations_benchmark_3_0['5.2.2']['Status'] = False - # CIS Check 4.2.2 Total - Adding All Block Volumes to total + # CIS Check 5.2.2 Total - Adding All Block Volumes to total self.cis_foundations_benchmark_3_0['5.2.2']['Total'] = self.__boot_volumes # CIS Section 5.3.1 FSS Checks @@ -4719,6 +4814,7 @@ def __report_cis_analyze_tenancy_data(self): # CIS Check 4.3.1 Total - Adding All Block Volumes to total self.cis_foundations_benchmark_3_0['5.3.1']['Total'] = self.__file_storage_system + def __cis_check_assets(self): # CIS Section 6 Checks # Checking if more than one compartment because of the ManagedPaaS Compartment if len(self.__compartments) < 2: @@ -4774,21 +4870,41 @@ def __obp_init_regional_checks(self): "drgs": [], "findings": [], "status": False - }, + } } + ########################################################################## - # OBP Budgets Check + # OBP Budgets Check ########################################################################## def __obp_check_budget(self): if len(self.__budgets) > 0: for budget in self.__budgets: - if budget['alert_rule_count'] > 0 and budget['target_compartment_id'] == self.__tenancy.id: - self.obp_foundations_checks['Cost_Tracking_Budgets']['Status'] = True - self.obp_foundations_checks['Cost_Tracking_Budgets']['OBP'].append(budget) + if ( + budget["alert_rule_count"] > 0 + and budget["target_compartment_id"] == self.__tenancy.id + ): + for alert in budget["alerts"]: + if alert.type == "FORECAST": + self.obp_foundations_checks["Cost_Tracking_Budgets"]["Status"] = True + self.obp_foundations_checks["Cost_Tracking_Budgets"]["OBP"].append(budget) + break + else: + self.obp_foundations_checks["Cost_Tracking_Budgets"]["Findings"].append(budget) else: - self.obp_foundations_checks['Cost_Tracking_Budgets']['Findings'].append(budget) + self.obp_foundations_checks["Cost_Tracking_Budgets"]["Findings"].append(budget) + + ####################################### + # OBP Quotas Checks + ####################################### + def __obp_check_quotas(self): + if self.__quotas: + self.obp_foundations_checks['Quotas']['Status'] = True + self.obp_foundations_checks['Quotas']['OBP'] = self.__quotas + ####################################### + # OBP Audit Logs to SIEM check + ####################################### def __obp_check_audit_log_compartments(self): # Building a Hash Table of Parent Child Hierarchy for Audit dict_of_compartments = {} @@ -4922,7 +5038,10 @@ def __obp_check_audit_log_compartments(self): exists_already = list(filter(lambda source: source['id'] == record['id'] and source['region'] == record['region'], self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['OBP'])) if not exists_already: self.obp_foundations_checks['SIEM_Audit_Log_All_Comps']['OBP'].append(record) - + + ####################################### + # OBP Cloud Guard Check + ####################################### def __obp_check_cloud_guard(self): ####################################### # Cloud Guard Checks @@ -5270,6 +5389,58 @@ def __obp_check_bucket_logs(self): self.obp_foundations_checks['SIEM_Read_Bucket_Logs']['Status'] = True + ####################################### + # OBP Service Limit Check + ####################################### + def __obp_check_close_service_limits(self): + if True: + for limit in self.__service_limits: + # If the limit is greater than 80% we should note it for an OBP + if limit['service_limit_availability'] and limit['service_limit_availability'] >= 80.0: + self.obp_foundations_checks['Service_Limits']['Findings'].append(limit) + else: + self.obp_foundations_checks['Service_Limits']['OBP'].append(limit) + + if self.obp_foundations_checks['Service_Limits']['Findings']: + self.obp_foundations_checks['Service_Limits']['Status'] = False + elif self.obp_foundations_checks['Service_Limits']['OBP']: + self.obp_foundations_checks['Service_Limits']['Status'] = True + ####################################### + # OBP ADB Checks + ####################################### + def __obp_check_adbs(self): + for adb in self.__autonomous_databases: + if not adb['is_mtls_connection_required']: + self.obp_foundations_checks['ADB_MTLS']['Findings'].append(adb) + else: + self.obp_foundations_checks['ADB_MTLS']['OBP'].append(adb) + if not adb['encryption_key']['provider'] == 'ORACLE_MANAGED': + self.obp_foundations_checks['ADB_CMK']['Findings'].append(adb) + else: + self.obp_foundations_checks['ADB_CMK']['OBP'].append(adb) + + if not adb['private_endpoint_ip']: + self.obp_foundations_checks['ADB_Private_IP']['Findings'].append(adb) + else: + self.obp_foundations_checks['ADB_Private_IP']['OBP'].append(adb) + + if not adb['data_safe_status'] == "REGISTERED": + self.obp_foundations_checks['ADB_DataSafe']['Findings'].append(adb) + else: + self.obp_foundations_checks['ADB_DataSafe']['OBP'].append(adb) + + if not adb['customer_contacts']: + self.obp_foundations_checks['ADB_Contacts']['Findings'].append(adb) + else: + self.obp_foundations_checks['ADB_Contacts']['OBP'].append(adb) + + for key in self.obp_foundations_checks.keys(): + if key.startswith("ADB_"): + if self.obp_foundations_checks[key]['Findings']: + self.obp_foundations_checks[key]['Status'] = False + else: + self.obp_foundations_checks[key]['Status'] = True + ########################################################################## # Analyzes Tenancy Data for Oracle Best Practices Report ########################################################################## @@ -5282,7 +5453,9 @@ def __obp_analyze_tenancy_data(self): self.__obp_check_certificates() self.__obp_check_bucket_logs() self.__obp_check_subnet_logs() - + self.__obp_check_close_service_limits() + self.__obp_check_adbs() + self.__obp_check_quotas() ########################################################################## # Orchestrates data collection and CIS report generation @@ -5319,8 +5492,8 @@ def __report_generate_cis_report(self, level): "Total": (str(len(recommendation['Total'])) if len(recommendation['Total']) > 0 else " "), "Compliance Percentage Per Recommendation": compliance_percentage, "Title": recommendation['Title'], - "CIS v8": recommendation['CISv8'], - "CCCS Guard Rail": recommendation['CCCS Guard Rail'], + self.__primary_framework_name : recommendation[self.__primary_framework_name], + self.__other_framework_name : recommendation[self.__other_framework_name], "Filename": report_filename if len(recommendation['Findings']) > 0 else " ", "Remediation": self.cis_report_data[key]['Remediation'] } @@ -5356,7 +5529,7 @@ def __report_generate_cis_report(self, level): summary_file_name = self.__print_to_json_file("cis", "summary_report", summary_report) summary_files.append(summary_file_name) - summary_file_name = self.__report_generate_html_summary_report("cis", "html_summary_report", summary_report) + summary_file_name = self.__report_generate_html_summary_report("cis", "summary_report", summary_report) summary_files.append(summary_file_name) if OUTPUT_DIAGRAMS: @@ -5373,7 +5546,7 @@ def __report_generate_cis_report(self, level): for key, recommendation in self.cis_foundations_benchmark_3_0.items(): if recommendation['Level'] <= level: - report_file_name = self.__print_to_csv_file("cis", recommendation['section'] + "_" + recommendation['recommendation_#'], recommendation['Findings']) + report_file_name = self.__print_to_csv_file("cis", f"{recommendation['section']}_{recommendation['recommendation_#']}", recommendation['Findings']) if report_file_name and self.__output_bucket: self.__os_copy_report_to_object_storage( self.__output_bucket, report_file_name) @@ -5381,8 +5554,10 @@ def __report_generate_cis_report(self, level): ########################################################################## # Generate summary diagrams ########################################################################## - diagram_colors = ['#4C825C','#C74634'] + diagram_colors = ['#4C825C', '#C74634'] diagram_values = ['Compliant', 'Non-compliant'] + diagram_colors_na = ['#4C825C', '#C74634', '#E0DEDE'] + diagram_values_na = ['Compliant', 'Non-compliant', 'Not applicable'] diagram_sections = ( 'Identity and Access Management', 'Networking', @@ -5397,17 +5572,22 @@ def __report_generate_cis_report(self, level): ########################################################################## # __cis_compliance ########################################################################## - def __cis_compliance(self, filename, title, values=None): + def __cis_compliance(self, filename, title, values=None, has_na_values=False): plt.close('all') - plt.figure(figsize=(6,5)) - wegdes, labels, pcttexts = plt.pie(values, labels=self.diagram_values, colors=self.diagram_colors, autopct='%.0f%%', wedgeprops={'linewidth': 3.0, 'edgecolor': 'white'}, startangle=90, counterclock=False, radius=1.1) + plt.figure(figsize=(6, 5)) + labels = self.diagram_values + colors = self.diagram_colors + if has_na_values: + labels = self.diagram_values_na + colors = self.diagram_colors_na + wegdes, labels, pcttexts = plt.pie(values, labels=labels, colors=colors, autopct='%.0f%%', wedgeprops={'linewidth': 3.0, 'edgecolor': 'white'}, startangle=90, counterclock=False, radius=1.1) for t in labels: t.set_fontweight(self.diagram_fontweight) for p in pcttexts: p.set_fontweight(self.diagram_fontweight) p.set_color(self.diagram_fontcolor_reverse) plt.title(title, fontweight=self.diagram_fontweight, pad=30.0) - plt.savefig(filename) + plt.savefig(filename, transparent=True) ########################################################################## # __cis_compliance_by_area @@ -5415,7 +5595,7 @@ def __cis_compliance(self, filename, title, values=None): def __cis_compliance_by_area(self, filename, title, section_values=None): plt.close('all') height = 0.4 - fig, ax = plt.subplots(figsize=(10,5), layout='compressed') + fig, ax = plt.subplots(figsize=(10, 5), layout='compressed') y = np.arange(len(self.diagram_sections)) p = ax.barh(y - height/2, section_values[self.diagram_values[0]], height, color=self.diagram_colors[0]) ax.bar_label(p, padding=-16, color=self.diagram_fontcolor_reverse, fontweight=self.diagram_fontweight) @@ -5427,7 +5607,7 @@ def __cis_compliance_by_area(self, filename, title, section_values=None): ax.set_yticklabels(self.diagram_sections, fontweight=self.diagram_fontweight) ax.invert_yaxis() plt.tick_params(left=False, right=False, labelbottom=False, bottom=False) - plt.savefig(filename) + plt.savefig(filename, transparent=True) ########################################################################## # __generate_compliance_diagram @@ -5435,13 +5615,16 @@ def __cis_compliance_by_area(self, filename, title, section_values=None): def __generate_compliance_diagram(self, header, file_subject, data): compliant = 0 non_compliant = 0 + not_applicable = 0 for finding in data: if finding['Compliant'] == 'Yes': compliant += 1 + elif finding['Compliant'] == 'N/A': + not_applicable += 1 else: non_compliant += 1 cis_compliance_file = self.__get_output_file_path(header, file_subject, '.png') - self.__cis_compliance(cis_compliance_file, 'CIS Recommendation Compliance', [compliant, non_compliant]) + self.__cis_compliance(cis_compliance_file, 'CIS Recommendation Compliance', [compliant, non_compliant, not_applicable] if not_applicable > 0 else [compliant, non_compliant], has_na_values=True if not_applicable > 0 else False) return cis_compliance_file ########################################################################## @@ -5453,10 +5636,13 @@ def __generate_compliance_by_area_diagram(self, header, file_subject, data): for section in self.diagram_sections: compliant = 0 non_compliant = 0 + not_applicable = 0 for finding in data: if section in finding['Section']: if finding['Compliant'] == 'Yes': compliant += 1 + elif finding['Compliant'] == 'N/A': + not_applicable += 1 else: non_compliant += 1 compliants.append(compliant) @@ -5537,12 +5723,18 @@ def __report_generate_html_summary_report(self, header, file_subject, data): .u30brand{height:50px;display:flex;flex-direction:column;justify-content:center;align-items:flex-start;max-width:1344px;padding:0 48px;margin:0 auto} .u30brandw1{display:flex;flex-direction:row;color:#fff;text-decoration:none;align-items:center} @media (max-width:1024px){.u30brand{padding:0 24px}} #u30skip2,#u30skip2content{transform:translateY(-100%);position:fixed} .rtl #u30{direction:rtl} #td_override { background: #fff; border-bottom: 1px solid rgba(122,115,110,0.2) !important } -
""") +
+
""") html_file.write(f'

{html_title.replace("-", "–")}

') + html_file.write(""" +
+
+
+ """) html_file.write(f'

Tenancy Name: {self.__tenancy.name}

') # Get the extract date r = result[0] - extract_date = r['extract_date'].replace('T',' ') + extract_date = r['extract_date'].replace('T', ' ') html_file.write(f'
Extract Date: {extract_date} UTC
') html_file.write('
') if OUTPUT_DIAGRAMS: @@ -5581,7 +5773,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data): column_width = '63%' html_file.write(f'{th}') html_file.write('') - # Creating HTML Table of the summary report + # Creating the compliant HTML Table of the summary report html_appendix = [] for row in result: compliant = row['Compliant'] @@ -5609,13 +5801,14 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write('Remediation') html_file.write(f'{str(row["Remediation"])}') html_file.write('Level') - html_file.write('CIS v8') - html_file.write('CCCS Guard Rail') + html_file.write(f'{self.__primary_framework_name}') + html_file.write(f'{self.__other_framework_name}') html_file.write('File') html_file.write(f'{str(row["Level"])}') - cis_v8 = str(row["CIS v8"]).replace("[","").replace("]","").replace("'","") - html_file.write(f'{cis_v8}') - html_file.write(f'{str(row["CCCS Guard Rail"])}') + primary_framework = str(row[self.__primary_framework_name]).replace("[", "").replace("]", "").replace("'", "") + other_framework = str(row[self.__other_framework_name]).replace("[", "").replace("]", "").replace("'", "") + html_file.write(f'{primary_framework}') + html_file.write(f'{other_framework}') v = str(row['Filename']) if v == ' ': html_file.write(' ') @@ -5648,11 +5841,11 @@ def __report_generate_html_summary_report(self, header, file_subject, data): column_width = '63%' html_file.write(f'{th}') html_file.write('') - # Creating HTML Table of the summary report + # Creating the non-compliant HTML Table of the summary report html_appendix = [] for row in result: compliant = row['Compliant'] - if compliant == 'Yes': + if compliant != 'No': continue html_appendix.append(row['Recommendation #']) text_color = 'red' @@ -5678,13 +5871,14 @@ def __report_generate_html_summary_report(self, header, file_subject, data): html_file.write('Remediation') html_file.write(f'{str(row["Remediation"])}') html_file.write('Level') - html_file.write('CIS v8') - html_file.write('CCCS Guard Rail') + html_file.write(f'{self.__primary_framework_name}') + html_file.write(f'{self.__other_framework_name}') html_file.write('File') html_file.write(f'{str(row["Level"])}') - cis_v8 = str(row["CIS v8"]).replace("[", "").replace("]", "").replace("'", "") - html_file.write(f'{cis_v8}') - html_file.write(f'{str(row["CCCS Guard Rail"])}') + primary_framework = str(row[self.__primary_framework_name]).replace("[", "").replace("]", "").replace("'", "") + other_framework = str(row[self.__other_framework_name]).replace("[", "").replace("]", "").replace("'", "") + html_file.write(f'{primary_framework}') + html_file.write(f'{other_framework}') v = str(row['Filename']) if v == ' ': html_file.write(' ') @@ -5734,7 +5928,7 @@ def __report_generate_html_summary_report(self, header, file_subject, data):
\n') - print("HTML: " + file_subject.ljust(22) + " --> " + file_path) + print(f"HTML: {file_subject.ljust(22)} --> {file_path}") # Used by Upload return file_path @@ -5755,10 +5949,11 @@ def __report_generate_obp_report(self): # Adding data to summary report for key, recommendation in self.obp_foundations_checks.items(): padding = str(key).ljust(25, " ") - print(padding + "\t\t" + str(recommendation['Status']) + "\t" + "\t" + str(len(recommendation['Findings'])) + "\t" + "\t" + str(len(recommendation['OBP']))) + compliant = ("Yes" if recommendation['Status'] is True else "No" if recommendation['Status'] is False else "N/A") + print(padding + "\t\t" + compliant + "\t" + "\t" + str(len(recommendation['Findings'])) + "\t" + "\t" + str(len(recommendation['OBP']))) record = { "Recommendation": str(key), - "Compliant": ('Yes' if recommendation['Status'] else 'No'), + "Compliant": compliant, "OBP": (str(len(recommendation['OBP'])) if len(recommendation['OBP']) > 0 else " "), "Findings": (str(len(recommendation['Findings'])) if len(recommendation['Findings']) > 0 else " "), "Documentation": recommendation['Documentation'] @@ -5824,7 +6019,8 @@ def __collect_tenancy_data(self): if self.__obp_checks: obp_home_region_functions = [ self.__budget_read_budgets, - self.__cloud_guard_read_cloud_guard_targets + self.__cloud_guard_read_cloud_guard_targets, + self.__quota_read, ] else: obp_home_region_functions = [] @@ -5886,8 +6082,8 @@ def __collect_tenancy_data(self): if self.__all_resources: all_resources = [ - self.__network_topology_dump, - self.__search_resources_all_resources_in_tenancy + self.__search_resources_all_resources_in_tenancy, + self.__service_limits_utilization ] else: all_resources = [] @@ -5941,6 +6137,7 @@ def __report_generate_raw_data_output(self): "keys_and_vaults": self.__kms_keys, "ons_subscriptions": self.__subscriptions, "budgets": self.__budgets, + "quotas" : self.__quotas, "service_connectors": list(self.__service_connectors.values()), "network_fastconnects": list(itertools.chain.from_iterable(self.__network_fastconnects.values())), "network_ipsec_connections": list(itertools.chain.from_iterable(self.__network_ipsec_connections.values())), @@ -5949,7 +6146,8 @@ def __report_generate_raw_data_output(self): "regions": self.__raw_regions, "network_drg_attachments": list(itertools.chain.from_iterable(self.__network_drg_attachments.values())), "instances": self.__Instance, - "certificates" : self.__raw_oci_certificates + "certificates" : self.__raw_oci_certificates, + "service_limits" : self.__service_limits } for key in raw_csv_files: rfn = self.__print_to_csv_file('raw_data', key, raw_csv_files[key]) @@ -5957,19 +6155,11 @@ def __report_generate_raw_data_output(self): raw_json_files = { "all_resources": self.__all_resources_json, - "oci_network_topologies": oci.util.to_dict(self.__network_topology_json) } for key in raw_json_files: rfn = self.__print_to_json_file('raw_data', key, raw_json_files[key]) list_report_file_names.append(rfn) - raw_pkl_files = { - "oci_network_topologies": self.__network_topology_json - } - for key in raw_pkl_files: - rfn = self.__print_to_pkl_file('raw_data', key, raw_json_files[key]) - list_report_file_names.append(rfn) - if self.__output_bucket: for raw_report in list_report_file_names: if raw_report: @@ -6054,6 +6244,8 @@ def __print_to_csv_file(self, header, file_subject, data): writer.writeheader() for row in result: + if 'rules' in row: + row['rules'] = str(row['rules']).replace('\n', '') writer.writerow(row) # print(row) @@ -6100,32 +6292,6 @@ def __print_to_json_file(self, header, file_subject, data): except Exception as e: raise Exception("Error in print_to_json_file: " + str(e.args)) - ########################################################################## - # Print to PKL - ########################################################################## - def __print_to_pkl_file(self, header, file_subject, data): - - try: - # if no data - if len(data) == 0: - return None - - # get the file name of the PKL - file_path = self.__get_output_file_path(header, file_subject, '.pkl') - - # Writing to json file - with open(file_path, 'wb') as pkl_file: - pickle.dump(data,pkl_file) - - - print("PKL: " + file_subject.ljust(22) + " --> " + file_path) - - # Used by Upload - return file_path - - - except Exception as e: - raise Exception("Error in __print_to_pkl_file: " + str(e.args)) ########################################################################## # Orchestrates Data collection and reports @@ -6173,8 +6339,8 @@ def get_obp_checks(self): # Create CSV Hyperlink ########################################################################## def __generate_csv_hyperlink(self, url, name): - if len(url) < 255: - return '=HYPERLINK("' + url + '","' + name + '")' + if len(url) < 2079: # Excel limit + return f'=HYPERLINK("{url}","{name}")' else: return url @@ -6384,7 +6550,7 @@ def execute_report(): config, signer = create_signer(cmd.file_location, cmd.config_profile, cmd.is_instance_principals, cmd.is_delegation_token, cmd.is_security_token) config['retry_strategy'] = oci.retry.DEFAULT_RETRY_STRATEGY report = CIS_Report(config, signer, cmd.proxy, cmd.output_bucket, cmd.report_directory, cmd.report_prefix, cmd.report_summary_json, cmd.print_to_screen, \ - cmd.regions, cmd.raw, cmd.obp, cmd.redact_output, oci_url=cmd.oci_url, debug=cmd.debug, all_resources=cmd.all_resources, disable_api_keys=cmd.disable_api_usage_check) + cmd.regions, cmd.raw, cmd.obp, cmd.redact_output, oci_url=cmd.oci_url, debug=cmd.debug, all_resources=cmd.all_resources, disable_api_keys=cmd.disable_api_usage_check) csv_report_directory = report.generate_reports(int(cmd.level)) if OUTPUT_TO_XLSX: @@ -6425,8 +6591,12 @@ def execute_report(): reader = csv.reader(f) for r, row in enumerate(reader): for c, col in enumerate(row): - # Skipping the deep link due to formating errors in xlsx - if "=HYPERLINK" not in col: + # Format URL only if the column starts with "=HYPERLINK" + if col.startswith("=HYPERLINK"): + url_info = re.findall(r'"(.*?)"', col) + if url_info and len(url_info[0]) < 2079: # Excel Link limit + worksheet.write_url(r, c, url_info[0], string=url_info[1]) + else: worksheet.write(r, c, col) worksheet.autofilter(0, 0, r - 1, c - 1) worksheet.autofit() diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/standard.sh b/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/standard.sh index a1f092241..b6d4ceec1 100755 --- a/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/standard.sh +++ b/security/security-design/shared-assets/oci-security-health-check-standard/files/oci-security-health-check-standard/standard.sh @@ -7,7 +7,7 @@ # # Author: Olaf Heimburger # -VERSION=250722 +VERSION=251104 graal_version=24.2.2 OS_TYPE=$(uname) diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/Example_Output.png b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/Example_Output.png index 7d58190f6..659ecb210 100644 Binary files a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/Example_Output.png and b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/Example_Output.png differ diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512 b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512 deleted file mode 100644 index 41dc40bce..000000000 --- a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512 +++ /dev/null @@ -1 +0,0 @@ -ede5f2a1f3889d4bf7a6503e272b4844f0dd9eb011045961d036f0c5b02a09f2fc0c0531d4560ec1b32f2a935cee8c94f6301695b813089103fbfc1682c4a96a oci-security-health-check-standard-250722.zip diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512256 b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512256 deleted file mode 100644 index 6724995f7..000000000 --- a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.sha512256 +++ /dev/null @@ -1 +0,0 @@ -d6477bf3727cecf96848bb0ffe0eb918f776433b029090fe08aab3aefae4f72d oci-security-health-check-standard-250722.zip diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip deleted file mode 100644 index ee7247030..000000000 Binary files a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-250722.zip and /dev/null differ diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512 b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512 new file mode 100644 index 000000000..e79a7f0da --- /dev/null +++ b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512 @@ -0,0 +1 @@ +3af7a1fa96792e1fd23ee12c57833fd7e602c7ad8785d41275c7b5839712b405e31d11ec3760660b8a8cf75331e7f3ca7376cd9779f70d9c6732bbf96701cd85 oci-security-health-check-standard-251104.zip \ No newline at end of file diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512256 b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512256 new file mode 100644 index 000000000..a183f6288 --- /dev/null +++ b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.sha512256 @@ -0,0 +1 @@ +fd68eb70092eb37c82539aac426dfa601dc15bab337ae94225dc8b0afb465a1b oci-security-health-check-standard-251104.zip \ No newline at end of file diff --git a/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip new file mode 100644 index 000000000..f92c250ef Binary files /dev/null and b/security/security-design/shared-assets/oci-security-health-check-standard/files/resources/oci-security-health-check-standard-251104.zip differ