From ef919c5c2a7be8ada3ae78fff75c5d4cb4abb27c Mon Sep 17 00:00:00 2001 From: Michelangelo Mori <328978+blkt@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:38:24 +0100 Subject: [PATCH 1/5] Add OSPS Baseline Level 1 rules. This change adds all currently implemented rule types for OSPS Baseline Level 1. Some rules were copy-pasted from rules like e.g. `branch_protection_allow_deletions` in order to (a) be able to change them independently and (b) change the name to something descriptive in the scope of Security Baseline. We generally do not foster this, but in this case we deemed simplicity was preferable to avoiding duplication. Along the rules themselves, tests were added to new, existing ones, and their copies. Fixes stacklok/minder-stories#198 --- data-sources/ghapi.yaml | 10 +++ profiles/github/security_baseline_1.yaml | 41 ----------- ...ranch_protection_allow_deletions.test.yaml | 49 +++++++++++++ ...ch_protection_allow_force_pushes.test.yaml | 49 +++++++++++++ rules_test.go | 68 ++++++++++--------- security-baseline/data-sources/ghapi.yaml | 1 + .../profiles/security-baseline-level-1.yaml | 37 ++++++++++ .../rule-types/github/osps-ac-03.test.yaml | 49 +++++++++++++ .../rule-types/github/osps-ac-03.yaml | 38 +++++++++++ .../rule-types/github/osps-ac-04.test.yaml | 49 +++++++++++++ .../rule-types/github/osps-ac-04.yaml | 37 ++++++++++ .../rule-types/github/osps-do-01.yaml | 44 ++++++++++++ .../rule-types/github/osps-do-02.test.yaml | 25 +++++++ .../contributing_file/CONTRIBUTING.md | 3 + .../CONTRIBUTING | 3 + .../contributing_folder/CONTRIBUTING/myfile | 5 ++ .../osps-do-02.testdata/no_data/README.md | 1 + .../rule-types/github/osps-do-02.yaml | 48 +++++++++++++ .../rule-types/github/osps-le-02.yaml | 55 +++++++++++++++ .../rule-types/github/osps-le-03.test.yaml | 31 +++++++++ .../osps-le-03.testdata/copying_file/COPYING | 28 ++++++++ .../license_file/LICENSE.md | 7 ++ .../license_file_no_extension/LICENSE | 7 ++ .../license_folder/LICENSE/myfile | 7 ++ .../github/osps-le-03.testdata/no_data/foo | 1 + .../rule-types/github/osps-le-03.yaml | 56 +++++++++++++++ .../rule-types/github/osps-qa-01.yaml | 40 +++++++++++ 27 files changed, 715 insertions(+), 74 deletions(-) delete mode 100644 profiles/github/security_baseline_1.yaml create mode 100644 rule-types/github/branch_protection_allow_deletions.test.yaml create mode 100644 rule-types/github/branch_protection_allow_force_pushes.test.yaml create mode 120000 security-baseline/data-sources/ghapi.yaml create mode 100644 security-baseline/profiles/security-baseline-level-1.yaml create mode 100644 security-baseline/rule-types/github/osps-ac-03.test.yaml create mode 100644 security-baseline/rule-types/github/osps-ac-03.yaml create mode 100644 security-baseline/rule-types/github/osps-ac-04.test.yaml create mode 100644 security-baseline/rule-types/github/osps-ac-04.yaml create mode 100644 security-baseline/rule-types/github/osps-do-01.yaml create mode 100644 security-baseline/rule-types/github/osps-do-02.test.yaml create mode 100644 security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md create mode 100644 security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING create mode 100644 security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile create mode 100644 security-baseline/rule-types/github/osps-do-02.testdata/no_data/README.md create mode 100644 security-baseline/rule-types/github/osps-do-02.yaml create mode 100644 security-baseline/rule-types/github/osps-le-02.yaml create mode 100644 security-baseline/rule-types/github/osps-le-03.test.yaml create mode 100644 security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING create mode 100644 security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md create mode 100644 security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE create mode 100644 security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile create mode 100644 security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo create mode 100644 security-baseline/rule-types/github/osps-le-03.yaml create mode 100644 security-baseline/rule-types/github/osps-qa-01.yaml diff --git a/data-sources/ghapi.yaml b/data-sources/ghapi.yaml index f9c8fcc..6fe3134 100644 --- a/data-sources/ghapi.yaml +++ b/data-sources/ghapi.yaml @@ -14,3 +14,13 @@ rest: type: string repo: type: string + repo_config: + endpoint: https://api.github.com/repos/{owner}/{repo} + parse: json + input_schema: + type: object + properties: + owner: + type: string + repo: + type: string diff --git a/profiles/github/security_baseline_1.yaml b/profiles/github/security_baseline_1.yaml deleted file mode 100644 index 8a796fd..0000000 --- a/profiles/github/security_baseline_1.yaml +++ /dev/null @@ -1,41 +0,0 @@ -version: v1 -type: profile -name: security_baseline_1 -display_name: Security Baseline 1 -context: - provider: github -alert: "off" -remediate: "off" -repository: - # OSPS-AC-03 and OSPS-AC-04: Branch protection - - type: branch_protection_enabled - params: - branch: "main" - def: {} - - type: branch_protection_require_pull_requests - params: - branch: "main" - def: - required_pull_request_reviews: true - - # OSPS-DO-02: Enforce CONTRIBUTING file presence - - type: enforce_file - def: - file: "CONTRIBUTING.md" - content: "" - params: {} - - # OSPS-LE-03: Enforce license file - - type: enforce_file - def: - file: "LICENSE" - content: "" - params: {} - - # OSPS-LE-02: Ensure OSI/FSF approved license - - type: permissive_license - def: {} - - # OSPS-QA-01: Repository visibility check - - type: source_code_is_public - def: {} diff --git a/rule-types/github/branch_protection_allow_deletions.test.yaml b/rule-types/github/branch_protection_allow_deletions.test.yaml new file mode 100644 index 0000000..eb94da2 --- /dev/null +++ b/rule-types/github/branch_protection_allow_deletions.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_deletions": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_deletions": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/rule-types/github/branch_protection_allow_force_pushes.test.yaml b/rule-types/github/branch_protection_allow_force_pushes.test.yaml new file mode 100644 index 0000000..5d44329 --- /dev/null +++ b/rule-types/github/branch_protection_allow_force_pushes.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/rules_test.go b/rules_test.go index 42ef0c4..42b438a 100644 --- a/rules_test.go +++ b/rules_test.go @@ -131,50 +131,52 @@ func TestRuleTypes(t *testing.T) { require.NoError(t, os.Setenv("REGO_ENABLE_PRINT", "true")) - // iterate rule types directory - err := walkRuleTypesTests(t, func(t *testing.T, rt *minderv1.RuleType, tc *RuleTest, rtDataPath string) { - var opts []tkv1.Option - if rt.Def.Ingest.Type == "git" { - opts = append(opts, gitTestOpts(t, tc, rtDataPath)) - } else if rt.Def.Ingest.Type == "rest" { - opts = append(opts, httpTestOpts(t, tc, rtDataPath)) - } else { - t.Skipf("Unsupported ingest type %s", rt.Def.Ingest.Type) - } + for _, folder := range []string{"rule-types", "security-baseline/rule-types"} { + // iterate rule types directory + err := walkRuleTypesTests(t, folder, func(t *testing.T, rt *minderv1.RuleType, tc *RuleTest, rtDataPath string) { + var opts []tkv1.Option + if rt.Def.Ingest.Type == "git" { + opts = append(opts, gitTestOpts(t, tc, rtDataPath)) + } else if rt.Def.Ingest.Type == "rest" { + opts = append(opts, httpTestOpts(t, tc, rtDataPath)) + } else { + t.Skipf("Unsupported ingest type %s", rt.Def.Ingest.Type) + } - ztw := zerolog.NewTestWriter(t) - zerolog.SetGlobalLevel(zerolog.DebugLevel) - ctx := zerolog.New(ztw).With().Timestamp().Logger().WithContext(context.Background()) + ztw := zerolog.NewTestWriter(t) + zerolog.SetGlobalLevel(zerolog.DebugLevel) + ctx := zerolog.New(ztw).With().Timestamp().Logger().WithContext(context.Background()) - tk := tkv1.NewTestKit(opts...) - rte, err := rtengine.NewRuleTypeEngine(ctx, rt, tk, nil) - require.NoError(t, err) + tk := tkv1.NewTestKit(opts...) + rte, err := rtengine.NewRuleTypeEngine(ctx, rt, tk, nil) + require.NoError(t, err) - val := rte.GetRuleInstanceValidator() - require.NoError(t, val.ValidateRuleDefAgainstSchema(tc.Def), "Failed to validate rule definition against schema") - require.NoError(t, val.ValidateParamsAgainstSchema(tc.Params), "Failed to validate params against schema") + val := rte.GetRuleInstanceValidator() + require.NoError(t, val.ValidateRuleDefAgainstSchema(tc.Def), "Failed to validate rule definition against schema") + require.NoError(t, val.ValidateParamsAgainstSchema(tc.Params), "Failed to validate params against schema") - if tk.ShouldOverrideIngest() { - rte.WithCustomIngester(tk) - } + if tk.ShouldOverrideIngest() { + rte.WithCustomIngester(tk) + } - _, err = rte.Eval(ctx, tc.Entity.Entity, tc.Def, tc.Params, tkv1.NewVoidResultSink()) - if tc.Expect == ExpectPass { - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) + _, err = rte.Eval(ctx, tc.Entity.Entity, tc.Def, tc.Params, tkv1.NewVoidResultSink()) + if tc.Expect == ExpectPass { + require.NoError(t, err) + } else { + require.Error(t, err) + } + }) - if err != nil { - t.Error(err) + if err != nil { + t.Error(err) + } } } -func walkRuleTypesTests(t *testing.T, testfunc RuleTypeTestFunc) error { +func walkRuleTypesTests(t *testing.T, folder string, testfunc RuleTypeTestFunc) error { t.Helper() - return filepath.Walk("rule-types", func(path string, info os.FileInfo, err error) error { + return filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { if err != nil { return err } diff --git a/security-baseline/data-sources/ghapi.yaml b/security-baseline/data-sources/ghapi.yaml new file mode 120000 index 0000000..48e59b4 --- /dev/null +++ b/security-baseline/data-sources/ghapi.yaml @@ -0,0 +1 @@ +data-sources/ghapi.yaml \ No newline at end of file diff --git a/security-baseline/profiles/security-baseline-level-1.yaml b/security-baseline/profiles/security-baseline-level-1.yaml new file mode 100644 index 0000000..0363755 --- /dev/null +++ b/security-baseline/profiles/security-baseline-level-1.yaml @@ -0,0 +1,37 @@ +version: v1 +type: profile +name: security-baseline-level-1 +display_name: OSPS Security Baseline - Level 1 +context: + provider: github +alert: "off" +remediate: "off" +repository: + # OSPS-AC-03: Prevent overwriting git history + - name: osps-ac-03 + type: osps-ac-03 + def: {} + # OSPS-AC-04: Prevent permanent branch deletion + - name: osps-ac-04 + type: osps-ac-04 + def: {} + # OSPS-DO-01: Projects has public discussion mechanisms + - name: osps-do-01 + type: osps-do-01 + def: {} + # OSPS-DO-02: Enforce CONTRIBUTING file presence + - name: osps-do-02 + type: osps-do-02 + def: {} + # OSPS-LE-02: Ensure OSI/FSF approved license + - name: osps-le-02 + type: osps-le-02 + def: {} + # OSPS-LE-03: LICENSE or COPYING files are available available + - name: osps-le-03 + type: osps-le-03 + def: {} + # OSPS-QA-01: Repository visibility check + - name: osps-qa-01 + type: osps-qa-01 + def: {} diff --git a/security-baseline/rule-types/github/osps-ac-03.test.yaml b/security-baseline/rule-types/github/osps-ac-03.test.yaml new file mode 100644 index 0000000..5d44329 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-03.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_force_pushes": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/security-baseline/rule-types/github/osps-ac-03.yaml b/security-baseline/rule-types/github/osps-ac-03.yaml new file mode 100644 index 0000000..7aa3b5a --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-03.yaml @@ -0,0 +1,38 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-ac-03 +display_name: Prevent overwriting git history +short_failure_message: Force pushes are allowed +severity: + value: info +context: + provider: github +description: Disallow force pushes to the branch +guidance: | + Ensure that the appropriate setting is disabled for the branch + protection rule. + + This setting prevents users with push access to force push to the + branch. + + For more information, see [GitHub's + documentation](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/branches/{{ .Entity.DefaultBranch }}/protection' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Not Protected"} + eval: + type: jq + jq: + - ingested: + def: ".allow_force_pushes.enabled" + constant: false diff --git a/security-baseline/rule-types/github/osps-ac-04.test.yaml b/security-baseline/rule-types/github/osps-ac-04.test.yaml new file mode 100644 index 0000000..eb94da2 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-04.test.yaml @@ -0,0 +1,49 @@ +tests: + - name: "force push not allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "pass" + http: + status: 200 + body: '{"allow_deletions": {"enabled": false}}' + - name: "force push allowed" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 200 + body: '{"allow_deletions": {"enabled": true}}' + - name: "not found" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 404 + body: '{"woot": "woot"}' + - name: "internal error" + def: {} + params: {} + entity: + type: repository + entity: + owner: "mindersec" + name: "minder" + expect: "fail" + http: + status: 502 + body: '{"woot": "woot"}' diff --git a/security-baseline/rule-types/github/osps-ac-04.yaml b/security-baseline/rule-types/github/osps-ac-04.yaml new file mode 100644 index 0000000..7c06c24 --- /dev/null +++ b/security-baseline/rule-types/github/osps-ac-04.yaml @@ -0,0 +1,37 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-ac-04 +display_name: Prevent permanent branch deletion +short_failure_message: Branch protection allows deletions +severity: + value: info +context: + provider: github +description: Prevents the branch from being deleted +guidance: | + Ensure that the "Allow deletions" setting is disabled for the branch + protection rule. + + Prevent users from deleting matching branches. + + For more information, see [GitHub's + documentation](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/branches/{{ .Entity.DefaultBranch }}/protection' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "Not Protected"} + eval: + type: jq + jq: + - ingested: + def: ".allow_deletions.enabled" + constant: false diff --git a/security-baseline/rule-types/github/osps-do-01.yaml b/security-baseline/rule-types/github/osps-do-01.yaml new file mode 100644 index 0000000..6a6a44a --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-01.yaml @@ -0,0 +1,44 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-do-01 +display_name: The project has mechanisms for public discussion +short_failure_message: The project does not publicize mechanisms for public discussion. +severity: + value: info +context: + provider: github +description: | + Projects should encourage open communication and collaboration + within the their community, enabling users to provide feedback and + discuss proposed changes or usage challenges. +guidance: | + Enable "Issues" or "Discussions" via the + [Settings](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository) + page on GitHub. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + data_sources: + - name: ghapi + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + repo := minder.datasource.ghapi.repo_config({ + "owner": input.properties["github/repo_owner"], + "repo": input.properties["github/repo_name"] + }) + + allow if repo.body.has_issues + allow if repo.body.has_discussions diff --git a/security-baseline/rule-types/github/osps-do-02.test.yaml b/security-baseline/rule-types/github/osps-do-02.test.yaml new file mode 100644 index 0000000..5bdb54d --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.test.yaml @@ -0,0 +1,25 @@ +tests: + - name: "Should find CONTRIBUTING" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_file_no_extension + - name: "Should find CONTRIBUTING.md" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_file + - name: "Should find CONTRIBUTING folder" + def: {} + params: {} + expect: "pass" + git: + repo_base: contributing_folder + - name: "Should fail if absent" + def: {} + params: {} + expect: "fail" + git: + repo_base: no_data diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md new file mode 100644 index 0000000..3abb714 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing to Foo + +We welcome contributions, and the rest of this doc is slap-dash! Sorry! diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING new file mode 100644 index 0000000..b978351 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_file_no_extension/CONTRIBUTING @@ -0,0 +1,3 @@ +** Contributing to Foo ** + +We welcome contributions, and the rest of this doc is slap-dash! Sorry! diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile new file mode 100644 index 0000000..2f7cc31 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/contributing_folder/CONTRIBUTING/myfile @@ -0,0 +1,5 @@ +################### +# Contributor Guide +################### + +This project has a lot to read. Get started! diff --git a/security-baseline/rule-types/github/osps-do-02.testdata/no_data/README.md b/security-baseline/rule-types/github/osps-do-02.testdata/no_data/README.md new file mode 100644 index 0000000..3d42fcb --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.testdata/no_data/README.md @@ -0,0 +1 @@ +I'm empty! \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-do-02.yaml b/security-baseline/rule-types/github/osps-do-02.yaml new file mode 100644 index 0000000..875e452 --- /dev/null +++ b/security-baseline/rule-types/github/osps-do-02.yaml @@ -0,0 +1,48 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-do-02 +display_name: Contribution process is explained +short_failure_message: No CONTRIBUTING file or folder was found +severity: + value: info +context: + provider: github +description: | + Ensure that either a CONTRIBUTING file or CONTRIBUTING/ folder is + available. +guidance: | + Source code must be accompanied by a `CONTRIBUTING` file or a + `CONTRIBUTING/` folder at the root of the project source tree. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + files := file.ls_glob("./CONTRIBUTING*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./CONTRIBUTING/*") + + some name + content := file.read(files[name]) + "" != content + } diff --git a/security-baseline/rule-types/github/osps-le-02.yaml b/security-baseline/rule-types/github/osps-le-02.yaml new file mode 100644 index 0000000..2c0a82d --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-02.yaml @@ -0,0 +1,55 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-le-02 +display_name: License meets the OSI or the FSF definition +short_failure_message: License does not meet OSI or FSF definition +severity: + value: info +context: + provider: github +description: | + Ensure that the project’s source code is distributed under a + recognized and legally enforceable open source software license. +guidance: | + Ensure that the project’s source code is distributed under a + recognized and legally enforceable open source software license, + providing clarity on how the code can be used and shared by others. +def: + in_entity: repository + rule_schema: {} + ingest: + type: rest + rest: + endpoint: '/repos/{{.Entity.Owner}}/{{.Entity.Name}}/license' + parse: json + fallback: + - http_code: 404 + body: | + {"http_status": 404, "message": "License details not found} + eval: + type: rego + data_sources: + - name: spdx + rego: + type: constraints + def: | + package minder + + import future.keywords.every + import future.keywords.if + + violations[{"msg": msg}] { + license := input.ingested.license.spdx_id + + resp2 := minder.datasource.spdx.licenses({}) + licenses := resp2.body.licenses + osi := { l.licenseId | l := licenses[_]; l.isOsiApproved } + fsf := { l.licenseId | l := licenses[_]; l.isFsfLibre } + approved_licenses := osi | fsf + + count(approved_licenses) != 0 + license != null + not license in approved_licenses + msg := sprintf("License %s is not OSI/FSF approved", [license]) + } diff --git a/security-baseline/rule-types/github/osps-le-03.test.yaml b/security-baseline/rule-types/github/osps-le-03.test.yaml new file mode 100644 index 0000000..a1de54c --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.test.yaml @@ -0,0 +1,31 @@ +tests: + - name: "Should find LICENSE" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_file_no_extension + - name: "Should find LICENSE.md" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_file + - name: "Should find COPYING" + def: {} + params: {} + expect: "pass" + git: + repo_base: copying_file + - name: "Should find LICENSE folder" + def: {} + params: {} + expect: "pass" + git: + repo_base: license_folder + - name: "Should fail if absent" + def: {} + params: {} + expect: "fail" + git: + repo_base: no_data diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING b/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING new file mode 100644 index 0000000..45706de --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/copying_file/COPYING @@ -0,0 +1,28 @@ + + Note that the only valid version of the GPL as far as this project + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + HOWEVER, in order to allow a migration to GPLv3 if that seems like + a good idea, I also ask that people involved with the project make + their preferences known. In particular, if you trust me to make that + decision, you might note so in your copyright message, ie something + like + + This file is licensed under the GPL v2, or a later version + at the discretion of Linus. + + might avoid issues. But we can also just decide to synchronize and + contact all copyright holders on record if/when the occasion arises. + + Linus Torvalds + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md b/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_file/LICENSE.md @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE b/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_file_no_extension/LICENSE @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile b/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile new file mode 100644 index 0000000..3a34bc3 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/license_folder/LICENSE/myfile @@ -0,0 +1,7 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +... diff --git a/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo b/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo new file mode 100644 index 0000000..3d42fcb --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.testdata/no_data/foo @@ -0,0 +1 @@ +I'm empty! \ No newline at end of file diff --git a/security-baseline/rule-types/github/osps-le-03.yaml b/security-baseline/rule-types/github/osps-le-03.yaml new file mode 100644 index 0000000..40e89b7 --- /dev/null +++ b/security-baseline/rule-types/github/osps-le-03.yaml @@ -0,0 +1,56 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-le-03 +display_name: LICENSE or COPYING files are available available +short_failure_message: No LICENSE or COPYING file found. +severity: + value: info +context: + provider: github +description: | + Ensure that either LICENSE file, COPYING file, or LICENSE/ folder + are available. +guidance: | + Source code must be accompanied by a `LICENSE` or `COPYING` file, or + a `LICENSE/` folder at the root of the project source tree. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + files := file.ls_glob("./LICENSE*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./COPYING*") + + some name + content := file.read(files[name]) + "" != content + } + + allow if { + files := file.ls_glob("./LICENSE/*") + + some name + content := file.read(files[name]) + "" != content + } diff --git a/security-baseline/rule-types/github/osps-qa-01.yaml b/security-baseline/rule-types/github/osps-qa-01.yaml new file mode 100644 index 0000000..e8837f7 --- /dev/null +++ b/security-baseline/rule-types/github/osps-qa-01.yaml @@ -0,0 +1,40 @@ +version: v1 +release_phase: alpha +type: rule-type +name: osps-qa-01 +display_name: The project's source code is publicly readable +short_failure_message: The project's source code is not publicly readable. +severity: + value: info +context: + provider: github +description: | + Enable users to access and review the project’s source code and + history, promoting transparency and collaboration within the project + community. +guidance: | + Change repository visibility via the + [Settings](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility#changing-a-repositorys-visibility) + page on GitHub. +def: + in_entity: repository + rule_schema: {} + ingest: + type: git + eval: + type: rego + rego: + type: deny-by-default + def: | + package minder + + import future.keywords.every + import future.keywords.if + + default allow := false + + allow if { + # This rule checks whether the repository is private using + # info tied to the entity itself. + not input.properties["is_private"] + } From 1a1b1dd464257571f6be8ee4284e4e44c090b735 Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Fri, 17 Jan 2025 15:51:19 -0800 Subject: [PATCH 2/5] Update security-baseline/rule-types/github/osps-do-01.yaml --- security-baseline/rule-types/github/osps-do-01.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security-baseline/rule-types/github/osps-do-01.yaml b/security-baseline/rule-types/github/osps-do-01.yaml index 6a6a44a..7235487 100644 --- a/security-baseline/rule-types/github/osps-do-01.yaml +++ b/security-baseline/rule-types/github/osps-do-01.yaml @@ -20,7 +20,10 @@ def: in_entity: repository rule_schema: {} ingest: - type: git + type: rest + rest: + endpoint: "/repos/{{.Entity.Owner}}/{{.Entity.Name}}" + parse: json eval: type: rego data_sources: From 5173b95364b3a6f9615d16d4e813bb1bd9d4ec2c Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Fri, 17 Jan 2025 15:51:26 -0800 Subject: [PATCH 3/5] Update security-baseline/rule-types/github/osps-do-01.yaml --- security-baseline/rule-types/github/osps-do-01.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/security-baseline/rule-types/github/osps-do-01.yaml b/security-baseline/rule-types/github/osps-do-01.yaml index 7235487..0d8d83f 100644 --- a/security-baseline/rule-types/github/osps-do-01.yaml +++ b/security-baseline/rule-types/github/osps-do-01.yaml @@ -33,8 +33,7 @@ def: def: | package minder - import future.keywords.every - import future.keywords.if + import rego.v1 default allow := false From a654270434a8f2189205f4584af9a96ab97b9808 Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Fri, 17 Jan 2025 15:51:38 -0800 Subject: [PATCH 4/5] Update security-baseline/rule-types/github/osps-do-01.yaml --- security-baseline/rule-types/github/osps-do-01.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/security-baseline/rule-types/github/osps-do-01.yaml b/security-baseline/rule-types/github/osps-do-01.yaml index 0d8d83f..464c5e6 100644 --- a/security-baseline/rule-types/github/osps-do-01.yaml +++ b/security-baseline/rule-types/github/osps-do-01.yaml @@ -37,10 +37,5 @@ def: default allow := false - repo := minder.datasource.ghapi.repo_config({ - "owner": input.properties["github/repo_owner"], - "repo": input.properties["github/repo_name"] - }) - - allow if repo.body.has_issues - allow if repo.body.has_discussions + allow if input.ingested.has_issues + allow if input.ingested.has_discussions From a18f866b7153a903994282c730e32ff4e79daefa Mon Sep 17 00:00:00 2001 From: Evan Anderson Date: Fri, 17 Jan 2025 15:51:48 -0800 Subject: [PATCH 5/5] Update security-baseline/rule-types/github/osps-qa-01.yaml --- security-baseline/rule-types/github/osps-qa-01.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/security-baseline/rule-types/github/osps-qa-01.yaml b/security-baseline/rule-types/github/osps-qa-01.yaml index e8837f7..24b0bb2 100644 --- a/security-baseline/rule-types/github/osps-qa-01.yaml +++ b/security-baseline/rule-types/github/osps-qa-01.yaml @@ -20,7 +20,10 @@ def: in_entity: repository rule_schema: {} ingest: - type: git + type: rest + rest: + endpoint: "/repos/{{.Entity.Owner}}/{{.Entity.Name}}" + parse: json eval: type: rego rego: