diff --git a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/policies.tf b/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/policies.tf deleted file mode 100644 index d6d5c0950..000000000 --- a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/policies.tf +++ /dev/null @@ -1,47 +0,0 @@ -# AWS > IAM > Root > Approved -resource "turbot_policy_setting" "aws_iam_root_approved" { - resource = turbot_policy_pack.main.id - type = "tmod:@turbot/aws-iam#/policy/types/rootApproved" - value = "Check: Approved" -} - -# AWS > IAM > Root > Approved > Custom -resource "turbot_policy_setting" "aws_iam_root_approved_custom" { - resource = turbot_policy_pack.main.id - type = "tmod:@turbot/aws-iam#/policy/types/rootApprovedCustom" - template_input = <<-EOT - { - root { - mfaActive: get(path: "mfa_active") - } - } - EOT - template = <<-EOT - {%- if $.root.mfaActive == "true" -%} - - {%- set data = { - "title": "MFA Enabled", - "result": "Approved", - "message": "MFA is enabled on root account" - } -%} - - {%- elif $.root.mfaActive == "false" -%} - - {%- set data = { - "title": "MFA Enabled", - "result": "Not approved", - "message": "MFA is not enabled on root account" - } -%} - - {%- else -%} - - {%- set data = { - "title": "MFA Enabled", - "result": "Skip", - "message": "No data for MFA yet" - } -%} - - {%- endif -%} - {{ data | json }} - EOT -} diff --git a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/README.md b/policy_packs/aws/iam/check_root_account_security_usage/README.md similarity index 68% rename from policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/README.md rename to policy_packs/aws/iam/check_root_account_security_usage/README.md index 5474726ec..746f9da4f 100644 --- a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/README.md +++ b/policy_packs/aws/iam/check_root_account_security_usage/README.md @@ -3,13 +3,17 @@ categories: ["access management", "security"] primary_category: "security" --- -# Check MFA Is Enabled for AWS IAM Root Accounts +# Check Root Account Access Usage -Ensuring Multi-Factor Authentication (MFA) is enabled for AWS IAM root accounts is critical as it provides an additional layer of security beyond just a password, significantly reducing the risk of unauthorized access. This protection helps prevent potential security breaches and enhances overall account security by requiring a second form of verification. +Monitoring access activity for AWS IAM root accounts is essential for maintaining a secure cloud environment. This policy checks for critical access indicators that could pose security risks if left unmonitored — including MFA status, recent usage of the root password, and access key activity. -This [policy pack](https://turbot.com/guardrails/docs/concepts/policy-packs) can help you configure the following settings for IAM root accounts: +Root accounts are highly privileged and should ideally remain unused. This policy ensures that any recent access patterns — whether via password or keys — are detected and flagged if they fall outside the approved window. -- Check and alarm if root accounts do not have MFA enabled +This [policy pack](https://turbot.com/guardrails/docs/concepts/policy-packs) helps you enforce the following controls on IAM root accounts: + - Check and alert if MFA is not enabled + - Detect if the root password was used in the last 14 days + - Check if Access Key 1 or Access Key 2 was used within the last 14 days + - Identify active access keys that are unused but still present ## Documentation @@ -53,7 +57,7 @@ Clone: ```sh git clone https://github.com/turbot/guardrails-samples.git -cd guardrails-samples/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts +cd guardrails-samples/policy_packs/aws/iam/check_root_account_access_usage ``` Run the Terraform to create the policy pack in your workspace: diff --git a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/main.tf b/policy_packs/aws/iam/check_root_account_security_usage/main.tf similarity index 100% rename from policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/main.tf rename to policy_packs/aws/iam/check_root_account_security_usage/main.tf diff --git a/policy_packs/aws/iam/check_root_account_security_usage/policies.tf b/policy_packs/aws/iam/check_root_account_security_usage/policies.tf new file mode 100644 index 000000000..dfedf8c9e --- /dev/null +++ b/policy_packs/aws/iam/check_root_account_security_usage/policies.tf @@ -0,0 +1,126 @@ +# AWS > IAM > Root > Approved +resource "turbot_policy_setting" "aws_iam_root_approved" { + resource = turbot_policy_pack.main.id + type = "tmod:@turbot/aws-iam#/policy/types/rootApproved" + value = "Check: Approved" +} + +# AWS > IAM > Root > Approved > Custom +resource "turbot_policy_setting" "aws_iam_root_approved_custom" { + resource = turbot_policy_pack.main.id + type = "tmod:@turbot/aws-iam#/policy/types/rootApprovedCustom" + template_input = <<-EOT + { + root { + mfaActive: get(path: "mfa_active") + passwordEnabled: get(path: "password_enabled") + passwordLastUsed: get(path: "password_last_used") + accessKey1Active: get(path: "access_key_1_active") + accessKey1LastUsed: get(path: "access_key_1_last_used") + accessKey2Active: get(path: "access_key_2_active") + accessKey2LastUsed: get(path: "access_key_2_last_used") + } + } +EOT + template = <<-EOT +{%- set now = "now" | date("constructor") -%} +{%- set nowMs = now | date("getTime") -%} +{%- set fourteenDaysMs = 14 * 24 * 60 * 60 * 1000 -%} +{%- set fourteenDaysAgo = nowMs - fourteenDaysMs -%} + +[ + {# MFA Check #} + {%- if $.root.mfaActive == "true" -%} + { + "title": "MFA", + "result": "Approved", + "message": "MFA is enabled" + }, + {%- else -%} + { + "title": "MFA", + "result": "Not approved", + "message": "MFA is not enabled" + }, + {%- endif -%} + + {# Password Usage Check #} + {%- if $.root.passwordEnabled == "true" and $.root.passwordLastUsed -%} + {%- set pwdMs = $.root.passwordLastUsed | date("getTime") -%} + {%- if pwdMs > fourteenDaysAgo -%} + { + "title": "Password Usage", + "result": "Not approved", + "message": "Root password was used within the last 14 days" + }, + {%- else -%} + { + "title": "Password Usage", + "result": "Approved", + "message": "Root password has not been used in the last 14 days" + }, + {%- endif -%} + {%- elif $.root.passwordEnabled == "false" -%} + { + "title": "Password Usage", + "result": "Approved", + "message": "Root password is disabled" + }, + {%- else -%} + { + "title": "Password Usage", + "result": "Approved", + "message": "Password enabled but never used" + }, + {%- endif -%} + + {# Access Key 1 Check #} + {%- if $.root.accessKey1Active == "true" and $.root.accessKey1LastUsed -%} + {%- set ak1Ms = $.root.accessKey1LastUsed | date("getTime") -%} + {%- if ak1Ms > fourteenDaysAgo -%} + { + "title": "Access Key 1", + "result": "Not approved", + "message": "Access Key 1 was used within the last 14 days" + }, + {%- else -%} + { + "title": "Access Key 1", + "result": "Approved", + "message": "Access Key 1 not used in last 14 days" + }, + {%- endif -%} + {%- else -%} + { + "title": "Access Key 1", + "result": "Approved", + "message": "Access Key 1 inactive or never used" + }, + {%- endif -%} + + {# Access Key 2 Check #} + {%- if $.root.accessKey2Active == "true" and $.root.accessKey2LastUsed -%} + {%- set ak2Ms = $.root.accessKey2LastUsed | date("getTime") -%} + {%- if ak2Ms > fourteenDaysAgo -%} + { + "title": "Access Key 2", + "result": "Not approved", + "message": "Access Key 2 was used within the last 14 days" + } + {%- else -%} + { + "title": "Access Key 2", + "result": "Approved", + "message": "Access Key 2 not used in last 14 days" + } + {%- endif -%} + {%- else -%} + { + "title": "Access Key 2", + "result": "Approved", + "message": "Access Key 2 inactive or never used" + } + {%- endif -%} +] +EOT +} diff --git a/policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/providers.tf b/policy_packs/aws/iam/check_root_account_security_usage/providers.tf similarity index 100% rename from policy_packs/aws/iam/check_mfa_is_enabled_for_root_accounts/providers.tf rename to policy_packs/aws/iam/check_root_account_security_usage/providers.tf