Files
trivy/pkg/fanal/artifact/remote/git.go
2022-07-03 20:03:21 +03:00

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
}