move artifact package over

Signed-off-by: Meredith Lancaster <malancas@github.com>
This commit is contained in:
Meredith Lancaster 2024-03-01 16:16:20 -07:00
parent 3a08c03cc7
commit 97c10f4c04
10 changed files with 525 additions and 1 deletions

View file

@ -0,0 +1,74 @@
package artifact
import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/github/gh-attestation/pkg/artifact/oci"
)
type artifactType int
const (
ociArtifactType artifactType = iota
fileArtifactType
)
// DigestedArtifact abstracts the software artifact being verified
type DigestedArtifact struct {
URL string
digest string
digestAlg string
}
func normalizeReference(reference string, pathSeparator rune) (normalized string, artifactType artifactType, err error) {
switch {
case strings.HasPrefix(reference, "oci://"):
return reference[6:], ociArtifactType, nil
case strings.HasPrefix(reference, "file://"):
uri, err := url.ParseRequestURI(reference)
if err != nil {
return "", 0, fmt.Errorf("failed to parse reference URI: %w", err)
}
var path string
if pathSeparator == '/' {
// Unix paths use forward slashes like URIs, so no need to modify
path = uri.Path
} else {
// Windows paths should be normalized to use backslashes
path = strings.ReplaceAll(uri.Path, "/", string(pathSeparator))
// Remove leading slash from Windows paths if present
if strings.HasPrefix(path, string(pathSeparator)) {
path = path[1:]
}
}
return filepath.Clean(path), fileArtifactType, nil
}
// Treat any other reference as a local file path
return filepath.Clean(reference), fileArtifactType, nil
}
func NewDigestedArtifact(client oci.Client, reference, digestAlg string) (artifact *DigestedArtifact, err error) {
normalized, artifactType, err := normalizeReference(reference, os.PathSeparator)
if err != nil {
return nil, err
}
if artifactType == ociArtifactType {
// TODO: should we allow custom digestAlg for OCI artifacts?
return digestContainerImageArtifact(normalized, client)
}
return digestLocalFileArtifact(normalized, digestAlg)
}
// Digest returns the digest of the artifact
func (a *DigestedArtifact) Digest() string {
return a.digest
}
// DigestWithAlg returns the digest:algorithm of the artifact
func (a *DigestedArtifact) DigestWithAlg() string {
return fmt.Sprintf("%s:%s", a.digestAlg, a.digest)
}