Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea/
data/
dist/
*.tar.gz
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

# Variables
REGISTRY_URL := ghcr.io
NAMESPACE := chris-cmsoft
POLICY_NAME := local-ssh-policies
NAMESPACE := compliance-framework
POLICY_NAME := plugin-github-settings-policies
VERSION := latest
POLICY_DIR := ./ssh # Directory containing your .rego files
POLICY_DIR := ./policies # Directory containing your .rego files

# Build and Push Commands
.PHONY: all build bundle push clean
Expand Down
43 changes: 20 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Template for policies for use in Compliance Framework plugins
# Template for policies for use in the Github Settings plugin

## Testing

Expand All @@ -19,37 +19,34 @@ make build
## Running policies locally

```shell
opa eval -I -b policies -f pretty data.compliance_framework.local_ssh <<EOF
{
"passwordauthentication": [
"yes"
],
"permitrootlogin": [
"with-password"
],
"pubkeyauthentication": [
"no"
]
}
EOF
cat example-data/testorg-unremediated.json | opa eval -I -b policies -f pretty data.compliance_framework
```

## Writing policies.

Policies are written in the [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) language.

```rego
package ssh.deny_password_auth

import future.keywords.in
package compliance-framework.mfa_enabled

violation[{
"title": "Host SSH is using password authentication.",
"description": "Host SSH should not use password, as this is insecure to brute force attacks from external sources.",
"remarks": "Migrate to using SSH Public Keys, and switch off password authentication."
}] {
"yes" in input.passwordauthentication
violation[] {
input.organization.two_factor_requirement_enabled == false
}

title := "Two Factor Authentication is required at an organization level"
description := "Two factor authentication should be enabled and enforced for all users within the Github Organization to make it harder for malicious actors to gain access to the organizations settings and repositories & settings"
remarks := "More information from Github can be found here: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization"

controls := [
{
"class": "SAMA_CSF_1.0",
"control-id": "3.3.5",
"statement-ids": [
"4.e",
"f.1.a",
]
},
]
```

## Metadata
Expand Down
63 changes: 63 additions & 0 deletions example-data/testorg-unremediated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"organization": {
"login": "test-org",
"id": 1234567,
"node_id": "O_abcdefg",
"url": "https://api.github.com/orgs/test-org",
"repos_url": "https://api.github.com/orgs/test-org/repos",
"events_url": "https://api.github.com/orgs/test-org/events",
"hooks_url": "https://api.github.com/orgs/test-org/hooks",
"issues_url": "https://api.github.com/orgs/test-org/issues",
"members_url": "https://api.github.com/orgs/test-org/members{/member}",
"public_members_url": "https://api.github.com/orgs/test-org/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/1234567?v=4",
"description": null,
"is_verified": false,
"has_organization_projects": true,
"has_repository_projects": true,
"public_repos": 0,
"public_gists": 0,
"followers": 0,
"following": 0,
"html_url": "https://github.com/test-org",
"created_at": "2025-04-09T15:36:21Z",
"updated_at": "2025-04-09T15:38:25Z",
"archived_at": null,
"type": "Organization",
"total_private_repos": 0,
"owned_private_repos": 0,
"private_gists": 0,
"disk_usage": 0,
"collaborators": 0,
"billing_email": "test@example.com",
"default_repository_permission": "read",
"members_can_create_repositories": true,
"two_factor_requirement_enabled": false,
"members_allowed_repository_creation_type": "all",
"members_can_create_public_repositories": true,
"members_can_create_private_repositories": true,
"members_can_create_internal_repositories": false,
"members_can_create_pages": true,
"members_can_fork_private_repositories": false,
"web_commit_signoff_required": false,
"deploy_keys_enabled_for_repositories": false,
"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
},
"advanced_security_enabled_for_new_repositories": false,
"dependabot_alerts_enabled_for_new_repositories": false,
"dependabot_security_updates_enabled_for_new_repositories": false,
"dependency_graph_enabled_for_new_repositories": false,
"secret_scanning_enabled_for_new_repositories": false,
"secret_scanning_push_protection_enabled_for_new_repositories": false,
"secret_scanning_push_protection_custom_link_enabled": false,
"secret_scanning_push_protection_custom_link": null,
"secret_scanning_validity_checks_enabled": false
}
}
63 changes: 63 additions & 0 deletions example-data/testorg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"organization": {
"login": "test-org",
"id": 1234567,
"node_id": "O_abcdefg",
"url": "https://api.github.com/orgs/test-org",
"repos_url": "https://api.github.com/orgs/test-org/repos",
"events_url": "https://api.github.com/orgs/test-org/events",
"hooks_url": "https://api.github.com/orgs/test-org/hooks",
"issues_url": "https://api.github.com/orgs/test-org/issues",
"members_url": "https://api.github.com/orgs/test-org/members{/member}",
"public_members_url": "https://api.github.com/orgs/test-org/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/1234567?v=4",
"description": null,
"is_verified": false,
"has_organization_projects": true,
"has_repository_projects": true,
"public_repos": 0,
"public_gists": 0,
"followers": 0,
"following": 0,
"html_url": "https://github.com/test-org",
"created_at": "2025-04-09T15:36:21Z",
"updated_at": "2025-04-09T15:38:25Z",
"archived_at": null,
"type": "Organization",
"total_private_repos": 0,
"owned_private_repos": 0,
"private_gists": 0,
"disk_usage": 0,
"collaborators": 0,
"billing_email": "test@example.com",
"default_repository_permission": "read",
"members_can_create_repositories": true,
"two_factor_requirement_enabled": true,
"members_allowed_repository_creation_type": "all",
"members_can_create_public_repositories": false,
"members_can_create_private_repositories": true,
"members_can_create_internal_repositories": true,
"members_can_create_pages": false,
"members_can_fork_private_repositories": false,
"web_commit_signoff_required": true,
"deploy_keys_enabled_for_repositories": true,
"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
},
"advanced_security_enabled_for_new_repositories": true,
"dependabot_alerts_enabled_for_new_repositories": true,
"dependabot_security_updates_enabled_for_new_repositories": true,
"dependency_graph_enabled_for_new_repositories": true,
"secret_scanning_enabled_for_new_repositories": true,
"secret_scanning_push_protection_enabled_for_new_repositories": true,
"secret_scanning_push_protection_custom_link_enabled": true,
"secret_scanning_push_protection_custom_link": null,
"secret_scanning_validity_checks_enabled": true
}
}
17 changes: 0 additions & 17 deletions policies/example.rego

This file was deleted.

11 changes: 0 additions & 11 deletions policies/example_test.rego

This file was deleted.

47 changes: 47 additions & 0 deletions policies/gh_org_mfa_enabled.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package compliance_framework.mfa_enabled
# METADATA
# title: Github Settings - Organizations - Two Factor Authentication Required
# description: Ensure that 2FA is enabled for all users within the organization, making it harder for TAs to gain access to the organization's repos and settings
# custom:
# controls:
# - <control-id>
# schedule: "* * * * *"


violation[{}] if {
input.organization.two_factor_requirement_enabled == false
}

title := "Two Factor Authentication is required at an organization level"
description := "Two factor authentication should be enabled and enforced for all users within the Github Organization to make it harder for malicious actors to gain access to the organizations settings and repositories & settings"
remarks := "More information from Github can be found here: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization"

controls := [
# SAMA Cyber Security Framework v1.0
# https://rulebook.sama.gov.sa/en/cyber-security-framework-2
# Class: SAMA_CSF_1.0
#
# 3.3: Cyber Security Operations and Technology
# https://rulebook.sama.gov.sa/en/33-cyber-security-operations-and-technology-0
{
"class": "SAMA_CSF_1.0",
"control-id": "3.3.5", # Identity and Access Management https://rulebook.sama.gov.sa/en/335-identity-and-access-management-0
"statement-ids": [
"4.e",
"f.1.a",
]
},

# NIST SP 800-53 v5.1.1
# https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r5.pdf
# Class SP800-53-enhancement
# ia: Identification and Authentication
{
"class": "SP800-53-enhancement",
"control-id": "ia-2.1", # Multi-factor Authentication to Privileged Accounts
},
{
"class": "SP800-53-enhancement",
"control-id": "ia-2.2", # Multi-factor Authentication for Non-privileged Accounts
},
]
17 changes: 17 additions & 0 deletions policies/gh_org_mfa_enabled_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package compliance_framework.mfa_enabled

test_mfa_enabled if {
count(violation) == 0 with input as {
"organization": {
"two_factor_requirement_enabled": true
}
}
}

test_mfa_violate_if_disabled if {
count(violation) > 0 with input as {
"organization": {
"two_factor_requirement_enabled": false
}
}
}
31 changes: 31 additions & 0 deletions policies/gh_org_public_repos.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# METADATA
# title: Github Settings - Organizations - Public Repos and Gists
# description: "The organization should not have any public repos or gists if it is a sensitive organization"
# custom:
# controls:
# - <control-id>
# schedule: "* * * * *"


package compliance_framework.public_repos

checks["repos"] if {
input.organization.public_repos > 0
}

checks["gists"] if {
input.organization.public_gists > 0
}

violation[{}] if {
some check in checks
}


title := "No Public Repos or Gists"
description := "The Organization should not have any public repositories or gists attached to it"

# No direct controls in the frameworks at the moment
# But will be useful when we are mapping ISO 27001, data privacy or custom
# IPR frameworks generated either as a standard or a custom catalog
controls := []
19 changes: 19 additions & 0 deletions policies/gh_org_public_repos_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package compliance_framework.public_repos

test_public_repos_is_zero if {
count(violation) == 0 with input as {
"organization": {
"pubic_repos": 0,
"public_gists": 0
}
}
}

test_public_repos_violate_when_higher if {
count(violation) > 0 with input as {
"organization": {
"public_repos": 10,
"public_gists": 0
}
}
}
Loading