mirror of
https://github.com/ossf/scorecard.git
synced 2024-09-20 05:27:12 +03:00
2d9319601e
* enable forbidigo for print statements. include reasoning as message exposed to developer. Signed-off-by: Spencer Schrock <sschrock@google.com> * remove or grant exceptions for existing print statements Signed-off-by: Spencer Schrock <sschrock@google.com> * swap stdout to stderr Signed-off-by: Spencer Schrock <sschrock@google.com> * separate msg from regex for better readability. Signed-off-by: Spencer Schrock <sschrock@google.com> --------- Signed-off-by: Spencer Schrock <sschrock@google.com>
274 lines
7.2 KiB
Go
274 lines
7.2 KiB
Go
// Copyright 2020 OpenSSF 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 options implements Scorecard options.
|
|
package options
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/caarlos0/env/v6"
|
|
|
|
"github.com/ossf/scorecard/v4/clients"
|
|
sclog "github.com/ossf/scorecard/v4/log"
|
|
)
|
|
|
|
// Options define common options for configuring scorecard.
|
|
type Options struct {
|
|
Repo string
|
|
Local string
|
|
Commit string
|
|
LogLevel string
|
|
Format string
|
|
NPM string
|
|
PyPI string
|
|
RubyGems string
|
|
Nuget string
|
|
PolicyFile string
|
|
ResultsFile string
|
|
ChecksToRun []string
|
|
Metadata []string
|
|
CommitDepth int
|
|
ShowDetails bool
|
|
// Feature flags.
|
|
EnableSarif bool `env:"ENABLE_SARIF"`
|
|
EnableScorecardV6 bool `env:"SCORECARD_V6"`
|
|
EnableScorecardExperimental bool `env:"SCORECARD_EXPERIMENTAL"`
|
|
}
|
|
|
|
// New creates a new instance of `Options`.
|
|
func New() *Options {
|
|
opts := &Options{}
|
|
if err := env.Parse(opts); err != nil {
|
|
log.Printf("could not parse env vars, using default options: %v", err)
|
|
}
|
|
// Defaulting.
|
|
// TODO(options): Consider moving this to a separate function/method.
|
|
if opts.Commit == "" {
|
|
opts.Commit = DefaultCommit
|
|
}
|
|
if opts.Format == "" {
|
|
opts.Format = FormatDefault
|
|
}
|
|
if opts.LogLevel == "" {
|
|
opts.LogLevel = DefaultLogLevel
|
|
}
|
|
return opts
|
|
}
|
|
|
|
const (
|
|
// DefaultCommit specifies the default commit reference to use.
|
|
DefaultCommit = clients.HeadSHA
|
|
|
|
// Formats.
|
|
// FormatJSON specifies that results should be output in JSON format.
|
|
FormatJSON = "json"
|
|
// FormatFJSON specifies that results should be output in JSON format,
|
|
// but with structured findings.
|
|
FormatFJSON = "finding"
|
|
// FormatPJSON specifies that results should be output in probe JSON format.
|
|
FormatPJSON = "probe"
|
|
// FormatSJSON specifies that results should be output in structured JSON format.
|
|
FormatSJSON = "structured"
|
|
// FormatSarif specifies that results should be output in SARIF format.
|
|
FormatSarif = "sarif"
|
|
// FormatDefault specifies that results should be output in default format.
|
|
FormatDefault = "default"
|
|
// FormatRaw specifies that results should be output in raw format.
|
|
FormatRaw = "raw"
|
|
|
|
// Environment variables.
|
|
// EnvVarEnableSarif is the environment variable which controls enabling
|
|
// SARIF logging.
|
|
EnvVarEnableSarif = "ENABLE_SARIF"
|
|
// EnvVarScorecardV6 is the environment variable which enables scorecard v6
|
|
// options.
|
|
EnvVarScorecardV6 = "SCORECARD_V6"
|
|
// EnvVarScorecardExperimental is the environment variable which enables experimental
|
|
// features.
|
|
EnvVarScorecardExperimental = "SCORECARD_EXPERIMENTAL"
|
|
)
|
|
|
|
var (
|
|
// DefaultLogLevel retrieves the default log level.
|
|
DefaultLogLevel = sclog.DefaultLevel.String()
|
|
|
|
errCommitIsEmpty = errors.New("commit should be non-empty")
|
|
errFormatNotSupported = errors.New("unsupported format")
|
|
errFormatSupportedWithExperimental = errors.New("format supported only with SCORECARD_EXPERIMENTAL=1")
|
|
errPolicyFileNotSupported = errors.New("policy file is not supported yet")
|
|
errRawOptionNotSupported = errors.New("raw option is not supported yet")
|
|
errRepoOptionMustBeSet = errors.New(
|
|
"exactly one of `repo`, `npm`, `pypi`, `rubygems`, `nuget` or `local` must be set",
|
|
)
|
|
errSARIFNotSupported = errors.New("SARIF format is not supported yet")
|
|
errValidate = errors.New("some options could not be validated")
|
|
)
|
|
|
|
// Validate validates scorecard configuration options.
|
|
// TODO(options): Cleanup error messages.
|
|
func (o *Options) Validate() error {
|
|
var errs []error
|
|
|
|
// Validate exactly one of `--repo`, `--npm`, `--pypi`, `--rubygems`, `--nuget`, `--local` is enabled.
|
|
if boolSum(o.Repo != "",
|
|
o.NPM != "",
|
|
o.PyPI != "",
|
|
o.RubyGems != "",
|
|
o.Nuget != "",
|
|
o.Local != "") != 1 {
|
|
errs = append(
|
|
errs,
|
|
errRepoOptionMustBeSet,
|
|
)
|
|
}
|
|
|
|
// Validate SARIF features are flag-guarded.
|
|
if !o.isSarifEnabled() {
|
|
if o.Format == FormatSarif {
|
|
errs = append(
|
|
errs,
|
|
errSARIFNotSupported,
|
|
)
|
|
}
|
|
if o.PolicyFile != "" {
|
|
errs = append(
|
|
errs,
|
|
errPolicyFileNotSupported,
|
|
)
|
|
}
|
|
}
|
|
|
|
// Validate V6 features are flag-guarded.
|
|
if !o.isV6Enabled() {
|
|
if o.Format == FormatRaw {
|
|
errs = append(
|
|
errs,
|
|
errRawOptionNotSupported,
|
|
)
|
|
}
|
|
}
|
|
|
|
if !o.isExperimentalEnabled() {
|
|
if o.Format == FormatSJSON ||
|
|
o.Format == FormatFJSON ||
|
|
o.Format == FormatPJSON {
|
|
errs = append(
|
|
errs,
|
|
errFormatSupportedWithExperimental,
|
|
)
|
|
}
|
|
}
|
|
|
|
// Validate format.
|
|
if !validateFormat(o.Format) {
|
|
errs = append(
|
|
errs,
|
|
errFormatNotSupported,
|
|
)
|
|
}
|
|
|
|
// Validate `commit` is non-empty.
|
|
if o.Commit == "" {
|
|
errs = append(
|
|
errs,
|
|
errCommitIsEmpty,
|
|
)
|
|
}
|
|
|
|
if len(errs) != 0 {
|
|
return fmt.Errorf(
|
|
"%w: %+v",
|
|
errValidate,
|
|
errs,
|
|
)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func boolSum(bools ...bool) int {
|
|
sum := 0
|
|
for _, b := range bools {
|
|
if b {
|
|
sum++
|
|
}
|
|
}
|
|
return sum
|
|
}
|
|
|
|
// Feature flags.
|
|
|
|
// GitHub integration support.
|
|
// See https://github.com/ossf/scorecard-action/issues/1107.
|
|
// NOTE: We don't add a field to to the Option structure to simplify
|
|
// integration. If we did, the Action would also need to be aware
|
|
// of the integration and pass the relevant values. This
|
|
// would add redundancy and complicate maintenance.
|
|
func (o *Options) IsInternalGitHubIntegrationEnabled() bool {
|
|
return (os.Getenv("CI") == "true") &&
|
|
(os.Getenv("SCORECARD_INTERNAL_GITHUB_INTEGRATION") == "1") &&
|
|
(os.Getenv("GITHUB_EVENT_NAME") == "dynamic")
|
|
}
|
|
|
|
// Checks returns the list of checks and honours the
|
|
// GitHub integration.
|
|
func (o *Options) Checks() []string {
|
|
if o.IsInternalGitHubIntegrationEnabled() {
|
|
// Overwrite the list of checks.
|
|
s := os.Getenv("SCORECARD_INTERNAL_GITHUB_CHECKS")
|
|
l := strings.Split(s, ",")
|
|
for i := range l {
|
|
l[i] = strings.TrimSpace(l[i])
|
|
}
|
|
return l
|
|
}
|
|
return o.ChecksToRun
|
|
}
|
|
|
|
// isExperimentalEnabled returns true if experimental features were enabled via
|
|
// environment variable.
|
|
func (o *Options) isExperimentalEnabled() bool {
|
|
value, _ := os.LookupEnv(EnvVarScorecardExperimental)
|
|
return value == "1"
|
|
}
|
|
|
|
// isSarifEnabled returns true if SARIF format was specified in options or via
|
|
// environment variable.
|
|
func (o *Options) isSarifEnabled() bool {
|
|
// UPGRADEv4: remove.
|
|
_, enabled := os.LookupEnv(EnvVarEnableSarif)
|
|
return o.EnableSarif || enabled
|
|
}
|
|
|
|
// isV6Enabled returns true if v6 functionality was specified in options or via
|
|
// environment variable.
|
|
func (o *Options) isV6Enabled() bool {
|
|
_, enabled := os.LookupEnv(EnvVarScorecardV6)
|
|
return o.EnableScorecardV6 || enabled
|
|
}
|
|
|
|
func validateFormat(format string) bool {
|
|
switch format {
|
|
case FormatJSON, FormatSJSON, FormatFJSON,
|
|
FormatPJSON, FormatSarif, FormatDefault, FormatRaw:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|