Add hash to results (JSON, SARIF) (#892)

* add hash to result

* add json file
This commit is contained in:
laurentsimon 2021-08-24 09:50:47 -07:00 committed by GitHub
parent 6403eb1382
commit ad134ac30d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 154 additions and 108 deletions

108
pkg/json.go Normal file
View File

@ -0,0 +1,108 @@
// Copyright 2021 Security Scorecard Authors
//
// 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.
package pkg
import (
"encoding/json"
"fmt"
"io"
"go.uber.org/zap/zapcore"
"github.com/ossf/scorecard/v2/checker"
sce "github.com/ossf/scorecard/v2/errors"
)
//nolint
type jsonCheckResultV2 struct {
Details []string
Score int
Reason string
Name string
}
type jsonScorecardResultV2 struct {
Repo string
Date string
Commit string
Checks []jsonCheckResultV2
Metadata []string
}
// AsJSON outputs the result in JSON format with a newline at the end.
// If called on []ScorecardResult will create NDJson formatted output.
// UPGRADEv2: will be removed.
func (r *ScorecardResult) AsJSON(showDetails bool, logLevel zapcore.Level, writer io.Writer) error {
encoder := json.NewEncoder(writer)
if showDetails {
if err := encoder.Encode(r); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
}
out := ScorecardResult{
Repo: r.Repo,
Date: r.Date,
Metadata: r.Metadata,
}
// UPGRADEv2: remove nolint after ugrade.
//nolint
for _, checkResult := range r.Checks {
tmpResult := checker.CheckResult{
Name: checkResult.Name,
Pass: checkResult.Pass,
Confidence: checkResult.Confidence,
}
out.Checks = append(out.Checks, tmpResult)
}
if err := encoder.Encode(out); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
}
// AsJSON2 exports results as JSON for new detail format.
func (r *ScorecardResult) AsJSON2(showDetails bool, logLevel zapcore.Level, writer io.Writer) error {
encoder := json.NewEncoder(writer)
out := jsonScorecardResultV2{
Repo: r.Repo,
Date: r.Date.Format("2006-01-02"),
Commit: r.CommitSHA,
Metadata: r.Metadata,
}
//nolint
for _, checkResult := range r.Checks {
tmpResult := jsonCheckResultV2{
Name: checkResult.Name,
Reason: checkResult.Reason,
Score: checkResult.Score,
}
if showDetails {
for _, d := range checkResult.Details2 {
tmpResult.Details = append(tmpResult.Details, d.Msg.Text)
}
}
out.Checks = append(out.Checks, tmpResult)
}
if err := encoder.Encode(out); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
}

View File

@ -327,7 +327,7 @@ func scoreToLevel(minScore, score int) string {
}
}
func createSARIFHeader(url, category, name, version string, t time.Time) sarif210 {
func createSARIFHeader(url, category, name, version, commit string, t time.Time) sarif210 {
return sarif210{
Schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
Version: "2.1.0",
@ -345,7 +345,7 @@ func createSARIFHeader(url, category, name, version string, t time.Time) sarif21
// See https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning#runautomationdetails-object.
AutomationDetails: automationDetails{
// Time formatting: https://pkg.go.dev/time#pkg-constants.
ID: fmt.Sprintf("%s/%s/%s", category, name, t.Format(time.RFC822Z)),
ID: fmt.Sprintf("%s/%s/%s", category, name, fmt.Sprintf("%s-%s", commit, t.Format(time.RFC822Z))),
},
},
},
@ -397,7 +397,7 @@ func (r *ScorecardResult) AsSARIF(version string, showDetails bool, logLevel zap
// see https://docs.github.com/en/code-security/secure-coding/integrating-with-code-scanning/sarif-support-for-code-scanning#supported-sarif-output-file-properties,
// https://github.com/microsoft/sarif-tutorials.
sarif := createSARIFHeader("https://github.com/ossf/scorecard",
"supply-chain", "scorecard", version, r.Date)
"supply-chain", "scorecard", version, r.CommitSHA, r.Date)
results := []result{}
rules := []rule{}

View File

@ -39,6 +39,7 @@ func TestSATIFOutput(t *testing.T) {
Tags string `yaml:"tags"`
}
commit := "68bc59901773ab4c051dfcea0cc4201a1567ab32"
date, e := time.Parse(time.RFC822Z, "17 Aug 21 18:57 +0000")
if e != nil {
panic(fmt.Errorf("time.Parse: %w", e))
@ -71,8 +72,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{
@ -115,8 +117,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{
@ -172,8 +175,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{
@ -282,8 +286,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{
@ -377,8 +382,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{
@ -419,8 +425,9 @@ func TestSATIFOutput(t *testing.T) {
},
},
result: ScorecardResult{
Repo: "repo not used",
Date: date,
Repo: "repo not used",
Date: date,
CommitSHA: commit,
Checks: []checker.CheckResult{
{
Details2: []checker.CheckDetail{

View File

@ -92,9 +92,20 @@ func RunScorecards(ctx context.Context,
return ScorecardResult{}, err
}
commits, err := repoClient.ListCommits()
if err != nil {
//nolint:wrapcheck
return ScorecardResult{}, err
}
if len(commits) == 0 {
//nolint:wrapcheck
return ScorecardResult{}, sce.Create(sce.ErrScorecardInternal, "no commits found")
}
ret := ScorecardResult{
Repo: repo.URL(),
Date: time.Now(),
Repo: repo.URL(),
Date: time.Now(),
CommitSHA: commits[0].SHA,
}
resultsCh := make(chan checker.CheckResult)
go runEnabledChecks(ctx, repo, checksToRun, repoClient,

View File

@ -16,7 +16,6 @@ package pkg
import (
"encoding/csv"
"encoding/json"
"fmt"
"io"
"os"
@ -33,90 +32,11 @@ import (
// ScorecardResult struct is returned on a successful Scorecard run.
type ScorecardResult struct {
Repo string
Date time.Time
Checks []checker.CheckResult
Metadata []string
}
//nolint
type jsonCheckResultV2 struct {
Details []string
Score int
Reason string
Name string
}
type jsonScorecardResultV2 struct {
Repo string
Date string
Checks []jsonCheckResultV2
Metadata []string
}
// AsJSON outputs the result in JSON format with a newline at the end.
// If called on []ScorecardResult will create NDJson formatted output.
// UPGRADEv2: will be removed.
func (r *ScorecardResult) AsJSON(showDetails bool, logLevel zapcore.Level, writer io.Writer) error {
encoder := json.NewEncoder(writer)
if showDetails {
if err := encoder.Encode(r); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
}
out := ScorecardResult{
Repo: r.Repo,
Date: r.Date,
Metadata: r.Metadata,
}
// UPGRADEv2: remove nolint after ugrade.
//nolint
for _, checkResult := range r.Checks {
tmpResult := checker.CheckResult{
Name: checkResult.Name,
Pass: checkResult.Pass,
Confidence: checkResult.Confidence,
}
out.Checks = append(out.Checks, tmpResult)
}
if err := encoder.Encode(out); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
}
// AsJSON2 exports results as JSON for new detail format.
func (r *ScorecardResult) AsJSON2(showDetails bool, logLevel zapcore.Level, writer io.Writer) error {
encoder := json.NewEncoder(writer)
out := jsonScorecardResultV2{
Repo: r.Repo,
Date: r.Date.Format("2006-01-02"),
Metadata: r.Metadata,
}
//nolint
for _, checkResult := range r.Checks {
tmpResult := jsonCheckResultV2{
Name: checkResult.Name,
Reason: checkResult.Reason,
Score: checkResult.Score,
}
if showDetails {
for _, d := range checkResult.Details2 {
tmpResult.Details = append(tmpResult.Details, d.Msg.Text)
}
}
out.Checks = append(out.Checks, tmpResult)
}
if err := encoder.Encode(out); err != nil {
//nolint:wrapcheck
return sce.Create(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}
return nil
Repo string
Date time.Time
CommitSHA string
Checks []checker.CheckResult
Metadata []string
}
// AsCSV outputs ScorecardResult in CSV format.

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {

View File

@ -4,7 +4,7 @@
"runs": [
{
"automationDetails": {
"id": "supply-chain/scorecard/17 Aug 21 18:57 +0000"
"id": "supply-chain/scorecard/68bc59901773ab4c051dfcea0cc4201a1567ab32-17 Aug 21 18:57 +0000"
},
"tool": {
"driver": {