From e6860fe9a9bd31f01575e9f25489108a568cac4e Mon Sep 17 00:00:00 2001 From: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:25:09 -0400 Subject: [PATCH 1/2] chore: bump go version for build (#132) * chore: bump go version for build Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> * chore: bump tooling to match new go version Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> * chore: stereoscope update Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> --------- Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Signed-off-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> --- .binny.yaml | 4 ++-- .github/actions/bootstrap/action.yaml | 2 +- .golangci.yaml | 3 +-- .goreleaser.yaml | 6 +++++- cmd/grant/cli/command/check.go | 4 ++-- cmd/grant/cli/command/list.go | 4 ++-- go.mod | 4 ++-- go.sum | 4 ++-- 8 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.binny.yaml b/.binny.yaml index 1cc41fb..3240e19 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -65,14 +65,14 @@ tools: - name: goreleaser version: - want: v1.25.1 + want: v2.3.2 method: github-release with: repo: goreleaser/goreleaser - name: golangci-lint version: - want: v1.54.2 + want: v1.61.0 method: github-release with: repo: golangci/golangci-lint diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml index 657c683..2247369 100644 --- a/.github/actions/bootstrap/action.yaml +++ b/.github/actions/bootstrap/action.yaml @@ -4,7 +4,7 @@ inputs: go-version: description: "Go version to install" required: true - default: "1.22.x" + default: "1.23.x" cache-key-prefix: description: "Prefix all cache keys with this value" required: true diff --git a/.golangci.yaml b/.golangci.yaml index c2ca0ca..1db5706 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -15,7 +15,6 @@ linters: - dogsled - dupl - errcheck - - exportloopref - funlen - gocognit - goconst @@ -79,4 +78,4 @@ run: # - structcheck # The owner seems to have abandoned the linter. Replaced by "unused". # - testpackage # - varcheck # The owner seems to have abandoned the linter. Replaced by "unused". -# - wsl # this doens't have an auto-fixer yet and is pretty noisy (https://github.com/bombsimon/wsl/issues/90) \ No newline at end of file +# - wsl # this doens't have an auto-fixer yet and is pretty noisy (https://github.com/bombsimon/wsl/issues/90) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 00bb542..fd0b8e3 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,3 +1,7 @@ +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=jcroql +version: 2 + release: prerelease: auto draft: false @@ -60,7 +64,7 @@ nfpms: - deb brews: - - tap: + - repository: owner: anchore name: homebrew-grant token: "{{.Env.HOMEBREW_TOKEN}}" diff --git a/cmd/grant/cli/command/check.go b/cmd/grant/cli/command/check.go index 987c022..bdaa8b1 100644 --- a/cmd/grant/cli/command/check.go +++ b/cmd/grant/cli/command/check.go @@ -68,11 +68,11 @@ func Check(app clio.Application) *cobra.Command { Use: "check", Short: "Verify licenses in the SBOM conform to the configured policy", Args: cobra.ArbitraryArgs, - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(_ *cobra.Command, args []string) error { userInputs = args return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return runCheck(cfg, userInputs) }, }, cfg) diff --git a/cmd/grant/cli/command/list.go b/cmd/grant/cli/command/list.go index 043b3b2..b0bcada 100644 --- a/cmd/grant/cli/command/list.go +++ b/cmd/grant/cli/command/list.go @@ -31,11 +31,11 @@ func List(app clio.Application) *cobra.Command { Use: "list", Short: "List the licenses detected in the given OCI image, sbom, or directory/file", Args: cobra.ArbitraryArgs, - PreRunE: func(cmd *cobra.Command, args []string) error { + PreRunE: func(_ *cobra.Command, args []string) error { userInputs = args return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { return runList(cfg, userInputs) }, }, cfg) diff --git a/go.mod b/go.mod index 61b93f2..a6539a8 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/anchore/grant -go 1.22.4 +go 1.23.2 require ( github.com/anchore/bubbly v0.0.0-20231115205105-6542675d79fe github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 - github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a + github.com/anchore/go-logger v0.0.0-20240925152809-a16bcaef4ee4 github.com/anchore/stereoscope v0.0.3 github.com/anchore/syft v1.13.0 github.com/charmbracelet/bubbletea v1.1.1 diff --git a/go.sum b/go.sum index 15fda8e..b954967 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,8 @@ github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d h1:ZD4wdCBgJJzJybjTU github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d/go.mod h1:Xh4ObY3fmoMzOEVXwDtS1uK44JC7+nRD0n29/1KYFYg= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537 h1:GjNGuwK5jWjJMyVppBjYS54eOiiSNv4Ba869k4wh72Q= github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537/go.mod h1:1aiktV46ATCkuVg0O573ZrH56BUawTECPETbZyBcqT8= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw= -github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a/go.mod h1:ubLFmlsv8/DFUQrZwY5syT5/8Er3ugSr4rDFwHsE3hg= +github.com/anchore/go-logger v0.0.0-20240925152809-a16bcaef4ee4 h1:wu6JP0Uiw4cgOJu6MwinMjEK8OV8Uf/nZgG6Xu/Ue9w= +github.com/anchore/go-logger v0.0.0-20240925152809-a16bcaef4ee4/go.mod h1:CyK090ySIgB8Y29so1Mhqh3T/apkpL6kUsfY/c+GmfM= github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb h1:iDMnx6LIjtjZ46C0akqveX83WFzhpTD3eqOthawb5vU= github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb/go.mod h1:DmTY2Mfcv38hsHbG78xMiTDdxFtkHpgYNVDPsF2TgHk= github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc= From 7a8dc6bf317e959d1f7c133de6a60ce6d059d522 Mon Sep 17 00:00:00 2001 From: Mike Frederick Date: Thu, 3 Oct 2024 11:49:40 -0400 Subject: [PATCH 2/2] fix: Update to support #101 (#124) Signed-off-by: Mike Frederick Co-authored-by: Christopher Angelo Phillips <32073428+spiffcs@users.noreply.github.com> --- grant/policy.go | 22 ++++--- grant/policy_test.go | 136 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 8 deletions(-) diff --git a/grant/policy.go b/grant/policy.go index 23d2aed..723458a 100644 --- a/grant/policy.go +++ b/grant/policy.go @@ -7,7 +7,6 @@ import ( ) // Policy is a structure of rules that define how licenses are denied -// TODO: maybe there should be a strict option that denies all and then only allows what is explicitly allowed type Policy struct { Rules Rules MatchNonSPDX bool @@ -51,10 +50,6 @@ func (p Policy) IsEmpty() bool { // IsDenied returns true if the given license is denied by the policy func (p Policy) IsDenied(license License, pkg *Package) (bool, *Rule) { for _, rule := range p.Rules { - if rule.Mode != Deny { - continue - } - var toMatch string if license.IsSPDX() { toMatch = strings.ToLower(license.LicenseID) @@ -63,16 +58,27 @@ func (p Policy) IsDenied(license License, pkg *Package) (bool, *Rule) { } toMatch = strings.ToLower(toMatch) + // If there is a match and the content to match is not an empty string if rule.Glob.Match(toMatch) && toMatch != "" { + var returnVal bool + // set the return value based on the rule mode + if rule.Mode == Allow { + returnVal = false + } else { + returnVal = true + } if pkg == nil { - return true, &rule + return returnVal, &rule } for _, exception := range rule.Exceptions { if exception.Match(pkg.Name) { - return false, &rule + // flip the return value based on the exception + returnVal = !returnVal + + return returnVal, &rule } } - return true, &rule + return returnVal, &rule } } return false, nil diff --git a/grant/policy_test.go b/grant/policy_test.go index d563463..186caf9 100644 --- a/grant/policy_test.go +++ b/grant/policy_test.go @@ -114,3 +114,139 @@ func Test_Policy_DenyAll(t *testing.T) { }) } } + +func Test_Policy_Exceptions(t *testing.T) { + tests := []struct { + name string + p Policy + want struct { + denied bool + rule *Rule + } + }{ + { + name: "Policy Default Deny All denies all licenses", + p: Policy{ + Rules: Rules{Rule{ + Name: "default-deny-all", + Glob: glob.MustCompile("*"), + Exceptions: []glob.Glob{glob.MustCompile("MIT")}, + Mode: Deny, + Reason: "grant by default will deny all licenses", + }}, + MatchNonSPDX: false, + }, + want: struct { + denied bool + rule *Rule + }{ + denied: false, + rule: &Rule{ + Name: "default-deny-all", + Glob: glob.MustCompile("*"), + Exceptions: []glob.Glob{glob.MustCompile("MIT")}, + Mode: Deny, + Reason: "grant by default will deny all licenses", + }, + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + denied, rule := tc.p.IsDenied(License{LicenseID: "MIT", SPDXExpression: "MIT"}, &Package{ID: "MIT", Name: "MIT"}) + if denied != tc.want.denied { + t.Errorf("Expected %t, got %t", tc.want.denied, denied) + } + if diff := cmp.Diff(tc.want.rule, rule); diff != "" { + t.Errorf("IsDenied() mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func Test_Policy_Allow(t *testing.T) { + tests := []struct { + name string + p Policy + want struct { + denied bool + rule *Rule + } + }{ + { + name: "Policy Allow MIT", + p: Policy{ + Rules: Rules{Rule{ + Name: "allow MIT", + Glob: glob.MustCompile("mit"), + Exceptions: []glob.Glob{}, + Mode: Allow, + Reason: "grant allow MIT", + }, Rule{ + Name: "deny gpl", + Glob: glob.MustCompile("gpl"), + Exceptions: []glob.Glob{}, + Mode: Deny, + Reason: "grant deny gpl", + }}, + MatchNonSPDX: false, + }, + want: struct { + denied bool + rule *Rule + }{ + denied: false, + rule: &Rule{ + Name: "allow MIT", + Glob: glob.MustCompile("mit"), + Exceptions: []glob.Glob{}, + Mode: Allow, + Reason: "grant allow MIT", + }, + }, + }, + { + name: "Policy Deny MIT", + p: Policy{ + Rules: Rules{Rule{ + Name: "deny MIT", + Glob: glob.MustCompile("mit"), + Exceptions: []glob.Glob{}, + Mode: Deny, + Reason: "grant deny MIT", + }, Rule{ + Name: "allow gpl", + Glob: glob.MustCompile("gpl"), + Exceptions: []glob.Glob{}, + Mode: Allow, + Reason: "grant allow gpl", + }}, + MatchNonSPDX: false, + }, + want: struct { + denied bool + rule *Rule + }{ + denied: true, + rule: &Rule{ + Name: "deny MIT", + Glob: glob.MustCompile("mit"), + Exceptions: []glob.Glob{}, + Mode: Deny, + Reason: "grant deny MIT", + }, + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + denied, rule := tc.p.IsDenied(License{LicenseID: "MIT", SPDXExpression: "MIT"}, nil) + if denied != tc.want.denied { + t.Errorf("Expected %t, got %t", tc.want.denied, denied) + } + if diff := cmp.Diff(tc.want.rule, rule); diff != "" { + t.Errorf("IsDenied() mismatch (-want +got):\n%s", diff) + } + }) + } +}