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 57cca1d0..e79e3ddc 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 4843610c..3f21bda2 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 ae36ad36..d127ba64 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 a4727ac8..8683bc0a 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 825c4dd2..efea6123 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 1140c8be..d12da89f 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 c7ab997c..ff9e80f9 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 7b551c50..0c9c0be0 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 80fd667d..4be349cb 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 49fa51b6..7361d99f 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 6d12ccb0..2244bf53 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 46b763da..3a7d6313 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 76fc153c..4a41be71 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 5ee7dd0f..06551f03 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 9f9d8d68..9ce09e9a 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 e9da305c..18762737 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 85521ef2..a5ee842c 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 cf9f21eb..be28b486 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 326f417c..2db2d92f 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 0377786b..7ae657f2 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 87b88b75..800ebdcf 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 9710f25c..00000000 --- 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 e69de29b..00000000 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 bfbf065a..00000000 --- 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 30a01463..00000000 --- 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 8b2202fd..c5cbf8a8 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 48b94f35..5c8c948d 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 47375a07..aeb52eb3 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 00000000..7c7a12ce --- /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 d19f1d02..02d3b1b3 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 8df7411a..d22e826c 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 f1b61c48..f1bffb62 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 f1b61c48..f1bffb62 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 aa11f2be..70b07da0 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 f1b61c48..f1bffb62 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 241e163b..9cb4cd21 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 6aa9bab4..00000000 --- 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 c4834d5f..00000000 --- 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 f28d316b..00000000 --- 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 00000000..a36de6df --- /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 00000000..09ace3cf --- /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