Skip to content

Commit

Permalink
Merge branch 'main' into feature-codeowners-branch-protection
Browse files Browse the repository at this point in the history
  • Loading branch information
raghavkaul committed Jul 20, 2022
2 parents f98c399 + 096cbd0 commit 377be84
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 70 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ $ ./slsa-verifier-linux-amd64 \
--tag vX.Y.Z
```
When verification passes, it guarantees that the binary you downloaded was generated using the source code of this repository.
If you're interested in reading more about SLSA, visit the official [slsa.dev](slsa.dev).
If you're interested in reading more about SLSA, visit the official [slsa.dev](https://slsa.dev).

1. Add the binary to your `GOPATH/bin` directory (use `go env GOPATH` to
identify your directory if necessary)
Expand Down
8 changes: 6 additions & 2 deletions checks/evaluation/pinned_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,14 @@ func PinningDependencies(name string, dl checker.DetailLogger,
}

func generateRemediation(rr *checker.Dependency) *checker.Remediation {
if rr.Type == checker.DependencyUseTypeGHAction {
switch rr.Type {
case checker.DependencyUseTypeGHAction:
return remediation.CreateWorkflowPinningRemediation(rr.Location.Path)
case checker.DependencyUseTypeDockerfileContainerImage:
return remediation.CreateDockerfilePinningRemediation(rr.Name)
default:
return nil
}
return nil
}

func updatePinningResults(rr *checker.Dependency,
Expand Down
76 changes: 39 additions & 37 deletions dependencydiff/dependencydiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ package dependencydiff
import (
"context"
"fmt"
"path"

"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/checks"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/clients/githubrepo"
sce "github.com/ossf/scorecard/v4/errors"
"github.com/ossf/scorecard/v4/log"
"github.com/ossf/scorecard/v4/pkg"
Expand Down Expand Up @@ -69,8 +67,6 @@ func GetDependencyDiffResults(
return nil, fmt.Errorf("error in fetchRawDependencyDiffData: %w", err)
}

// Initialize the repo and client(s) corresponding to the checks to run.
err = initRepoAndClientByChecks(&dCtx)
if err != nil {
return nil, fmt.Errorf("error in initRepoAndClientByChecks: %w", err)
}
Expand All @@ -81,21 +77,20 @@ func GetDependencyDiffResults(
return dCtx.results, nil
}

func initRepoAndClientByChecks(dCtx *dependencydiffContext) error {
func initRepoAndClientByChecks(dCtx *dependencydiffContext, dSrcRepo string) error {
repo, repoClient, ossFuzzClient, ciiClient, vulnsClient, err := checker.GetClients(
dCtx.ctx, path.Join(dCtx.ownerName, dCtx.repoName), "", dCtx.logger,
dCtx.ctx, dSrcRepo, "", dCtx.logger,
)
if err != nil {
return fmt.Errorf("error creating the github repo: %w", err)
return fmt.Errorf("error getting the github repo and clients: %w", err)
}
// If the caller doesn't specify the checks to run, run all checks and return all the clients.
dCtx.ghRepo = repo
dCtx.ghRepoClient = repoClient
// If the caller doesn't specify the checks to run, run all the checks and return all the clients.
if dCtx.checkNamesToRun == nil || len(dCtx.checkNamesToRun) == 0 {
dCtx.ghRepo, dCtx.ghRepoClient, dCtx.ossFuzzClient, dCtx.ciiClient, dCtx.vulnsClient =
repo, repoClient, ossFuzzClient, ciiClient, vulnsClient
dCtx.ossFuzzClient, dCtx.ciiClient, dCtx.vulnsClient = ossFuzzClient, ciiClient, vulnsClient
return nil
}
dCtx.ghRepo = repo
dCtx.ghRepoClient = githubrepo.CreateGithubRepoClient(dCtx.ctx, dCtx.logger)
for _, cn := range dCtx.checkNamesToRun {
switch cn {
case checks.CheckFuzzing:
Expand Down Expand Up @@ -125,33 +120,40 @@ func getScorecardCheckResults(dCtx *dependencydiffContext) error {
Version: d.Version,
Name: d.Name,
}
// Run the checks on all types if (1) the type is found in changeTypesToCheck or (2) no types are specified.
TypeFoundOrNoneGiven := dCtx.changeTypesToCheck[*d.ChangeType] ||
(dCtx.changeTypesToCheck == nil || len(dCtx.changeTypesToCheck) == 0)
// For now we skip those without source repo urls.
// TODO (#2063): use the BigQuery dataset to supplement null source repo URLs to fetch the Scorecard results for them.
if d.SourceRepository != nil && *d.SourceRepository != "" {
if d.ChangeType != nil && (dCtx.changeTypesToCheck[*d.ChangeType] || dCtx.changeTypesToCheck == nil) {
// Run scorecard on those types of dependencies that the caller would like to check.
// If the input map changeTypesToCheck is empty, by default, we run checks for all valid types.
// TODO (#2064): use the Scorecare REST API to retrieve the Scorecard result statelessly.
scorecardResult, err := pkg.RunScorecards(
dCtx.ctx,
dCtx.ghRepo,
// TODO (#2065): In future versions, ideally, this should be
// the commitSHA corresponding to d.Version instead of HEAD.
clients.HeadSHA,
checksToRun,
dCtx.ghRepoClient,
dCtx.ossFuzzClient,
dCtx.ciiClient,
dCtx.vulnsClient,
)
// If the run fails, we leave the current dependency scorecard result empty and record the error
// rather than letting the entire API return nil since we still expect results for other dependencies.
if err != nil {
depCheckResult.ScorecardResultsWithError.Error = sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("error running the scorecard checks: %v", err))
} else { // Otherwise, we record the scorecard check results for this dependency.
depCheckResult.ScorecardResultsWithError.ScorecardResults = &scorecardResult
}
if d.SourceRepository != nil && TypeFoundOrNoneGiven {
// Initialize the repo and client(s) corresponding to the checks to run.
err = initRepoAndClientByChecks(dCtx, *d.SourceRepository)
if err != nil {
return fmt.Errorf("error init repo and clients: %w", err)
}

// Run scorecard on those types of dependencies that the caller would like to check.
// If the input map changeTypesToCheck is empty, by default, we run the checks for all valid types.
// TODO (#2064): use the Scorecare REST API to retrieve the Scorecard result statelessly.
scorecardResult, err := pkg.RunScorecards(
dCtx.ctx,
dCtx.ghRepo,
// TODO (#2065): In future versions, ideally, this should be
// the commitSHA corresponding to d.Version instead of HEAD.
clients.HeadSHA,
checksToRun,
dCtx.ghRepoClient,
dCtx.ossFuzzClient,
dCtx.ciiClient,
dCtx.vulnsClient,
)
// If the run fails, we leave the current dependency scorecard result empty and record the error
// rather than letting the entire API return nil since we still expect results for other dependencies.
if err != nil {
depCheckResult.ScorecardResultsWithError.Error = sce.WithMessage(sce.ErrScorecardInternal,
fmt.Sprintf("error running the scorecard checks: %v", err))
} else { // Otherwise, we record the scorecard check results for this dependency.
depCheckResult.ScorecardResultsWithError.ScorecardResults = &scorecardResult
}
}
dCtx.results = append(dCtx.results, depCheckResult)
Expand Down
34 changes: 14 additions & 20 deletions dependencydiff/dependencydiff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,25 @@ func Test_initRepoAndClientByChecks(t *testing.T) {
t.Parallel()
//nolint
tests := []struct {
name string
dCtx dependencydiffContext
wantGhRepo, wantRepoClient, wantFuzzClient bool
wantVulnClient, wantCIIClient bool
wantErr bool
name string
dCtx dependencydiffContext
srcRepo string
wantRepoClient, wantFuzzClient bool
wantVulnClient, wantCIIClient bool
wantErr bool
}{
{
name: "error creating repo",
dCtx: dependencydiffContext{
logger: log.NewLogger(log.InfoLevel),
ctx: context.Background(),
ownerName: path.Join("host_not_exist.com", "owner_not_exist"),
repoName: "repo_not_exist",
checkNamesToRun: []string{},
},
wantGhRepo: false,
srcRepo: path.Join(
"host_not_exist.com",
"owner_not_exist",
"repo_not_exist",
),
wantRepoClient: false,
wantFuzzClient: false,
wantVulnClient: false,
Expand All @@ -99,13 +102,9 @@ func Test_initRepoAndClientByChecks(t *testing.T) {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
err := initRepoAndClientByChecks(&tt.dCtx)
err := initRepoAndClientByChecks(&tt.dCtx, tt.srcRepo)
if (err != nil) != tt.wantErr {
t.Errorf("initRepoAndClientByChecks() error = {%v}, want error: %v", err, tt.wantErr)
return
}
if (tt.dCtx.ghRepo != nil) != tt.wantGhRepo {
t.Errorf("init repo error, wantGhRepo: %v, got %v", tt.wantGhRepo, tt.dCtx.ghRepo)
t.Errorf("initClientByChecks() error = {%v}, want error: %v", err, tt.wantErr)
return
}
if (tt.dCtx.ghRepoClient != nil) != tt.wantRepoClient {
Expand Down Expand Up @@ -151,12 +150,7 @@ func Test_getScorecardCheckResults(t *testing.T) {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
err := initRepoAndClientByChecks(&tt.dCtx)
if err != nil {
t.Errorf("init repo and client error")
return
}
err = getScorecardCheckResults(&tt.dCtx)
err := getScorecardCheckResults(&tt.dCtx)
if (err != nil) != tt.wantErr {
t.Errorf("getScorecardCheckResults() error = {%v}, want error: %v", err, tt.wantErr)
return
Expand Down
26 changes: 17 additions & 9 deletions pkg/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,24 @@ func DetailToString(d *checker.CheckDetail, logLevel log.Level) string {
return ""
}

switch {
case d.Msg.Path != "" && d.Msg.Offset != 0 && d.Msg.EndOffset != 0 && d.Msg.Offset < d.Msg.EndOffset:
return fmt.Sprintf("%s: %s: %s:%d-%d", typeToString(d.Type), d.Msg.Text, d.Msg.Path, d.Msg.Offset, d.Msg.EndOffset)
case d.Msg.Path != "" && d.Msg.Offset != 0:
return fmt.Sprintf("%s: %s: %s:%d", typeToString(d.Type), d.Msg.Text, d.Msg.Path, d.Msg.Offset)
case d.Msg.Path != "" && d.Msg.Offset == 0:
return fmt.Sprintf("%s: %s: %s", typeToString(d.Type), d.Msg.Text, d.Msg.Path)
default:
return fmt.Sprintf("%s: %s", typeToString(d.Type), d.Msg.Text)
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s: %s", typeToString(d.Type), d.Msg.Text))

if d.Msg.Path != "" {
sb.WriteString(fmt.Sprintf(": %s", d.Msg.Path))
if d.Msg.Offset != 0 {
sb.WriteString(fmt.Sprintf(":%d", d.Msg.Offset))
}
if d.Msg.EndOffset != 0 && d.Msg.Offset < d.Msg.EndOffset {
sb.WriteString(fmt.Sprintf("-%d", d.Msg.EndOffset))
}
}

if d.Msg.Remediation != nil {
sb.WriteString(fmt.Sprintf(": %s", d.Msg.Remediation.HelpText))
}

return sb.String()
}

func detailsToString(details []checker.CheckDetail, logLevel log.Level) (string, bool) {
Expand Down
144 changes: 144 additions & 0 deletions pkg/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2022 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 (
"testing"

"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/log"
)

func TestDetailString(t *testing.T) {
t.Parallel()
tests := []struct {
name string
detail checker.CheckDetail
log log.Level
want string
}{
{
name: "ignoreDebug",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "should not appear",
},
Type: checker.DetailDebug,
},
log: log.DefaultLevel,
want: "",
},
{
name: "includeDebug",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "should appear",
},
Type: checker.DetailDebug,
},
log: log.DebugLevel,
want: "Debug: should appear",
},
{
name: "onlyType",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text",
},
{
name: "displayPath",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
Path: "Dockerfile",
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text: Dockerfile",
},
{
name: "displayStartOffset",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
Path: "Dockerfile",
Offset: 1,
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text: Dockerfile:1",
},
{
name: "displayEndOffset",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
Path: "Dockerfile",
Offset: 1,
EndOffset: 7,
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text: Dockerfile:1-7",
},
{
name: "ignoreInvalidEndOffset",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
Path: "Dockerfile",
Offset: 3,
EndOffset: 2,
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text: Dockerfile:3",
},
{
name: "includeRemediation",
detail: checker.CheckDetail{
Msg: checker.LogMessage{
Text: "some meaningful text",
Path: "Dockerfile",
Remediation: &checker.Remediation{
HelpText: "fix x by doing y",
},
},
Type: checker.DetailWarn,
},
log: log.DefaultLevel,
want: "Warn: some meaningful text: Dockerfile: fix x by doing y",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := DetailToString(&tt.detail, tt.log)
if got != tt.want {
t.Errorf("got %v, want %v", got, tt.want)
}
})
}
}
Loading

0 comments on commit 377be84

Please sign in to comment.