From 6783eba4f7b69004e03746cbe6756a65e05c8a68 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Fri, 12 Dec 2025 16:23:46 +0100 Subject: [PATCH 01/13] implemented abstract openssf metric provider and its implementations --- .../.eslintrc.js | 1 + .../README.md | 5 + .../package.json | 41 +++++++ .../src/clients/OpenSSFClient.ts | 49 ++++++++ .../src/clients/types.ts | 42 +++++++ .../src/clients/utils.ts | 41 +++++++ .../src/index.ts | 23 ++++ .../metricProviders/AbstractMetricProvider.ts | 106 ++++++++++++++++++ .../BinaryArtifactsMetricProvider.ts | 35 ++++++ .../BranchProtectionMetricProvider.ts | 35 ++++++ .../CIIBestPracticesMetricProvider.ts | 35 ++++++ .../metricProviders/CITestsMetricProvider.ts | 35 ++++++ .../CodeReviewMetricProvider.ts | 35 ++++++ .../ContributorsMetricProvider.ts | 35 ++++++ .../DangerousWorkflowMetricProvider.ts | 35 ++++++ .../DependencyUpdateToolMetricProvider.ts | 35 ++++++ .../metricProviders/FuzzingMetricProvider.ts | 35 ++++++ .../metricProviders/LicenseMetricProvider.ts | 35 ++++++ .../MaintainedMetricProvider.ts | 35 ++++++ .../PackagingMetricProvider.ts | 35 ++++++ .../PinnedDependenciesMetricProvider.ts | 35 ++++++ .../src/metricProviders/SASTMetricProvider.ts | 35 ++++++ .../SecurityPolicyMetricProvider.ts | 35 ++++++ .../SignedReleasesMetricProvider.ts | 35 ++++++ .../TokenPermissionsMetricProvider.ts | 35 ++++++ .../VulnerabilitiesMetricProvider.ts | 35 ++++++ .../src/module.ts | 68 +++++++++++ 27 files changed, 1006 insertions(+) create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/.eslintrc.js create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/.eslintrc.js b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md new file mode 100644 index 0000000000..647949b904 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md @@ -0,0 +1,5 @@ +# @red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf + +The openssf backend module for the scorecard plugin. + +_This plugin was created through the Backstage CLI_ diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json new file mode 100644 index 0000000000..be4e820380 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json @@ -0,0 +1,41 @@ +{ + "name": "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf", + "version": "0.1.0", + "license": "Apache-2.0", + "private": true, + "description": "The openssf backend module for the scorecard plugin.", + "main": "src/index.ts", + "types": "src/index.ts", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module", + "pluginId": "scorecard" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-plugin-api": "^1.5.0", + "@backstage/catalog-client": "^1.12.1", + "@backstage/catalog-model": "^1.7.6", + "@red-hat-developer-hub/backstage-plugin-scorecard-common": "workspace:^", + "@red-hat-developer-hub/backstage-plugin-scorecard-node": "workspace:^" + }, + "devDependencies": { + "@backstage/backend-test-utils": "^1.10.0", + "@backstage/cli": "^0.34.5" + }, + "files": [ + "dist" + ] +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts new file mode 100644 index 0000000000..6cc39b4bba --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts @@ -0,0 +1,49 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OpenSSFResponse } from './types'; + +export class OpenSSFClient { + private readonly OPENSSF_API_BASE_URL = + 'https://api.securityscorecards.dev/projects'; + + async getScorecard(owner: string, repo: string): Promise { + const apiUrl = `${this.OPENSSF_API_BASE_URL}/github.com/${owner}/${repo}`; + + const response = await fetch(apiUrl, { + method: 'GET', + headers: { + Accept: 'application/json', + }, + }); + + if (!response.ok) { + throw new Error( + `OpenSSF API request failed with status ${response.status}: ${response.statusText}`, + ); + } + + const data: OpenSSFResponse = await response.json(); + + if (typeof data.score !== 'number') { + throw new Error( + `Invalid response from OpenSSF API: score is not a number`, + ); + } + + return data; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts new file mode 100644 index 0000000000..a4f60fa7c5 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts @@ -0,0 +1,42 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface OpenSSFCheckDocumentation { + short: string; + url: string; +} + +export interface OpenSSFCheck { + name: string; + score: number; + reason: string; + details: string[] | null; + documentation: OpenSSFCheckDocumentation; +} + +export interface OpenSSFResponse { + date: string; + repo: { + name: string; + commit: string; + }; + scorecard: { + version: string; + commit: string; + }; + score: number; + checks: OpenSSFCheck[]; +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts new file mode 100644 index 0000000000..27c5ca4b89 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts @@ -0,0 +1,41 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { type Entity, stringifyEntityRef } from '@backstage/catalog-model'; + +export const getRepositoryInformationFromEntity = ( + entity: Entity, +): { owner: string; repo: string } => { + const projectSlug = entity.metadata.annotations?.['openssf/project']; + if (!projectSlug) { + throw new Error( + `Missing annotation 'github.com/project-slug' for entity ${stringifyEntityRef( + entity, + )}`, + ); + } + + const [owner, repo] = projectSlug.split('/'); + if (!owner || !repo) { + throw new Error( + `Invalid format of 'github.com/project-slug' ${projectSlug} for entity ${stringifyEntityRef( + entity, + )}`, + ); + } + + return { owner, repo }; +}; diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts new file mode 100644 index 0000000000..5317fd8110 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The openssf backend module for the scorecard plugin. + * + * @packageDocumentation + */ + +export { scorecardModuleOpenSSF as default } from './module'; diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts new file mode 100644 index 0000000000..69a65ffb6b --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -0,0 +1,106 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; +import { type Entity } from '@backstage/catalog-model'; +import { + DEFAULT_NUMBER_THRESHOLDS, + Metric, + ThresholdConfig, +} from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; +import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; + +import { OpenSSFClient } from '../clients/OpenSSFClient'; +import { getRepositoryInformationFromEntity } from '../clients/utils'; + +/** + * Abstract base class for OpenSSF metric providers. + * Extracts a specific check from the OpenSSF scorecard response. + * + * Subclasses must implement: + * - getCheckName(): The name of the check to extract (e.g., "Maintained", "Code-Review") + * - getMetricName(): The metric name for the provider ID (e.g., "maintained", "code_review") + * - getMetricTitle(): Display title for the metric + * - getMetricDescription(): Description of what the metric measures + */ +export abstract class AbstractMetricProvider + implements MetricProvider<'number'> +{ + protected readonly openSSFClient: OpenSSFClient; + protected readonly thresholds: ThresholdConfig; + + constructor(thresholds?: ThresholdConfig) { + this.openSSFClient = new OpenSSFClient(); + this.thresholds = thresholds ?? DEFAULT_NUMBER_THRESHOLDS; + } + + protected abstract getMetricName(): string; + + protected abstract getMetricDisplayTitle(): string; + + protected abstract getMetricDescription(): string; + + getProviderDatasourceId(): string { + return 'openssf'; + } + + getProviderId(): string { + const normalizedName = this.getMetricName() + .toLowerCase() + .replace(/-/g, '_'); + return `openssf.${normalizedName}`; + } + + getMetricType(): 'number' { + return 'number'; + } + + getMetric(): Metric<'number'> { + return { + id: this.getProviderId(), + title: this.getMetricDisplayTitle(), + description: this.getMetricDescription(), + type: this.getMetricType(), + history: true, + }; + } + + getMetricThresholds(): ThresholdConfig { + return this.thresholds; + } + + getCatalogFilter(): Record { + return { + 'metadata.annotations.github.com/project-slug': CATALOG_FILTER_EXISTS, + }; + } + + async calculateMetric(entity: Entity): Promise { + const { owner, repo } = getRepositoryInformationFromEntity(entity); + const scorecard = await this.openSSFClient.getScorecard(owner, repo); + + const metricName = this.getMetricName(); + const metric = scorecard.checks.find(c => c.name === metricName); + + if (!metric) { + throw new Error( + `OpenSSF check '${metricName}' not found in scorecard for ${owner}/${repo}`, + ); + } + + return metric.score; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts new file mode 100644 index 0000000000..6fac25ecfb --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Binary-Artifacts check. + * Determines if the project has generated executable (binary) artifacts in the source repository. + */ +export class BinaryArtifactsMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Binary-Artifacts'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Binary Artifacts'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has generated executable (binary) artifacts in the source repository according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts new file mode 100644 index 0000000000..a5b4954e9b --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Branch-Protection check. + * Determines if the default and release branches are protected with GitHub's branch protection settings. + */ +export class BranchProtectionMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Branch-Protection'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Branch Protection'; + } + + protected getMetricDescription(): string { + return "Determines if the default and release branches are protected with GitHub's branch protection settings according to OpenSSF Security Scorecards."; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts new file mode 100644 index 0000000000..d444ce03ad --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF CII-Best-Practices check. + * Determines if the project has an OpenSSF (formerly CII) Best Practices Badge. + */ +export class CIIBestPracticesMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'CII-Best-Practices'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF CII Best Practices'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has an OpenSSF (formerly CII) Best Practices Badge according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts new file mode 100644 index 0000000000..b384101773 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF CI-Tests check. + * Determines if the project runs tests before pull requests are merged. + */ +export class CITestsMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'CI-Tests'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF CI Tests'; + } + + protected getMetricDescription(): string { + return 'Determines if the project runs tests before pull requests are merged according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts new file mode 100644 index 0000000000..d897691eab --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Code-Review check. + * Determines if the project requires human code review before pull requests are merged. + */ +export class CodeReviewMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Code-Review'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Code Review'; + } + + protected getMetricDescription(): string { + return 'Determines if the project requires human code review before pull requests (aka merge requests) are merged according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts new file mode 100644 index 0000000000..b44c57db73 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Contributors check. + * Determines if the project has a set of contributors from multiple organizations (e.g., companies). + */ +export class ContributorsMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Contributors'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Contributors'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has a set of contributors from multiple organizations (e.g., companies) according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts new file mode 100644 index 0000000000..9f454a98d6 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Dangerous-Workflow check. + * Determines if the project's GitHub Action workflows avoid dangerous patterns. + */ +export class DangerousWorkflowMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Dangerous-Workflow'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Dangerous Workflow'; + } + + protected getMetricDescription(): string { + return "Determines if the project's GitHub Action workflows avoid dangerous patterns according to OpenSSF Security Scorecards."; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts new file mode 100644 index 0000000000..1daad1dd71 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Dependency-Update-Tool check. + * Determines if the project uses a dependency update tool. + */ +export class DependencyUpdateToolMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Dependency-Update-Tool'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Dependency Update Tool'; + } + + protected getMetricDescription(): string { + return 'Determines if the project uses a dependency update tool according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts new file mode 100644 index 0000000000..e4f6cc9a5f --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Fuzzing check. + * Determines if the project uses fuzzing. + */ +export class FuzzingMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Fuzzing'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Fuzzing'; + } + + protected getMetricDescription(): string { + return 'Determines if the project uses fuzzing according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts new file mode 100644 index 0000000000..f27cdff418 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF License check. + * Determines if the project has defined a license. + */ +export class LicenseMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'License'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF License'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has defined a license according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts new file mode 100644 index 0000000000..7451cf8a8c --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Maintained check. + * Determines if the project is "actively maintained". + */ +export class MaintainedMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Maintained'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Maintained'; + } + + protected getMetricDescription(): string { + return 'Determines if the project is "actively maintained" according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts new file mode 100644 index 0000000000..7c244f9a66 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Packaging check. + * Determines if the project is published as a package that others can easily download, install, easily update, and uninstall. + */ +export class PackagingMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Packaging'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Packaging'; + } + + protected getMetricDescription(): string { + return 'Determines if the project is published as a package that others can easily download, install, easily update, and uninstall according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts new file mode 100644 index 0000000000..ed73a00cda --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Pinned-Dependencies check. + * Determines if the project has declared and pinned the dependencies of its build process. + */ +export class PinnedDependenciesMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Pinned-Dependencies'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Pinned Dependencies'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has declared and pinned the dependencies of its build process according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts new file mode 100644 index 0000000000..63a7399f7a --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF SAST check. + * Determines if the project uses static code analysis. + */ +export class SASTMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'SAST'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF SAST'; + } + + protected getMetricDescription(): string { + return 'Determines if the project uses static code analysis according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts new file mode 100644 index 0000000000..1260ab1cf9 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Security-Policy check. + * Determines if the project has published a security policy. + */ +export class SecurityPolicyMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Security-Policy'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Security Policy'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has published a security policy according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts new file mode 100644 index 0000000000..b7601f3fa5 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Signed-Releases check. + * Determines if the project cryptographically signs release artifacts. + */ +export class SignedReleasesMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Signed-Releases'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Signed Releases'; + } + + protected getMetricDescription(): string { + return 'Determines if the project cryptographically signs release artifacts according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts new file mode 100644 index 0000000000..146c817b15 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Token-Permissions check. + * Determines if the project's workflows follow the principle of least privilege. + */ +export class TokenPermissionsMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Token-Permissions'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Token Permissions'; + } + + protected getMetricDescription(): string { + return "Determines if the project's workflows follow the principle of least privilege according to OpenSSF Security Scorecards."; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts new file mode 100644 index 0000000000..7ac6675690 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts @@ -0,0 +1,35 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Metric provider for OpenSSF Vulnerabilities check. + * Determines if the project has open, known unfixed vulnerabilities. + */ +export class VulnerabilitiesMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Vulnerabilities'; + } + + protected getMetricDisplayTitle(): string { + return 'OpenSSF Vulnerabilities'; + } + + protected getMetricDescription(): string { + return 'Determines if the project has open, known unfixed vulnerabilities according to OpenSSF Security Scorecards.'; + } +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts new file mode 100644 index 0000000000..b3324ddfcb --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts @@ -0,0 +1,68 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createBackendModule } from '@backstage/backend-plugin-api'; +import { scorecardMetricsExtensionPoint } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; +import { BinaryArtifactsMetricProvider } from './metricProviders/BinaryArtifactsMetricProvider'; +import { BranchProtectionMetricProvider } from './metricProviders/BranchProtectionMetricProvider'; +import { CITestsMetricProvider } from './metricProviders/CITestsMetricProvider'; +import { CIIBestPracticesMetricProvider } from './metricProviders/CIIBestPracticesMetricProvider'; +import { CodeReviewMetricProvider } from './metricProviders/CodeReviewMetricProvider'; +import { ContributorsMetricProvider } from './metricProviders/ContributorsMetricProvider'; +import { DangerousWorkflowMetricProvider } from './metricProviders/DangerousWorkflowMetricProvider'; +import { DependencyUpdateToolMetricProvider } from './metricProviders/DependencyUpdateToolMetricProvider'; +import { FuzzingMetricProvider } from './metricProviders/FuzzingMetricProvider'; +import { LicenseMetricProvider } from './metricProviders/LicenseMetricProvider'; +import { MaintainedMetricProvider } from './metricProviders/MaintainedMetricProvider'; +import { PackagingMetricProvider } from './metricProviders/PackagingMetricProvider'; +import { PinnedDependenciesMetricProvider } from './metricProviders/PinnedDependenciesMetricProvider'; +import { SASTMetricProvider } from './metricProviders/SASTMetricProvider'; +import { SecurityPolicyMetricProvider } from './metricProviders/SecurityPolicyMetricProvider'; +import { SignedReleasesMetricProvider } from './metricProviders/SignedReleasesMetricProvider'; +import { TokenPermissionsMetricProvider } from './metricProviders/TokenPermissionsMetricProvider'; +import { VulnerabilitiesMetricProvider } from './metricProviders/VulnerabilitiesMetricProvider'; + +export const scorecardModuleOpenSSF = createBackendModule({ + pluginId: 'scorecard', + moduleId: 'openssf', + register(reg) { + reg.registerInit({ + deps: { + metrics: scorecardMetricsExtensionPoint, + }, + async init({ metrics }) { + // Register all OpenSSF metric providers + metrics.addMetricProvider(new BinaryArtifactsMetricProvider()); + metrics.addMetricProvider(new BranchProtectionMetricProvider()); + metrics.addMetricProvider(new CITestsMetricProvider()); + metrics.addMetricProvider(new CIIBestPracticesMetricProvider()); + metrics.addMetricProvider(new CodeReviewMetricProvider()); + metrics.addMetricProvider(new ContributorsMetricProvider()); + metrics.addMetricProvider(new DangerousWorkflowMetricProvider()); + metrics.addMetricProvider(new DependencyUpdateToolMetricProvider()); + metrics.addMetricProvider(new FuzzingMetricProvider()); + metrics.addMetricProvider(new LicenseMetricProvider()); + metrics.addMetricProvider(new MaintainedMetricProvider()); + metrics.addMetricProvider(new PackagingMetricProvider()); + metrics.addMetricProvider(new PinnedDependenciesMetricProvider()); + metrics.addMetricProvider(new SASTMetricProvider()); + metrics.addMetricProvider(new SecurityPolicyMetricProvider()); + metrics.addMetricProvider(new SignedReleasesMetricProvider()); + metrics.addMetricProvider(new TokenPermissionsMetricProvider()); + metrics.addMetricProvider(new VulnerabilitiesMetricProvider()); + }, + }); + }, +}); From b84d08e08a9f02e62e9aa9614448ec51f77bbde2 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 16 Dec 2025 12:31:51 +0100 Subject: [PATCH 02/13] feat: make OpenSSFClient baseUrl and gitServiceHost configurable; add unit tests --- .../scorecard/packages/backend/package.json | 1 + .../scorecard/packages/backend/src/index.ts | 5 + .../src/clients/OpenSSFClient.test.ts | 97 ++++++++ .../src/clients/OpenSSFClient.ts | 14 +- .../src/clients/utils.ts | 4 +- .../AbstractMetricProvider.test.ts | 227 ++++++++++++++++++ .../metricProviders/AbstractMetricProvider.ts | 2 +- 7 files changed, 344 insertions(+), 6 deletions(-) create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts diff --git a/workspaces/scorecard/packages/backend/package.json b/workspaces/scorecard/packages/backend/package.json index 23c935c0b9..6f3dbb7da9 100644 --- a/workspaces/scorecard/packages/backend/package.json +++ b/workspaces/scorecard/packages/backend/package.json @@ -48,6 +48,7 @@ "@red-hat-developer-hub/backstage-plugin-scorecard-backend": "workspace:^", "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-github": "workspace:^", "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira": "workspace:^", + "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf": "workspace:^", "app": "link:../app", "better-sqlite3": "^9.0.0", "node-gyp": "^10.0.0", diff --git a/workspaces/scorecard/packages/backend/src/index.ts b/workspaces/scorecard/packages/backend/src/index.ts index e8b86ef04c..fabda70bd2 100644 --- a/workspaces/scorecard/packages/backend/src/index.ts +++ b/workspaces/scorecard/packages/backend/src/index.ts @@ -72,4 +72,9 @@ backend.add( '@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira' ), ); +backend.add( + import( + '@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf' + ), +); backend.start(); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts new file mode 100644 index 0000000000..c1d7007933 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { OpenSSFClient } from './OpenSSFClient'; +import { OpenSSFResponse } from './types'; + +describe('OpenSSFClient', () => { + let client: OpenSSFClient; + + const mockOpenSSFResponse: OpenSSFResponse = { + date: '2024-01-15', + repo: { + name: 'github.com/owner/test', + commit: 'abc123', + }, + scorecard: { + version: '4.0.0', + commit: 'def456', + }, + score: 7.5, + checks: [], + }; + + beforeEach(() => { + jest.clearAllMocks(); + client = new OpenSSFClient(); + globalThis.fetch = jest.fn(); + }); + + describe('getScorecard', () => { + it('should return the scorecard', async () => { + // mocked fetch behaviour for the test + (globalThis.fetch as jest.Mock).mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue(mockOpenSSFResponse), + }); + + const scorecard = await client.getScorecard('owner', 'test'); + expect(scorecard).toEqual(mockOpenSSFResponse); + }); + + it('should throw an error if the API returns a non-ok response', async () => { + // mock response from the API + (globalThis.fetch as jest.Mock).mockResolvedValue({ + ok: false, + status: 404, + statusText: 'Not Found', + }); + + await expect(client.getScorecard('wrong', 'test')).rejects.toThrow( + 'OpenSSF API request failed with status 404: Not Found', + ); + }); + + it('should throw an error if the score is not a number', async () => { + // mock response from the API + const responseWithoutScore = { + ...mockOpenSSFResponse, + score: 'not a number', + }; + + // mocked fetch behaviour for the test + (globalThis.fetch as jest.Mock).mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue(responseWithoutScore), + }); + + await expect(client.getScorecard('owner', 'test')).rejects.toThrow( + 'Invalid response from OpenSSF API: score is not a number', + ); + }); + + it('should throw an error if API request fails', async () => { + // mocked fetch behaviour for the test + (globalThis.fetch as jest.Mock).mockRejectedValue( + new Error('API request failed'), + ); + + await expect(client.getScorecard('owner', 'test')).rejects.toThrow( + 'API request failed', + ); + }); + }); +}); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts index 6cc39b4bba..983bd753dd 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts @@ -17,11 +17,19 @@ import { OpenSSFResponse } from './types'; export class OpenSSFClient { - private readonly OPENSSF_API_BASE_URL = - 'https://api.securityscorecards.dev/projects'; + private readonly baseUrl: string; + private readonly gitServiceHost: string; + + constructor( + baseUrl: string = 'https://api.securityscorecards.dev/projects', + gitServiceHost: string = 'github.com', + ) { + this.baseUrl = baseUrl; + this.gitServiceHost = gitServiceHost; + } async getScorecard(owner: string, repo: string): Promise { - const apiUrl = `${this.OPENSSF_API_BASE_URL}/github.com/${owner}/${repo}`; + const apiUrl = `${this.baseUrl}/${this.gitServiceHost}/${owner}/${repo}`; const response = await fetch(apiUrl, { method: 'GET', diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts index 27c5ca4b89..03ec0cf43d 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/utils.ts @@ -22,7 +22,7 @@ export const getRepositoryInformationFromEntity = ( const projectSlug = entity.metadata.annotations?.['openssf/project']; if (!projectSlug) { throw new Error( - `Missing annotation 'github.com/project-slug' for entity ${stringifyEntityRef( + `Missing annotation 'openssf/project' for entity ${stringifyEntityRef( entity, )}`, ); @@ -31,7 +31,7 @@ export const getRepositoryInformationFromEntity = ( const [owner, repo] = projectSlug.split('/'); if (!owner || !repo) { throw new Error( - `Invalid format of 'github.com/project-slug' ${projectSlug} for entity ${stringifyEntityRef( + `Invalid format of 'openssf/project' ${projectSlug} for entity ${stringifyEntityRef( entity, )}`, ); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts new file mode 100644 index 0000000000..1fc73f9939 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts @@ -0,0 +1,227 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; +import { type Entity } from '@backstage/catalog-model'; +import { + DEFAULT_NUMBER_THRESHOLDS, + ThresholdConfig, +} from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; + +import { OpenSSFClient } from '../clients/OpenSSFClient'; +import { OpenSSFResponse } from '../clients/types'; +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +// Mock the OpenSSFClient module +jest.mock('../clients/OpenSSFClient'); + +// Concrete implementation for testing the abstract class +class TestMetricProvider extends AbstractMetricProvider { + protected getMetricName(): string { + return 'Test-Metric'; + } + + protected getMetricDisplayTitle(): string { + return 'Test Metric Title'; + } + + protected getMetricDescription(): string { + return 'Test metric description'; + } +} + +describe('AbstractMetricProvider', () => { + let provider: TestMetricProvider; + let mockGetScorecard: jest.Mock; + + const mockOpenSSFResponse: OpenSSFResponse = { + date: '2024-01-15', + repo: { + name: 'github.com/owner/test', + commit: 'abc123', + }, + scorecard: { + version: '4.0.0', + commit: 'def456', + }, + score: 7.5, + checks: [ + { + name: 'Test-Metric', + score: 8, + reason: 'Test reason', + details: null, + documentation: { + short: 'Short doc', + url: 'https://example.com', + }, + }, + { + name: 'Other-Metric', + score: 6, + reason: 'Other reason', + details: null, + documentation: { + short: 'Other doc', + url: 'https://example.com/other', + }, + }, + ], + }; + + const createMockEntity = (projectSlug?: string): Entity => ({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test-component', + annotations: projectSlug ? { 'openssf/project': projectSlug } : undefined, + }, + }); + + beforeEach(() => { + jest.clearAllMocks(); + + // Setup mock for OpenSSFClient + mockGetScorecard = jest.fn().mockResolvedValue(mockOpenSSFResponse); + (OpenSSFClient as jest.Mock).mockImplementation(() => ({ + getScorecard: mockGetScorecard, + })); + + provider = new TestMetricProvider(); + }); + + describe('getProviderDatasourceId', () => { + it('should return "openssf"', () => { + expect(provider.getProviderDatasourceId()).toBe('openssf'); + }); + }); + + describe('getProviderId', () => { + it('should return normalized provider ID with openssf prefix', () => { + expect(provider.getProviderId()).toBe('openssf.test_metric'); + }); + + it('should convert hyphens to underscores and lowercase', () => { + // The metric name is "Test-Metric", should become "test_metric" + expect(provider.getProviderId()).toBe('openssf.test_metric'); + }); + }); + + describe('getMetricType', () => { + it('should return "number"', () => { + expect(provider.getMetricType()).toBe('number'); + }); + }); + + describe('getMetric', () => { + it('should return metric object with correct properties', () => { + const metric = provider.getMetric(); + + expect(metric).toEqual({ + id: 'openssf.test_metric', + title: 'Test Metric Title', + description: 'Test metric description', + type: 'number', + history: true, + }); + }); + }); + + describe('getMetricThresholds', () => { + it('should return default thresholds when none provided', () => { + expect(provider.getMetricThresholds()).toEqual(DEFAULT_NUMBER_THRESHOLDS); + }); + + it('should return custom thresholds when provided', () => { + const customThresholds: ThresholdConfig = { + green: 9, + yellow: 7, + red: 4, + }; + const customProvider = new TestMetricProvider(customThresholds); + + expect(customProvider.getMetricThresholds()).toEqual(customThresholds); + }); + }); + + describe('getCatalogFilter', () => { + it('should return filter for openssf/project-slug annotation', () => { + expect(provider.getCatalogFilter()).toEqual({ + 'metadata.annotations.openssf/project-slug': CATALOG_FILTER_EXISTS, + }); + }); + }); + + describe('calculateMetric', () => { + it('should call OpenSSFClient with owner and repo from entity', async () => { + const entity = createMockEntity('owner/test'); + + await provider.calculateMetric(entity); + + expect(mockGetScorecard).toHaveBeenCalledWith('owner', 'test'); + }); + + it('should return the score for the matching metric', async () => { + const entity = createMockEntity('owner/test'); + + const score = await provider.calculateMetric(entity); + + // provider has getMetricName() returning 'Test-Metric', so score should be 8 + expect(score).toBe(8); + }); + + it('should throw error when metric is not found in scorecard', async () => { + const responseWithoutMetric: OpenSSFResponse = { + ...mockOpenSSFResponse, + checks: [ + { + name: 'Different-Metric', + score: 5, + reason: 'Different reason', + details: null, + documentation: { + short: 'Different doc', + url: 'https://example.com/different', + }, + }, + ], + }; + mockGetScorecard.mockResolvedValue(responseWithoutMetric); + + const entity = createMockEntity('owner/test'); + + await expect(provider.calculateMetric(entity)).rejects.toThrow( + "OpenSSF check 'Test-Metric' not found in scorecard for owner/test", + ); + }); + + it('should throw error when entity is missing openssf/project annotation', async () => { + const entity = createMockEntity(); + + await expect(provider.calculateMetric(entity)).rejects.toThrow( + "Missing annotation 'openssf/project'", + ); + }); + + it('should throw error when project slug has invalid format', async () => { + const entity = createMockEntity('invalid-slug-without-slash'); + + await expect(provider.calculateMetric(entity)).rejects.toThrow( + "Invalid format of 'openssf/project'", + ); + }); + }); +}); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts index 69a65ffb6b..f47ad1f1ac 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -84,7 +84,7 @@ export abstract class AbstractMetricProvider getCatalogFilter(): Record { return { - 'metadata.annotations.github.com/project-slug': CATALOG_FILTER_EXISTS, + 'metadata.annotations.openssf/project-slug': CATALOG_FILTER_EXISTS, }; } From 450506ac6169ceca46536572dcd3941acde8aaef Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 16 Dec 2025 14:21:49 +0100 Subject: [PATCH 03/13] feat: fix openssf annotation --- .../src/metricProviders/AbstractMetricProvider.test.ts | 2 +- .../src/metricProviders/AbstractMetricProvider.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts index 1fc73f9939..17ce1089c7 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts @@ -160,7 +160,7 @@ describe('AbstractMetricProvider', () => { describe('getCatalogFilter', () => { it('should return filter for openssf/project-slug annotation', () => { expect(provider.getCatalogFilter()).toEqual({ - 'metadata.annotations.openssf/project-slug': CATALOG_FILTER_EXISTS, + 'metadata.annotations.openssf/project': CATALOG_FILTER_EXISTS, }); }); }); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts index f47ad1f1ac..c39fc291c0 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -84,7 +84,7 @@ export abstract class AbstractMetricProvider getCatalogFilter(): Record { return { - 'metadata.annotations.openssf/project-slug': CATALOG_FILTER_EXISTS, + 'metadata.annotations.openssf/project': CATALOG_FILTER_EXISTS, }; } From ec8024c7bf8693448c712a7c0db6f11865ddc14e Mon Sep 17 00:00:00 2001 From: Jessica He Date: Tue, 16 Dec 2025 15:15:56 -0500 Subject: [PATCH 04/13] use createOpenSSFMetricProviders Signed-off-by: Jessica He --- .../BinaryArtifactsMetricProvider.ts | 35 ---- .../BranchProtectionMetricProvider.ts | 35 ---- .../CIIBestPracticesMetricProvider.ts | 35 ---- .../metricProviders/CITestsMetricProvider.ts | 35 ---- .../CodeReviewMetricProvider.ts | 35 ---- .../ContributorsMetricProvider.ts | 35 ---- .../DangerousWorkflowMetricProvider.ts | 35 ---- .../DependencyUpdateToolMetricProvider.ts | 35 ---- .../metricProviders/FuzzingMetricProvider.ts | 35 ---- .../metricProviders/LicenseMetricProvider.ts | 35 ---- .../MaintainedMetricProvider.ts | 35 ---- .../PackagingMetricProvider.ts | 35 ---- .../PinnedDependenciesMetricProvider.ts | 35 ---- .../src/metricProviders/SASTMetricProvider.ts | 35 ---- .../SecurityPolicyMetricProvider.ts | 35 ---- .../SignedReleasesMetricProvider.ts | 35 ---- .../TokenPermissionsMetricProvider.ts | 35 ---- .../VulnerabilitiesMetricProvider.ts | 35 ---- .../metricProviders/openSSFMetricProviders.ts | 183 ++++++++++++++++++ .../src/module.ts | 38 +--- workspaces/scorecard/yarn.lock | 15 ++ 21 files changed, 200 insertions(+), 666 deletions(-) delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts delete mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts deleted file mode 100644 index 6fac25ecfb..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BinaryArtifactsMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Binary-Artifacts check. - * Determines if the project has generated executable (binary) artifacts in the source repository. - */ -export class BinaryArtifactsMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Binary-Artifacts'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Binary Artifacts'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has generated executable (binary) artifacts in the source repository according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts deleted file mode 100644 index a5b4954e9b..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/BranchProtectionMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Branch-Protection check. - * Determines if the default and release branches are protected with GitHub's branch protection settings. - */ -export class BranchProtectionMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Branch-Protection'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Branch Protection'; - } - - protected getMetricDescription(): string { - return "Determines if the default and release branches are protected with GitHub's branch protection settings according to OpenSSF Security Scorecards."; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts deleted file mode 100644 index d444ce03ad..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CIIBestPracticesMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF CII-Best-Practices check. - * Determines if the project has an OpenSSF (formerly CII) Best Practices Badge. - */ -export class CIIBestPracticesMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'CII-Best-Practices'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF CII Best Practices'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has an OpenSSF (formerly CII) Best Practices Badge according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts deleted file mode 100644 index b384101773..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CITestsMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF CI-Tests check. - * Determines if the project runs tests before pull requests are merged. - */ -export class CITestsMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'CI-Tests'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF CI Tests'; - } - - protected getMetricDescription(): string { - return 'Determines if the project runs tests before pull requests are merged according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts deleted file mode 100644 index d897691eab..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/CodeReviewMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Code-Review check. - * Determines if the project requires human code review before pull requests are merged. - */ -export class CodeReviewMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Code-Review'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Code Review'; - } - - protected getMetricDescription(): string { - return 'Determines if the project requires human code review before pull requests (aka merge requests) are merged according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts deleted file mode 100644 index b44c57db73..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/ContributorsMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Contributors check. - * Determines if the project has a set of contributors from multiple organizations (e.g., companies). - */ -export class ContributorsMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Contributors'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Contributors'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has a set of contributors from multiple organizations (e.g., companies) according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts deleted file mode 100644 index 9f454a98d6..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DangerousWorkflowMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Dangerous-Workflow check. - * Determines if the project's GitHub Action workflows avoid dangerous patterns. - */ -export class DangerousWorkflowMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Dangerous-Workflow'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Dangerous Workflow'; - } - - protected getMetricDescription(): string { - return "Determines if the project's GitHub Action workflows avoid dangerous patterns according to OpenSSF Security Scorecards."; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts deleted file mode 100644 index 1daad1dd71..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DependencyUpdateToolMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Dependency-Update-Tool check. - * Determines if the project uses a dependency update tool. - */ -export class DependencyUpdateToolMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Dependency-Update-Tool'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Dependency Update Tool'; - } - - protected getMetricDescription(): string { - return 'Determines if the project uses a dependency update tool according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts deleted file mode 100644 index e4f6cc9a5f..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/FuzzingMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Fuzzing check. - * Determines if the project uses fuzzing. - */ -export class FuzzingMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Fuzzing'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Fuzzing'; - } - - protected getMetricDescription(): string { - return 'Determines if the project uses fuzzing according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts deleted file mode 100644 index f27cdff418..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/LicenseMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF License check. - * Determines if the project has defined a license. - */ -export class LicenseMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'License'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF License'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has defined a license according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts deleted file mode 100644 index 7451cf8a8c..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/MaintainedMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Maintained check. - * Determines if the project is "actively maintained". - */ -export class MaintainedMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Maintained'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Maintained'; - } - - protected getMetricDescription(): string { - return 'Determines if the project is "actively maintained" according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts deleted file mode 100644 index 7c244f9a66..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PackagingMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Packaging check. - * Determines if the project is published as a package that others can easily download, install, easily update, and uninstall. - */ -export class PackagingMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Packaging'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Packaging'; - } - - protected getMetricDescription(): string { - return 'Determines if the project is published as a package that others can easily download, install, easily update, and uninstall according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts deleted file mode 100644 index ed73a00cda..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/PinnedDependenciesMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Pinned-Dependencies check. - * Determines if the project has declared and pinned the dependencies of its build process. - */ -export class PinnedDependenciesMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Pinned-Dependencies'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Pinned Dependencies'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has declared and pinned the dependencies of its build process according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts deleted file mode 100644 index 63a7399f7a..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SASTMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF SAST check. - * Determines if the project uses static code analysis. - */ -export class SASTMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'SAST'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF SAST'; - } - - protected getMetricDescription(): string { - return 'Determines if the project uses static code analysis according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts deleted file mode 100644 index 1260ab1cf9..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SecurityPolicyMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Security-Policy check. - * Determines if the project has published a security policy. - */ -export class SecurityPolicyMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Security-Policy'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Security Policy'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has published a security policy according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts deleted file mode 100644 index b7601f3fa5..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/SignedReleasesMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Signed-Releases check. - * Determines if the project cryptographically signs release artifacts. - */ -export class SignedReleasesMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Signed-Releases'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Signed Releases'; - } - - protected getMetricDescription(): string { - return 'Determines if the project cryptographically signs release artifacts according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts deleted file mode 100644 index 146c817b15..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/TokenPermissionsMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Token-Permissions check. - * Determines if the project's workflows follow the principle of least privilege. - */ -export class TokenPermissionsMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Token-Permissions'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Token Permissions'; - } - - protected getMetricDescription(): string { - return "Determines if the project's workflows follow the principle of least privilege according to OpenSSF Security Scorecards."; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts deleted file mode 100644 index 7ac6675690..0000000000 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/VulnerabilitiesMetricProvider.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Red Hat, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AbstractMetricProvider } from './AbstractMetricProvider'; - -/** - * Metric provider for OpenSSF Vulnerabilities check. - * Determines if the project has open, known unfixed vulnerabilities. - */ -export class VulnerabilitiesMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { - return 'Vulnerabilities'; - } - - protected getMetricDisplayTitle(): string { - return 'OpenSSF Vulnerabilities'; - } - - protected getMetricDescription(): string { - return 'Determines if the project has open, known unfixed vulnerabilities according to OpenSSF Security Scorecards.'; - } -} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts new file mode 100644 index 0000000000..16c4ed78fc --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts @@ -0,0 +1,183 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ThresholdConfig } from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; +import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; +import { AbstractMetricProvider } from './AbstractMetricProvider'; + +/** + * Configuration for an OpenSSF metric provider. + */ +interface OpenSSFMetricConfig { + /** The name of the OpenSSF check (e.g., "Maintained", "Code-Review") */ + name: string; + /** Display title for the metric (e.g., "OpenSSF Maintained") */ + displayTitle: string; + /** Description of what the metric measures */ + description: string; +} + +/** + * All available OpenSSF Security Scorecard metrics. + */ +const OPENSSF_METRICS: OpenSSFMetricConfig[] = [ + { + name: 'Binary-Artifacts', + displayTitle: 'OpenSSF Binary Artifacts', + description: + 'Determines if the project has generated executable (binary) artifacts in the source repository according to OpenSSF Security Scorecards.', + }, + { + name: 'Branch-Protection', + displayTitle: 'OpenSSF Branch Protection', + description: + "Determines if the default and release branches are protected with GitHub's branch protection settings according to OpenSSF Security Scorecards.", + }, + { + name: 'CII-Best-Practices', + displayTitle: 'OpenSSF CII Best Practices', + description: + 'Determines if the project has an OpenSSF (formerly CII) Best Practices Badge according to OpenSSF Security Scorecards.', + }, + { + name: 'CI-Tests', + displayTitle: 'OpenSSF CI Tests', + description: + 'Determines if the project runs tests before pull requests are merged according to OpenSSF Security Scorecards.', + }, + { + name: 'Code-Review', + displayTitle: 'OpenSSF Code Review', + description: + 'Determines if the project requires human code review before pull requests (aka merge requests) are merged according to OpenSSF Security Scorecards.', + }, + { + name: 'Contributors', + displayTitle: 'OpenSSF Contributors', + description: + 'Determines if the project has a set of contributors from multiple organizations (e.g., companies) according to OpenSSF Security Scorecards.', + }, + { + name: 'Dangerous-Workflow', + displayTitle: 'OpenSSF Dangerous Workflow', + description: + "Determines if the project's GitHub Action workflows avoid dangerous patterns according to OpenSSF Security Scorecards.", + }, + { + name: 'Dependency-Update-Tool', + displayTitle: 'OpenSSF Dependency Update Tool', + description: + 'Determines if the project uses a dependency update tool according to OpenSSF Security Scorecards.', + }, + { + name: 'Fuzzing', + displayTitle: 'OpenSSF Fuzzing', + description: + 'Determines if the project uses fuzzing according to OpenSSF Security Scorecards.', + }, + { + name: 'License', + displayTitle: 'OpenSSF License', + description: + 'Determines if the project has defined a license according to OpenSSF Security Scorecards.', + }, + { + name: 'Maintained', + displayTitle: 'OpenSSF Maintained', + description: + 'Determines if the project is "actively maintained" according to OpenSSF Security Scorecards.', + }, + { + name: 'Packaging', + displayTitle: 'OpenSSF Packaging', + description: + 'Determines if the project is published as a package that others can easily download, install, easily update, and uninstall according to OpenSSF Security Scorecards.', + }, + { + name: 'Pinned-Dependencies', + displayTitle: 'OpenSSF Pinned Dependencies', + description: + 'Determines if the project has declared and pinned the dependencies of its build process according to OpenSSF Security Scorecards.', + }, + { + name: 'SAST', + displayTitle: 'OpenSSF SAST', + description: + 'Determines if the project uses static code analysis according to OpenSSF Security Scorecards.', + }, + { + name: 'Security-Policy', + displayTitle: 'OpenSSF Security Policy', + description: + 'Determines if the project has published a security policy according to OpenSSF Security Scorecards.', + }, + { + name: 'Signed-Releases', + displayTitle: 'OpenSSF Signed Releases', + description: + 'Determines if the project cryptographically signs release artifacts according to OpenSSF Security Scorecards.', + }, + { + name: 'Token-Permissions', + displayTitle: 'OpenSSF Token Permissions', + description: + "Determines if the project's workflows follow the principle of least privilege according to OpenSSF Security Scorecards.", + }, + { + name: 'Vulnerabilities', + displayTitle: 'OpenSSF Vulnerabilities', + description: + 'Determines if the project has open, known unfixed vulnerabilities according to OpenSSF Security Scorecards.', + }, +]; + +/** + * Configurable metric provider for OpenSSF Security Scorecards. + * Extracts a specific check from the OpenSSF scorecard response based on the provided configuration. + */ +class ConfigurableMetricProvider extends AbstractMetricProvider { + constructor( + private readonly config: OpenSSFMetricConfig, + thresholds?: ThresholdConfig, + ) { + super(thresholds); + } + + protected getMetricName(): string { + return this.config.name; + } + + protected getMetricDisplayTitle(): string { + return this.config.displayTitle; + } + + protected getMetricDescription(): string { + return this.config.description; + } +} + +/** + * Creates all OpenSSF metric providers. + * @param thresholds Optional threshold configuration to apply to all providers + * @returns Array of OpenSSF metric providers + */ +export function createOpenSSFMetricProviders( + thresholds?: ThresholdConfig, +): MetricProvider<'number'>[] { + return OPENSSF_METRICS.map( + config => new ConfigurableMetricProvider(config, thresholds), + ); +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts index b3324ddfcb..c267a7788e 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts @@ -15,24 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; import { scorecardMetricsExtensionPoint } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; -import { BinaryArtifactsMetricProvider } from './metricProviders/BinaryArtifactsMetricProvider'; -import { BranchProtectionMetricProvider } from './metricProviders/BranchProtectionMetricProvider'; -import { CITestsMetricProvider } from './metricProviders/CITestsMetricProvider'; -import { CIIBestPracticesMetricProvider } from './metricProviders/CIIBestPracticesMetricProvider'; -import { CodeReviewMetricProvider } from './metricProviders/CodeReviewMetricProvider'; -import { ContributorsMetricProvider } from './metricProviders/ContributorsMetricProvider'; -import { DangerousWorkflowMetricProvider } from './metricProviders/DangerousWorkflowMetricProvider'; -import { DependencyUpdateToolMetricProvider } from './metricProviders/DependencyUpdateToolMetricProvider'; -import { FuzzingMetricProvider } from './metricProviders/FuzzingMetricProvider'; -import { LicenseMetricProvider } from './metricProviders/LicenseMetricProvider'; -import { MaintainedMetricProvider } from './metricProviders/MaintainedMetricProvider'; -import { PackagingMetricProvider } from './metricProviders/PackagingMetricProvider'; -import { PinnedDependenciesMetricProvider } from './metricProviders/PinnedDependenciesMetricProvider'; -import { SASTMetricProvider } from './metricProviders/SASTMetricProvider'; -import { SecurityPolicyMetricProvider } from './metricProviders/SecurityPolicyMetricProvider'; -import { SignedReleasesMetricProvider } from './metricProviders/SignedReleasesMetricProvider'; -import { TokenPermissionsMetricProvider } from './metricProviders/TokenPermissionsMetricProvider'; -import { VulnerabilitiesMetricProvider } from './metricProviders/VulnerabilitiesMetricProvider'; +import { createOpenSSFMetricProviders } from './metricProviders/openSSFMetricProviders'; export const scorecardModuleOpenSSF = createBackendModule({ pluginId: 'scorecard', @@ -44,24 +27,7 @@ export const scorecardModuleOpenSSF = createBackendModule({ }, async init({ metrics }) { // Register all OpenSSF metric providers - metrics.addMetricProvider(new BinaryArtifactsMetricProvider()); - metrics.addMetricProvider(new BranchProtectionMetricProvider()); - metrics.addMetricProvider(new CITestsMetricProvider()); - metrics.addMetricProvider(new CIIBestPracticesMetricProvider()); - metrics.addMetricProvider(new CodeReviewMetricProvider()); - metrics.addMetricProvider(new ContributorsMetricProvider()); - metrics.addMetricProvider(new DangerousWorkflowMetricProvider()); - metrics.addMetricProvider(new DependencyUpdateToolMetricProvider()); - metrics.addMetricProvider(new FuzzingMetricProvider()); - metrics.addMetricProvider(new LicenseMetricProvider()); - metrics.addMetricProvider(new MaintainedMetricProvider()); - metrics.addMetricProvider(new PackagingMetricProvider()); - metrics.addMetricProvider(new PinnedDependenciesMetricProvider()); - metrics.addMetricProvider(new SASTMetricProvider()); - metrics.addMetricProvider(new SecurityPolicyMetricProvider()); - metrics.addMetricProvider(new SignedReleasesMetricProvider()); - metrics.addMetricProvider(new TokenPermissionsMetricProvider()); - metrics.addMetricProvider(new VulnerabilitiesMetricProvider()); + metrics.addMetricProvider(...createOpenSSFMetricProviders()); }, }); }, diff --git a/workspaces/scorecard/yarn.lock b/workspaces/scorecard/yarn.lock index d25c737194..9e95ef78ae 100644 --- a/workspaces/scorecard/yarn.lock +++ b/workspaces/scorecard/yarn.lock @@ -11089,6 +11089,20 @@ __metadata: languageName: unknown linkType: soft +"@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf@workspace:^, @red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf@workspace:plugins/scorecard-backend-module-openssf": + version: 0.0.0-use.local + resolution: "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf@workspace:plugins/scorecard-backend-module-openssf" + dependencies: + "@backstage/backend-plugin-api": ^1.5.0 + "@backstage/backend-test-utils": ^1.10.0 + "@backstage/catalog-client": ^1.12.1 + "@backstage/catalog-model": ^1.7.6 + "@backstage/cli": ^0.34.5 + "@red-hat-developer-hub/backstage-plugin-scorecard-common": "workspace:^" + "@red-hat-developer-hub/backstage-plugin-scorecard-node": "workspace:^" + languageName: unknown + linkType: soft + "@red-hat-developer-hub/backstage-plugin-scorecard-backend@workspace:^, @red-hat-developer-hub/backstage-plugin-scorecard-backend@workspace:plugins/scorecard-backend": version: 0.0.0-use.local resolution: "@red-hat-developer-hub/backstage-plugin-scorecard-backend@workspace:plugins/scorecard-backend" @@ -16454,6 +16468,7 @@ __metadata: "@red-hat-developer-hub/backstage-plugin-scorecard-backend": "workspace:^" "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-github": "workspace:^" "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira": "workspace:^" + "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf": "workspace:^" app: "link:../app" better-sqlite3: ^9.0.0 node-gyp: ^10.0.0 From 4eb490d80ab8be6c6bab8cfbea5c1fcc9013dfec Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Mon, 22 Dec 2025 11:30:46 +0100 Subject: [PATCH 05/13] refactored the implemented classes for OpenSSFMetric providers; reviewed the OpenSSF thresholds --- .../examples/openssf-scorecard-only.yaml | 14 +++++ .../scorecard/packages/backend/src/index.ts | 12 ++-- .../src/index.ts | 2 +- .../metricProviders/AbstractMetricProvider.ts | 6 +- .../DefaultOpenSSFMetricProvider.test.ts | 54 +++++++++++++++++ .../DefaultOpenSSFMetricProvider.ts | 58 +++++++++++++++++++ ...SSFMetricProviders.ts => OpenSSFConfig.ts} | 50 +++------------- .../src/module.ts | 11 ++-- 8 files changed, 153 insertions(+), 54 deletions(-) create mode 100644 workspaces/scorecard/examples/openssf-scorecard-only.yaml create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.test.ts create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts rename workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/{openSSFMetricProviders.ts => OpenSSFConfig.ts} (80%) diff --git a/workspaces/scorecard/examples/openssf-scorecard-only.yaml b/workspaces/scorecard/examples/openssf-scorecard-only.yaml new file mode 100644 index 0000000000..37f34491a3 --- /dev/null +++ b/workspaces/scorecard/examples/openssf-scorecard-only.yaml @@ -0,0 +1,14 @@ +--- +# Component with OpenSSF Scorecard +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: rhdh-plugins + annotations: + github.com/project-slug: redhat-developer/rhdh-plugins + openssf/project: redhat-developer/rhdh-plugins + backstage.io/source-location: url:https://github.com/redhat-developer/rhdh-plugins +spec: + type: service + owner: guests + lifecycle: experimental diff --git a/workspaces/scorecard/packages/backend/src/index.ts b/workspaces/scorecard/packages/backend/src/index.ts index fabda70bd2..9b4a1f8729 100644 --- a/workspaces/scorecard/packages/backend/src/index.ts +++ b/workspaces/scorecard/packages/backend/src/index.ts @@ -20,8 +20,9 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-app-backend')); backend.add(import('@backstage/plugin-proxy-backend')); -backend.add(import('@backstage/plugin-scaffolder-backend')); -backend.add(import('@backstage/plugin-scaffolder-backend-module-github')); +// TODO: Temporarily disabled - isolated-vm native module build issue +// backend.add(import('@backstage/plugin-scaffolder-backend')); +// backend.add(import('@backstage/plugin-scaffolder-backend-module-github')); backend.add(import('@backstage/plugin-techdocs-backend')); // auth plugin @@ -33,9 +34,10 @@ backend.add(import('@backstage/plugin-auth-backend-module-github-provider')); // catalog plugin backend.add(import('@backstage/plugin-catalog-backend')); -backend.add( - import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), -); +// TODO: Temporarily disabled - depends on scaffolder +// backend.add( +// import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), +// ); // See https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors backend.add(import('@backstage/plugin-catalog-backend-module-logs')); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts index 5317fd8110..934f1f3d6a 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/index.ts @@ -20,4 +20,4 @@ * @packageDocumentation */ -export { scorecardModuleOpenSSF as default } from './module'; +export { scorecardOpenSFFModule as default } from './module'; diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts index c39fc291c0..f7159beb37 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -47,11 +47,11 @@ export abstract class AbstractMetricProvider this.thresholds = thresholds ?? DEFAULT_NUMBER_THRESHOLDS; } - protected abstract getMetricName(): string; + abstract getMetricName(): string; - protected abstract getMetricDisplayTitle(): string; + abstract getMetricDisplayTitle(): string; - protected abstract getMetricDescription(): string; + abstract getMetricDescription(): string; getProviderDatasourceId(): string { return 'openssf'; diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.test.ts new file mode 100644 index 0000000000..1a710addbd --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createDefaultOpenSSFMetricProviders, + DefaultOpenSSFMetricProvider, +} from './DefaultOpenSSFMetricProvider'; +import { OPENSSF_METRICS, OPENSSF_THRESHOLDS } from './OpenSSFConfig'; + +describe('DefaultOpenSSFMetricProviderTests', () => { + it('should create a default OpenSSF metric provider', () => { + const provider = new DefaultOpenSSFMetricProvider( + OPENSSF_METRICS[0], + OPENSSF_THRESHOLDS, + ); + expect(provider.getMetricDisplayTitle()).toBe( + OPENSSF_METRICS[0].displayTitle, + ); + expect(provider.getMetricDescription()).toBe( + OPENSSF_METRICS[0].description, + ); + expect(provider.getMetricThresholds()).toBe(OPENSSF_THRESHOLDS); + }); + + it('should create a default OpenSSF metric provider with custom thresholds', () => { + const provider = new DefaultOpenSSFMetricProvider( + OPENSSF_METRICS[0], + OPENSSF_THRESHOLDS, + ); + expect(provider).toBeDefined(); + }); + + it('should create all default OpenSSF metric providers', () => { + const providers = createDefaultOpenSSFMetricProviders(OPENSSF_THRESHOLDS); + expect(providers.length).toBe(OPENSSF_METRICS.length); + for (const provider of providers) { + expect(provider).toBeInstanceOf(DefaultOpenSSFMetricProvider); + expect(provider.getMetricThresholds()).toBe(OPENSSF_THRESHOLDS); + } + }); +}); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts new file mode 100644 index 0000000000..3bd61d7b54 --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts @@ -0,0 +1,58 @@ +/* + * Copyright Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ThresholdConfig } from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; +import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; +import { AbstractMetricProvider } from './AbstractMetricProvider'; +import { OPENSSF_METRICS } from './OpenSSFConfig'; + +/** + * Default metric provider for OpenSSF Security Scorecards. + * Extracts a specific check from the OpenSSF scorecard response based on the provided configuration. + */ +export class DefaultOpenSSFMetricProvider extends AbstractMetricProvider { + constructor( + private readonly config: OpenSSFMetricConfig, + thresholds?: ThresholdConfig, + ) { + super(thresholds); + } + + getMetricName(): string { + return this.config.name; + } + + getMetricDisplayTitle(): string { + return this.config.displayTitle; + } + + getMetricDescription(): string { + return this.config.description; + } +} + +/** + * Creates all default OpenSSF metric providers. + * @param thresholds Optional threshold configuration to apply to all providers + * @returns Array of OpenSSF metric providers + */ +export function createDefaultOpenSSFMetricProviders( + thresholds?: ThresholdConfig, +): MetricProvider<'number'>[] { + return OPENSSF_METRICS.map( + config => new DefaultOpenSSFMetricProvider(config, thresholds), + ); +} diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFConfig.ts similarity index 80% rename from workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts rename to workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFConfig.ts index 16c4ed78fc..3018edcb6f 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/openSSFMetricProviders.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/OpenSSFConfig.ts @@ -15,13 +15,11 @@ */ import { ThresholdConfig } from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; -import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; -import { AbstractMetricProvider } from './AbstractMetricProvider'; /** * Configuration for an OpenSSF metric provider. */ -interface OpenSSFMetricConfig { +export interface OpenSSFMetricConfig { /** The name of the OpenSSF check (e.g., "Maintained", "Code-Review") */ name: string; /** Display title for the metric (e.g., "OpenSSF Maintained") */ @@ -33,7 +31,7 @@ interface OpenSSFMetricConfig { /** * All available OpenSSF Security Scorecard metrics. */ -const OPENSSF_METRICS: OpenSSFMetricConfig[] = [ +export const OPENSSF_METRICS: OpenSSFMetricConfig[] = [ { name: 'Binary-Artifacts', displayTitle: 'OpenSSF Binary Artifacts', @@ -144,40 +142,10 @@ const OPENSSF_METRICS: OpenSSFMetricConfig[] = [ }, ]; -/** - * Configurable metric provider for OpenSSF Security Scorecards. - * Extracts a specific check from the OpenSSF scorecard response based on the provided configuration. - */ -class ConfigurableMetricProvider extends AbstractMetricProvider { - constructor( - private readonly config: OpenSSFMetricConfig, - thresholds?: ThresholdConfig, - ) { - super(thresholds); - } - - protected getMetricName(): string { - return this.config.name; - } - - protected getMetricDisplayTitle(): string { - return this.config.displayTitle; - } - - protected getMetricDescription(): string { - return this.config.description; - } -} - -/** - * Creates all OpenSSF metric providers. - * @param thresholds Optional threshold configuration to apply to all providers - * @returns Array of OpenSSF metric providers - */ -export function createOpenSSFMetricProviders( - thresholds?: ThresholdConfig, -): MetricProvider<'number'>[] { - return OPENSSF_METRICS.map( - config => new ConfigurableMetricProvider(config, thresholds), - ); -} +export const OPENSSF_THRESHOLDS: ThresholdConfig = { + rules: [ + { key: 'error', expression: '<2' }, + { key: 'warning', expression: '2-7' }, + { key: 'success', expression: '>7' }, + ], +}; diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts index c267a7788e..9ca937c14c 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/module.ts @@ -15,9 +15,10 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; import { scorecardMetricsExtensionPoint } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; -import { createOpenSSFMetricProviders } from './metricProviders/openSSFMetricProviders'; +import { createDefaultOpenSSFMetricProviders } from './metricProviders/DefaultOpenSSFMetricProvider'; +import { OPENSSF_THRESHOLDS } from './metricProviders/OpenSSFConfig'; -export const scorecardModuleOpenSSF = createBackendModule({ +export const scorecardOpenSFFModule = createBackendModule({ pluginId: 'scorecard', moduleId: 'openssf', register(reg) { @@ -26,8 +27,10 @@ export const scorecardModuleOpenSSF = createBackendModule({ metrics: scorecardMetricsExtensionPoint, }, async init({ metrics }) { - // Register all OpenSSF metric providers - metrics.addMetricProvider(...createOpenSSFMetricProviders()); + // Register all default OpenSSF metric providers + metrics.addMetricProvider( + ...createDefaultOpenSSFMetricProviders(OPENSSF_THRESHOLDS), + ); }, }); }, From f7f50daeb3889fd1149536989b9286efca92f8c0 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Mon, 22 Dec 2025 17:27:07 +0100 Subject: [PATCH 06/13] fixed 4 ts errors reported by yarn tsc:full --- .../metricProviders/AbstractMetricProvider.test.ts | 14 ++++++++------ .../DefaultOpenSSFMetricProvider.ts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts index 17ce1089c7..472c5c63ac 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts @@ -30,15 +30,15 @@ jest.mock('../clients/OpenSSFClient'); // Concrete implementation for testing the abstract class class TestMetricProvider extends AbstractMetricProvider { - protected getMetricName(): string { + getMetricName(): string { return 'Test-Metric'; } - protected getMetricDisplayTitle(): string { + getMetricDisplayTitle(): string { return 'Test Metric Title'; } - protected getMetricDescription(): string { + getMetricDescription(): string { return 'Test metric description'; } } @@ -147,9 +147,11 @@ describe('AbstractMetricProvider', () => { it('should return custom thresholds when provided', () => { const customThresholds: ThresholdConfig = { - green: 9, - yellow: 7, - red: 4, + rules: [ + { key: 'success', expression: '>9' }, + { key: 'warning', expression: '7-9' }, + { key: 'error', expression: '<7' }, + ], }; const customProvider = new TestMetricProvider(customThresholds); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts index 3bd61d7b54..968488bdbe 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts @@ -17,7 +17,7 @@ import { ThresholdConfig } from '@red-hat-developer-hub/backstage-plugin-scorecard-common'; import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecard-node'; import { AbstractMetricProvider } from './AbstractMetricProvider'; -import { OPENSSF_METRICS } from './OpenSSFConfig'; +import { OPENSSF_METRICS, OpenSSFMetricConfig } from './OpenSSFConfig'; /** * Default metric provider for OpenSSF Security Scorecards. From ecd093168dfafd4cb7fdf605b6b54c3344386942 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Mon, 22 Dec 2025 17:36:12 +0100 Subject: [PATCH 07/13] add api-report --- .../scorecard-backend-module-openssf/report.api.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 workspaces/scorecard/plugins/scorecard-backend-module-openssf/report.api.md diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/report.api.md b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/report.api.md new file mode 100644 index 0000000000..b7526723bd --- /dev/null +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/report.api.md @@ -0,0 +1,11 @@ +## API Report File for "@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @public (undocumented) +const scorecardOpenSFFModule: BackendFeature; +export default scorecardOpenSFFModule; +``` From f9ba9dc88f26ef961d71b79f129222955be52d05 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 23 Dec 2025 10:45:45 +0100 Subject: [PATCH 08/13] review work --- workspaces/scorecard/packages/backend/src/index.ts | 5 ++--- .../plugins/scorecard-backend-module-openssf/package.json | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/workspaces/scorecard/packages/backend/src/index.ts b/workspaces/scorecard/packages/backend/src/index.ts index 9b4a1f8729..76a6235f4d 100644 --- a/workspaces/scorecard/packages/backend/src/index.ts +++ b/workspaces/scorecard/packages/backend/src/index.ts @@ -20,9 +20,8 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-app-backend')); backend.add(import('@backstage/plugin-proxy-backend')); -// TODO: Temporarily disabled - isolated-vm native module build issue -// backend.add(import('@backstage/plugin-scaffolder-backend')); -// backend.add(import('@backstage/plugin-scaffolder-backend-module-github')); +backend.add(import('@backstage/plugin-scaffolder-backend')); +backend.add(import('@backstage/plugin-scaffolder-backend-module-github')); backend.add(import('@backstage/plugin-techdocs-backend')); // auth plugin diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json index be4e820380..32455ebd58 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/package.json @@ -11,9 +11,15 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "repository": { + "type": "git", + "url": "https://github.com/redhat-developer/rhdh-plugins", + "directory": "workspaces/scorecard/plugins/scorecard-backend-module-openssf" + }, "backstage": { "role": "backend-plugin-module", - "pluginId": "scorecard" + "pluginId": "scorecard", + "pluginPackage": "@red-hat-developer-hub/backstage-plugin-scorecard-backend" }, "scripts": { "start": "backstage-cli package start", From 3b7c562124f569826ecb1950097aaf4bd1e4e84e Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 23 Dec 2025 14:02:56 +0100 Subject: [PATCH 09/13] Throws error when metric score is lower than 0 or higher than 10; Added unit tests; Added documentation; Review work --- .../README.md | 128 +++++++++++++++++- .../AbstractMetricProvider.test.ts | 16 +++ .../metricProviders/AbstractMetricProvider.ts | 5 +- .../plugins/scorecard-backend/README.md | 10 +- .../scorecard-backend/docs/providers.md | 1 + 5 files changed, 152 insertions(+), 8 deletions(-) diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md index 647949b904..1bbaf6fdae 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/README.md @@ -1,5 +1,127 @@ -# @red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf +# Scorecard Backend Module for OpenSSF -The openssf backend module for the scorecard plugin. +This is an extension module to the `backstage-plugin-scorecard-backend` plugin. It provides [OpenSSF Security Scorecard](https://securityscorecards.dev/) metrics for software components registered in the Backstage catalog. -_This plugin was created through the Backstage CLI_ +## Overview + +The OpenSSF Security Scorecards project provides automated security assessments for open source projects hosted on GitHub. This module fetches scorecard data from the public OpenSSF API and exposes individual security check scores as metrics in Backstage. + +## Prerequisites + +Before installing this module, ensure that the Scorecard backend plugin is integrated into your Backstage instance. Follow the [Scorecard backend plugin README](../scorecard-backend/README.md) for setup instructions. + +## Installation + +To install this backend module: + +```bash +# From your root directory +yarn workspace backend add @red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf +``` + +```ts +// packages/backend/src/index.ts +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +// Scorecard backend plugin +backend.add( + import('@red-hat-developer-hub/backstage-plugin-scorecard-backend'), +); + +// Install the OpenSSF module +/* highlight-add-next-line */ +backend.add( + import( + '@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf' + ), +); + +backend.start(); +``` + +## Entity Annotations + +For the OpenSSF metrics to work, your catalog entities must have the required annotation: + +```yaml +# catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: my-service + annotations: + # Required: GitHub repository in owner/repo format + openssf/project: owner/repo +spec: + type: service + lifecycle: production + owner: my-team +``` + +The `openssf/project` annotation should contain the GitHub repository path in `owner/repo` format (e.g., `kubernetes/kubernetes`). + +## Configuration + +This module uses the public OpenSSF Security Scorecards API (`api.securityscorecards.dev`) and does not require any additional configuration in `app-config.yaml`. + +### Thresholds + +Thresholds define conditions that determine which category a metric value belongs to (`error`, `warning`, or `success`). Check out detailed explanation of [threshold configuration](../scorecard-backend/docs/thresholds.md). + +All OpenSSF metrics use the following **fixed** thresholds: + +| Category | Expression | Description | +| -------- | ---------- | --------------------------------- | +| Error | `<2` | Score less than 2 | +| Warning | `2-7` | Score between 2 and 7 (inclusive) | +| Success | `>7` | Score greater than 7 | + +> **Note:** These thresholds are not configurable via `app-config.yaml`. They are defined in the module source code. + +## Available Metrics + +This module provides 18 metrics corresponding to the [OpenSSF Security Scorecard checks](https://github.com/ossf/scorecard/blob/main/docs/checks.md). Each metric returns a score from 0 to 10. + +| Metric ID | Risk | Description | +| -------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- | +| `openssf.binary_artifacts` | High | Determines if the project has generated executable (binary) artifacts in the source repository. | +| `openssf.branch_protection` | High | Determines if the default and release branches are protected with GitHub's branch protection or repository rules settings. | +| `openssf.cii_best_practices` | Low | Determines if the project has an OpenSSF (formerly CII) Best Practices Badge. | +| `openssf.ci_tests` | Low | Determines if the project runs tests before pull requests are merged. | +| `openssf.code_review` | High | Determines if the project requires human code review before pull requests are merged. | +| `openssf.contributors` | Low | Determines if the project has contributors from multiple organizations. | +| `openssf.dangerous_workflow` | Critical | Determines if the project's GitHub Action workflows avoid dangerous patterns. | +| `openssf.dependency_update_tool` | High | Determines if the project uses a dependency update tool. | +| `openssf.fuzzing` | Medium | Determines if the project uses fuzzing. | +| `openssf.license` | Low | Determines if the project has defined a license. | +| `openssf.maintained` | High | Determines if the project is "actively maintained". | +| `openssf.packaging` | Medium | Determines if the project is published as a package that others can easily download, install, update, and uninstall. | +| `openssf.pinned_dependencies` | Medium | Determines if the project has declared and pinned the dependencies of its build process. | +| `openssf.sast` | Medium | Determines if the project uses static code analysis. | +| `openssf.security_policy` | Medium | Determines if the project has published a security policy. | +| `openssf.signed_releases` | High | Determines if the project cryptographically signs release artifacts. | +| `openssf.token_permissions` | High | Determines if the project's automated workflow tokens follow the principle of least privilege. | +| `openssf.vulnerabilities` | High | Determines if the project has open, unfixed vulnerabilities in its codebase or dependencies using OSV. | + +## Troubleshooting + +### Metric shows "not found" + +This can occur if: + +- The repository has not been analyzed by OpenSSF Scorecards yet +- The repository is private (OpenSSF only analyzes public repositories) +- The repository path in the annotation is incorrect +- The metric score is lower than -1 or higher than 10. + +### No data for my repository + +OpenSSF Security Scorecards only analyzes **public GitHub repositories**. Private repositories and repositories on other Git hosting services are not supported. + +To verify your repository has scorecard data, visit: + +``` +https://api.securityscorecards.dev/projects/github.com/{owner}/{repo} +``` diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts index 472c5c63ac..81237c4562 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts @@ -225,5 +225,21 @@ describe('AbstractMetricProvider', () => { "Invalid format of 'openssf/project'", ); }); + + it('should throw error when metric score is less than 0', async () => { + const entity = createMockEntity('owner/test'); + mockOpenSSFResponse.checks[0].score = -1; + await expect(provider.calculateMetric(entity)).rejects.toThrow( + "OpenSSF check 'Test-Metric' has invalid score -1 for owner/test", + ); + }); + + it('should throw error when metric score is greater than 10', async () => { + const entity = createMockEntity('owner/test'); + mockOpenSSFResponse.checks[0].score = 11; + await expect(provider.calculateMetric(entity)).rejects.toThrow( + "OpenSSF check 'Test-Metric' has invalid score 11 for owner/test", + ); + }); }); }); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts index f7159beb37..e1a99555e0 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -99,8 +99,11 @@ export abstract class AbstractMetricProvider throw new Error( `OpenSSF check '${metricName}' not found in scorecard for ${owner}/${repo}`, ); + } else if (metric.score < 0 || metric.score > 10) { + throw new Error( + `OpenSSF check '${metricName}' has invalid score ${metric.score} for ${owner}/${repo}`, + ); } - return metric.score; } } diff --git a/workspaces/scorecard/plugins/scorecard-backend/README.md b/workspaces/scorecard/plugins/scorecard-backend/README.md index ce21286518..0ac27cf7e2 100644 --- a/workspaces/scorecard/plugins/scorecard-backend/README.md +++ b/workspaces/scorecard/plugins/scorecard-backend/README.md @@ -75,15 +75,17 @@ The Scorecard plugin collects metrics from third-party data sources using metric The following metric providers are available: -| Provider | Metric ID | Title | Description | Type | -| ---------- | ------------------ | ---------------- | ------------------------------------- | ------ | -| **GitHub** | `github.open_prs` | GitHub open PRs | Count of open Pull Requests in GitHub | number | -| **Jira** | `jira.open_issues` | Jira open issues | The number of opened issues in Jira | number | +| Provider | Metric ID | Title | Description | Type | +| ----------- | ------------------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------ | +| **GitHub** | `github.open_prs` | GitHub open PRs | Count of open Pull Requests in GitHub | number | +| **Jira** | `jira.open_issues` | Jira open issues | The number of opened issues in Jira | number | +| **OpenSSF** | `openssf.*` | OpenSSF Security Scorecards | 18 security metrics from OpenSSF Scorecards (e.g., `openssf.code_review`, `openssf.maintained`). Each returns a score from 0-10. | number | To use these providers, install the corresponding backend modules: - GitHub: [`@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-github`](../scorecard-backend-module-github/README.md) - Jira: [`@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-jira`](../scorecard-backend-module-jira/README.md) +- OpenSSF: [`@red-hat-developer-hub/backstage-plugin-scorecard-backend-module-openssf`](../scorecard-backend-module-openssf/README.md) ## Thresholds diff --git a/workspaces/scorecard/plugins/scorecard-backend/docs/providers.md b/workspaces/scorecard/plugins/scorecard-backend/docs/providers.md index 929526ac99..b2b7b6f586 100644 --- a/workspaces/scorecard/plugins/scorecard-backend/docs/providers.md +++ b/workspaces/scorecard/plugins/scorecard-backend/docs/providers.md @@ -179,3 +179,4 @@ The following are examples of existing metric providers that you can reference: - **GitHub Datasource**: [GithubOpenPRsProvider](../../scorecard-backend-module-github/src/metricProviders/GithubOpenPRsProvider.ts) - **Jira Datasource**: [JiraOpenIssuesProvider](../../scorecard-backend-module-jira/src/metricProviders/JiraOpenIssuesProvider.ts) +- **OpenSSF Datasource**: [DefaultOpenSSFMetricProvider](../../scorecard-backend-module-openssf/src/metricProviders/DefaultOpenSSFMetricProvider.ts) From 8806a2ece27c4def192560fe39ad41e4f51ae762 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Tue, 23 Dec 2025 15:08:48 +0100 Subject: [PATCH 10/13] review work --- .../scorecard/packages/backend/src/index.ts | 7 +++---- .../src/clients/OpenSSFClient.test.ts | 18 ------------------ .../src/clients/OpenSSFClient.ts | 6 ------ .../src/clients/types.ts | 2 +- .../AbstractMetricProvider.test.ts | 3 ++- .../metricProviders/AbstractMetricProvider.ts | 6 +++++- 6 files changed, 11 insertions(+), 31 deletions(-) diff --git a/workspaces/scorecard/packages/backend/src/index.ts b/workspaces/scorecard/packages/backend/src/index.ts index 76a6235f4d..fabda70bd2 100644 --- a/workspaces/scorecard/packages/backend/src/index.ts +++ b/workspaces/scorecard/packages/backend/src/index.ts @@ -33,10 +33,9 @@ backend.add(import('@backstage/plugin-auth-backend-module-github-provider')); // catalog plugin backend.add(import('@backstage/plugin-catalog-backend')); -// TODO: Temporarily disabled - depends on scaffolder -// backend.add( -// import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), -// ); +backend.add( + import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'), +); // See https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors backend.add(import('@backstage/plugin-catalog-backend-module-logs')); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts index c1d7007933..ca5f406255 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.test.ts @@ -65,24 +65,6 @@ describe('OpenSSFClient', () => { ); }); - it('should throw an error if the score is not a number', async () => { - // mock response from the API - const responseWithoutScore = { - ...mockOpenSSFResponse, - score: 'not a number', - }; - - // mocked fetch behaviour for the test - (globalThis.fetch as jest.Mock).mockResolvedValue({ - ok: true, - json: jest.fn().mockResolvedValue(responseWithoutScore), - }); - - await expect(client.getScorecard('owner', 'test')).rejects.toThrow( - 'Invalid response from OpenSSF API: score is not a number', - ); - }); - it('should throw an error if API request fails', async () => { // mocked fetch behaviour for the test (globalThis.fetch as jest.Mock).mockRejectedValue( diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts index 983bd753dd..efda22c59f 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/OpenSSFClient.ts @@ -46,12 +46,6 @@ export class OpenSSFClient { const data: OpenSSFResponse = await response.json(); - if (typeof data.score !== 'number') { - throw new Error( - `Invalid response from OpenSSF API: score is not a number`, - ); - } - return data; } } diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts index a4f60fa7c5..ce9b777410 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/clients/types.ts @@ -22,7 +22,7 @@ export interface OpenSSFCheckDocumentation { export interface OpenSSFCheck { name: string; score: number; - reason: string; + reason: string | null; details: string[] | null; documentation: OpenSSFCheckDocumentation; } diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts index 81237c4562..5d51a618c3 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.test.ts @@ -229,8 +229,9 @@ describe('AbstractMetricProvider', () => { it('should throw error when metric score is less than 0', async () => { const entity = createMockEntity('owner/test'); mockOpenSSFResponse.checks[0].score = -1; + mockOpenSSFResponse.checks[0].reason = 'Repository not found.'; await expect(provider.calculateMetric(entity)).rejects.toThrow( - "OpenSSF check 'Test-Metric' has invalid score -1 for owner/test", + "OpenSSF check 'Test-Metric' has invalid score -1 for owner/test. Reason: Repository not found.", ); }); diff --git a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts index e1a99555e0..cddf5c1506 100644 --- a/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts +++ b/workspaces/scorecard/plugins/scorecard-backend-module-openssf/src/metricProviders/AbstractMetricProvider.ts @@ -101,7 +101,11 @@ export abstract class AbstractMetricProvider ); } else if (metric.score < 0 || metric.score > 10) { throw new Error( - `OpenSSF check '${metricName}' has invalid score ${metric.score} for ${owner}/${repo}`, + `OpenSSF check '${metricName}' has invalid score ${ + metric.score + } for ${owner}/${repo}. Reason: ${ + metric.reason ?? 'No reason provided' + }`, ); } return metric.score; From 0a5f8365534bd62ff4704320fc6c0b365956c7f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 23 Dec 2025 16:08:05 +0100 Subject: [PATCH 11/13] Update workspaces/scorecard/examples/openssf-scorecard-only.yaml Co-authored-by: Dominika Zemanovicova <36102317+dzemanov@users.noreply.github.com> --- workspaces/scorecard/examples/openssf-scorecard-only.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/workspaces/scorecard/examples/openssf-scorecard-only.yaml b/workspaces/scorecard/examples/openssf-scorecard-only.yaml index 37f34491a3..6cf69fb9bf 100644 --- a/workspaces/scorecard/examples/openssf-scorecard-only.yaml +++ b/workspaces/scorecard/examples/openssf-scorecard-only.yaml @@ -5,9 +5,9 @@ kind: Component metadata: name: rhdh-plugins annotations: - github.com/project-slug: redhat-developer/rhdh-plugins - openssf/project: redhat-developer/rhdh-plugins - backstage.io/source-location: url:https://github.com/redhat-developer/rhdh-plugins + github.com/project-slug: backstage/backstage + openssf/project: backstage/backstage + backstage.io/source-location: url:https://github.com/backstage/backstage spec: type: service owner: guests From fe5b1f98f443a0cf2ee51c23791a2f24755b76db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 23 Dec 2025 16:08:14 +0100 Subject: [PATCH 12/13] Update workspaces/scorecard/examples/openssf-scorecard-only.yaml Co-authored-by: Dominika Zemanovicova <36102317+dzemanov@users.noreply.github.com> --- workspaces/scorecard/examples/openssf-scorecard-only.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/scorecard/examples/openssf-scorecard-only.yaml b/workspaces/scorecard/examples/openssf-scorecard-only.yaml index 6cf69fb9bf..e8775e732d 100644 --- a/workspaces/scorecard/examples/openssf-scorecard-only.yaml +++ b/workspaces/scorecard/examples/openssf-scorecard-only.yaml @@ -3,7 +3,7 @@ apiVersion: backstage.io/v1alpha1 kind: Component metadata: - name: rhdh-plugins + name: openssf-scorecard-only annotations: github.com/project-slug: backstage/backstage openssf/project: backstage/backstage From f49e0fb57a0a9dcf52a187aa8c20908448494a25 Mon Sep 17 00:00:00 2001 From: Andre Lizardo Date: Wed, 24 Dec 2025 10:27:13 +0100 Subject: [PATCH 13/13] removed extra whitespace --- workspaces/scorecard/examples/openssf-scorecard-only.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/scorecard/examples/openssf-scorecard-only.yaml b/workspaces/scorecard/examples/openssf-scorecard-only.yaml index e8775e732d..00adb4328d 100644 --- a/workspaces/scorecard/examples/openssf-scorecard-only.yaml +++ b/workspaces/scorecard/examples/openssf-scorecard-only.yaml @@ -6,7 +6,7 @@ metadata: name: openssf-scorecard-only annotations: github.com/project-slug: backstage/backstage - openssf/project: backstage/backstage + openssf/project: backstage/backstage backstage.io/source-location: url:https://github.com/backstage/backstage spec: type: service