From 7e423a1ee195fd28f88ce67437160708aed2eff6 Mon Sep 17 00:00:00 2001 From: Scott Piper Date: Fri, 25 Oct 2019 08:28:38 -0600 Subject: [PATCH 1/4] Added parliament support --- Pipfile | 1 + audit_config.yaml | 6 ++++++ shared/audit.py | 2 ++ shared/iam_audit.py | 37 +++++++++++++++++++++++++++++++++++++ tests/unit/test_audit.py | 3 ++- 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index b9ce12a6a..57c610e3c 100644 --- a/Pipfile +++ b/Pipfile @@ -15,6 +15,7 @@ matplotlib = "==2.2.2" policyuniverse = "==1.1.0.1" PyYAML = "==4.2b4" Jinja2 = "==2.10.1" +parliament [dev-packages] autoflake = "==0.7" diff --git a/audit_config.yaml b/audit_config.yaml index 84d069141..fe800cdb2 100644 --- a/audit_config.yaml +++ b/audit_config.yaml @@ -204,6 +204,12 @@ IAM_UNEXPECTED_S3_EXFIL_PRINCIPAL: is_global: True group: IAM +IAM_LINTER: + title: IAM linting issues + description: Issues identified by the IAM linter Parliament + severity: Low + is_global: True + group: IAM IAM_NAME_DOES_NOT_INDICATE_ADMIN: title: Name does not indicate admin diff --git a/shared/audit.py b/shared/audit.py index a97f44bbb..8400ff2bf 100644 --- a/shared/audit.py +++ b/shared/audit.py @@ -206,7 +206,9 @@ def audit_guardduty(findings, region): def audit_iam(findings, region): + # By calling the code to find the admins, we'll excercise the code that finds problems. find_admins_in_account(region, findings) + # By default we get the findings for the admins, but we can also look for specific # privileges, so we'll look for who has s3:ListAllMyBuckets and then only use those # findings that are for a compute resource having this privilege diff --git a/shared/iam_audit.py b/shared/iam_audit.py index 9b5a8fca7..936759490 100644 --- a/shared/iam_audit.py +++ b/shared/iam_audit.py @@ -6,12 +6,14 @@ import os.path from policyuniverse.policy import Policy +from parliament import analyze_policy_string from netaddr import IPNetwork from shared.common import Finding, make_list, get_us_east_1 from shared.query import query_aws, get_parameter_file from shared.nodes import Account, Region + KNOWN_BAD_POLICIES = { "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM": "Use AmazonSSMManagedInstanceCore instead and add privs as needed", "arn:aws:iam::aws:policy/service-role/AmazonMachineLearningRoleforRedshiftDataSource": "Use AmazonMachineLearningRoleforRedshiftDataSourceV2 instead", @@ -196,6 +198,17 @@ def find_admins_in_account( check_for_bad_policy(findings, region, policy["Arn"], policy_doc) + analyzed_policy = analyze_policy_string(json.dumps(policy_doc)) + for f in analyzed_policy.findings: + findings.add( + Finding( + region, + "IAM_LINTER", + policy["Arn"], + resource_details={"issue": str(f.issue), "severity": str(f.severity), "location": str(f.location), "policy": policy_doc}, + ) + ) + policy_action_counts[policy["Arn"]] = policy_action_count(policy_doc, location) if is_admin_policy( @@ -260,6 +273,18 @@ def find_admins_in_account( for policy in role["RolePolicyList"]: policy_doc = policy["PolicyDocument"] + + analyzed_policy = analyze_policy_string(json.dumps(policy_doc)) + for f in analyzed_policy.findings: + findings.add( + Finding( + region, + "IAM_LINTER", + policy["Arn"], + resource_details={"issue": str(f.issue), "severity": str(f.severity), "location": str(f.location), "policy": policy_doc}, + ) + ) + if is_admin_policy( policy_doc, location, @@ -430,6 +455,18 @@ def find_admins_in_account( ) for policy in user.get("UserPolicyList", []): policy_doc = policy["PolicyDocument"] + + analyzed_policy = analyze_policy_string(json.dumps(policy_doc)) + for f in analyzed_policy.findings: + findings.add( + Finding( + region, + "IAM_LINTER", + policy["Arn"], + resource_details={"issue": str(f.issue), "severity": str(f.severity), "location": str(f.location), "policy": policy_doc}, + ) + ) + if is_admin_policy( policy_doc, location, diff --git a/tests/unit/test_audit.py b/tests/unit/test_audit.py index edf15df39..2f800e11e 100644 --- a/tests/unit/test_audit.py +++ b/tests/unit/test_audit.py @@ -44,7 +44,8 @@ def test_audit(self): "IAM_KNOWN_BAD_POLICY", "IAM_ROLE_ALLOWS_ASSUMPTION_FROM_ANYWHERE", "EC2_OLD", - "IAM_UNEXPECTED_S3_EXFIL_PRINCIPAL" + "IAM_UNEXPECTED_S3_EXFIL_PRINCIPAL", + "IAM_LINTER" ] ), ) From e2073c992ed6524a0ffa8099e6af9130acf72b0d Mon Sep 17 00:00:00 2001 From: Scott Piper Date: Mon, 18 Nov 2019 09:23:41 -0700 Subject: [PATCH 2/4] Set parliament versin to fix pipenv issue --- Pipfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 57c610e3c..8cfe5d89e 100644 --- a/Pipfile +++ b/Pipfile @@ -15,7 +15,7 @@ matplotlib = "==2.2.2" policyuniverse = "==1.1.0.1" PyYAML = "==4.2b4" Jinja2 = "==2.10.1" -parliament +parliament = "==0.2.1" [dev-packages] autoflake = "==0.7" From 2d9ed76523c2c44d9d5b05ddb511cfa68299dbe6 Mon Sep 17 00:00:00 2001 From: Scott Piper Date: Mon, 18 Nov 2019 09:31:25 -0700 Subject: [PATCH 3/4] Bump parliament version --- Pipfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 8cfe5d89e..cdec9bbe5 100644 --- a/Pipfile +++ b/Pipfile @@ -15,7 +15,7 @@ matplotlib = "==2.2.2" policyuniverse = "==1.1.0.1" PyYAML = "==4.2b4" Jinja2 = "==2.10.1" -parliament = "==0.2.1" +parliament = "==0.2.2" [dev-packages] autoflake = "==0.7" From c0dcc77bc506afa0144675d7e5bc3dec4ebb9247 Mon Sep 17 00:00:00 2001 From: Scott Piper Date: Mon, 18 Nov 2019 11:22:40 -0700 Subject: [PATCH 4/4] Bump version of parliament and CloudMapper --- Pipfile | 2 +- cloudmapper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Pipfile b/Pipfile index cdec9bbe5..b36b15e30 100644 --- a/Pipfile +++ b/Pipfile @@ -15,7 +15,7 @@ matplotlib = "==2.2.2" policyuniverse = "==1.1.0.1" PyYAML = "==4.2b4" Jinja2 = "==2.10.1" -parliament = "==0.2.2" +parliament = "==0.2.3" [dev-packages] autoflake = "==0.7" diff --git a/cloudmapper.py b/cloudmapper.py index ef2162cf8..8f274c29a 100755 --- a/cloudmapper.py +++ b/cloudmapper.py @@ -30,7 +30,7 @@ import pkgutil import importlib -__version__ = "2.7.2" +__version__ = "2.8.0" def show_help(commands):