From e610c2514d3a0eef9463875c138bbc7c8cf25d6d Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:41:04 +0200 Subject: [PATCH] feat(iam): improve disable credentials checks (#2909) --- ...ndational_security_best_practices_aws.json | 3 +- prowler/compliance/aws/cis_1.4_aws.json | 3 +- prowler/compliance/aws/cis_1.5_aws.json | 3 +- prowler/compliance/aws/cis_2.0_aws.json | 3 +- prowler/compliance/aws/cisa_aws.json | 3 +- prowler/compliance/aws/ens_rd2022_aws.json | 10 +- .../aws/fedramp_low_revision_4_aws.json | 6 +- .../aws/fedramp_moderate_revision_4_aws.json | 21 +- prowler/compliance/aws/ffiec_aws.json | 3 +- prowler/compliance/aws/gdpr_aws.json | 3 +- .../aws/gxp_21_cfr_part_11_aws.json | 9 +- prowler/compliance/aws/hipaa_aws.json | 9 +- prowler/compliance/aws/iso27001_2013_aws.json | 9 +- prowler/compliance/aws/mitre_attack_aws.json | 9 +- .../aws/nist_800_171_revision_2_aws.json | 21 +- .../aws/nist_800_53_revision_4_aws.json | 15 +- .../aws/nist_800_53_revision_5_aws.json | 114 +++-- prowler/compliance/aws/nist_csf_1.1_aws.json | 6 +- prowler/compliance/aws/pci_3.2.1_aws.json | 3 +- prowler/compliance/aws/soc2_aws.json | 3 +- prowler/config/config.yaml | 6 + .../iam_disable_30_days_credentials.py | 104 ---- .../__init__.py | 0 ..._disable_90_days_credentials.metadata.json | 32 -- .../iam_disable_90_days_credentials.py | 104 ---- .../__init__.py | 0 .../iam_user_accesskey_unused.metadata.json} | 6 +- .../iam_user_accesskey_unused.py} | 35 +- .../__init__.py | 0 ..._user_console_access_unused.metadata.json} | 6 +- .../iam_user_console_access_unused.py | 40 ++ tests/lib/check/check_test.py | 16 +- tests/lib/check/fixtures/groupsA.json | 4 +- tests/lib/check/fixtures/metadata.json | 6 +- tests/lib/outputs/fixtures/metadata.json | 6 +- tests/lib/outputs/outputs_test.py | 26 +- .../lib/security_hub/fixtures/metadata.json | 6 +- .../aws/lib/security_hub/security_hub_test.py | 6 +- .../iam_disable_30_days_credentials_test.py | 449 ------------------ .../iam_disable_45_days_credentials_test.py | 448 ----------------- .../iam_disable_90_days_credentials_test.py | 446 ----------------- .../iam_user_accesskey_unused_test.py | 274 +++++++++++ .../iam_user_console_access_unused_test.py | 158 ++++++ 43 files changed, 693 insertions(+), 1741 deletions(-) delete mode 100644 prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.py delete mode 100644 prowler/providers/aws/services/iam/iam_disable_90_days_credentials/__init__.py delete mode 100644 prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.metadata.json delete mode 100644 prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.py rename prowler/providers/aws/services/iam/{iam_disable_30_days_credentials => iam_user_accesskey_unused}/__init__.py (100%) rename prowler/providers/aws/services/iam/{iam_disable_30_days_credentials/iam_disable_30_days_credentials.metadata.json => iam_user_accesskey_unused/iam_user_accesskey_unused.metadata.json} (85%) rename prowler/providers/aws/services/iam/{iam_disable_45_days_credentials/iam_disable_45_days_credentials.py => iam_user_accesskey_unused/iam_user_accesskey_unused.py} (73%) rename prowler/providers/aws/services/iam/{iam_disable_45_days_credentials => iam_user_console_access_unused}/__init__.py (100%) rename prowler/providers/aws/services/iam/{iam_disable_45_days_credentials/iam_disable_45_days_credentials.metadata.json => iam_user_console_access_unused/iam_user_console_access_unused.metadata.json} (85%) create mode 100644 prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.py delete mode 100644 tests/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials_test.py delete mode 100644 tests/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials_test.py delete mode 100644 tests/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials_test.py create mode 100644 tests/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused_test.py create mode 100644 tests/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused_test.py diff --git a/prowler/compliance/aws/aws_foundational_security_best_practices_aws.json b/prowler/compliance/aws/aws_foundational_security_best_practices_aws.json index 57cca1d0ec..e79e3ddccc 100644 --- a/prowler/compliance/aws/aws_foundational_security_best_practices_aws.json +++ b/prowler/compliance/aws/aws_foundational_security_best_practices_aws.json @@ -367,7 +367,8 @@ "iam_user_mfa_enabled_console_access", "iam_root_hardware_mfa_enabled", "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_aws_attached_policy_no_administrative_privileges", "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges" diff --git a/prowler/compliance/aws/cis_1.4_aws.json b/prowler/compliance/aws/cis_1.4_aws.json index 4843610c01..3f21bda262 100644 --- a/prowler/compliance/aws/cis_1.4_aws.json +++ b/prowler/compliance/aws/cis_1.4_aws.json @@ -71,7 +71,8 @@ "Id": "1.12", "Description": "Ensure credentials unused for 45 days or greater are disabled", "Checks": [ - "iam_disable_45_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ], "Attributes": [ { diff --git a/prowler/compliance/aws/cis_1.5_aws.json b/prowler/compliance/aws/cis_1.5_aws.json index ae36ad369c..d127ba64fe 100644 --- a/prowler/compliance/aws/cis_1.5_aws.json +++ b/prowler/compliance/aws/cis_1.5_aws.json @@ -71,7 +71,8 @@ "Id": "1.12", "Description": "Ensure credentials unused for 45 days or greater are disabled", "Checks": [ - "iam_disable_45_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ], "Attributes": [ { diff --git a/prowler/compliance/aws/cis_2.0_aws.json b/prowler/compliance/aws/cis_2.0_aws.json index a4727ac8ba..8683bc0aad 100644 --- a/prowler/compliance/aws/cis_2.0_aws.json +++ b/prowler/compliance/aws/cis_2.0_aws.json @@ -71,7 +71,8 @@ "Id": "1.12", "Description": "Ensure credentials unused for 45 days or greater are disabled", "Checks": [ - "iam_disable_45_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ], "Attributes": [ { diff --git a/prowler/compliance/aws/cisa_aws.json b/prowler/compliance/aws/cisa_aws.json index 825c4dd2db..efea612301 100644 --- a/prowler/compliance/aws/cisa_aws.json +++ b/prowler/compliance/aws/cisa_aws.json @@ -97,7 +97,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "kms_cmk_rotation_enabled", "awslambda_function_not_publicly_accessible", "awslambda_function_not_publicly_accessible", diff --git a/prowler/compliance/aws/ens_rd2022_aws.json b/prowler/compliance/aws/ens_rd2022_aws.json index 1140c8bec6..d12da89f43 100644 --- a/prowler/compliance/aws/ens_rd2022_aws.json +++ b/prowler/compliance/aws/ens_rd2022_aws.json @@ -306,7 +306,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_rotate_access_key_90_days" ] }, @@ -332,7 +333,8 @@ ], "Checks": [ "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_rotate_access_key_90_days" ] }, @@ -485,8 +487,8 @@ } ], "Checks": [ - "iam_disable_30_days_credentials", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/fedramp_low_revision_4_aws.json b/prowler/compliance/aws/fedramp_low_revision_4_aws.json index c7ab997c19..ff9e80f9d3 100644 --- a/prowler/compliance/aws/fedramp_low_revision_4_aws.json +++ b/prowler/compliance/aws/fedramp_low_revision_4_aws.json @@ -36,7 +36,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_hardware_mfa_enabled", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "rds_instance_integration_cloudwatch_logs", "redshift_cluster_audit_logging", "s3_bucket_server_access_logging_enabled", @@ -64,7 +65,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", diff --git a/prowler/compliance/aws/fedramp_moderate_revision_4_aws.json b/prowler/compliance/aws/fedramp_moderate_revision_4_aws.json index 7b551c501a..0c9c0be0ed 100644 --- a/prowler/compliance/aws/fedramp_moderate_revision_4_aws.json +++ b/prowler/compliance/aws/fedramp_moderate_revision_4_aws.json @@ -29,7 +29,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "securityhub_enabled" ] }, @@ -103,7 +104,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -156,7 +158,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -173,7 +176,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -197,7 +201,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -259,7 +264,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -301,7 +307,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", diff --git a/prowler/compliance/aws/ffiec_aws.json b/prowler/compliance/aws/ffiec_aws.json index 80fd667d4f..4be349cb96 100644 --- a/prowler/compliance/aws/ffiec_aws.json +++ b/prowler/compliance/aws/ffiec_aws.json @@ -591,7 +591,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/gdpr_aws.json b/prowler/compliance/aws/gdpr_aws.json index 49fa51b602..7361d99f00 100644 --- a/prowler/compliance/aws/gdpr_aws.json +++ b/prowler/compliance/aws/gdpr_aws.json @@ -44,7 +44,8 @@ "iam_support_role_created", "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "kms_cmk_rotation_enabled", "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", diff --git a/prowler/compliance/aws/gxp_21_cfr_part_11_aws.json b/prowler/compliance/aws/gxp_21_cfr_part_11_aws.json index 6d12ccb015..2244bf5307 100644 --- a/prowler/compliance/aws/gxp_21_cfr_part_11_aws.json +++ b/prowler/compliance/aws/gxp_21_cfr_part_11_aws.json @@ -92,7 +92,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -177,7 +178,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -323,7 +325,8 @@ "iam_password_policy_symbol", "iam_password_policy_uppercase", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, diff --git a/prowler/compliance/aws/hipaa_aws.json b/prowler/compliance/aws/hipaa_aws.json index 46b763da68..3a7d6313e9 100644 --- a/prowler/compliance/aws/hipaa_aws.json +++ b/prowler/compliance/aws/hipaa_aws.json @@ -177,7 +177,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -286,7 +287,8 @@ "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -343,7 +345,8 @@ "iam_password_policy_uppercase", "iam_password_policy_reuse_24", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/iso27001_2013_aws.json b/prowler/compliance/aws/iso27001_2013_aws.json index 76fc153cf8..4a41be7124 100644 --- a/prowler/compliance/aws/iso27001_2013_aws.json +++ b/prowler/compliance/aws/iso27001_2013_aws.json @@ -866,7 +866,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -1042,7 +1043,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -1250,7 +1252,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/mitre_attack_aws.json b/prowler/compliance/aws/mitre_attack_aws.json index 5ee7dd0f84..06551f03f2 100644 --- a/prowler/compliance/aws/mitre_attack_aws.json +++ b/prowler/compliance/aws/mitre_attack_aws.json @@ -167,7 +167,8 @@ "iam_customer_unattached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_expired_server_certificates_stored", - "iam_disable_30_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_no_root_access_key", "iam_no_custom_policy_permissive_role_assumption", "iam_password_policy_expires_passwords_within_90_days_or_less", @@ -673,7 +674,8 @@ "iam_policy_allows_privilege_escalation", "iam_policy_no_full_access_to_cloudtrail", "iam_policy_no_full_access_to_kms", - "iam_disable_30_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_no_root_access_key", "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", @@ -720,7 +722,8 @@ "Checks": [ "guardduty_is_enabled", "config_recorder_all_regions_enabled", - "iam_disable_30_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_password_policy_expires_passwords_within_90_days_or_less", "iam_password_policy_lowercase", "iam_password_policy_minimum_length_14", diff --git a/prowler/compliance/aws/nist_800_171_revision_2_aws.json b/prowler/compliance/aws/nist_800_171_revision_2_aws.json index 9f9d8d683d..9ce09e9a20 100644 --- a/prowler/compliance/aws/nist_800_171_revision_2_aws.json +++ b/prowler/compliance/aws/nist_800_171_revision_2_aws.json @@ -29,7 +29,8 @@ "iam_no_root_access_key", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -70,7 +71,8 @@ "iam_no_root_access_key", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -133,7 +135,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -152,7 +155,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -574,7 +578,8 @@ "Checks": [ "iam_password_policy_reuse_24", "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -596,7 +601,8 @@ "iam_password_policy_uppercase", "iam_password_policy_reuse_24", "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -613,7 +619,8 @@ "Checks": [ "iam_password_policy_reuse_24", "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/nist_800_53_revision_4_aws.json b/prowler/compliance/aws/nist_800_53_revision_4_aws.json index e9da305c15..1876273797 100644 --- a/prowler/compliance/aws/nist_800_53_revision_4_aws.json +++ b/prowler/compliance/aws/nist_800_53_revision_4_aws.json @@ -20,7 +20,8 @@ "guardduty_is_enabled", "iam_password_policy_reuse_24", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "securityhub_enabled" ] }, @@ -37,7 +38,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -107,7 +109,8 @@ "iam_root_mfa_enabled", "iam_no_root_access_key", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "rds_instance_integration_cloudwatch_logs", "redshift_cluster_audit_logging", "s3_bucket_server_access_logging_enabled", @@ -131,7 +134,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_url_public", "rds_snapshots_public_access", "redshift_cluster_public_access", @@ -225,7 +229,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_url_public", "rds_instance_no_public_access", "rds_snapshots_public_access", diff --git a/prowler/compliance/aws/nist_800_53_revision_5_aws.json b/prowler/compliance/aws/nist_800_53_revision_5_aws.json index 85521ef23b..a5ee842c6c 100644 --- a/prowler/compliance/aws/nist_800_53_revision_5_aws.json +++ b/prowler/compliance/aws/nist_800_53_revision_5_aws.json @@ -28,7 +28,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -47,7 +48,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -65,7 +67,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -83,7 +86,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -101,7 +105,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -118,7 +123,8 @@ ], "Checks": [ "iam_password_policy_minimum_length_14", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -166,7 +172,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -225,7 +232,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -260,7 +268,8 @@ } ], "Checks": [ - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { @@ -284,7 +293,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_policy_attached_only_to_group_or_roles", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -364,7 +374,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -394,7 +405,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -424,7 +436,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -454,7 +467,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -484,7 +498,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -514,7 +529,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -544,7 +560,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -574,7 +591,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -603,7 +621,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -633,7 +652,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -652,7 +672,8 @@ ], "Checks": [ "secretsmanager_automatic_rotation_enabled", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", "iam_rotate_access_key_90_days", @@ -693,7 +714,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -723,7 +745,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -753,7 +776,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -780,7 +804,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -817,7 +842,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -870,7 +896,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -916,7 +943,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -946,7 +974,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -976,7 +1005,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -1102,7 +1132,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -1145,7 +1176,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -1497,7 +1529,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -2673,7 +2706,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -2753,7 +2787,8 @@ "iam_no_root_access_key", "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "kms_cmk_rotation_enabled", "s3_bucket_default_encryption", "s3_bucket_secure_transport_policy", @@ -3010,7 +3045,8 @@ "iam_no_root_access_key", "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "kms_cmk_rotation_enabled", "s3_bucket_default_encryption", "s3_bucket_secure_transport_policy", @@ -3979,7 +4015,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "awslambda_function_not_publicly_accessible", "awslambda_function_url_public", "rds_instance_no_public_access", @@ -5457,7 +5494,8 @@ "iam_rotate_access_key_90_days", "iam_user_mfa_enabled_console_access", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, diff --git a/prowler/compliance/aws/nist_csf_1.1_aws.json b/prowler/compliance/aws/nist_csf_1.1_aws.json index cf9f21ebf8..be28b4866b 100644 --- a/prowler/compliance/aws/nist_csf_1.1_aws.json +++ b/prowler/compliance/aws/nist_csf_1.1_aws.json @@ -574,7 +574,8 @@ "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", "iam_rotate_access_key_90_days", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "secretsmanager_automatic_rotation_enabled" ] }, @@ -630,7 +631,8 @@ "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", "iam_no_root_access_key", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/compliance/aws/pci_3.2.1_aws.json b/prowler/compliance/aws/pci_3.2.1_aws.json index 326f417cf9..2db2d92f59 100644 --- a/prowler/compliance/aws/pci_3.2.1_aws.json +++ b/prowler/compliance/aws/pci_3.2.1_aws.json @@ -162,7 +162,8 @@ "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", "iam_user_mfa_enabled_console_access", - "iam_disable_90_days_credentials", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", "iam_password_policy_minimum_length_14", "iam_password_policy_lowercase", "iam_password_policy_number", diff --git a/prowler/compliance/aws/soc2_aws.json b/prowler/compliance/aws/soc2_aws.json index 0377786b92..7ae657f2d7 100644 --- a/prowler/compliance/aws/soc2_aws.json +++ b/prowler/compliance/aws/soc2_aws.json @@ -49,7 +49,8 @@ "iam_aws_attached_policy_no_administrative_privileges", "iam_customer_attached_policy_no_administrative_privileges", "iam_inline_policy_no_administrative_privileges", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ] }, { diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 87b88b754d..800ebdcf56 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -1,5 +1,11 @@ # AWS Configuration aws: + # AWS IAM Configuration + # aws.iam_user_accesskey_unused --> CIS recommends 45 days + max_unused_access_keys_days: 45 + # aws.iam_user_console_access_unused --> CIS recommends 45 days + max_console_access_days: 45 + # AWS EC2 Configuration # aws.ec2_elastic_ip_shodan shodan_api_key: null diff --git a/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.py b/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.py deleted file mode 100644 index 9710f25c89..0000000000 --- a/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.py +++ /dev/null @@ -1,104 +0,0 @@ -import datetime - -from prowler.lib.check.models import Check, Check_Report_AWS -from prowler.providers.aws.services.iam.iam_client import iam_client - -maximum_expiration_days = 30 - - -class iam_disable_30_days_credentials(Check): - def execute(self) -> Check_Report_AWS: - findings = [] - for user in iam_client.users: - report = Check_Report_AWS(self.metadata()) - report.resource_id = user.name - report.resource_arn = user.arn - report.resource_tags = user.tags - report.region = iam_client.region - if user.password_last_used: - time_since_insertion = ( - datetime.datetime.now() - - datetime.datetime.strptime( - str(user.password_last_used), "%Y-%m-%d %H:%M:%S+00:00" - ) - ) - if time_since_insertion.days > maximum_expiration_days: - report.status = "FAIL" - report.status_extended = f"User {user.name} has not logged in to the console in the past {maximum_expiration_days} days." - else: - report.status = "PASS" - report.status_extended = f"User {user.name} has logged in to the console in the past {maximum_expiration_days} days." - else: - report.status = "PASS" - report.status_extended = ( - f"User {user.name} does not have a console password or is unused." - ) - - # Append report - findings.append(report) - - for user in iam_client.credential_report: - if ( - user["access_key_1_active"] != "true" - and user["access_key_2_active"] != "true" - ): - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] - report.resource_arn = user["arn"] - report.status = "PASS" - report.status_extended = ( - f"User {user['user']} does not have access keys." - ) - findings.append(report) - - else: - old_access_keys = False - if user["access_key_1_active"] == "true": - if user["access_key_1_last_used_date"] != "N/A": - access_key_1_last_used_date = ( - datetime.datetime.now() - - datetime.datetime.strptime( - user["access_key_1_last_used_date"], - "%Y-%m-%dT%H:%M:%S+00:00", - ) - ) - if access_key_1_last_used_date.days > maximum_expiration_days: - old_access_keys = True - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] + "/AccessKey1" - report.resource_arn = user["arn"] - report.status = "FAIL" - report.status_extended = f"User {user['user']} has not used access key 1 in the last {maximum_expiration_days} days ({access_key_1_last_used_date.days} days)." - findings.append(report) - - if user["access_key_2_active"] == "true": - if user["access_key_2_last_used_date"] != "N/A": - access_key_2_last_used_date = ( - datetime.datetime.now() - - datetime.datetime.strptime( - user["access_key_2_last_used_date"], - "%Y-%m-%dT%H:%M:%S+00:00", - ) - ) - if access_key_2_last_used_date.days > maximum_expiration_days: - old_access_keys = True - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] + "/AccessKey2" - report.resource_arn = user["arn"] - report.status = "FAIL" - report.status_extended = f"User {user['user']} has not used access key 2 in the last {maximum_expiration_days} days ({access_key_2_last_used_date.days} days)." - findings.append(report) - - if not old_access_keys: - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] - report.resource_arn = user["arn"] - report.status = "PASS" - report.status_extended = f"User {user['user']} does not have unused access keys for {maximum_expiration_days} days." - findings.append(report) - - return findings diff --git a/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/__init__.py b/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.metadata.json b/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.metadata.json deleted file mode 100644 index bfbf065a67..0000000000 --- a/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.metadata.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Categories": [], - "CheckID": "iam_disable_90_days_credentials", - "CheckTitle": "Ensure credentials unused for 90 days or greater are disabled", - "CheckType": [ - "Software and Configuration Checks" - ], - "DependsOn": [], - "Description": "Ensure credentials unused for 90 days or greater are disabled", - "Notes": "", - "Provider": "aws", - "RelatedTo": [], - "RelatedUrl": "", - "Remediation": { - "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" - }, - "Recommendation": { - "Text": "Find the credentials that they were using and ensure that they are no longer operational. Ideally; you delete credentials if they are no longer needed. You can always recreate them at a later date if the need arises. At the very least; you should change the password or deactivate the access keys so that the former users no longer have access.", - "Url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_finding-unused.html" - } - }, - "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", - "ResourceType": "AwsIamUser", - "Risk": "AWS IAM users can access AWS resources using different types of credentials (passwords or access keys). It is recommended that all credentials that have been unused in 90 or greater days be removed or deactivated.", - "ServiceName": "iam", - "Severity": "medium", - "SubServiceName": "" -} diff --git a/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.py b/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.py deleted file mode 100644 index 30a01463c4..0000000000 --- a/prowler/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials.py +++ /dev/null @@ -1,104 +0,0 @@ -import datetime - -from prowler.lib.check.models import Check, Check_Report_AWS -from prowler.providers.aws.services.iam.iam_client import iam_client - -maximum_expiration_days = 90 - - -class iam_disable_90_days_credentials(Check): - def execute(self) -> Check_Report_AWS: - findings = [] - for user in iam_client.users: - report = Check_Report_AWS(self.metadata()) - report.resource_id = user.name - report.resource_arn = user.arn - report.resource_tags = user.tags - report.region = iam_client.region - if user.password_last_used: - time_since_insertion = ( - datetime.datetime.now() - - datetime.datetime.strptime( - str(user.password_last_used), "%Y-%m-%d %H:%M:%S+00:00" - ) - ) - if time_since_insertion.days > maximum_expiration_days: - report.status = "FAIL" - report.status_extended = f"User {user.name} has not logged in to the console in the past {maximum_expiration_days} days." - else: - report.status = "PASS" - report.status_extended = f"User {user.name} has logged in to the console in the past {maximum_expiration_days} days." - else: - report.status = "PASS" - report.status_extended = ( - f"User {user.name} does not have a console password or is unused." - ) - - # Append report - findings.append(report) - - for user in iam_client.credential_report: - if ( - user["access_key_1_active"] != "true" - and user["access_key_2_active"] != "true" - ): - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] - report.resource_arn = user["arn"] - report.status = "PASS" - report.status_extended = ( - f"User {user['user']} does not have access keys." - ) - findings.append(report) - - else: - old_access_keys = False - if user["access_key_1_active"] == "true": - if user["access_key_1_last_used_date"] != "N/A": - access_key_1_last_used_date = ( - datetime.datetime.now() - - datetime.datetime.strptime( - user["access_key_1_last_used_date"], - "%Y-%m-%dT%H:%M:%S+00:00", - ) - ) - if access_key_1_last_used_date.days > maximum_expiration_days: - old_access_keys = True - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] + "/AccessKey1" - report.resource_arn = user["arn"] - report.status = "FAIL" - report.status_extended = f"User {user['user']} has not used access key 1 in the last {maximum_expiration_days} days ({access_key_1_last_used_date.days} days)." - findings.append(report) - - if user["access_key_2_active"] == "true": - if user["access_key_2_last_used_date"] != "N/A": - access_key_2_last_used_date = ( - datetime.datetime.now() - - datetime.datetime.strptime( - user["access_key_2_last_used_date"], - "%Y-%m-%dT%H:%M:%S+00:00", - ) - ) - if access_key_2_last_used_date.days > maximum_expiration_days: - old_access_keys = True - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] + "/AccessKey2" - report.resource_arn = user["arn"] - report.status = "FAIL" - report.status_extended = f"User {user['user']} has not used access key 2 in the last {maximum_expiration_days} days ({access_key_2_last_used_date.days} days)." - findings.append(report) - - if not old_access_keys: - report = Check_Report_AWS(self.metadata()) - report.region = iam_client.region - report.resource_id = user["user"] - report.resource_arn = user["arn"] - report.status = "PASS" - report.status_extended = f"User {user['user']} does not have unused access keys for {maximum_expiration_days} days." - findings.append(report) - - return findings diff --git a/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/__init__.py b/prowler/providers/aws/services/iam/iam_user_accesskey_unused/__init__.py similarity index 100% rename from prowler/providers/aws/services/iam/iam_disable_30_days_credentials/__init__.py rename to prowler/providers/aws/services/iam/iam_user_accesskey_unused/__init__.py diff --git a/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.metadata.json b/prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.metadata.json similarity index 85% rename from prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.metadata.json rename to prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.metadata.json index 8b2202fd09..c5cbf8a86e 100644 --- a/prowler/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials.metadata.json +++ b/prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.metadata.json @@ -1,7 +1,7 @@ { "Provider": "aws", - "CheckID": "iam_disable_30_days_credentials", - "CheckTitle": "Ensure credentials unused for 30 days or greater are disabled", + "CheckID": "iam_user_accesskey_unused", + "CheckTitle": "Ensure User Access Keys unused are disabled", "CheckType": [ "Software and Configuration Checks" ], @@ -10,7 +10,7 @@ "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", "ResourceType": "AwsIamUser", - "Description": "Ensure credentials unused for 30 days or greater are disabled", + "Description": "Ensure User Access Keys unused are disabled", "Risk": "To increase the security of your AWS account; remove IAM user credentials (that is; passwords and access keys) that are not needed. For example; when users leave your organization or no longer need AWS access.", "RelatedUrl": "", "Remediation": { diff --git a/prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.py b/prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.py similarity index 73% rename from prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.py rename to prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.py index 48b94f3500..5c8c948daa 100644 --- a/prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.py +++ b/prowler/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused.py @@ -3,40 +3,13 @@ import datetime from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.services.iam.iam_client import iam_client -maximum_expiration_days = 45 - -class iam_disable_45_days_credentials(Check): +class iam_user_accesskey_unused(Check): def execute(self) -> Check_Report_AWS: + maximum_expiration_days = iam_client.audit_config.get( + "max_unused_access_keys_days", 45 + ) findings = [] - for user in iam_client.users: - report = Check_Report_AWS(self.metadata()) - report.resource_id = user.name - report.resource_arn = user.arn - report.resource_tags = user.tags - report.region = iam_client.region - if user.password_last_used: - time_since_insertion = ( - datetime.datetime.now() - - datetime.datetime.strptime( - str(user.password_last_used), "%Y-%m-%d %H:%M:%S+00:00" - ) - ) - if time_since_insertion.days > maximum_expiration_days: - report.status = "FAIL" - report.status_extended = f"User {user.name} has not logged in to the console in the past 45 days." - else: - report.status = "PASS" - report.status_extended = f"User {user.name} has logged in to the console in the past 45 days." - else: - report.status = "PASS" - report.status_extended = ( - f"User {user.name} does not have a console password or is unused." - ) - - # Append report - findings.append(report) - for user in iam_client.credential_report: if ( user["access_key_1_active"] != "true" diff --git a/prowler/providers/aws/services/iam/iam_disable_45_days_credentials/__init__.py b/prowler/providers/aws/services/iam/iam_user_console_access_unused/__init__.py similarity index 100% rename from prowler/providers/aws/services/iam/iam_disable_45_days_credentials/__init__.py rename to prowler/providers/aws/services/iam/iam_user_console_access_unused/__init__.py diff --git a/prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.metadata.json b/prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.metadata.json similarity index 85% rename from prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.metadata.json rename to prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.metadata.json index 47375a07ca..aeb52eb3ba 100644 --- a/prowler/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials.metadata.json +++ b/prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.metadata.json @@ -1,7 +1,7 @@ { "Provider": "aws", - "CheckID": "iam_disable_45_days_credentials", - "CheckTitle": "Ensure credentials unused for 45 days or greater are disabled", + "CheckID": "iam_user_console_access_unused", + "CheckTitle": "Ensure unused user console access are disabled", "CheckType": [ "Software and Configuration Checks" ], @@ -10,7 +10,7 @@ "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", "Severity": "medium", "ResourceType": "AwsIamUser", - "Description": "Ensure credentials unused for 45 days or greater are disabled", + "Description": "Ensure unused user console access are disabled", "Risk": "To increase the security of your AWS account; remove IAM user credentials (that is; passwords and access keys) that are not needed. For example; when users leave your organization or no longer need AWS access.", "RelatedUrl": "", "Remediation": { diff --git a/prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.py b/prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.py new file mode 100644 index 0000000000..7c7a12ce83 --- /dev/null +++ b/prowler/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused.py @@ -0,0 +1,40 @@ +import datetime + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.iam.iam_client import iam_client + + +class iam_user_console_access_unused(Check): + def execute(self) -> Check_Report_AWS: + maximum_expiration_days = iam_client.audit_config.get( + "max_console_access_days", 45 + ) + findings = [] + for user in iam_client.users: + report = Check_Report_AWS(self.metadata()) + report.resource_id = user.name + report.resource_arn = user.arn + report.resource_tags = user.tags + report.region = iam_client.region + if user.password_last_used: + time_since_insertion = ( + datetime.datetime.now() + - datetime.datetime.strptime( + str(user.password_last_used), "%Y-%m-%d %H:%M:%S+00:00" + ) + ) + if time_since_insertion.days > maximum_expiration_days: + report.status = "FAIL" + report.status_extended = f"User {user.name} has not logged in to the console in the past {maximum_expiration_days} days ({time_since_insertion.days} days)." + else: + report.status = "PASS" + report.status_extended = f"User {user.name} has logged in to the console in the past {maximum_expiration_days} days ({time_since_insertion.days} days)." + else: + report.status = "PASS" + report.status_extended = ( + f"User {user.name} does not have a console password or is unused." + ) + + # Append report + findings.append(report) + return findings diff --git a/tests/lib/check/check_test.py b/tests/lib/check/check_test.py index d19f1d0233..02d3b1b3a1 100644 --- a/tests/lib/check/check_test.py +++ b/tests/lib/check/check_test.py @@ -295,8 +295,8 @@ class Test_Check: "metadata_path": f"{os.path.dirname(os.path.realpath(__file__))}/fixtures/metadata.json", }, "expected": { - "CheckID": "iam_disable_30_days_credentials", - "CheckTitle": "Ensure credentials unused for 30 days or greater are disabled", + "CheckID": "iam_user_accesskey_unused", + "CheckTitle": "Ensure Access Keys unused are disabled", "ServiceName": "iam", "Severity": "low", }, @@ -398,22 +398,22 @@ class Test_Check: { "input": { "checks_to_run": { - "iam_disable_30_days_credentials", - "iam_disable_90_days_credentials", + "iam_user_console_access_unused", + "iam_user_accesskey_unused", }, "excluded_services": {"ec2"}, "provider": "aws", }, "expected": { - "iam_disable_30_days_credentials", - "iam_disable_90_days_credentials", + "iam_user_console_access_unused", + "iam_user_accesskey_unused", }, }, { "input": { "checks_to_run": { - "iam_disable_30_days_credentials", - "iam_disable_90_days_credentials", + "iam_user_console_access_unused", + "iam_user_accesskey_unused", }, "excluded_services": {"iam"}, "provider": "aws", diff --git a/tests/lib/check/fixtures/groupsA.json b/tests/lib/check/fixtures/groupsA.json index 8df7411a80..d22e826c41 100644 --- a/tests/lib/check/fixtures/groupsA.json +++ b/tests/lib/check/fixtures/groupsA.json @@ -9,8 +9,8 @@ }, "iam": { "checks": [ - "iam_disable_30_days_credentials", - "iam_disable_90_days_credentials" + "iam_user_accesskey_unused", + "iam_user_console_access_unused" ], "description": "Identity and Access Management" } diff --git a/tests/lib/check/fixtures/metadata.json b/tests/lib/check/fixtures/metadata.json index f1b61c4888..f1bffb6273 100644 --- a/tests/lib/check/fixtures/metadata.json +++ b/tests/lib/check/fixtures/metadata.json @@ -3,8 +3,8 @@ "cat1", "cat2" ], - "CheckID": "iam_disable_30_days_credentials", - "CheckTitle": "Ensure credentials unused for 30 days or greater are disabled", + "CheckID": "iam_user_accesskey_unused", + "CheckTitle": "Ensure Access Keys unused are disabled", "CheckType": [ "Software and Configuration Checks" ], @@ -25,7 +25,7 @@ "othercheck1", "othercheck2" ], - "Description": "Ensure credentials unused for 30 days or greater are disabled", + "Description": "Ensure Access Keys unused are disabled", "Notes": "additional information", "Provider": "aws", "RelatedTo": [ diff --git a/tests/lib/outputs/fixtures/metadata.json b/tests/lib/outputs/fixtures/metadata.json index f1b61c4888..f1bffb6273 100644 --- a/tests/lib/outputs/fixtures/metadata.json +++ b/tests/lib/outputs/fixtures/metadata.json @@ -3,8 +3,8 @@ "cat1", "cat2" ], - "CheckID": "iam_disable_30_days_credentials", - "CheckTitle": "Ensure credentials unused for 30 days or greater are disabled", + "CheckID": "iam_user_accesskey_unused", + "CheckTitle": "Ensure Access Keys unused are disabled", "CheckType": [ "Software and Configuration Checks" ], @@ -25,7 +25,7 @@ "othercheck1", "othercheck2" ], - "Description": "Ensure credentials unused for 30 days or greater are disabled", + "Description": "Ensure Access Keys unused are disabled", "Notes": "additional information", "Provider": "aws", "RelatedTo": [ diff --git a/tests/lib/outputs/outputs_test.py b/tests/lib/outputs/outputs_test.py index aa11f2be4d..70b07da0da 100644 --- a/tests/lib/outputs/outputs_test.py +++ b/tests/lib/outputs/outputs_test.py @@ -27,8 +27,8 @@ from prowler.lib.outputs.file_descriptors import fill_file_descriptors from prowler.lib.outputs.json import ( fill_json_asff, fill_json_ocsf, - generate_json_asff_status, generate_json_asff_resource_tags, + generate_json_asff_status, generate_json_ocsf_severity_id, generate_json_ocsf_status, generate_json_ocsf_status_id, @@ -989,8 +989,8 @@ class Test_Outputs: expected = Check_Output_JSON_OCSF( finding=Finding( - title="Ensure credentials unused for 30 days or greater are disabled", - desc="Ensure credentials unused for 30 days or greater are disabled", + title="Ensure Access Keys unused are disabled", + desc="Ensure Access Keys unused are disabled", supporting_data={ "Risk": "Risk associated.", "Notes": "additional information", @@ -1007,7 +1007,7 @@ class Test_Outputs: ), types=["Software and Configuration Checks"], src_url="https://serviceofficialsiteorpageforthissubject", - uid="prowler-aws-iam_disable_30_days_credentials-123456789012-eu-west-1-test-resource", + uid="prowler-aws-iam_user_accesskey_unused-123456789012-eu-west-1-test-resource", related_events=[ "othercheck1", "othercheck2", @@ -1050,8 +1050,8 @@ class Test_Outputs: version=prowler_version, vendor_name="Prowler/ProwlerPro", feature=Feature( - name="iam_disable_30_days_credentials", - uid="iam_disable_30_days_credentials", + name="iam_user_accesskey_unused", + uid="iam_user_accesskey_unused", version=prowler_version, ), ), @@ -1117,8 +1117,8 @@ class Test_Outputs: expected = Check_Output_JSON_OCSF( finding=Finding( - title="Ensure credentials unused for 30 days or greater are disabled", - desc="Ensure credentials unused for 30 days or greater are disabled", + title="Ensure Access Keys unused are disabled", + desc="Ensure Access Keys unused are disabled", supporting_data={ "Risk": "Risk associated.", "Notes": "additional information", @@ -1135,7 +1135,7 @@ class Test_Outputs: ), types=["Software and Configuration Checks"], src_url="https://serviceofficialsiteorpageforthissubject", - uid="prowler-aws-iam_disable_30_days_credentials-123456789012-eu-west-1-test-resource", + uid="prowler-aws-iam_user_accesskey_unused-123456789012-eu-west-1-test-resource", related_events=[ "othercheck1", "othercheck2", @@ -1178,8 +1178,8 @@ class Test_Outputs: version=prowler_version, vendor_name="Prowler/ProwlerPro", feature=Feature( - name="iam_disable_30_days_credentials", - uid="iam_disable_30_days_credentials", + name="iam_user_accesskey_unused", + uid="iam_user_accesskey_unused", version=prowler_version, ), ), @@ -1333,10 +1333,10 @@ class Test_Outputs: output_options = mock.MagicMock() output_options.bulk_checks_metadata = {} output_options.bulk_checks_metadata[ - "iam_disable_30_days_credentials" + "iam_user_accesskey_unused" ] = mock.MagicMock() output_options.bulk_checks_metadata[ - "iam_disable_30_days_credentials" + "iam_user_accesskey_unused" ].Compliance = bulk_check_metadata assert get_check_compliance(finding, "aws", output_options) == { diff --git a/tests/providers/aws/lib/security_hub/fixtures/metadata.json b/tests/providers/aws/lib/security_hub/fixtures/metadata.json index f1b61c4888..f1bffb6273 100644 --- a/tests/providers/aws/lib/security_hub/fixtures/metadata.json +++ b/tests/providers/aws/lib/security_hub/fixtures/metadata.json @@ -3,8 +3,8 @@ "cat1", "cat2" ], - "CheckID": "iam_disable_30_days_credentials", - "CheckTitle": "Ensure credentials unused for 30 days or greater are disabled", + "CheckID": "iam_user_accesskey_unused", + "CheckTitle": "Ensure Access Keys unused are disabled", "CheckType": [ "Software and Configuration Checks" ], @@ -25,7 +25,7 @@ "othercheck1", "othercheck2" ], - "Description": "Ensure credentials unused for 30 days or greater are disabled", + "Description": "Ensure Access Keys unused are disabled", "Notes": "additional information", "Provider": "aws", "RelatedTo": [ diff --git a/tests/providers/aws/lib/security_hub/security_hub_test.py b/tests/providers/aws/lib/security_hub/security_hub_test.py index 241e163b84..9cb4cd2151 100644 --- a/tests/providers/aws/lib/security_hub/security_hub_test.py +++ b/tests/providers/aws/lib/security_hub/security_hub_test.py @@ -122,7 +122,7 @@ class Test_SecurityHub: AWS_REGION_1: [ { "SchemaVersion": "2018-10-08", - "Id": f"prowler-iam_disable_30_days_credentials-{AWS_ACCOUNT_ID}-{AWS_REGION_1}-ee26b0dd4", + "Id": f"prowler-iam_user_accesskey_unused-{AWS_ACCOUNT_ID}-{AWS_REGION_1}-ee26b0dd4", "ProductArn": f"arn:aws:securityhub:{AWS_REGION_1}::product/prowler/prowler", "RecordState": "ACTIVE", "ProductFields": { @@ -130,14 +130,14 @@ class Test_SecurityHub: "ProviderVersion": "3.9.0", "ProwlerResourceName": "test", }, - "GeneratorId": "prowler-iam_disable_30_days_credentials", + "GeneratorId": "prowler-iam_user_accesskey_unused", "AwsAccountId": f"{AWS_ACCOUNT_ID}", "Types": ["Software and Configuration Checks"], "FirstObservedAt": timestamp_utc.strftime("%Y-%m-%dT%H:%M:%SZ"), "UpdatedAt": timestamp_utc.strftime("%Y-%m-%dT%H:%M:%SZ"), "CreatedAt": timestamp_utc.strftime("%Y-%m-%dT%H:%M:%SZ"), "Severity": {"Label": "LOW"}, - "Title": "Ensure credentials unused for 30 days or greater are disabled", + "Title": "Ensure Access Keys unused are disabled", "Description": "test", "Resources": [ { diff --git a/tests/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials_test.py b/tests/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials_test.py deleted file mode 100644 index 6aa9bab4e5..0000000000 --- a/tests/providers/aws/services/iam/iam_disable_30_days_credentials/iam_disable_30_days_credentials_test.py +++ /dev/null @@ -1,449 +0,0 @@ -import datetime -from unittest import mock - -from boto3 import client, session -from moto import mock_iam - -from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info -from prowler.providers.common.models import Audit_Metadata - -AWS_ACCOUNT_NUMBER = "123456789012" -AWS_REGION = "us-east-1" - - -class Test_iam_disable_30_days_credentials_test: - # Mocked Audit Info - def set_mocked_audit_info(self): - audit_info = AWS_Audit_Info( - session_config=None, - original_session=None, - audit_session=session.Session( - profile_name=None, - botocore_session=None, - region_name=AWS_REGION, - ), - audited_account=AWS_ACCOUNT_NUMBER, - audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root", - audited_user_id=None, - audited_partition="aws", - audited_identity_arn=None, - profile=None, - profile_region=AWS_REGION, - credentials=None, - assumed_role_info=None, - audited_regions=None, - organizations_metadata=None, - audit_resources=None, - mfa_enabled=False, - audit_metadata=Audit_Metadata( - services_scanned=0, - expected_checks=[], - completed_checks=0, - audit_progress=0, - ), - ) - return audit_info - - @mock_iam - def test_iam_user_logged_30_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=2) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} has logged in to the console in the past 30 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged_30_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=60) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "FAIL" - assert ( - result[0].status_extended - == f"User {user} has not logged in to the console in the past 30 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.users[0].password_last_used = "" - # raise Exception - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_no_access_keys(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.credential_report[0][ - "access_key_1_last_rotated" - ] == "N/A" - service_client.credential_report[0][ - "access_key_2_last_rotated" - ] == "N/A" - - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_1_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 30 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_2_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 2 in the last 30 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey2" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 3 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 30 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - assert result[2].status == "FAIL" - assert ( - result[2].status_extended - == f"User {user} has not used access key 2 in the last 30 days (100 days)." - ) - assert result[2].resource_id == user + "/AccessKey2" - assert result[2].resource_arn == arn - assert result[2].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=10) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_30_days_credentials.iam_disable_30_days_credentials import ( - iam_disable_30_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_30_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have unused access keys for 30 days." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION diff --git a/tests/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials_test.py b/tests/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials_test.py deleted file mode 100644 index c4834d5f45..0000000000 --- a/tests/providers/aws/services/iam/iam_disable_45_days_credentials/iam_disable_45_days_credentials_test.py +++ /dev/null @@ -1,448 +0,0 @@ -import datetime -from unittest import mock - -from boto3 import client, session -from moto import mock_iam - -from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info -from prowler.providers.common.models import Audit_Metadata - -AWS_ACCOUNT_NUMBER = "123456789012" -AWS_REGION = "us-east-1" - - -class Test_iam_disable_45_days_credentials_test: - # Mocked Audit Info - def set_mocked_audit_info(self): - audit_info = AWS_Audit_Info( - session_config=None, - original_session=None, - audit_session=session.Session( - profile_name=None, - botocore_session=None, - region_name=AWS_REGION, - ), - audited_account=AWS_ACCOUNT_NUMBER, - audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root", - audited_user_id=None, - audited_partition="aws", - audited_identity_arn=None, - profile=None, - profile_region=AWS_REGION, - credentials=None, - assumed_role_info=None, - audited_regions=None, - organizations_metadata=None, - audit_resources=None, - mfa_enabled=False, - audit_metadata=Audit_Metadata( - services_scanned=0, - expected_checks=[], - completed_checks=0, - audit_progress=0, - ), - ) - return audit_info - - @mock_iam - def test_iam_user_logged_45_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=2) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} has logged in to the console in the past 45 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged_45_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=60) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "FAIL" - assert ( - result[0].status_extended - == f"User {user} has not logged in to the console in the past 45 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.users[0].password_last_used = "" - # raise Exception - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_no_access_keys(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0][ - "access_key_1_last_rotated" - ] == "N/A" - service_client.credential_report[0][ - "access_key_2_last_rotated" - ] == "N/A" - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_1_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 45 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_2_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 2 in the last 45 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey2" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 3 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 45 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - assert result[2].status == "FAIL" - assert ( - result[2].status_extended - == f"User {user} has not used access key 2 in the last 45 days (100 days)." - ) - assert result[2].resource_id == user + "/AccessKey2" - assert result[2].resource_arn == arn - assert result[2].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=10) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have unused access keys for 45 days." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION diff --git a/tests/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials_test.py b/tests/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials_test.py deleted file mode 100644 index f28d316b7f..0000000000 --- a/tests/providers/aws/services/iam/iam_disable_90_days_credentials/iam_disable_90_days_credentials_test.py +++ /dev/null @@ -1,446 +0,0 @@ -import datetime -from unittest import mock - -from boto3 import client, session -from moto import mock_iam - -from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info -from prowler.providers.common.models import Audit_Metadata - -AWS_ACCOUNT_NUMBER = "123456789012" -AWS_REGION = "us-east-1" - - -class Test_iam_disable_90_days_credentials_test: - # Mocked Audit Info - def set_mocked_audit_info(self): - audit_info = AWS_Audit_Info( - session_config=None, - original_session=None, - audit_session=session.Session( - profile_name=None, - botocore_session=None, - region_name=AWS_REGION, - ), - audited_account=AWS_ACCOUNT_NUMBER, - audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root", - audited_user_id=None, - audited_partition="aws", - audited_identity_arn=None, - profile=None, - profile_region=AWS_REGION, - credentials=None, - assumed_role_info=None, - audited_regions=None, - organizations_metadata=None, - audit_resources=None, - mfa_enabled=False, - audit_metadata=Audit_Metadata( - services_scanned=0, - expected_checks=[], - completed_checks=0, - audit_progress=0, - ), - ) - return audit_info - - @mock_iam - def test_iam_user_logged_90_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=2) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_90_days_credentials() - result = check.execute() - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} has logged in to the console in the past 90 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged_90_days(self): - password_last_used = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%d %H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.users[0].password_last_used = password_last_used - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "FAIL" - assert ( - result[0].status_extended - == f"User {user} has not logged in to the console in the past 90 days." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_iam_user_not_logged(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.users[0].password_last_used = "" - # raise Exception - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_no_access_keys(self): - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.credential_report[0][ - "access_key_1_last_rotated" - ] == "N/A" - service_client.credential_report[0][ - "access_key_2_last_rotated" - ] == "N/A" - - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have access keys." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_1_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 90 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_access_key_2_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 2 in the last 90 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey2" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_not_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=100) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_90_days_credentials.iam_disable_90_days_credentials import ( - iam_disable_90_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_90_days_credentials() - result = check.execute() - assert len(result) == 3 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "FAIL" - assert ( - result[1].status_extended - == f"User {user} has not used access key 1 in the last 90 days (100 days)." - ) - assert result[1].resource_id == user + "/AccessKey1" - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION - assert result[2].status == "FAIL" - assert ( - result[2].status_extended - == f"User {user} has not used access key 2 in the last 90 days (100 days)." - ) - assert result[2].resource_id == user + "/AccessKey2" - assert result[2].resource_arn == arn - assert result[2].region == AWS_REGION - - @mock_iam - def test_user_both_access_keys_used(self): - credentials_last_rotated = ( - datetime.datetime.now() - datetime.timedelta(days=10) - ).strftime("%Y-%m-%dT%H:%M:%S+00:00") - iam_client = client("iam") - user = "test-user" - arn = iam_client.create_user(UserName=user)["User"]["Arn"] - - from prowler.providers.aws.services.iam.iam_service import IAM - - audit_info = self.set_mocked_audit_info() - - with mock.patch( - "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", - new=audit_info, - ): - with mock.patch( - "prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials.iam_client", - new=IAM(audit_info), - ) as service_client: - from prowler.providers.aws.services.iam.iam_disable_45_days_credentials.iam_disable_45_days_credentials import ( - iam_disable_45_days_credentials, - ) - - service_client.credential_report[0]["access_key_1_active"] = "true" - service_client.credential_report[0][ - "access_key_1_last_used_date" - ] = credentials_last_rotated - - service_client.credential_report[0]["access_key_2_active"] = "true" - service_client.credential_report[0][ - "access_key_2_last_used_date" - ] = credentials_last_rotated - - check = iam_disable_45_days_credentials() - result = check.execute() - assert len(result) == 2 - assert result[0].status == "PASS" - assert ( - result[0].status_extended - == f"User {user} does not have a console password or is unused." - ) - assert result[0].resource_id == user - assert result[0].resource_arn == arn - assert result[0].region == AWS_REGION - assert result[1].status == "PASS" - assert ( - result[1].status_extended - == f"User {user} does not have unused access keys for 45 days." - ) - assert result[1].resource_id == user - assert result[1].resource_arn == arn - assert result[1].region == AWS_REGION diff --git a/tests/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused_test.py b/tests/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused_test.py new file mode 100644 index 0000000000..a36de6dffc --- /dev/null +++ b/tests/providers/aws/services/iam/iam_user_accesskey_unused/iam_user_accesskey_unused_test.py @@ -0,0 +1,274 @@ +import datetime +from unittest import mock + +from boto3 import client, session +from moto import mock_iam + +from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info +from prowler.providers.common.models import Audit_Metadata + +AWS_ACCOUNT_NUMBER = "123456789012" +AWS_REGION = "us-east-1" + + +class Test_iam_user_accesskey_unused_test: + # Mocked Audit Info + def set_mocked_audit_info(self): + audit_info = AWS_Audit_Info( + session_config=None, + original_session=None, + audit_session=session.Session( + profile_name=None, + botocore_session=None, + region_name=AWS_REGION, + ), + audited_account=AWS_ACCOUNT_NUMBER, + audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root", + audited_user_id=None, + audited_partition="aws", + audited_identity_arn=None, + profile=None, + profile_region=AWS_REGION, + credentials=None, + assumed_role_info=None, + audited_regions=None, + organizations_metadata=None, + audit_resources=None, + mfa_enabled=False, + audit_metadata=Audit_Metadata( + services_scanned=0, + expected_checks=[], + completed_checks=0, + audit_progress=0, + ), + audit_config={"max_unused_access_keys_days": 45}, + ) + return audit_info + + @mock_iam + def test_user_no_access_keys(self): + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused import ( + iam_user_accesskey_unused, + ) + + service_client.credential_report[0][ + "access_key_1_last_rotated" + ] == "N/A" + service_client.credential_report[0][ + "access_key_2_last_rotated" + ] == "N/A" + + check = iam_user_accesskey_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"User {user} does not have access keys." + ) + assert result[0].resource_id == user + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + @mock_iam + def test_user_access_key_1_not_used(self): + credentials_last_rotated = ( + datetime.datetime.now() - datetime.timedelta(days=100) + ).strftime("%Y-%m-%dT%H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused import ( + iam_user_accesskey_unused, + ) + + service_client.credential_report[0]["access_key_1_active"] = "true" + service_client.credential_report[0][ + "access_key_1_last_used_date" + ] = credentials_last_rotated + + check = iam_user_accesskey_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"User {user} has not used access key 1 in the last 45 days (100 days)." + ) + assert result[0].resource_id == user + "/AccessKey1" + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + @mock_iam + def test_user_access_key_2_not_used(self): + credentials_last_rotated = ( + datetime.datetime.now() - datetime.timedelta(days=100) + ).strftime("%Y-%m-%dT%H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused import ( + iam_user_accesskey_unused, + ) + + service_client.credential_report[0]["access_key_2_active"] = "true" + service_client.credential_report[0][ + "access_key_2_last_used_date" + ] = credentials_last_rotated + + check = iam_user_accesskey_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"User {user} has not used access key 2 in the last 45 days (100 days)." + ) + assert result[0].resource_id == user + "/AccessKey2" + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + @mock_iam + def test_user_both_access_keys_not_used(self): + credentials_last_rotated = ( + datetime.datetime.now() - datetime.timedelta(days=100) + ).strftime("%Y-%m-%dT%H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused import ( + iam_user_accesskey_unused, + ) + + service_client.credential_report[0]["access_key_1_active"] = "true" + service_client.credential_report[0][ + "access_key_1_last_used_date" + ] = credentials_last_rotated + + service_client.credential_report[0]["access_key_2_active"] = "true" + service_client.credential_report[0][ + "access_key_2_last_used_date" + ] = credentials_last_rotated + + check = iam_user_accesskey_unused() + result = check.execute() + assert len(result) == 2 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"User {user} has not used access key 1 in the last 45 days (100 days)." + ) + assert result[0].resource_id == user + "/AccessKey1" + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + assert result[1].status == "FAIL" + assert ( + result[1].status_extended + == f"User {user} has not used access key 2 in the last 45 days (100 days)." + ) + assert result[1].resource_id == user + "/AccessKey2" + assert result[1].resource_arn == arn + assert result[1].region == AWS_REGION + + @mock_iam + def test_user_both_access_keys_used(self): + credentials_last_rotated = ( + datetime.datetime.now() - datetime.timedelta(days=10) + ).strftime("%Y-%m-%dT%H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_accesskey_unused.iam_user_accesskey_unused import ( + iam_user_accesskey_unused, + ) + + service_client.credential_report[0]["access_key_1_active"] = "true" + service_client.credential_report[0][ + "access_key_1_last_used_date" + ] = credentials_last_rotated + + service_client.credential_report[0]["access_key_2_active"] = "true" + service_client.credential_report[0][ + "access_key_2_last_used_date" + ] = credentials_last_rotated + + check = iam_user_accesskey_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"User {user} does not have unused access keys for 45 days." + ) + assert result[0].resource_id == user + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION diff --git a/tests/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused_test.py b/tests/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused_test.py new file mode 100644 index 0000000000..09ace3cf0b --- /dev/null +++ b/tests/providers/aws/services/iam/iam_user_console_access_unused/iam_user_console_access_unused_test.py @@ -0,0 +1,158 @@ +import datetime +from unittest import mock + +from boto3 import client, session +from moto import mock_iam + +from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info +from prowler.providers.common.models import Audit_Metadata + +AWS_ACCOUNT_NUMBER = "123456789012" +AWS_REGION = "us-east-1" + + +class Test_iam_user_console_access_unused_test: + # Mocked Audit Info + def set_mocked_audit_info(self): + audit_info = AWS_Audit_Info( + session_config=None, + original_session=None, + audit_session=session.Session( + profile_name=None, + botocore_session=None, + region_name=AWS_REGION, + ), + audited_account=AWS_ACCOUNT_NUMBER, + audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root", + audited_user_id=None, + audited_partition="aws", + audited_identity_arn=None, + profile=None, + profile_region=AWS_REGION, + credentials=None, + assumed_role_info=None, + audited_regions=None, + organizations_metadata=None, + audit_resources=None, + mfa_enabled=False, + audit_metadata=Audit_Metadata( + services_scanned=0, + expected_checks=[], + completed_checks=0, + audit_progress=0, + ), + audit_config={"max_console_access_days": 45}, + ) + return audit_info + + @mock_iam + def test_iam_user_logged_45_days(self): + password_last_used = ( + datetime.datetime.now() - datetime.timedelta(days=2) + ).strftime("%Y-%m-%d %H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused import ( + iam_user_console_access_unused, + ) + + service_client.users[0].password_last_used = password_last_used + check = iam_user_console_access_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"User {user} has logged in to the console in the past 45 days (2 days)." + ) + assert result[0].resource_id == user + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + @mock_iam + def test_iam_user_not_logged_45_days(self): + password_last_used = ( + datetime.datetime.now() - datetime.timedelta(days=60) + ).strftime("%Y-%m-%d %H:%M:%S+00:00") + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused import ( + iam_user_console_access_unused, + ) + + service_client.users[0].password_last_used = password_last_used + check = iam_user_console_access_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"User {user} has not logged in to the console in the past 45 days (60 days)." + ) + assert result[0].resource_id == user + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION + + @mock_iam + def test_iam_user_not_logged(self): + iam_client = client("iam") + user = "test-user" + arn = iam_client.create_user(UserName=user)["User"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + audit_info = self.set_mocked_audit_info() + + with mock.patch( + "prowler.providers.aws.lib.audit_info.audit_info.current_audit_info", + new=audit_info, + ): + with mock.patch( + "prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused.iam_client", + new=IAM(audit_info), + ) as service_client: + from prowler.providers.aws.services.iam.iam_user_console_access_unused.iam_user_console_access_unused import ( + iam_user_console_access_unused, + ) + + service_client.users[0].password_last_used = "" + # raise Exception + check = iam_user_console_access_unused() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"User {user} does not have a console password or is unused." + ) + assert result[0].resource_id == user + assert result[0].resource_arn == arn + assert result[0].region == AWS_REGION