mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
135 lines
2.9 KiB
Go
135 lines
2.9 KiB
Go
package remote
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"net/url"
|
|
"os"
|
|
|
|
git "github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
|
"github.com/aquasecurity/trivy/pkg/fanal/artifact/local"
|
|
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
|
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
|
)
|
|
|
|
type Artifact struct {
|
|
url string
|
|
local artifact.Artifact
|
|
}
|
|
|
|
func NewArtifact(rawurl string, c cache.ArtifactCache, artifactOpt artifact.Option) (
|
|
artifact.Artifact, func(), error) {
|
|
cleanup := func() {}
|
|
|
|
u, err := newURL(rawurl)
|
|
if err != nil {
|
|
return nil, cleanup, err
|
|
}
|
|
|
|
tmpDir, err := ioutil.TempDir("", "fanal-remote")
|
|
if err != nil {
|
|
return nil, cleanup, err
|
|
}
|
|
|
|
cloneOptions := git.CloneOptions{
|
|
URL: u.String(),
|
|
Auth: gitAuth(),
|
|
Progress: os.Stdout,
|
|
Depth: 1,
|
|
InsecureSkipTLS: artifactOpt.InsecureSkipTLS,
|
|
}
|
|
|
|
// suppress clone output if noProgress
|
|
if artifactOpt.NoProgress {
|
|
cloneOptions.Progress = nil
|
|
}
|
|
|
|
_, err = git.PlainClone(tmpDir, false, &cloneOptions)
|
|
if err != nil {
|
|
return nil, cleanup, xerrors.Errorf("git error: %w", err)
|
|
}
|
|
|
|
cleanup = func() {
|
|
_ = os.RemoveAll(tmpDir)
|
|
}
|
|
|
|
art, err := local.NewArtifact(tmpDir, c, artifactOpt)
|
|
if err != nil {
|
|
return nil, cleanup, xerrors.Errorf("fs artifact: %w", err)
|
|
}
|
|
|
|
return Artifact{
|
|
url: rawurl,
|
|
local: art,
|
|
}, cleanup, nil
|
|
}
|
|
|
|
func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error) {
|
|
ref, err := a.local.Inspect(ctx)
|
|
if err != nil {
|
|
return types.ArtifactReference{}, xerrors.Errorf("remote repository error: %w", err)
|
|
}
|
|
|
|
ref.Name = a.url
|
|
ref.Type = types.ArtifactRemoteRepository
|
|
|
|
return ref, nil
|
|
}
|
|
|
|
func (Artifact) Clean(_ types.ArtifactReference) error {
|
|
return nil
|
|
}
|
|
|
|
func newURL(rawurl string) (*url.URL, error) {
|
|
u, err := url.Parse(rawurl)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("url parse error: %w", err)
|
|
}
|
|
// "https://" can be omitted
|
|
// e.g. github.com/aquasecurity/trivy
|
|
if u.Scheme == "" {
|
|
u.Scheme = "https"
|
|
}
|
|
|
|
return u, nil
|
|
}
|
|
|
|
// Helper function to check for a GitHub/GitLab token from env vars in order to
|
|
// make authenticated requests to access private repos
|
|
func gitAuth() *http.BasicAuth {
|
|
|
|
var auth *http.BasicAuth
|
|
|
|
// The username can be anything for HTTPS Git operations
|
|
gitUsername := "fanal-aquasecurity-scan"
|
|
|
|
// We first check if a GitHub token was provided
|
|
githubToken := os.Getenv("GITHUB_TOKEN")
|
|
if githubToken != "" {
|
|
auth = &http.BasicAuth{
|
|
Username: gitUsername,
|
|
Password: githubToken,
|
|
}
|
|
return auth
|
|
}
|
|
|
|
// Otherwise we check if a GitLab token was provided
|
|
gitlabToken := os.Getenv("GITLAB_TOKEN")
|
|
if gitlabToken != "" {
|
|
auth = &http.BasicAuth{
|
|
Username: gitUsername,
|
|
Password: gitlabToken,
|
|
}
|
|
return auth
|
|
}
|
|
|
|
// If no token was provided, we simply return a nil,
|
|
// which will make the request to be unauthenticated
|
|
return nil
|
|
|
|
}
|