package packagelock import ( "context" "fmt" "github.com/go-logr/logr" "github.com/google/go-containerregistry/pkg/name" "go.uber.org/multierr" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/v1/google" gremote "github.com/google/go-containerregistry/pkg/v1/remote" "edge-infra.dev/pkg/f8n/warehouse" "edge-infra.dev/pkg/f8n/warehouse/oci" "edge-infra.dev/pkg/f8n/warehouse/oci/remote" ) func InspectPackageLock(ctx context.Context, log logr.Logger, plf PackageLock, location string, project string, repository string) error { var expectationErrs []error keychain := authn.NewMultiKeychain( google.Keychain, authn.DefaultKeychain, ) for _, pkg := range plf.Packages { log.Info(fmt.Sprintf("validating %s", pkg.Name)) for _, ver := range pkg.Versions { digestRef := fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s@%s", location, project, repository, pkg.Name, ver.Digest) ref, err := name.ParseReference(digestRef) if err != nil { return err } digestArtifact, err := remote.Get(ref, []remote.Option{ remote.WithContext(ctx), gremote.WithAuthFromKeychain(keychain), }..., ) if err != nil { return err } digestAnnos, err := oci.Annotations(digestArtifact) if err != nil { return err } expectedVersion, found := digestAnnos[warehouse.AnnotationVersion] if !found { err := fmt.Errorf("no version annotation found for pkg %s@%s", pkg.Name, ver.Digest) expectationErrs = append(expectationErrs, err) continue } if tagErrors := validateTagAnnotations(location, project, repository, pkg.Name, expectedVersion, ver.Tags); tagErrors != nil { expectationErrs = append(expectationErrs, tagErrors) continue } } } if err := multierr.Combine(expectationErrs...); err != nil { return fmt.Errorf("all pkg versions must be the same. one or more differ: %+v", err) } return nil } func validateTagAnnotations(location string, project string, repository string, pkgName string, expectedVersion string, tags []string) error { var tagErrors []error for _, tag := range tags { if tag == "latest" { continue } tagRef := fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s:%s", location, project, repository, pkgName, tag) ref, err := name.ParseReference(tagRef) if err != nil { tagErrors = append(tagErrors, err) continue } tagArtifact, err := remote.Get(ref) if err != nil { tagErrors = append(tagErrors, err) continue } tagAnnos, err := oci.Annotations(tagArtifact) if err != nil { tagErrors = append(tagErrors, err) continue } tagVersion, found := tagAnnos[warehouse.AnnotationVersion] if !found { tagErrors = append(tagErrors, fmt.Errorf("tag %s did not contain a version annotation", tag)) continue } if tagVersion != expectedVersion { tagErrors = append(tagErrors, fmt.Errorf("tag %s version annotation %s did not match expected version %s", tag, tagVersion, expectedVersion)) continue } } if err := multierr.Combine(tagErrors...); err != nil { return fmt.Errorf("one or more tag versions did not match digest annotation version: %w", err) } return nil }