From 722e0e6fc224bcae396a264642a6a658803f891b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 19 Dec 2024 11:49:33 +0000 Subject: [PATCH] Introduce OpenSSF Best Practices Badge rule Add a rule that ensures that the project has an OpenSSF Best Practices badge at the specified level (defaulting to: "passing"). This is driven by the OpenSSF Best Practices data source, which queries bestpractices.dev. Add the new rule type to the OpenSSF Scorecard profile. --- data-sources/openssf_bestpractices.yaml | 17 +++++ profiles/github/openssf_scorecard.yaml | 3 +- rule-types/github/openssf_bestpractices.yaml | 77 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 data-sources/openssf_bestpractices.yaml create mode 100644 rule-types/github/openssf_bestpractices.yaml diff --git a/data-sources/openssf_bestpractices.yaml b/data-sources/openssf_bestpractices.yaml new file mode 100644 index 0000000..d15829f --- /dev/null +++ b/data-sources/openssf_bestpractices.yaml @@ -0,0 +1,17 @@ +--- +version: v1 +type: data-source +name: openssf_bestpractices +context: {} +rest: + def: + lookup: + endpoint: 'https://www.bestpractices.dev/projects/{id}.json' + parse: json + input_schema: + properties: + id: + type: string + description: The project ID to lookup + required: + - id diff --git a/profiles/github/openssf_scorecard.yaml b/profiles/github/openssf_scorecard.yaml index cd64fa3..616fea1 100644 --- a/profiles/github/openssf_scorecard.yaml +++ b/profiles/github/openssf_scorecard.yaml @@ -18,7 +18,8 @@ repository: # CI-Tests - type: workflow_pull_request def: {} - # CII-Best-Practices + - type: openssf_bestpractices # CII-Best-Practices + def: {} - type: branch_protection_require_pull_request_approving_review_count # Code-Review def: required_approving_review_count: 1 diff --git a/rule-types/github/openssf_bestpractices.yaml b/rule-types/github/openssf_bestpractices.yaml new file mode 100644 index 0000000..72f42b3 --- /dev/null +++ b/rule-types/github/openssf_bestpractices.yaml @@ -0,0 +1,77 @@ +--- +version: v1 +release_phase: alpha +type: rule-type +name: openssf_bestpractices +display_name: Verifies the project has earned an OpenSSF Best Practices Badge +short_failure_message: OpenSSF Best Practices Badge is missing +severity: + value: low +context: + provider: github +description: | + Verifies that a repository contains an OpenSSF Best Practices badge at + the specified level. + + This rule type checks for the existence of a image declared in Markdown, + referencing the project's badge on the Best Practices badge site. +guidance: | + Add your project to [OpenSSF Best Practices](https://www.bestpractices.dev/en) + to get a Best Practices badge, then add the badge to your project's README to + show your certification. +def: + in_entity: repository + # Defines the schema for writing a rule with this rule being checked + # In this case there are no settings that need to be configured + rule_schema: + type: object + properties: + filename: + type: string + description: | + The path to the README that links to the badge + default: README.md + level: + type: string + description: | + The required achievement level. + enum: + - in_progress + - passing + - silver + - gold + default: passing + # Defines the configuration for ingesting data relevant for the rule + ingest: + type: git + git: {} + eval: + type: rego + data_sources: + - name: openssf_bestpractices + rego: + type: deny-by-default + def: | + package minder + import rego.v1 + + default allow := false + default message := "OpenSSF Best Practices Badge is missing" + + levels := { "in_progress": 1, "passing": 2, "silver": 3, "gold": 4 } + + allow if { + file.exists(input.profile.filename) + readme := file.read(input.profile.filename) + + badge := regex.find_all_string_submatch_n(`\[[^\]]+\]\(https:\/\/www\.bestpractices\.dev\/projects\/([\d]+)\/badge\)`, readme, 1) + project_id := badge[0][1] + + badge_data := minder.datasource.openssf_bestpractices.lookup({"id": project_id }) + + levels[badge_data.body.badge_level] >= levels[input.profile.level] + } + # Defines the configuration for alerting on the rule + alert: + type: security_advisory + security_advisory: {}