hub/internal/tracker/helpers.go

192 lines
5.2 KiB
Go

package tracker
import (
"context"
"fmt"
"regexp"
"github.com/artifacthub/hub/internal/hub"
"github.com/artifacthub/hub/internal/tracker/source/container"
"github.com/artifacthub/hub/internal/tracker/source/falco"
"github.com/artifacthub/hub/internal/tracker/source/generic"
"github.com/artifacthub/hub/internal/tracker/source/helm"
"github.com/artifacthub/hub/internal/tracker/source/helmplugin"
"github.com/artifacthub/hub/internal/tracker/source/krew"
"github.com/artifacthub/hub/internal/tracker/source/olm"
"github.com/artifacthub/hub/internal/tracker/source/tekton"
"github.com/spf13/viper"
)
const (
cloudNativeSecurityHub = "https://github.com/falcosecurity/cloud-native-security-hub/resources/falco"
)
// GetRepositories gets the repositories the tracker will process based on the
// configuration provided:
//
// - If a list of repositories names, those will be the repositories returned
// provided they are found.
// - If a list of repositories kinds is provided, all repositories of those
// kinds will be returned.
// - Otherwise, all the repositories will be returned.
//
// NOTE: disabled repositories will be filtered out.
func GetRepositories(
ctx context.Context,
cfg *viper.Viper,
rm hub.RepositoryManager,
) ([]*hub.Repository, error) {
reposNames := cfg.GetStringSlice("tracker.repositoriesNames")
reposKinds := cfg.GetStringSlice("tracker.repositoriesKinds")
var repos []*hub.Repository
switch {
case len(reposNames) > 0:
for _, name := range reposNames {
repo, err := rm.GetByName(ctx, name, true)
if err != nil {
return nil, fmt.Errorf("error getting repository %s: %w", name, err)
}
repos = append(repos, repo)
}
case len(reposKinds) > 0:
var kinds []hub.RepositoryKind
for _, kindName := range reposKinds {
kind, err := hub.GetKindFromName(kindName)
if err != nil {
return nil, fmt.Errorf("invalid repository kind found in config: %s", kindName)
}
kinds = append(kinds, kind)
}
result, err := rm.Search(ctx, &hub.SearchRepositoryInput{
Kinds: kinds,
IncludeCredentials: true,
})
if err != nil {
return nil, fmt.Errorf("error getting repositories for kinds (%#v): %w", kinds, err)
}
repos = result.Repositories
default:
result, err := rm.Search(ctx, &hub.SearchRepositoryInput{
IncludeCredentials: true,
})
if err != nil {
return nil, fmt.Errorf("error getting all repositories: %w", err)
}
repos = result.Repositories
}
// Filter out disabled repositories
var reposFiltered []*hub.Repository
for _, repo := range repos {
if !repo.Disabled {
reposFiltered = append(reposFiltered, repo)
}
}
return reposFiltered, nil
}
// SetupSource returns the tracker source that should be used for the
// repository provided.
func SetupSource(i *hub.TrackerSourceInput) hub.TrackerSource {
var source hub.TrackerSource
switch i.Repository.Kind {
case hub.Container:
source = container.NewTrackerSource(i)
case hub.Falco:
// Temporary solution to maintain backwards compatibility with
// the only Falco rules repository registered at the moment in
// artifacthub.io using the structure and metadata format used
// by the cloud native security hub.
if i.Repository.URL == cloudNativeSecurityHub {
source = falco.NewTrackerSource(i)
} else {
source = generic.NewTrackerSource(i)
}
case hub.Helm:
source = helm.NewTrackerSource(i)
case hub.HelmPlugin:
source = helmplugin.NewTrackerSource(i)
case hub.Krew:
source = krew.NewTrackerSource(i)
case hub.OLM:
source = olm.NewTrackerSource(i)
case
hub.ArgoTemplate,
hub.Backstage,
hub.CoreDNS,
hub.Gatekeeper,
hub.Headlamp,
hub.InspektorGadget,
hub.KCL,
hub.KedaScaler,
hub.Keptn,
hub.KnativeClientPlugin,
hub.KubeArmor,
hub.Kubewarden,
hub.Kyverno,
hub.OPA,
hub.TBAction:
source = generic.NewTrackerSource(i)
case hub.TektonTask, hub.TektonPipeline, hub.TektonStepAction:
source = tekton.NewTrackerSource(i)
}
return source
}
// setVerifiedPublisherFlag sets the repository verified publisher flag for the
// repository provided when needed.
func setVerifiedPublisherFlag(
ctx context.Context,
rm hub.RepositoryManager,
r *hub.Repository,
md *hub.RepositoryMetadata,
) error {
var verifiedPublisher bool
if md != nil {
if r.RepositoryID == md.RepositoryID {
verifiedPublisher = true
}
}
if r.VerifiedPublisher != verifiedPublisher {
err := rm.SetVerifiedPublisher(ctx, r.RepositoryID, verifiedPublisher)
if err != nil {
return fmt.Errorf("error setting verified publisher flag: %w", err)
}
}
return nil
}
// shouldIgnorePackage checks if the package provided should be ignored.
func shouldIgnorePackage(md *hub.RepositoryMetadata, name, version string) bool {
if md == nil {
return false
}
for _, ignoreEntry := range md.Ignore {
if matchesEntry(ignoreEntry, name, version) {
return true
}
}
return false
}
// matchesEntry checks if the package name and version provide match a given
// ignore entry.
func matchesEntry(ignoreEntry *hub.RepositoryIgnoreEntry, name, version string) bool {
if ignoreEntry.Name != name {
return false
}
if version == "" {
return true
}
versionMatch, err := regexp.Match(ignoreEntry.Version, []byte(version))
if err != nil {
return false
}
if versionMatch {
return true
}
return false
}