Skip to content

Commit

Permalink
feat: add OSSF provider
Browse files Browse the repository at this point in the history
  • Loading branch information
UlisesGascon committed Dec 12, 2024
1 parent 772481f commit 1ecd406
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 7 deletions.
105 changes: 103 additions & 2 deletions __tests__/__snapshots__/providers.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`GitHub Providers mappers Should map organization data correctly 1`] = `
exports[`GitHub Provider mappers Should map organization data correctly 1`] = `
{
"advanced_security_enabled_for_new_repositories": false,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
Expand Down Expand Up @@ -53,7 +53,7 @@ exports[`GitHub Providers mappers Should map organization data correctly 1`] = `
}
`;

exports[`GitHub Providers mappers Should map repository data correctly 1`] = `
exports[`GitHub Provider mappers Should map repository data correctly 1`] = `
{
"allow_auto_merge": false,
"allow_forking": true,
Expand Down Expand Up @@ -114,3 +114,104 @@ exports[`GitHub Providers mappers Should map repository data correctly 1`] = `
"watchers_count": 80,
}
`;

exports[`OSSF Provider mappers Should map scorecard data correctly 1`] = `
{
"analysis_score": 6,
"analysis_time": "2024-12-11T23:55:17Z",
"binary_artifacts_details": undefined,
"binary_artifacts_documentation": "Determines if the project has generated executable (binary) artifacts in the source repository.",
"binary_artifacts_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#binary-artifacts",
"binary_artifacts_reason": "no binaries found in the repo",
"binary_artifacts_score": 10,
"branch_protection_details": undefined,
"branch_protection_documentation": "Determines if the default and release branches are protected with GitHub's branch protection settings.",
"branch_protection_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#branch-protection",
"branch_protection_reason": "branch protection is not maximal on development and all release branches",
"branch_protection_score": 3,
"ci_tests_details": undefined,
"ci_tests_documentation": "Determines if the project runs tests before pull requests are merged.",
"ci_tests_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#ci-tests",
"ci_tests_reason": "13 out of 19 merged PRs checked by a CI test -- score normalized to 6",
"ci_tests_score": 6,
"cii_best_practices_details": undefined,
"cii_best_practices_documentation": "Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.",
"cii_best_practices_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#cii-best-practices",
"cii_best_practices_reason": "no effort to earn an OpenSSF best practices badge detected",
"cii_best_practices_score": 0,
"code_review_details": undefined,
"code_review_documentation": "Determines if the project requires human code review before pull requests (aka merge requests) are merged.",
"code_review_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#code-review",
"code_review_reason": "Found 9/30 approved changesets -- score normalized to 3",
"code_review_score": 3,
"contributors_details": undefined,
"contributors_documentation": "Determines if the project has a set of contributors from multiple organizations (e.g., companies).",
"contributors_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#contributors",
"contributors_reason": "project has 21 contributing companies or organizations",
"contributors_score": 10,
"dangerous_workflow_details": undefined,
"dangerous_workflow_documentation": "Determines if the project's GitHub Action workflows avoid dangerous patterns.",
"dangerous_workflow_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#dangerous-workflow",
"dangerous_workflow_reason": "no dangerous workflow patterns detected",
"dangerous_workflow_score": 10,
"dependency_update_tool_details": undefined,
"dependency_update_tool_documentation": "Determines if the project uses a dependency update tool.",
"dependency_update_tool_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#dependency-update-tool",
"dependency_update_tool_reason": "no update tool detected",
"dependency_update_tool_score": 0,
"fuzzing_details": undefined,
"fuzzing_documentation": "Determines if the project uses fuzzing.",
"fuzzing_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#fuzzing",
"fuzzing_reason": "project is not fuzzed",
"fuzzing_score": 0,
"license_details": "Info: project has a license file: LICENSE:0
Info: FSF or OSI recognized license: MIT License: LICENSE:0",
"license_documentation": "Determines if the project has defined a license.",
"license_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#license",
"license_reason": "license file detected",
"license_score": 10,
"maintained_details": undefined,
"maintained_documentation": "Determines if the project is "actively maintained".",
"maintained_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#maintained",
"maintained_reason": "30 commit(s) and 21 issue activity found in the last 90 days -- score normalized to 10",
"maintained_score": 10,
"packaging_details": undefined,
"packaging_documentation": "Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.",
"packaging_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#packaging",
"packaging_reason": "packaging workflow not detected",
"packaging_score": -1,
"pinned_dependencies_details": undefined,
"pinned_dependencies_documentation": "Determines if the project has declared and pinned the dependencies of its build process.",
"pinned_dependencies_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#pinned-dependencies",
"pinned_dependencies_reason": "dependency not pinned by hash detected -- score normalized to 4",
"pinned_dependencies_score": 4,
"repo_commit": "e739f419e56442b754e4fea6dbcf98c1c8d00dda",
"sast_details": undefined,
"sast_documentation": "Determines if the project uses static code analysis.",
"sast_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#sast",
"sast_reason": "SAST tool is not run on all commits -- score normalized to 0",
"sast_score": 0,
"scorecard_commit": "ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4",
"scorecard_version": "v5.0.0",
"security_policy_details": undefined,
"security_policy_documentation": "Determines if the project has published a security policy.",
"security_policy_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#security-policy",
"security_policy_reason": "security policy file detected",
"security_policy_score": 10,
"signed_releases_details": undefined,
"signed_releases_documentation": "Determines if the project cryptographically signs release artifacts.",
"signed_releases_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#signed-releases",
"signed_releases_reason": "no releases found",
"signed_releases_score": -1,
"token_permissions_details": undefined,
"token_permissions_documentation": "Determines if the project's workflows follow the principle of least privilege.",
"token_permissions_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#token-permissions",
"token_permissions_reason": "detected GitHub workflow tokens with excessive permissions",
"token_permissions_score": 9,
"vulnerabilities_details": undefined,
"vulnerabilities_documentation": "Determines if the project has open, known unfixed vulnerabilities.",
"vulnerabilities_documentation_url": "https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#vulnerabilities",
"vulnerabilities_reason": "2 existing vulnerabilities detected",
"vulnerabilities_score": 8,
}
`;
21 changes: 18 additions & 3 deletions __tests__/providers.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
const { github } = require('../src/providers')
const { github, ossf } = require('../src/providers')
const {
sampleGithubOrg,
sampleGithubRepository
sampleGithubRepository,
sampleOSSFScorecardResult
} = require('../__fixtures__')

describe('GitHub Providers', () => {
describe('GitHub Provider', () => {
describe('fetchOrgByLogin', () => {
it.todo('Should fetch organization by login')
it.todo('Should throw an error if the organization does not exist')
Expand Down Expand Up @@ -35,3 +36,17 @@ describe('GitHub Providers', () => {
})
})
})

describe('OSSF Provider', () => {
describe('performScorecardAnalysis', () => {
it.todo('Should perform scorecard analysis')
it.todo('Should throw an error if the repository does not exist')
it.todo('Should throw an error if there are network issues')
})
describe('mappers', () => {
it('Should map scorecard data correctly', () => {
const mappedData = ossf.mappers.result(sampleOSSFScorecardResult)
expect(mappedData).toMatchSnapshot()
})
})
})
49 changes: 47 additions & 2 deletions src/providers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const { Octokit } = require('octokit')
const { ensureGithubToken } = require('../utils')
const { logger, ensureGithubToken } = require('../utils')
const { simplifyObject } = require('@ulisesgascon/simplify-object')
const util = require('util')
const exec = util.promisify(require('node:child_process').exec)
const { ossfScorecardSettings } = require('../config').getConfig()

const debug = require('debug')('providers:github')

const fetchOrgByLogin = async (login) => {
Expand Down Expand Up @@ -54,6 +58,23 @@ const fetchRepoByFullName = async (fullName) => {
return data
}

const performScorecardAnalysis = async (repo) => {
ensureGithubToken()
logger.log(`Running OSSF Scorecard for repository (${repo.full_name})...`)

const start = new Date().getTime()
const { stdout, stderr } = await exec(`docker run -e GITHUB_AUTH_TOKEN=${process.env.GITHUB_TOKEN} --rm ${ossfScorecardSettings.dockerImage} --repo=${repo.html_url} --show-details --format=json`)
if (stderr) {
console.error(stderr)
throw new Error(`Error running OSSF Scorecard for repository (${repo.full_name})`)
}
const data = JSON.parse(stdout)
const end = new Date().getTime()
data.analysis_execution_time = (end - start)
logger.log(`OSSF Scorecard finished successfully for repository (${repo.full_name}) in ${data.analysis_execution_time / 1000}s`)
return data
}

const github = {
fetchOrgByLogin,
fetchOrgReposListByLogin,
Expand Down Expand Up @@ -130,6 +151,30 @@ const github = {
}
}

const ossf = {
performScorecardAnalysis,
mappers: {
result: (data) => {
const output = {}
output.analysis_score = data.score
output.analysis_time = data.date
output.repo_commit = data.repo?.commit
output.scorecard_version = data.scorecard?.version
output.scorecard_commit = data.scorecard?.commit
data.checks?.forEach((check, i) => {
const checkName = check.name.toLowerCase().replaceAll('-', '_')
output[`${checkName}_reason`] = check.reason
output[`${checkName}_score`] = check.score
output[`${checkName}_documentation_url`] = check.documentation?.url
output[`${checkName}_documentation`] = check.documentation?.short
output[`${checkName}_details`] = check.details?.join('\n')
})
return output
}
}
}

module.exports = {
github
github,
ossf
}

0 comments on commit 1ecd406

Please sign in to comment.