From 1ba35030de8f6c93762fe9eb9185a2a81b18c825 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Tue, 2 Sep 2025 14:31:53 +0100 Subject: [PATCH 1/3] feat: change to nested structure --- example-data/testorg-unremediated.json | 14 ++++++++------ example-data/testorg.json | 14 ++++++++------ policies/gh_org_mfa_enabled.rego | 2 +- policies/gh_org_mfa_enabled_test.rego | 8 ++++++-- policies/gh_org_public_repos.rego | 10 +++++----- policies/gh_org_public_repos_test.rego | 12 ++++++++---- 6 files changed, 36 insertions(+), 24 deletions(-) diff --git a/example-data/testorg-unremediated.json b/example-data/testorg-unremediated.json index bbf4c67..bd7926c 100644 --- a/example-data/testorg-unremediated.json +++ b/example-data/testorg-unremediated.json @@ -1,4 +1,5 @@ { + "settings": { "login": "test-org", "id": 1234567, "node_id": "O_abcdefg", @@ -43,11 +44,11 @@ "members_can_create_public_pages": true, "members_can_create_private_pages": true, "plan": { - "name": "free", - "space": 976562499, - "private_repos": 10000, - "filled_seats": 2, - "seats": 1 + "name": "free", + "space": 976562499, + "private_repos": 10000, + "filled_seats": 2, + "seats": 1 }, "advanced_security_enabled_for_new_repositories": false, "dependabot_alerts_enabled_for_new_repositories": false, @@ -58,4 +59,5 @@ "secret_scanning_push_protection_custom_link_enabled": false, "secret_scanning_push_protection_custom_link": null, "secret_scanning_validity_checks_enabled": false -} \ No newline at end of file + } +} diff --git a/example-data/testorg.json b/example-data/testorg.json index 776e00f..946e674 100644 --- a/example-data/testorg.json +++ b/example-data/testorg.json @@ -1,4 +1,5 @@ { + "settings": { "login": "test-org", "id": 1234567, "node_id": "O_abcdefg", @@ -43,11 +44,11 @@ "members_can_create_public_pages": false, "members_can_create_private_pages": true, "plan": { - "name": "free", - "space": 976562499, - "private_repos": 10000, - "filled_seats": 2, - "seats": 1 + "name": "free", + "space": 976562499, + "private_repos": 10000, + "filled_seats": 2, + "seats": 1 }, "advanced_security_enabled_for_new_repositories": true, "dependabot_alerts_enabled_for_new_repositories": true, @@ -58,4 +59,5 @@ "secret_scanning_push_protection_custom_link_enabled": true, "secret_scanning_push_protection_custom_link": null, "secret_scanning_validity_checks_enabled": true -} \ No newline at end of file + } +} diff --git a/policies/gh_org_mfa_enabled.rego b/policies/gh_org_mfa_enabled.rego index 2ada568..494144d 100644 --- a/policies/gh_org_mfa_enabled.rego +++ b/policies/gh_org_mfa_enabled.rego @@ -1,7 +1,7 @@ package compliance_framework.mfa_enabled violation[{}] if { - input.two_factor_requirement_enabled == false + input.settings.two_factor_requirement_enabled == false } title := "Two Factor Authentication is required at an organization level" diff --git a/policies/gh_org_mfa_enabled_test.rego b/policies/gh_org_mfa_enabled_test.rego index ca33023..9534d0c 100644 --- a/policies/gh_org_mfa_enabled_test.rego +++ b/policies/gh_org_mfa_enabled_test.rego @@ -2,12 +2,16 @@ package compliance_framework.mfa_enabled test_mfa_enabled if { count(violation) == 0 with input as { - "two_factor_requirement_enabled": true + "settings": { + "two_factor_requirement_enabled": true + } } } test_mfa_violate_if_disabled if { count(violation) > 0 with input as { - "two_factor_requirement_enabled": false + "settings": { + "two_factor_requirement_enabled": false + } } } \ No newline at end of file diff --git a/policies/gh_org_public_repos.rego b/policies/gh_org_public_repos.rego index d765d6a..4ab13a6 100644 --- a/policies/gh_org_public_repos.rego +++ b/policies/gh_org_public_repos.rego @@ -1,15 +1,15 @@ package compliance_framework.public_repos -checks["repos"] if { - input.public_repos > 0 +_checks["repos"] if { + input.settings.public_repos > 0 } -checks["gists"] if { - input.public_gists > 0 +_checks["gists"] if { + input.settings.public_gists > 0 } violation[{}] if { - some check in checks + some check in _checks } diff --git a/policies/gh_org_public_repos_test.rego b/policies/gh_org_public_repos_test.rego index 962561d..a98d212 100644 --- a/policies/gh_org_public_repos_test.rego +++ b/policies/gh_org_public_repos_test.rego @@ -2,14 +2,18 @@ package compliance_framework.public_repos test_public_repos_is_zero if { count(violation) == 0 with input as { - "pubic_repos": 0, - "public_gists": 0 + "settings": { + "public_repos": 0, + "public_gists": 0 + } } } test_public_repos_violate_when_higher if { count(violation) > 0 with input as { - "public_repos": 10, - "public_gists": 0 + "settings": { + "public_repos": 10, + "public_gists": 0 + } } } \ No newline at end of file From 97f28779f50dae333c43d716f7b35753c85ee74a Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Wed, 3 Sep 2025 11:02:16 +0100 Subject: [PATCH 2/3] feat: Add teams rego policies --- policies/gh_teams_privacy_closed.rego | 9 +++++++ policies/gh_teams_privacy_closed_test.rego | 31 ++++++++++++++++++++++ policies/gh_teams_security_found.rego | 18 +++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 policies/gh_teams_privacy_closed.rego create mode 100644 policies/gh_teams_privacy_closed_test.rego create mode 100644 policies/gh_teams_security_found.rego diff --git a/policies/gh_teams_privacy_closed.rego b/policies/gh_teams_privacy_closed.rego new file mode 100644 index 0000000..3538243 --- /dev/null +++ b/policies/gh_teams_privacy_closed.rego @@ -0,0 +1,9 @@ +package compliance_framework.teams_privacy_closed + +violation[{}] if { + some team in input.teams + team.privacy != "closed" +} + +title := "All teams are private within the organization" +description := "All teams within the organization must be set to private to ensure sensitive information is not exposed." \ No newline at end of file diff --git a/policies/gh_teams_privacy_closed_test.rego b/policies/gh_teams_privacy_closed_test.rego new file mode 100644 index 0000000..d2e6978 --- /dev/null +++ b/policies/gh_teams_privacy_closed_test.rego @@ -0,0 +1,31 @@ +package compliance_framework.teams_privacy_closed + +test_teams_privacy_closed if { + count(violation) == 0 with input as { + "teams": [ + { + "name": "team1", + "privacy": "closed" + }, + { + "name": "team2", + "privacy": "closed" + } + ] + } +} + +test_teams_privacy_open if { + count(violation) > 0 with input as { + "teams": [ + { + "name": "team1", + "privacy": "open" + }, + { + "name": "team2", + "privacy": "closed" + } + ] + } +} diff --git a/policies/gh_teams_security_found.rego b/policies/gh_teams_security_found.rego new file mode 100644 index 0000000..18561a1 --- /dev/null +++ b/policies/gh_teams_security_found.rego @@ -0,0 +1,18 @@ +package compliance_framework.teams_security_found + +_team_with_security if { + some team in input.teams + contains(team.name, "security") +} + +_team_with_security if { + some team in input.teams + contains(team.description, "security") +} + +violation[{}] if { + not _team_with_security +} + +title := "Security Teams are present within Github" +description := "A dedicated security team should be created in the organization to manage security-related tasks and incidents, as well as provide consulting when required." From 340c39b3b3427c0adf544e4a2c3f272fa7b514c5 Mon Sep 17 00:00:00 2001 From: Sam Sherar Date: Wed, 3 Sep 2025 11:14:00 +0100 Subject: [PATCH 3/3] fix: case-insensitivity check --- policies/gh_teams_security_found.rego | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/policies/gh_teams_security_found.rego b/policies/gh_teams_security_found.rego index 18561a1..1c13ab4 100644 --- a/policies/gh_teams_security_found.rego +++ b/policies/gh_teams_security_found.rego @@ -2,12 +2,12 @@ package compliance_framework.teams_security_found _team_with_security if { some team in input.teams - contains(team.name, "security") + contains(lower(team.name), "security") } _team_with_security if { some team in input.teams - contains(team.description, "security") + contains(lower(team.description), "security") } violation[{}] if {