Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #1227 - Get licenses for NuGet packages #3329

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
102fe66
- Add new DotNet- / Nuget-Cataloger-Configuration.
HeyeOpenSource Oct 14, 2024
df81198
- Added NuGet license resolver.
HeyeOpenSource Oct 14, 2024
49ad147
- Inject NuGet license parser into DotNet catalogers.
HeyeOpenSource Oct 14, 2024
a0d4098
fix: improve go binary semver extraction for traefik (#3325)
westonsteimel Oct 14, 2024
276c734
chore(deps): update CPE dictionary index (#3323)
anchore-actions-token-generator[bot] Oct 14, 2024
61b5a83
- Implemented the FieldDescriber interface for the cmd/syft/internal/…
HeyeOpenSource Oct 14, 2024
1659c46
- Added the missing DotNet config field to the cmd/syft/internal/opti…
HeyeOpenSource Oct 14, 2024
50e75eb
chore(deps): bump github/codeql-action from 3.26.12 to 3.26.13 (#3327)
dependabot[bot] Oct 14, 2024
5566af1
chore(deps): bump anchore/sbom-action from 0.17.2 to 0.17.3 (#3326)
dependabot[bot] Oct 14, 2024
81edaa9
chore(deps): update stereoscope to 93f8a11331e3d50f751e4d0ec5b63f3df3…
anchore-actions-token-generator[bot] Oct 14, 2024
1a69e5e
chore(deps): update stereoscope to 1cc8a41d447d0d092699be2b700b8ba62e…
anchore-actions-token-generator[bot] Oct 14, 2024
4644a0b
- Corrected DotNet config field description.
HeyeOpenSource Oct 15, 2024
37fbd5f
- Added more safeguards and comments to the private getDefaultProvide…
HeyeOpenSource Oct 15, 2024
00e2895
- Refactored NuGet license resolver.
HeyeOpenSource Oct 15, 2024
21a29dd
Merge branch 'main' into Issue_1227_Take_II
HeyeOpenSource Oct 15, 2024
60badab
- Refactored dotnet cataloger package to mitigate static analysis err…
HeyeOpenSource Oct 16, 2024
ba2c571
Merge branch 'main' into Issue_1227_Take_II
HeyeOpenSource Oct 16, 2024
5a7f484
- Corrected DefaultCatalogerConfig() comment.
HeyeOpenSource Oct 16, 2024
47928c9
- Minor correction for remote NuGet license retrieval from NuGet pack…
HeyeOpenSource Oct 16, 2024
97bb64a
- Extended dotnet configuration to allow for the use of credentials w…
HeyeOpenSource Oct 16, 2024
3b27e85
- Heavily restructured the license resolver in order to:
HeyeOpenSource Oct 16, 2024
037b96b
- Some more refactoring of the license resolver.
HeyeOpenSource Oct 16, 2024
10cf9dd
- Adapt dotnet cataloger config Unit Tests to commit 97bb64aa40db56a3…
HeyeOpenSource Oct 16, 2024
eb28e1a
Merge branch 'main' into Issue_1227_Take_II
HeyeOpenSource Oct 17, 2024
e5e288e
- Correct the package cataloger conventions for the dotnet catalogers.
HeyeOpenSource Oct 18, 2024
3c4e091
- Refactored and corrected license parser.
HeyeOpenSource Oct 18, 2024
9406809
- Extended config Unit Tests to include credentials.
HeyeOpenSource Oct 18, 2024
1286e44
- Added some license parser related Unit Tests.
HeyeOpenSource Oct 18, 2024
edde453
Merge branch 'main' into Issue_1227_Take_II
HeyeOpenSource Oct 18, 2024
0f5d505
Merge branch 'anchore:main' into Issue_1227_Take_II
HeyeOpenSource Oct 21, 2024
c769b7f
Merge branch 'anchore:main' into Issue_1227_Take_II
HeyeOpenSource Oct 22, 2024
4dfac93
- Adapted to changes in [Create single license scanner for all catalo…
HeyeOpenSource Oct 22, 2024
d362e77
Merge branch 'main' into Issue_1227_Take_II
HeyeOpenSource Oct 23, 2024
4e4dc67
- Refactoring.
HeyeOpenSource Oct 23, 2024
69d307d
- More refactoring.
HeyeOpenSource Oct 23, 2024
ab9ea30
- Try to fix static analysis by refactoring again.
HeyeOpenSource Oct 23, 2024
d66b934
- Try to fix static analysis by refactoring again.
HeyeOpenSource Oct 23, 2024
fda1188
- Remove the use of special environment variables for the dotnet cata…
HeyeOpenSource Oct 23, 2024
a745223
- Make local NuGet cache folder configurable.
HeyeOpenSource Oct 23, 2024
3ce5adf
- Adapted dotnet cataloger options to improve credential security.
HeyeOpenSource Oct 24, 2024
a92a4da
- Corrections for static analysis regressions.
HeyeOpenSource Oct 24, 2024
ae360d2
- Corrected test cases for the dotnet executable cataloger.
HeyeOpenSource Oct 24, 2024
f7017a1
- Properly reverted the original test case input.
HeyeOpenSource Oct 24, 2024
979b8ec
- Tie the dotnet search locally and -remotely options in to the ```en…
HeyeOpenSource Oct 24, 2024
f734ca7
- Compile fix.
HeyeOpenSource Oct 24, 2024
e234a78
- Logic correction *facepalm*.
HeyeOpenSource Oct 24, 2024
ca0e822
- Removed obsolete text-fixture files.
HeyeOpenSource Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/syft/internal/options/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/anchore/syft/syft/file/cataloger/executable"
"github.com/anchore/syft/syft/file/cataloger/filecontent"
"github.com/anchore/syft/syft/pkg/cataloger/binary"
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/pkg/cataloger/java"
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
Expand All @@ -42,6 +43,7 @@ type Catalog struct {

// ecosystem-specific cataloger configuration
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
DotNet dotnetConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
JavaScript javaScriptConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
LinuxKernel linuxKernelConfig `yaml:"linux-kernel" json:"linux-kernel" mapstructure:"linux-kernel"`
Expand Down Expand Up @@ -71,6 +73,7 @@ func DefaultCatalog() Catalog {
Package: defaultPackageConfig(),
LinuxKernel: defaultLinuxKernelConfig(),
Golang: defaultGolangConfig(),
DotNet: defaultDotnetConfig(),
Java: defaultJavaConfig(),
File: defaultFileConfig(),
Relationships: defaultRelationshipsConfig(),
Expand Down Expand Up @@ -165,6 +168,12 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
WithFromBuildSettings(cfg.Golang.MainModuleVersion.FromBuildSettings).
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
),
DotNet: dotnet.DefaultCatalogerConfig().
WithSearchLocalLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Dotnet, task.CSharp), cfg.DotNet.SearchLocalLicenses)).
WithLocalCachePaths(cfg.DotNet.LocalCachePaths).
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Dotnet, task.CSharp), cfg.DotNet.SearchRemoteLicenses)).
WithProviders(cfg.DotNet.Providers).
WithCredentials(cfg.DotNet.ProviderCredentials.String()),
JavaScript: javascript.DefaultCatalogerConfig().
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.JavaScript, task.Node, task.NPM), cfg.JavaScript.SearchRemoteLicenses)).
WithNpmBaseURL(cfg.JavaScript.NpmBaseURL),
Expand Down
120 changes: 120 additions & 0 deletions cmd/syft/internal/options/dotnet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package options

import (
"fmt"
"os"
"strings"

"github.com/anchore/clio"
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
)

type DotNetProviderCredentials []DotNetProviderCredential

func (dnpc DotNetProviderCredentials) String() string {
result := ""

partials := []string{}
for _, credential := range dnpc {
if credential.Valid() {
partials = append(partials, fmt.Sprintf("%s:%s", credential.Username, credential.Password))
}
}

if len(partials) > 0 {
result = strings.Join(partials, ",")
}

return result
}

type DotNetProviderCredential struct {
// IMPORTANT: do not show any credential information, use secret type to automatically redact the values
Username secret `yaml:"username" json:"username" mapstructure:"username"`
Password secret `yaml:"password" json:"password" mapstructure:"password"`
}

func (dnpc DotNetProviderCredential) Valid() bool {
return dnpc.Username != "" && dnpc.Password != ""
}

type dotnetConfig struct {
SearchLocalLicenses *bool `yaml:"search-local-licenses" json:"search-local-licenses" mapstructure:"search-local-licenses"`
LocalCachePaths string `yaml:"local-cache-paths" json:"local-cache-paths" mapstructure:"local-cache-paths"`
SearchRemoteLicenses *bool `yaml:"search-remote-licenses" json:"search-remote-licenses" mapstructure:"search-remote-licenses"`
Providers string `yaml:"package-providers,omitempty" json:"package-providers,omitempty" mapstructure:"package-providers"`
ProviderCredentials DotNetProviderCredentials `yaml:"package-provider-credentials,omitempty" json:"package-provider-credentials,omitempty" mapstructure:"package-provider-credentials"`
}

var _ interface {
clio.PostLoader
clio.FieldDescriber
} = (*dotnetConfig)(nil)

func retrieveCredentialByIndexExtension(index uint) (*DotNetProviderCredential, error) {
username, password := "", ""
if index == 0 {
username, password =
os.Getenv("SYFT_DOTNET_PACKAGE_PROVIDER_CREDENTIALS_USERNAME"),
os.Getenv("SYFT_DOTNET_PACKAGE_PROVIDER_CREDENTIALS_PASSWORD")
} else {
username, password =
os.Getenv(fmt.Sprintf("SYFT_DOTNET_PACKAGE_PROVIDER_CREDENTIALS_USERNAME_%d", index)),
os.Getenv(fmt.Sprintf("SYFT_DOTNET_PACKAGE_PROVIDER_CREDENTIALS_PASSWORD_%d", index))
}

candidateCredential := &DotNetProviderCredential{
Username: secret(username),
Password: secret(password),
}

if candidateCredential.Valid() {
return candidateCredential, nil
}
return nil, fmt.Errorf("credentials not found or invalid")
}

func (o *dotnetConfig) PostLoad() error {
var err error

index := uint(0)
for err == nil {
var credential *DotNetProviderCredential
if credential, err = retrieveCredentialByIndexExtension(index); err == nil {
o.ProviderCredentials = append(o.ProviderCredentials, *credential)
index++
}
}
return nil
}

func (o *dotnetConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
descriptions.Add(&o.SearchLocalLicenses, `search for NuGet package licences in the local cache of the system running Syft, note that this is outside the
container filesystem and probably outside the root of a local directory scan`)
descriptions.Add(&o.LocalCachePaths, `local cache folders (comma-separated) to use when retrieving NuGet packages locally,
if unset this defaults to the NuGet cache folders known to the DotNet environment`)
descriptions.Add(&o.SearchRemoteLicenses, `search for NuGet package licences by retrieving the package from a network proxy`)
descriptions.Add(&o.Providers, `remote NuGet package providers (comma-separated) to use when retrieving NuGet packages from the network,
if unset this defaults to the NuGet-repositories known to the DotNet environment`)
descriptions.Add(&o.ProviderCredentials, `remote NuGet package provider credentials to use when retrieving NuGet packages from the network.`)
}

func defaultDotnetConfig() dotnetConfig {
def := dotnet.DefaultCatalogerConfig()
providerCredentials := []DotNetProviderCredential{}
if len(def.ProviderCredentials) > 0 {
for _, credential := range def.ProviderCredentials {
providerCredentials = append(providerCredentials, DotNetProviderCredential{
Username: secret(credential.Username),
Password: secret(credential.Password),
})
}
}
return dotnetConfig{
SearchLocalLicenses: nil,
LocalCachePaths: strings.Join(def.LocalCachePaths, ","),
SearchRemoteLicenses: nil,
Providers: strings.Join(def.Providers, ","),
ProviderCredentials: providerCredentials,
}
}
17 changes: 15 additions & 2 deletions internal/task/package_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const (
JavaScript = "javascript"
Node = "node"
NPM = "npm"

// Dotnet ecosystem labels
Dotnet = "dotnet"
CSharp = "c#"
)

//nolint:funlen
Expand All @@ -73,7 +77,11 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
// language-specific package declared catalogers ///////////////////////////////////////////////////////////////////////////
newSimplePackageTaskFactory(cpp.NewConanCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "cpp", "conan"),
newSimplePackageTaskFactory(dart.NewPubspecLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dart"),
newSimplePackageTaskFactory(dotnet.NewDotnetDepsCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "dotnet", "c#"),
newPackageTaskFactory(
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
return dotnet.NewDotnetDepsCataloger(cfg.PackagesConfig.DotNet)
},
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, Dotnet, CSharp),
newSimplePackageTaskFactory(elixir.NewMixLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "elixir"),
newSimplePackageTaskFactory(erlang.NewRebarLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang"),
newSimplePackageTaskFactory(erlang.NewOTPCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "erlang", "otp"),
Expand Down Expand Up @@ -114,7 +122,12 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
newSimplePackageTaskFactory(ocaml.NewOpamPackageManagerCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.LanguageTag, "ocaml", "opam"),

// language-specific package for both image and directory scans (but not necessarily declared) ////////////////////////////////////////
newSimplePackageTaskFactory(dotnet.NewDotnetPortableExecutableCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "dotnet", "c#", "binary"),
newPackageTaskFactory(
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
return dotnet.NewDotnetPortableExecutableCataloger(cfg.PackagesConfig.DotNet)
},
pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, Dotnet, CSharp, "binary",
),
newSimplePackageTaskFactory(python.NewInstalledPackageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "python"),
newPackageTaskFactory(
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
Expand Down
8 changes: 8 additions & 0 deletions syft/cataloging/pkgcataloging/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pkgcataloging

import (
"github.com/anchore/syft/syft/pkg/cataloger/binary"
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/pkg/cataloger/java"
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
Expand All @@ -12,6 +13,7 @@ import (
type Config struct {
Binary binary.ClassifierCatalogerConfig `yaml:"binary" json:"binary" mapstructure:"binary"`
Golang golang.CatalogerConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
DotNet dotnet.CatalogerConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
JavaArchive java.ArchiveCatalogerConfig `yaml:"java-archive" json:"java-archive" mapstructure:"java-archive"`
JavaScript javascript.CatalogerConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
LinuxKernel kernel.LinuxKernelCatalogerConfig `yaml:"linux-kernel" json:"linux-kernel" mapstructure:"linux-kernel"`
Expand All @@ -22,6 +24,7 @@ func DefaultConfig() Config {
return Config{
Binary: binary.DefaultClassifierCatalogerConfig(),
Golang: golang.DefaultCatalogerConfig(),
DotNet: dotnet.DefaultCatalogerConfig(),
LinuxKernel: kernel.DefaultLinuxKernelCatalogerConfig(),
Python: python.DefaultCatalogerConfig(),
JavaArchive: java.DefaultArchiveCatalogerConfig(),
Expand All @@ -38,6 +41,11 @@ func (c Config) WithGolangConfig(cfg golang.CatalogerConfig) Config {
return c
}

func (c Config) WithDotNetConfig(cfg dotnet.CatalogerConfig) Config {
c.DotNet = cfg
return c
}

func (c Config) WithJavascriptConfig(cfg javascript.CatalogerConfig) Config {
c.JavaScript = cfg
return c
Expand Down
23 changes: 17 additions & 6 deletions syft/pkg/cataloger/dotnet/cataloger.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)

const (
dotnetDepsCatalogerName = "dotnet-deps-cataloger"
dotnetPortableExecutableCatalogerName = "dotnet-portable-executable-cataloger"
)

// NewDotnetDepsCataloger returns a new Dotnet cataloger object base on deps json files.
func NewDotnetDepsCataloger() pkg.Cataloger {
return generic.NewCataloger("dotnet-deps-cataloger").
WithParserByGlobs(parseDotnetDeps, "**/*.deps.json")
func NewDotnetDepsCataloger(opts CatalogerConfig) pkg.Cataloger {
c := dotnetDepsCataloger{
licenses: newNugetLicenseResolver(opts),
}
return generic.NewCataloger(dotnetDepsCatalogerName).
WithParserByGlobs(c.parseDotnetDeps, "**/*.deps.json")
}

// NewDotnetPortableExecutableCataloger returns a new Dotnet cataloger object base on portable executable files.
func NewDotnetPortableExecutableCataloger() pkg.Cataloger {
return generic.NewCataloger("dotnet-portable-executable-cataloger").
WithParserByGlobs(parseDotnetPortableExecutable, "**/*.dll", "**/*.exe")
func NewDotnetPortableExecutableCataloger(opts CatalogerConfig) pkg.Cataloger {
c := dotnetPortableExecutableCataloger{
licenses: newNugetLicenseResolver(opts),
}
return generic.NewCataloger(dotnetPortableExecutableCatalogerName).
WithParserByGlobs(c.parseDotnetPortableExecutable, "**/*.dll", "**/*.exe")
}
4 changes: 2 additions & 2 deletions syft/pkg/cataloger/dotnet/cataloger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ func TestCataloger_Globs(t *testing.T) {
{
name: "obtain deps.json files",
fixture: "test-fixtures/glob-paths",
cataloger: NewDotnetDepsCataloger(),
cataloger: NewDotnetDepsCataloger(DefaultCatalogerConfig()),
expected: []string{
"src/something.deps.json",
},
},
{
name: "obtain portable executable files",
fixture: "test-fixtures/glob-paths",
cataloger: NewDotnetPortableExecutableCataloger(),
cataloger: NewDotnetPortableExecutableCataloger(DefaultCatalogerConfig()),
expected: []string{
"src/something.dll",
"src/something.exe",
Expand Down
Loading
Loading