From fc581846edf0f01e294457d00acfc5b904e34738 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 07:20:12 +0000 Subject: [PATCH 1/6] build(deps): bump actions/setup-python from 5.1.1 to 5.2.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.1 to 5.2.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/39cd14951b08e74b54015e9e001cdefcf80e669f...f677139bbe7f9c59b41e40162b753c062f5d49a3) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/check-packs.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- .github/workflows/upload.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check-packs.yml b/.github/workflows/check-packs.yml index 18e8586b8..b3bbe76db 100644 --- a/.github/workflows/check-packs.yml +++ b/.github/workflows/check-packs.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Set python version - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 #v5.2.0 with: python-version: "3.11" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9b8a3837b..93dbc05df 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Set python version - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 #v5.2.0 with: python-version: "3.11" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c96cf05a..e601601b9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,7 +29,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} role-session-name: panther-analysis-release - name: Install Python - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 #v5.2.0 with: python-version: "3.11" - name: Create new panther-analysis release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e06682440..562fc8b1e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Set python version - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 #v5.2.0 with: python-version: "3.11" diff --git a/.github/workflows/upload.yml b/.github/workflows/upload.yml index 9c006f026..7bc2a82ea 100644 --- a/.github/workflows/upload.yml +++ b/.github/workflows/upload.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 - name: Set python version - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 #v5.2.0 with: python-version: "3.11" From 41e993b72091b1d8186758fe46a5f07bd7038160 Mon Sep 17 00:00:00 2001 From: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:36:29 -0600 Subject: [PATCH 2/6] AWS SAML Activity Tuning (#1341) Co-authored-by: ben-githubs <38414634+ben-githubs@users.noreply.github.com> --- rules/aws_cloudtrail_rules/aws_saml_activity.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rules/aws_cloudtrail_rules/aws_saml_activity.py b/rules/aws_cloudtrail_rules/aws_saml_activity.py index 12f0f2e53..be99ecb62 100644 --- a/rules/aws_cloudtrail_rules/aws_saml_activity.py +++ b/rules/aws_cloudtrail_rules/aws_saml_activity.py @@ -9,6 +9,9 @@ def rule(event): ":assumed-role/AWSServiceRoleForSSO/AWS-SSO" ): return False + # Don't alert on errors such as EntityAlreadyExistsException and NoSuchEntity + if event.get("errorCode"): + return False return ( event.get("eventSource") == "iam.amazonaws.com" and event.get("eventName") in SAML_ACTIONS ) From f67b9248b36bc1e4ce85e95e2c4436d6becdb4fe Mon Sep 17 00:00:00 2001 From: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> Date: Wed, 4 Sep 2024 09:54:53 -0600 Subject: [PATCH 3/6] Tuning Snyk Rules (#1340) * Tuning Snyk Rules * remove org.project.edit --- rules/snyk_rules/snyk_misc_settings.py | 15 ++++----- rules/snyk_rules/snyk_org_settings.py | 15 ++++----- rules/snyk_rules/snyk_ou_change.py | 17 +++++----- rules/snyk_rules/snyk_project_settings.py | 20 ++++++------ rules/snyk_rules/snyk_project_settings.yml | 32 +++++++++++++++++++ rules/snyk_rules/snyk_role_change.py | 27 ++++++++-------- rules/snyk_rules/snyk_svcacct_change.py | 25 +++++++-------- .../snyk_rules/snyk_system_externalaccess.py | 19 ++++++----- rules/snyk_rules/snyk_system_policysetting.py | 19 ++++++----- rules/snyk_rules/snyk_system_sso.py | 7 ++-- rules/snyk_rules/snyk_user_mgmt.py | 25 +++++++-------- test_scenarios/jsonl_to_testfile.py | 3 +- 12 files changed, 124 insertions(+), 100 deletions(-) diff --git a/rules/snyk_rules/snyk_misc_settings.py b/rules/snyk_rules/snyk_misc_settings.py index 0e4ae52e6..5fead94f4 100644 --- a/rules/snyk_rules/snyk_misc_settings.py +++ b/rules/snyk_rules/snyk_misc_settings.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -11,21 +10,21 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() operation = ".".join(action.split(".")[1:]).title() return ( f"Snyk: [{group_or_org}] Setting " f"[{operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) @@ -35,8 +34,8 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) diff --git a/rules/snyk_rules/snyk_org_settings.py b/rules/snyk_rules/snyk_org_settings.py index 6338f1944..e4d972f1a 100644 --- a/rules/snyk_rules/snyk_org_settings.py +++ b/rules/snyk_rules/snyk_org_settings.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -18,21 +17,21 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() operation = ".".join(action.split(".")[1:]).title() return ( f"Snyk: [{group_or_org}] Setting " f"[{operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) @@ -42,8 +41,8 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) diff --git a/rules/snyk_rules/snyk_ou_change.py b/rules/snyk_rules/snyk_ou_change.py index 671d15f6f..af7111e67 100644 --- a/rules/snyk_rules/snyk_ou_change.py +++ b/rules/snyk_rules/snyk_ou_change.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -21,19 +20,19 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() return ( f"Snyk: [{group_or_org}] Organizational Unit settings have been modified " f"via [{action}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) @@ -43,15 +42,15 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) def severity(event): - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if action.endswith((".remove", ".delete")): return "HIGH" if action.endswith((".edit")): diff --git a/rules/snyk_rules/snyk_project_settings.py b/rules/snyk_rules/snyk_project_settings.py index 3e9b2e05d..5b2cff1d6 100644 --- a/rules/snyk_rules/snyk_project_settings.py +++ b/rules/snyk_rules/snyk_project_settings.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context # The bodies of these actions are quite diverse. @@ -13,7 +12,6 @@ "org.project.attributes.edit", "org.project.add", "org.project.delete", - "org.project.edit", "org.project.fix_pr.manual_open", "org.project.ignore.create", "org.project.ignore.delete", @@ -34,21 +32,23 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + if event.deep_get("content", "after", "description") == "No new Code Analysis issues found": + return False + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() operation = ".".join(action.split(".")[1:]).title() return ( f"Snyk: [{group_or_org}] " f"[{operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) @@ -61,15 +61,15 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) def severity(event): - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if action == "org.project.fix_pr.manual_open": return "INFO" return "LOW" diff --git a/rules/snyk_rules/snyk_project_settings.yml b/rules/snyk_rules/snyk_project_settings.yml index 68fa0b5b3..8cc4f5782 100644 --- a/rules/snyk_rules/snyk_project_settings.yml +++ b/rules/snyk_rules/snyk_project_settings.yml @@ -71,3 +71,35 @@ Tests: "event": "group.sso.membership.sync", "groupId": "8fffffff-1555-4444-b000-b55555555555", } + - Name: Snyk Org Project Edit + ExpectedResult: false + Log: + { + "content": { + "snapshotId": "69af7170-87cc-4939-bbaf-1fd99f80cde4" + }, + "created": "2024-09-02 23:49:37.552000000", + "event": "org.project.edit", + "orgId": "69af7170-87cc-4939-bbaf-1fd99f80cde4", + "projectId": "69af7170-87cc-4939-bbaf-1fd99f80cde4" + } + - Name: Snyk No New Code Issues Found + ExpectedResult: false + Log: + { + "content": { + "after": { + "description": "No new Code Analysis issues found", + "state": "success" + }, + "before": { + "state": "processing" + }, + "prCheckPublicId": "69af7170-87cc-4939-bbaf-1fd99f80cde4", + "prChecksGroupPublicId": "69af7170-87cc-4939-bbaf-1fd99f80cde4" + }, + "created": "2024-08-27 14:02:48.823000000", + "event": "org.project.pr_check.edit", + "orgId": "69af7170-87cc-4939-bbaf-1fd99f80cde4", + "projectId": "69af7170-87cc-4939-bbaf-1fd99f80cde4" + } \ No newline at end of file diff --git a/rules/snyk_rules/snyk_role_change.py b/rules/snyk_rules/snyk_role_change.py index 268fd2d66..b345077c0 100644 --- a/rules/snyk_rules/snyk_role_change.py +++ b/rules/snyk_rules/snyk_role_change.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -19,29 +18,29 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" crud_operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() crud_operation = action.split(".")[-1].title() return ( f"Snyk: [{group_or_org}] Role " f"[{crud_operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) def alert_context(event): a_c = snyk_alert_context(event) - role = deep_get(event, "content", "after", "role", default=None) - if not role and "afterRoleName" in deep_get(event, "content", default={}): - role = deep_get(event, "content", "afterRoleName", default=None) + role = event.deep_get("content", "after", "role", default=None) + if not role and "afterRoleName" in event.deep_get("content", default={}): + role = event.deep_get("content", "afterRoleName", default=None) if role: a_c["role_permission"] = role return a_c @@ -49,17 +48,17 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) def severity(event): - role = deep_get(event, "content", "after", "role", default=None) - if not role and "afterRoleName" in deep_get(event, "content", default={}): - role = deep_get(event, "content", "afterRoleName", default=None) + role = event.deep_get("content", "after", "role", default=None) + if not role and "afterRoleName" in event.deep_get("content", default={}): + role = event.deep_get("content", "afterRoleName", default=None) if role == "ADMIN": return "CRITICAL" return "MEDIUM" diff --git a/rules/snyk_rules/snyk_svcacct_change.py b/rules/snyk_rules/snyk_svcacct_change.py index f1b4c97a6..d301009f6 100644 --- a/rules/snyk_rules/snyk_svcacct_change.py +++ b/rules/snyk_rules/snyk_svcacct_change.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -16,29 +15,29 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): group_or_org = "" crud_operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() crud_operation = action.split(".")[-1].title() return ( f"Snyk: [{group_or_org}] Service Account " f"[{crud_operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) def alert_context(event): a_c = snyk_alert_context(event) - role = deep_get(event, "content", "role", "role", default=None) + role = event.deep_get("content", "role", "role", default=None) if not role: - role = deep_get(event, "content", "role", default=None) + role = event.deep_get("content", "role", default=None) if role: a_c["role_permission"] = role return a_c @@ -46,18 +45,18 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) def severity(event): - action = deep_get(event, "event", default="") - role = deep_get(event, "content", "role", "role", default=None) + action = event.deep_get("event", default="") + role = event.deep_get("content", "role", "role", default=None) if not role: - role = deep_get(event, "content", "role", default=None) + role = event.deep_get("content", "role", default=None) if all( [role == "ADMIN", action.endswith((".service_account.create", ".service_account.delete"))] ): diff --git a/rules/snyk_rules/snyk_system_externalaccess.py b/rules/snyk_rules/snyk_system_externalaccess.py index 1a192454c..d2dc43aa9 100644 --- a/rules/snyk_rules/snyk_system_externalaccess.py +++ b/rules/snyk_rules/snyk_system_externalaccess.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -11,39 +10,39 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): - current_setting = deep_get(event, "content", "after", "isEnabled", default=False) - action = deep_get(event, "event", default="") + current_setting = event.deep_get("content", "after", "isEnabled", default=False) + action = event.deep_get("event", default="") if "." in action: action = action.split(".")[0].title() return ( f"Snyk: [{action}] External Access settings have been modified " f"to PermitExternalUsers:[{current_setting}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) def alert_context(event): a_c = snyk_alert_context(event) - current_setting = deep_get(event, "content", "after", "isEnabled", default=False) + current_setting = event.deep_get("content", "after", "isEnabled", default=False) a_c["current_setting"] = current_setting return a_c def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" ) def severity(event): - current_setting = deep_get(event, "content", "after", "isEnabled", default=False) + current_setting = event.deep_get("content", "after", "isEnabled", default=False) if current_setting: return "HIGH" return "INFO" diff --git a/rules/snyk_rules/snyk_system_policysetting.py b/rules/snyk_rules/snyk_system_policysetting.py index beaa2ae68..b5844c1f8 100644 --- a/rules/snyk_rules/snyk_system_policysetting.py +++ b/rules/snyk_rules/snyk_system_policysetting.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -14,28 +13,28 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): policy_type = "" - license_or_rule = deep_get(event, "content", "after", "configuration", default={}) + license_or_rule = event.deep_get("content", "after", "configuration", default={}) if "rules" in license_or_rule: policy_type = "security" elif "licenses" in license_or_rule: policy_type = "license" return ( f"Snyk: System [{policy_type}] Policy Setting event " - f"[{deep_get(event, 'event', default='')}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"[{event.deep_get('event', default='')}] " + f"performed by [{event.deep_get('userId', default='')}]" ) def alert_context(event): a_c = snyk_alert_context(event) a_c["policy_type"] = "" - license_or_rule = deep_get(event, "content", "after", "configuration", default={}) + license_or_rule = event.deep_get("content", "after", "configuration", default={}) if "rules" in license_or_rule: a_c["policy_type"] = "security" elif "licenses" in license_or_rule: @@ -46,8 +45,8 @@ def alert_context(event): def dedup(event): # Licenses can apply at org or group levels return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'content', 'publicId', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('content', 'publicId', default='')}" ) diff --git a/rules/snyk_rules/snyk_system_sso.py b/rules/snyk_rules/snyk_system_sso.py index 0f775f9b1..41bd7aded 100644 --- a/rules/snyk_rules/snyk_system_sso.py +++ b/rules/snyk_rules/snyk_system_sso.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -13,15 +12,15 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") return action in ACTIONS def title(event): return ( "Snyk: System SSO Setting event " - f"[{deep_get(event, 'event', default='')}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"[{event.deep_get('event', default='')}] " + f"performed by [{event.deep_get('userId', default='')}]" ) diff --git a/rules/snyk_rules/snyk_user_mgmt.py b/rules/snyk_rules/snyk_user_mgmt.py index 6ae378c42..f2201bf7b 100644 --- a/rules/snyk_rules/snyk_user_mgmt.py +++ b/rules/snyk_rules/snyk_user_mgmt.py @@ -1,5 +1,4 @@ from global_filter_snyk import filter_include_event -from panther_base_helpers import deep_get from panther_snyk_helpers import snyk_alert_context ACTIONS = [ @@ -26,13 +25,13 @@ def rule(event): if not filter_include_event(event): return False - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") # for org.user.add/group.user.add via SAML/SCIM # the attributes .userId and .content.publicUserId # have the same value if action.endswith(".user.add"): - target_user = deep_get(event, "content", "userPublicId", default="") - actor = deep_get(event, "userId", default="") + target_user = event.deep_get("content", "userPublicId", default="") + actor = event.deep_get("userId", default="") if target_user == actor: return False return action in ACTIONS @@ -41,14 +40,14 @@ def rule(event): def title(event): group_or_org = "" operation = "" - action = deep_get(event, "event", default="") + action = event.deep_get("event", default="") if "." in action: group_or_org = action.split(".")[0].title() operation = ".".join(action.split(".")[2:]).title() return ( f"Snyk: [{group_or_org}] User " f"[{operation}] " - f"performed by [{deep_get(event, 'userId', default='')}]" + f"performed by [{event.deep_get('userId', default='')}]" ) @@ -58,17 +57,17 @@ def alert_context(event): def dedup(event): return ( - f"{deep_get(event, 'userId', default='')}" - f"{deep_get(event, 'orgId', default='')}" - f"{deep_get(event, 'groupId', default='')}" - f"{deep_get(event, 'event', default='')}" + f"{event.deep_get('userId', default='')}" + f"{event.deep_get('orgId', default='')}" + f"{event.deep_get('groupId', default='')}" + f"{event.deep_get('event', default='')}" ) def severity(event): - role = deep_get(event, "content", "after", "role", default=None) - if not role and "afterRoleName" in deep_get(event, "content", default={}): - role = deep_get(event, "content", "afterRoleName", default=None) + role = event.deep_get("content", "after", "role", default=None) + if not role and "afterRoleName" in event.deep_get("content", default={}): + role = event.deep_get("content", "afterRoleName", default=None) if role == "ADMIN": return "CRITICAL" return "MEDIUM" diff --git a/test_scenarios/jsonl_to_testfile.py b/test_scenarios/jsonl_to_testfile.py index 3c779717e..6c1dff528 100644 --- a/test_scenarios/jsonl_to_testfile.py +++ b/test_scenarios/jsonl_to_testfile.py @@ -1,8 +1,9 @@ import argparse import csv import json -import os import logging +import os + import yaml From d195f9dff7371c6cf8088f0c6e4550cd71914569 Mon Sep 17 00:00:00 2001 From: ben-githubs <38414634+ben-githubs@users.noreply.github.com> Date: Wed, 4 Sep 2024 11:26:54 -0500 Subject: [PATCH 4/6] Update Pack Manifests with Data Models and Globals (#1342) * add missing data models to packs * add missing globals to packs --------- Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> --- packs/asana.yml | 3 +++ packs/atlassian.yml | 3 +++ packs/aws.yml | 2 ++ packs/azure_signin.yml | 3 +++ packs/box.yml | 3 +++ packs/cisco_umbrella_dns.yml | 3 ++- packs/cloudflare.yml | 3 +++ packs/credential_security.yml | 6 ++++++ packs/crowdstrike.yml | 2 ++ packs/crowdstrike_event_streams.yml | 3 +++ packs/gsuite_reports.yml | 2 ++ packs/multisource_correlations.yml | 14 +++++++++++++- packs/notion.yml | 9 ++++++--- packs/onelogin.yml | 3 +++ packs/slack.yml | 2 ++ packs/standard_ruleset.yml | 8 +++++++- packs/wiz.yml | 4 ++++ packs/zoom.yml | 5 +++-- 18 files changed, 70 insertions(+), 8 deletions(-) diff --git a/packs/asana.yml b/packs/asana.yml index 6e1346baf..e3ed3ccce 100644 --- a/packs/asana.yml +++ b/packs/asana.yml @@ -20,4 +20,7 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + # Data Model + - Standard.Asana.Audit DisplayName: "Panther Asana Pack" diff --git a/packs/atlassian.yml b/packs/atlassian.yml index 2e9616228..a729c0f30 100644 --- a/packs/atlassian.yml +++ b/packs/atlassian.yml @@ -9,4 +9,7 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + # Data Model + - Standard.Atlassian.Audit DisplayName: "Panther Atlassian Pack" diff --git a/packs/aws.yml b/packs/aws.yml index 0402ce05e..bb6233f4b 100644 --- a/packs/aws.yml +++ b/packs/aws.yml @@ -177,7 +177,9 @@ PackDefinition: # AWS DataModels - Standard.AWS.ALB - Standard.AWS.CloudTrail + - Standard.Amazon.EKS.Audit - Standard.AWS.S3ServerAccess + - Standard.AWS.VPCDns - Standard.AWS.VPCFlow - Standard.OCSF.NetworkActivity - Standard.OCSF.DnsActivity diff --git a/packs/azure_signin.yml b/packs/azure_signin.yml index 8669bf631..82feb941f 100644 --- a/packs/azure_signin.yml +++ b/packs/azure_signin.yml @@ -13,4 +13,7 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + # Data Models + - Standard.Azure.Audit.SignIn DisplayName: "Panther Azure.Audit SignIn Pack" diff --git a/packs/box.yml b/packs/box.yml index 2b0b593eb..b92654f19 100644 --- a/packs/box.yml +++ b/packs/box.yml @@ -18,4 +18,7 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + # Data Models + - Standard.Box.Event DisplayName: "Panther Box Pack" diff --git a/packs/cisco_umbrella_dns.yml b/packs/cisco_umbrella_dns.yml index 55cae731c..5723a00ef 100644 --- a/packs/cisco_umbrella_dns.yml +++ b/packs/cisco_umbrella_dns.yml @@ -4,5 +4,6 @@ Description: Group of all Cisco Umbrella detections PackDefinition: IDs: - CiscoUmbrella.DNS.Blocked - # Globals used in these detections + # Data Model + - Standard.CiscoUmbrella.DNS DisplayName: "Panther Cisco Umbrella Pack" diff --git a/packs/cloudflare.yml b/packs/cloudflare.yml index 80c6e0faa..5aa901364 100644 --- a/packs/cloudflare.yml +++ b/packs/cloudflare.yml @@ -14,3 +14,6 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + # Data Models + - Standard.Cloudflare.Firewall + - Standard.Cloudflare.HttpReq diff --git a/packs/credential_security.yml b/packs/credential_security.yml index b0dad1886..c11e46c5d 100644 --- a/packs/credential_security.yml +++ b/packs/credential_security.yml @@ -5,10 +5,16 @@ DisplayName: "Panther Credential Security Pack" PackDefinition: IDs: # Data Models + - Standard.Asana.Audit - Standard.Atlassian.Audit + - Standard.AWS.CloudTrail + - Standard.Crowdstrike.FDR - Standard.Github.Audit - Standard.Okta.SystemLog + - Standard.OneLogin.Events + - Standard.Slack.AuditLogs - Standard.Zendesk.AuditLog + - Standard.Zoom.Operation # Global Helpers - global_filter_auth0 - global_filter_github diff --git a/packs/crowdstrike.yml b/packs/crowdstrike.yml index 5ce41a668..6d90ef2f9 100644 --- a/packs/crowdstrike.yml +++ b/packs/crowdstrike.yml @@ -24,5 +24,7 @@ PackDefinition: - panther_config_defaults - panther_config_overrides # Data models + - Standard.AWS.VPCDns + - Standard.CiscoUmbrella.DNS - Standard.Crowdstrike.FDR DisplayName: "Panther Crowdstrike Pack" diff --git a/packs/crowdstrike_event_streams.yml b/packs/crowdstrike_event_streams.yml index ec9c55caf..cd22520f4 100644 --- a/packs/crowdstrike_event_streams.yml +++ b/packs/crowdstrike_event_streams.yml @@ -5,6 +5,9 @@ PackDefinition: IDs: - crowdstrike_event_streams_helpers - panther_base_helpers + - panther_config + - panther_config_defaults + - panther_config_overrides - Crowdstrike.AdminRoleAssigned - Crowdstrike.AllowlistRemoved diff --git a/packs/gsuite_reports.yml b/packs/gsuite_reports.yml index 828c0a5da..471be6e2e 100644 --- a/packs/gsuite_reports.yml +++ b/packs/gsuite_reports.yml @@ -39,4 +39,6 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + - panther_lookuptable_helpers DisplayName: "Panther GSuite Pack" diff --git a/packs/multisource_correlations.yml b/packs/multisource_correlations.yml index 78277452b..1500f6e7e 100644 --- a/packs/multisource_correlations.yml +++ b/packs/multisource_correlations.yml @@ -16,4 +16,16 @@ PackDefinition: - Okta.Login.Success - Push.Security.Authorized.IdP.Login - Okta.Login.Without.Push.Marker - - Push.Security.Phishing.Attack \ No newline at end of file + - Push.Security.Phishing.Attack + + # Data Models + - Standard.Okta.SystemLog + - Standard.Github.Audit + - Standard.AWS.CloudTrail + + # Global Helpers + - panther_base_helpers + - panther_config + - panther_config_defaults + - panther_config_overrides + - panther_event_type_helpers \ No newline at end of file diff --git a/packs/notion.yml b/packs/notion.yml index c0b683634..8e26d0ca8 100644 --- a/packs/notion.yml +++ b/packs/notion.yml @@ -18,13 +18,16 @@ PackDefinition: - Notion.SharingSettingsUpdated - Notion.TeamspaceOwnerAdded # Globals used in these detections - - panther_base_helpers - - panther_oss_helpers - - panther_notion_helpers - global_filter_notion + - panther_base_helpers - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + - panther_ipinfo_helpers + - panther_lookuptable_helpers + - panther_notion_helpers + - panther_oss_helpers # Data Model - Standard.Notion.AuditLogs DisplayName: "Panther Notion Pack" diff --git a/packs/onelogin.yml b/packs/onelogin.yml index 30f8166b5..cf985947d 100644 --- a/packs/onelogin.yml +++ b/packs/onelogin.yml @@ -20,4 +20,7 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + # Data Model + - Standard.OneLogin.Events DisplayName: "Panther OneLogin Pack" diff --git a/packs/slack.yml b/packs/slack.yml index 4766ae4ea..2437cceb5 100644 --- a/packs/slack.yml +++ b/packs/slack.yml @@ -32,3 +32,5 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + # Data Model + - Standard.Slack.AuditLogs diff --git a/packs/standard_ruleset.yml b/packs/standard_ruleset.yml index 41cad90e0..92f7f84b3 100644 --- a/packs/standard_ruleset.yml +++ b/packs/standard_ruleset.yml @@ -27,6 +27,12 @@ PackDefinition: - Standard.NewAWSAccountCreated - Standard.NewUserAccountCreated # Global Helpers + - panther_base_helpers + - panther_default + - panther_config + - panther_config_defaults + - panther_config_overrides - panther_event_type_helpers + - panther_ipinfo_helpers + - panther_lookuptable_helpers - panther_oss_helpers - - panther_default diff --git a/packs/wiz.yml b/packs/wiz.yml index d04e487ca..68b2cce38 100644 --- a/packs/wiz.yml +++ b/packs/wiz.yml @@ -5,3 +5,7 @@ DisplayName: "Panther Wiz Pack" PackDefinition: IDs: - Wiz.Alert.Passthrough + - panther_base_helpers + - panther_config + - panther_config_defaults + - panther_config_overrides diff --git a/packs/zoom.yml b/packs/zoom.yml index 454d05822..18a7ba113 100644 --- a/packs/zoom.yml +++ b/packs/zoom.yml @@ -16,8 +16,9 @@ PackDefinition: - Standard.Zoom.Operation # Globals used in these detections - panther_base_helpers - - panther_oss_helpers - - panther_zoom_helpers - panther_config - panther_config_defaults - panther_config_overrides + - panther_event_type_helpers + - panther_oss_helpers + - panther_zoom_helpers From dfa4abf85d0d4d45a01f478a7ff42b1d16007f97 Mon Sep 17 00:00:00 2001 From: biancafu-panther <165093171+biancafu-panther@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:02:27 -0600 Subject: [PATCH 5/6] Added get_actor_user method to GCP.AuditLog data model (#1343) --- data_models/gcp_data_model.py | 7 ++ data_models/gcp_data_model.yml | 4 +- ...s_get_access_token_privilege_escalation.py | 4 +- ..._get_access_token_privilege_escalation.yml | 66 +++++++++++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/data_models/gcp_data_model.py b/data_models/gcp_data_model.py index 26c7e82e7..46d236d1c 100644 --- a/data_models/gcp_data_model.py +++ b/data_models/gcp_data_model.py @@ -112,3 +112,10 @@ def get_verb(event): if deep_get(event, "protoPayload", "serviceName", default="") != "k8s.io": return "" return deep_get(event, "protoPayload", "methodName", default="").split(".")[-1] + + +def get_actor_user(event): + authentication_info = deep_get(event, "protoPayload", "authenticationInfo", default={}) + if principal_email := authentication_info.get("principalEmail"): + return principal_email + return authentication_info.get("principalSubject", "") diff --git a/data_models/gcp_data_model.yml b/data_models/gcp_data_model.yml index 9a4bfdea2..60614f9c5 100644 --- a/data_models/gcp_data_model.yml +++ b/data_models/gcp_data_model.yml @@ -7,7 +7,7 @@ Filename: gcp_data_model.py Enabled: true Mappings: - Name: actor_user - Path: $.protoPayload.authenticationInfo.principalEmail + Method: get_actor_user - Name: assigned_admin_role Method: get_iam_roles - Name: event_type @@ -35,7 +35,7 @@ Mappings: - Name: sourceIPs Method: get_source_ips - Name: username - Path: $.protoPayload.authenticationInfo.principalEmail + Method: get_actor_user - Name: userAgent Path: $.protoPayload.requestMetadata.callerSuppliedUserAgent - Name: verb diff --git a/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.py b/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.py index a0b73e0d3..44b90b4f9 100644 --- a/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.py +++ b/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.py @@ -17,9 +17,7 @@ def rule(event): def title(event): - actor = deep_get( - event, "protoPayload", "authenticationInfo", "principalEmail", default="" - ) + actor = event.udm("actor_user") operation = deep_get(event, "protoPayload", "methodName", default="") project_id = deep_get(event, "resource", "labels", "project_id", default="") diff --git a/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.yml b/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.yml index a273d9632..5e47cac31 100644 --- a/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.yml +++ b/rules/gcp_audit_rules/gcp_iam_service_accounts_get_access_token_privilege_escalation.yml @@ -18,6 +18,7 @@ Tests: ExpectedResult: true Log: { + "p_log_type": "GCP.AuditLog", "protoPayload": { "@type": "type.googleapis.com/google.cloud.audit.AuditLog", @@ -72,6 +73,7 @@ Tests: ExpectedResult: false Log: { + "p_log_type": "GCP.AuditLog", "protoPayload": { "@type": "type.googleapis.com/google.cloud.audit.AuditLog", @@ -122,3 +124,67 @@ Tests: "logName": "projects/some-project/logs/cloudaudit.googleapis.com%2Fdata_access", "receiveTimestamp": "2024-02-26T17:15:17.100020459Z", } + - Name: Principal Subject Used + ExpectedResult: true + Log: + { + "p_log_type": "GCP.AuditLog", + "insertId": "1dy9ihte4iyjz", + "logName": "projects/mylogs/logs/cloudaudit.googleapis.com%2Fdata_access", + "operation": { + "first": true, + "id": "10172500524907939495", + "last": true, + "producer": "­iamcredentials.googleapis.com" + }, + "protoPayload": { + "at_sign_type": "­type.googleapis.com/google.cloud.audit.AuditLog", + "authenticationInfo": { + "principalSubject": "example_principal_subject", + "serviceAccountDelegationInfo": [ + {} + ] + }, + "authorizationInfo": [ + { + "granted": true, + "permission": "iam.serviceAccounts.getAccessToken", + "resourceAttributes": {} + } + ], + "metadata": { + "identityDelegationChain": [ + "projects/-/serviceAccounts/xxxxx.iam.gserviceaccount.com" + ] + }, + "methodName": "GenerateAccessToken", + "request": { + "@type": "­type.googleapis.com/google.iam.credentials.v1.GenerateAccessTokenRequest", + "name": "projects/-/serviceAccounts/xxxxx.iam.gserviceaccount.com" + }, + "requestMetadata": { + "callerIP": "gce-internal-ip", + "callerSuppliedUserAgent": "google-api-go-client/0.5 gke-metadata-server,gzip(gfe)", + "destinationAttributes": {}, + "requestAttributes": { + "auth": {}, + "time": "2024-08-29T19:30:36.353462175Z" + } + }, + "resourceName": "projects/-/serviceAccounts/11111222223333444455", + "serviceName": "­iamcredentials.googleapis.com", + "status": {} + }, + "receiveTimestamp": "2024-08-29 19:30:36.424542070", + "resource": { + "labels": { + "email_id": "sample@email.com", + "project_id": "sample_project_id", + "unique_id": "11111222223333444455" + }, + "type": "service_account" + }, + "severity": "INFO", + "timestamp": "2024-08-29 19:30:36.339983306" + } + From 01473353a53fc4a980da54b14dc94d35314d4729 Mon Sep 17 00:00:00 2001 From: ben-githubs <38414634+ben-githubs@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:24:58 -0500 Subject: [PATCH 6/6] add missing pack items (#1345) Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com> --- packs/aws.yml | 6 +++++- packs/github.yml | 1 + packs/gsuite_reports.yml | 3 +++ packs/kubernetes.yml | 16 ++++++++++++++++ packs/okta.yml | 2 ++ packs/onepassword.yml | 2 ++ packs/snowflake.yml | 1 + 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packs/aws.yml b/packs/aws.yml index bb6233f4b..b0e549ee8 100644 --- a/packs/aws.yml +++ b/packs/aws.yml @@ -173,7 +173,11 @@ PackDefinition: - AWS.CloudTrail.UserAccessKeyAuth - AWS.CloudTrail.LoginProfileCreatedOrModified - AWS.Console.Login - + # Queries + - AWS Authentication from CrowdStrike Unmanaged Device + - Query.CloudTrail.Password.Spraying + - Query.VPC.DNS.Tunneling + - VPC Flow Port Scanning # AWS DataModels - Standard.AWS.ALB - Standard.AWS.CloudTrail diff --git a/packs/github.yml b/packs/github.yml index 4352b6dac..d0fcf0bb7 100644 --- a/packs/github.yml +++ b/packs/github.yml @@ -12,6 +12,7 @@ PackDefinition: - GitHub.Org.IpAllowlist - GitHub.Org.Moderators.Add - GitHub.Org.Modified + - Github.Repo.Archived - Github.Repo.CollaboratorChange - Github.Repo.Created #- GitHub.Repo.HookModified diff --git a/packs/gsuite_reports.yml b/packs/gsuite_reports.yml index 471be6e2e..3ecd1f099 100644 --- a/packs/gsuite_reports.yml +++ b/packs/gsuite_reports.yml @@ -41,4 +41,7 @@ PackDefinition: - panther_config_overrides - panther_event_type_helpers - panther_lookuptable_helpers + # Queries + - GSuite Many Docs Deleted Query + - GSuite Many Docs Downloaded Query DisplayName: "Panther GSuite Pack" diff --git a/packs/kubernetes.yml b/packs/kubernetes.yml index 9026cb7dd..9306e676b 100644 --- a/packs/kubernetes.yml +++ b/packs/kubernetes.yml @@ -20,3 +20,19 @@ PackDefinition: - Kubernetes.ServiceTypeNodePortDeployed - Kubernetes.UnauthenticatedAPIRequest - Kubernetes.UnauthorizedPodExecution + # Queries + - IOC Activity in K8 Control Plane + - Kubernetes Cron Job Created or Modified + - Kubernetes Pod Created in Pre-Configured or Default Name Spaces + - Kubernetes Service with Type Node Port Deployed + - New Admission Controller Created + - New DaemonSet Deployed to Kubernetes + - Pod Created or Modified Using the Host IPC Namespace + - Pod Created or Modified Using the Host PID Namespace + - Pod Created with Overly Permissive Linux Capabilities + - Pod attached to the Node Host Network + - Pod creation or modification to a Host Path Volume Mount + - Privileged Pod Created + - Secret Enumeration by a User + - Unauthenticated Kubernetes API Request + - Unauthorized Kubernetes Pod Execution \ No newline at end of file diff --git a/packs/okta.yml b/packs/okta.yml index 49f2fae72..9d0906103 100644 --- a/packs/okta.yml +++ b/packs/okta.yml @@ -35,6 +35,8 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + # Queries + - Okta Login From CrowdStrike Unmanaged Device # Data Model - Standard.Okta.SystemLog DisplayName: "Panther Okta Pack" diff --git a/packs/onepassword.yml b/packs/onepassword.yml index 386645dc0..6fb20019c 100644 --- a/packs/onepassword.yml +++ b/packs/onepassword.yml @@ -15,3 +15,5 @@ PackDefinition: - panther_config - panther_config_defaults - panther_config_overrides + # Queries + - 1Password Login From CrowdStrike Unmanaged Device Query diff --git a/packs/snowflake.yml b/packs/snowflake.yml index d8ae02c1d..7ee3b1511 100644 --- a/packs/snowflake.yml +++ b/packs/snowflake.yml @@ -13,6 +13,7 @@ PackDefinition: - Query.Snowflake.BruteForceByIp - Query.Snowflake.BruteForceByUsername - Query.Snowflake.ClientIp + - Query.Snowflake.ConfigurationDrift - Query.Snowflake.CopyIntoStage - Query.Snowflake.External.Shares - Query.Snowflake.FileDownloaded