2021-05-26 12:22:31 -05:00
|
|
|
// Package common ...
|
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2021-12-13 14:23:31 -05:00
|
|
|
goerrors "errors"
|
2022-02-20 20:32:44 -05:00
|
|
|
"fmt"
|
2021-05-26 12:22:31 -05:00
|
|
|
"path"
|
2022-02-01 21:02:05 -05:00
|
|
|
"strconv"
|
2023-01-09 15:37:44 -05:00
|
|
|
"strings"
|
2022-11-22 13:13:08 -05:00
|
|
|
"time"
|
2021-05-26 12:22:31 -05:00
|
|
|
|
2022-08-20 20:18:50 -05:00
|
|
|
notreg "github.com/notaryproject/notation-go/registry"
|
2021-05-26 12:22:31 -05:00
|
|
|
godigest "github.com/opencontainers/go-digest"
|
|
|
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
2022-10-20 11:39:20 -05:00
|
|
|
|
2021-12-03 22:50:58 -05:00
|
|
|
"zotregistry.io/zot/errors"
|
|
|
|
"zotregistry.io/zot/pkg/log"
|
|
|
|
"zotregistry.io/zot/pkg/storage"
|
2021-05-26 12:22:31 -05:00
|
|
|
)
|
|
|
|
|
2022-10-05 05:21:14 -05:00
|
|
|
type OciLayoutUtils interface { //nolint: interfacebloat
|
2022-10-22 15:46:13 -05:00
|
|
|
GetImageManifest(repo string, reference string) (ispec.Manifest, godigest.Digest, error)
|
|
|
|
GetImageManifests(repo string) ([]ispec.Descriptor, error)
|
|
|
|
GetImageBlobManifest(repo string, digest godigest.Digest) (ispec.Manifest, error)
|
2023-01-09 15:37:44 -05:00
|
|
|
GetImageInfo(repo string, configDigest godigest.Digest) (ispec.Image, error)
|
2022-07-12 07:58:04 -05:00
|
|
|
GetImageTagsWithTimestamp(repo string) ([]TagInfo, error)
|
2022-07-19 08:16:15 -05:00
|
|
|
GetImagePlatform(imageInfo ispec.Image) (string, string)
|
2022-07-12 07:58:04 -05:00
|
|
|
GetImageManifestSize(repo string, manifestDigest godigest.Digest) int64
|
2022-07-22 15:01:38 -05:00
|
|
|
GetRepoLastUpdated(repo string) (TagInfo, error)
|
2022-07-12 07:58:04 -05:00
|
|
|
GetExpandedRepoInfo(name string) (RepoInfo, error)
|
2022-07-19 08:16:15 -05:00
|
|
|
GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error)
|
2022-08-02 10:58:30 -05:00
|
|
|
CheckManifestSignature(name string, digest godigest.Digest) bool
|
2022-09-22 14:08:58 -05:00
|
|
|
GetRepositories() ([]string, error)
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
2021-01-25 13:04:03 -05:00
|
|
|
// OciLayoutInfo ...
|
2022-07-12 07:58:04 -05:00
|
|
|
type BaseOciLayoutUtils struct {
|
2021-09-30 08:27:13 -05:00
|
|
|
Log log.Logger
|
|
|
|
StoreController storage.StoreController
|
2021-05-26 12:22:31 -05:00
|
|
|
}
|
|
|
|
|
2022-07-12 07:58:04 -05:00
|
|
|
// NewBaseOciLayoutUtils initializes a new OciLayoutUtils object.
|
|
|
|
func NewBaseOciLayoutUtils(storeController storage.StoreController, log log.Logger) *BaseOciLayoutUtils {
|
|
|
|
return &BaseOciLayoutUtils{Log: log, StoreController: storeController}
|
2021-05-26 12:22:31 -05:00
|
|
|
}
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageManifest(repo string, reference string) (ispec.Manifest, godigest.Digest, error) {
|
2022-09-22 14:08:58 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(repo)
|
|
|
|
|
|
|
|
if reference == "" {
|
|
|
|
reference = "latest"
|
|
|
|
}
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
manifestBlob, digest, _, err := imageStore.GetImageManifest(repo, reference)
|
2022-09-22 14:08:58 -05:00
|
|
|
if err != nil {
|
2022-09-30 12:32:32 -05:00
|
|
|
return ispec.Manifest{}, "", err
|
2022-09-22 14:08:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
var manifest ispec.Manifest
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
err = json.Unmarshal(manifestBlob, &manifest)
|
2022-09-22 14:08:58 -05:00
|
|
|
if err != nil {
|
2022-09-30 12:32:32 -05:00
|
|
|
return ispec.Manifest{}, "", err
|
2022-09-22 14:08:58 -05:00
|
|
|
}
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
return manifest, digest, nil
|
2022-09-22 14:08:58 -05:00
|
|
|
}
|
|
|
|
|
2022-09-28 13:39:54 -05:00
|
|
|
// Provide a list of repositories from all the available image stores.
|
2022-09-22 14:08:58 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetRepositories() ([]string, error) {
|
|
|
|
defaultStore := olu.StoreController.DefaultStore
|
|
|
|
substores := olu.StoreController.SubStore
|
|
|
|
|
|
|
|
repoList, err := defaultStore.GetRepositories()
|
|
|
|
if err != nil {
|
|
|
|
return []string{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, sub := range substores {
|
|
|
|
repoListForSubstore, err := sub.GetRepositories()
|
|
|
|
if err != nil {
|
|
|
|
return []string{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
repoList = append(repoList, repoListForSubstore...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return repoList, nil
|
|
|
|
}
|
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
// Below method will return image path including root dir, root dir is determined by splitting.
|
2022-10-22 15:46:13 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageManifests(repo string) ([]ispec.Descriptor, error) {
|
2022-11-22 13:13:08 -05:00
|
|
|
var lockLatency time.Time
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(repo)
|
2021-05-26 12:22:31 -05:00
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
imageStore.RLock(&lockLatency)
|
|
|
|
defer imageStore.RUnlock(&lockLatency)
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
buf, err := imageStore.GetIndexContent(repo)
|
2021-05-26 12:22:31 -05:00
|
|
|
if err != nil {
|
2021-09-30 08:27:13 -05:00
|
|
|
if goerrors.Is(errors.ErrRepoNotFound, err) {
|
2021-05-26 12:22:31 -05:00
|
|
|
olu.Log.Error().Err(err).Msg("index.json doesn't exist")
|
|
|
|
|
|
|
|
return nil, errors.ErrRepoNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to open index.json")
|
|
|
|
|
|
|
|
return nil, errors.ErrRepoNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
var index ispec.Index
|
|
|
|
|
|
|
|
if err := json.Unmarshal(buf, &index); err != nil {
|
2022-10-22 15:46:13 -05:00
|
|
|
olu.Log.Error().Err(err).Str("dir", path.Join(imageStore.RootDir(), repo)).Msg("invalid JSON")
|
2021-12-13 14:23:31 -05:00
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
return nil, errors.ErrRepoNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
return index.Manifests, nil
|
|
|
|
}
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageBlobManifest(repo string, digest godigest.Digest) (ispec.Manifest, error) {
|
|
|
|
var blobIndex ispec.Manifest
|
2021-05-26 12:22:31 -05:00
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
var lockLatency time.Time
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(repo)
|
2021-09-30 08:27:13 -05:00
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
imageStore.RLock(&lockLatency)
|
|
|
|
defer imageStore.RUnlock(&lockLatency)
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
blobBuf, err := imageStore.GetBlobContent(repo, digest)
|
2021-05-26 12:22:31 -05:00
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to open image metadata file")
|
|
|
|
|
|
|
|
return blobIndex, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(blobBuf, &blobIndex); err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to marshal blob index")
|
|
|
|
|
|
|
|
return blobIndex, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return blobIndex, nil
|
|
|
|
}
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageInfo(repo string, configDigest godigest.Digest) (ispec.Image, error) {
|
2021-05-26 12:22:31 -05:00
|
|
|
var imageInfo ispec.Image
|
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
var lockLatency time.Time
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(repo)
|
2021-09-30 08:27:13 -05:00
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
imageStore.RLock(&lockLatency)
|
|
|
|
defer imageStore.RUnlock(&lockLatency)
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
blobBuf, err := imageStore.GetBlobContent(repo, configDigest)
|
2021-05-26 12:22:31 -05:00
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to open image layers file")
|
|
|
|
|
|
|
|
return imageInfo, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(blobBuf, &imageInfo); err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to marshal blob index")
|
|
|
|
|
|
|
|
return imageInfo, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return imageInfo, err
|
|
|
|
}
|
|
|
|
|
2021-01-25 13:04:03 -05:00
|
|
|
// GetImageTagsWithTimestamp returns a list of image tags with timestamp available in the specified repository.
|
2022-07-12 07:58:04 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageTagsWithTimestamp(repo string) ([]TagInfo, error) {
|
2021-01-25 13:04:03 -05:00
|
|
|
tagsInfo := make([]TagInfo, 0)
|
|
|
|
|
|
|
|
manifests, err := olu.GetImageManifests(repo)
|
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to read image manifests")
|
|
|
|
|
|
|
|
return tagsInfo, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, manifest := range manifests {
|
|
|
|
digest := manifest.Digest
|
|
|
|
|
2021-12-13 14:23:31 -05:00
|
|
|
val, ok := manifest.Annotations[ispec.AnnotationRefName]
|
2021-01-25 13:04:03 -05:00
|
|
|
if ok {
|
|
|
|
imageBlobManifest, err := olu.GetImageBlobManifest(repo, digest)
|
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to read image blob manifest")
|
|
|
|
|
|
|
|
return tagsInfo, err
|
|
|
|
}
|
|
|
|
|
|
|
|
imageInfo, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest)
|
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("unable to read image info")
|
|
|
|
|
|
|
|
return tagsInfo, err
|
|
|
|
}
|
|
|
|
|
2022-10-10 19:43:05 -05:00
|
|
|
timeStamp := GetImageLastUpdated(imageInfo)
|
2021-05-26 12:22:31 -05:00
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
tagsInfo = append(tagsInfo, TagInfo{Name: val, Timestamp: timeStamp, Digest: digest})
|
2021-05-26 12:22:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-25 13:04:03 -05:00
|
|
|
return tagsInfo, nil
|
2021-05-26 12:22:31 -05:00
|
|
|
}
|
|
|
|
|
2022-02-20 20:32:44 -05:00
|
|
|
// check notary signature corresponding to repo name, manifest digest and mediatype.
|
2022-07-12 07:58:04 -05:00
|
|
|
func (olu BaseOciLayoutUtils) checkNotarySignature(name string, digest godigest.Digest) bool {
|
2022-02-20 20:32:44 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(name)
|
2022-07-15 06:10:51 -05:00
|
|
|
mediaType := notreg.ArtifactTypeNotation
|
2022-02-20 20:32:44 -05:00
|
|
|
|
2022-11-08 03:38:16 -05:00
|
|
|
_, err := imageStore.GetOrasReferrers(name, digest, mediaType)
|
2022-02-20 20:32:44 -05:00
|
|
|
if err != nil {
|
2022-07-15 06:10:51 -05:00
|
|
|
olu.Log.Info().Err(err).Str("repo", name).Str("digest",
|
|
|
|
digest.String()).Str("mediatype", mediaType).Msg("invalid notary signature")
|
2022-02-20 20:32:44 -05:00
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// check cosign signature corresponding to manifest.
|
2022-07-12 07:58:04 -05:00
|
|
|
func (olu BaseOciLayoutUtils) checkCosignSignature(name string, digest godigest.Digest) bool {
|
2023-01-09 15:37:44 -05:00
|
|
|
if digest.Validate() != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-02-20 20:32:44 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(name)
|
|
|
|
|
|
|
|
// if manifest is signed using cosign mechanism, cosign adds a new manifest.
|
|
|
|
// new manifest is tagged as sha256-<manifest-digest>.sig.
|
2022-07-15 06:10:51 -05:00
|
|
|
reference := fmt.Sprintf("sha256-%s.sig", digest.Encoded())
|
2022-02-20 20:32:44 -05:00
|
|
|
|
2022-10-05 05:21:14 -05:00
|
|
|
_, _, _, err := imageStore.GetImageManifest(name, reference) //nolint: dogsled
|
2022-02-20 20:32:44 -05:00
|
|
|
if err != nil {
|
2022-07-15 06:10:51 -05:00
|
|
|
olu.Log.Info().Err(err).Str("repo", name).Str("digest",
|
|
|
|
digest.String()).Msg("invalid cosign signature")
|
2022-02-20 20:32:44 -05:00
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// checks if manifest is signed or not
|
|
|
|
// checks for notary or cosign signature
|
|
|
|
// if cosign signature found it does not looks for notary signature.
|
2022-08-02 10:58:30 -05:00
|
|
|
func (olu BaseOciLayoutUtils) CheckManifestSignature(name string, digest godigest.Digest) bool {
|
2022-02-20 20:32:44 -05:00
|
|
|
if !olu.checkCosignSignature(name, digest) {
|
2022-07-15 06:10:51 -05:00
|
|
|
return olu.checkNotarySignature(name, digest)
|
2022-02-20 20:32:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2022-07-19 08:16:15 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImagePlatform(imageConfig ispec.Image) (
|
2022-07-12 07:58:04 -05:00
|
|
|
string, string,
|
|
|
|
) {
|
|
|
|
return imageConfig.OS, imageConfig.Architecture
|
|
|
|
}
|
|
|
|
|
2022-07-19 08:16:15 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageConfigInfo(repo string, manifestDigest godigest.Digest) (ispec.Image, error) {
|
2022-07-12 07:58:04 -05:00
|
|
|
imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifestDigest)
|
|
|
|
if err != nil {
|
2022-07-19 08:16:15 -05:00
|
|
|
return ispec.Image{}, err
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
2022-07-19 08:16:15 -05:00
|
|
|
imageInfo, err := olu.GetImageInfo(repo, imageBlobManifest.Config.Digest)
|
2022-07-12 07:58:04 -05:00
|
|
|
if err != nil {
|
2022-07-19 08:16:15 -05:00
|
|
|
return ispec.Image{}, err
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
2022-07-19 08:16:15 -05:00
|
|
|
return imageInfo, nil
|
|
|
|
}
|
|
|
|
|
2022-07-12 07:58:04 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetImageManifestSize(repo string, manifestDigest godigest.Digest) int64 {
|
2022-07-20 04:30:34 -05:00
|
|
|
imageStore := olu.StoreController.GetImageStore(repo)
|
|
|
|
|
2022-11-22 13:13:08 -05:00
|
|
|
var lockLatency time.Time
|
|
|
|
|
|
|
|
imageStore.RLock(&lockLatency)
|
|
|
|
defer imageStore.RUnlock(&lockLatency)
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
manifestBlob, err := imageStore.GetBlobContent(repo, manifestDigest)
|
2022-07-12 07:58:04 -05:00
|
|
|
if err != nil {
|
2022-07-20 04:30:34 -05:00
|
|
|
olu.Log.Error().Err(err).Msg("error when getting manifest blob content")
|
2022-07-12 07:58:04 -05:00
|
|
|
|
2022-07-20 04:30:34 -05:00
|
|
|
return int64(len(manifestBlob))
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
2022-07-20 04:30:34 -05:00
|
|
|
return int64(len(manifestBlob))
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (olu BaseOciLayoutUtils) GetImageConfigSize(repo string, manifestDigest godigest.Digest) int64 {
|
|
|
|
imageBlobManifest, err := olu.GetImageBlobManifest(repo, manifestDigest)
|
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("can't get image blob manifest")
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2022-07-20 04:30:34 -05:00
|
|
|
return imageBlobManifest.Config.Size
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
2022-07-22 15:01:38 -05:00
|
|
|
func (olu BaseOciLayoutUtils) GetRepoLastUpdated(repo string) (TagInfo, error) {
|
2022-07-12 07:58:04 -05:00
|
|
|
tagsInfo, err := olu.GetImageTagsWithTimestamp(repo)
|
|
|
|
if err != nil || len(tagsInfo) == 0 {
|
2022-07-22 15:01:38 -05:00
|
|
|
return TagInfo{}, err
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
latestTag := GetLatestTag(tagsInfo)
|
|
|
|
|
2022-07-22 15:01:38 -05:00
|
|
|
return latestTag, nil
|
2022-07-12 07:58:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (olu BaseOciLayoutUtils) GetExpandedRepoInfo(name string) (RepoInfo, error) {
|
2022-02-01 21:02:05 -05:00
|
|
|
repo := RepoInfo{}
|
|
|
|
|
2022-07-29 09:51:10 -05:00
|
|
|
repoBlob2Size := make(map[string]int64, 10)
|
|
|
|
|
|
|
|
// made up of all manifests, configs and image layers
|
|
|
|
repoSize := int64(0)
|
|
|
|
|
2022-09-22 14:08:58 -05:00
|
|
|
imageSummaries := make([]ImageSummary, 0)
|
2022-02-01 21:02:05 -05:00
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
manifestList, err := olu.GetImageManifests(name)
|
2022-07-29 09:51:10 -05:00
|
|
|
if err != nil {
|
2022-09-13 09:20:44 -05:00
|
|
|
olu.Log.Error().Err(err).Msg("error getting image manifests")
|
|
|
|
|
|
|
|
return RepoInfo{}, err
|
2022-07-29 09:51:10 -05:00
|
|
|
}
|
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
lastUpdatedTag, err := olu.GetRepoLastUpdated(name)
|
2022-02-01 21:02:05 -05:00
|
|
|
if err != nil {
|
2022-09-13 09:20:44 -05:00
|
|
|
olu.Log.Error().Err(err).Msgf("can't get last updated manifest for repo: %s", name)
|
2022-02-01 21:02:05 -05:00
|
|
|
|
|
|
|
return RepoInfo{}, err
|
|
|
|
}
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
repoVendorsSet := make(map[string]bool, len(manifestList))
|
|
|
|
repoPlatformsSet := make(map[string]OsArch, len(manifestList))
|
2022-07-29 09:51:10 -05:00
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
var lastUpdatedImageSummary ImageSummary
|
|
|
|
|
2022-02-20 20:32:44 -05:00
|
|
|
for _, man := range manifestList {
|
2022-09-13 09:20:44 -05:00
|
|
|
imageLayersSize := int64(0)
|
|
|
|
|
2022-02-20 20:32:44 -05:00
|
|
|
tag, ok := man.Annotations[ispec.AnnotationRefName]
|
2022-02-01 21:02:05 -05:00
|
|
|
if !ok {
|
2022-10-22 15:46:13 -05:00
|
|
|
olu.Log.Info().Msgf("skipping manifest with digest %s because it doesn't have a tag",
|
|
|
|
man.Digest.String())
|
2022-08-26 09:53:42 -05:00
|
|
|
|
|
|
|
continue
|
2022-02-01 21:02:05 -05:00
|
|
|
}
|
|
|
|
|
2022-02-20 20:32:44 -05:00
|
|
|
manifest, err := olu.GetImageBlobManifest(name, man.Digest)
|
2022-02-01 21:02:05 -05:00
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msg("error getting image manifest blob")
|
|
|
|
|
|
|
|
return RepoInfo{}, err
|
|
|
|
}
|
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
isSigned := olu.CheckManifestSignature(name, man.Digest)
|
2022-02-20 20:32:44 -05:00
|
|
|
|
2022-07-29 09:51:10 -05:00
|
|
|
manifestSize := olu.GetImageManifestSize(name, man.Digest)
|
2022-10-22 15:46:13 -05:00
|
|
|
olu.Log.Debug().Msg(fmt.Sprintf("%v", man.Digest.String()))
|
2022-07-29 09:51:10 -05:00
|
|
|
configSize := manifest.Config.Size
|
|
|
|
|
|
|
|
repoBlob2Size[man.Digest.String()] = manifestSize
|
2022-10-22 15:46:13 -05:00
|
|
|
repoBlob2Size[manifest.Config.Digest.String()] = configSize
|
2022-07-29 09:51:10 -05:00
|
|
|
|
|
|
|
imageConfigInfo, err := olu.GetImageConfigInfo(name, man.Digest)
|
|
|
|
if err != nil {
|
|
|
|
olu.Log.Error().Err(err).Msgf("can't retrieve config info for the image %s %s", name, man.Digest)
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
opSys, arch := olu.GetImagePlatform(imageConfigInfo)
|
2022-07-29 09:51:10 -05:00
|
|
|
osArch := OsArch{
|
2023-01-09 15:37:44 -05:00
|
|
|
Os: opSys,
|
2022-07-29 09:51:10 -05:00
|
|
|
Arch: arch,
|
|
|
|
}
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
if opSys != "" || arch != "" {
|
|
|
|
osArchString := strings.TrimSpace(fmt.Sprintf("%s %s", opSys, arch))
|
|
|
|
repoPlatformsSet[osArchString] = osArch
|
|
|
|
}
|
2022-07-29 09:51:10 -05:00
|
|
|
|
2022-09-30 12:32:32 -05:00
|
|
|
layers := make([]LayerSummary, 0)
|
2022-02-01 21:02:05 -05:00
|
|
|
|
|
|
|
for _, layer := range manifest.Layers {
|
2022-09-30 12:32:32 -05:00
|
|
|
layerInfo := LayerSummary{}
|
2022-02-01 21:02:05 -05:00
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
layerInfo.Digest = layer.Digest.String()
|
2022-02-01 21:02:05 -05:00
|
|
|
|
2022-07-29 09:51:10 -05:00
|
|
|
repoBlob2Size[layerInfo.Digest] = layer.Size
|
|
|
|
|
2022-02-01 21:02:05 -05:00
|
|
|
layerInfo.Size = strconv.FormatInt(layer.Size, 10)
|
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
imageLayersSize += layer.Size
|
|
|
|
|
2022-02-01 21:02:05 -05:00
|
|
|
layers = append(layers, layerInfo)
|
|
|
|
}
|
|
|
|
|
2022-09-13 09:20:44 -05:00
|
|
|
imageSize := imageLayersSize + manifestSize + configSize
|
|
|
|
|
|
|
|
// get image info from manifest annotation, if not found get from image config labels.
|
|
|
|
annotations := GetAnnotations(manifest.Annotations, imageConfigInfo.Config.Labels)
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
if annotations.Vendor != "" {
|
|
|
|
repoVendorsSet[annotations.Vendor] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
imageConfigHistory := imageConfigInfo.History
|
|
|
|
allHistory := []LayerHistory{}
|
|
|
|
|
|
|
|
if len(imageConfigHistory) == 0 {
|
|
|
|
for _, layer := range layers {
|
|
|
|
allHistory = append(allHistory, LayerHistory{
|
|
|
|
Layer: layer,
|
|
|
|
HistoryDescription: HistoryDescription{},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// iterator over manifest layers
|
|
|
|
var layersIterator int
|
|
|
|
// since we are appending pointers, it is important to iterate with an index over slice
|
|
|
|
for i := range imageConfigHistory {
|
|
|
|
allHistory = append(allHistory, LayerHistory{
|
|
|
|
HistoryDescription: HistoryDescription{
|
|
|
|
Created: *imageConfigHistory[i].Created,
|
|
|
|
CreatedBy: imageConfigHistory[i].CreatedBy,
|
|
|
|
Author: imageConfigHistory[i].Author,
|
|
|
|
Comment: imageConfigHistory[i].Comment,
|
|
|
|
EmptyLayer: imageConfigHistory[i].EmptyLayer,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
if imageConfigHistory[i].EmptyLayer {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if layersIterator+1 > len(layers) {
|
|
|
|
olu.Log.Error().Err(errors.ErrBadLayerCount).
|
|
|
|
Msgf("error on creating layer history for imaeg %s %s", name, man.Digest)
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
allHistory[i].Layer = layers[layersIterator]
|
|
|
|
|
|
|
|
layersIterator++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
olu.Log.Debug().Msgf("all history %v", allHistory)
|
2022-09-13 09:20:44 -05:00
|
|
|
|
|
|
|
size := strconv.Itoa(int(imageSize))
|
2022-10-22 15:46:13 -05:00
|
|
|
manifestDigest := man.Digest.String()
|
|
|
|
configDigest := manifest.Config.Digest.String()
|
2022-10-10 19:43:05 -05:00
|
|
|
lastUpdated := GetImageLastUpdated(imageConfigInfo)
|
2022-09-13 09:20:44 -05:00
|
|
|
score := 0
|
|
|
|
|
|
|
|
imageSummary := ImageSummary{
|
|
|
|
RepoName: name,
|
|
|
|
Tag: tag,
|
|
|
|
LastUpdated: lastUpdated,
|
|
|
|
Digest: manifestDigest,
|
|
|
|
ConfigDigest: configDigest,
|
|
|
|
IsSigned: isSigned,
|
|
|
|
Size: size,
|
|
|
|
Platform: osArch,
|
|
|
|
Vendor: annotations.Vendor,
|
|
|
|
Score: score,
|
|
|
|
Description: annotations.Description,
|
|
|
|
Title: annotations.Title,
|
|
|
|
Documentation: annotations.Documentation,
|
|
|
|
Licenses: annotations.Licenses,
|
|
|
|
Labels: annotations.Labels,
|
|
|
|
Source: annotations.Source,
|
2022-09-22 14:08:58 -05:00
|
|
|
Layers: layers,
|
2023-01-09 15:37:44 -05:00
|
|
|
History: allHistory,
|
2022-09-13 09:20:44 -05:00
|
|
|
}
|
2022-02-01 21:02:05 -05:00
|
|
|
|
2022-09-22 14:08:58 -05:00
|
|
|
imageSummaries = append(imageSummaries, imageSummary)
|
|
|
|
|
2022-10-22 15:46:13 -05:00
|
|
|
if man.Digest.String() == lastUpdatedTag.Digest.String() {
|
2022-09-13 09:20:44 -05:00
|
|
|
lastUpdatedImageSummary = imageSummary
|
|
|
|
}
|
2022-07-29 09:51:10 -05:00
|
|
|
}
|
|
|
|
|
2022-09-22 14:08:58 -05:00
|
|
|
repo.ImageSummaries = imageSummaries
|
2022-09-13 09:20:44 -05:00
|
|
|
|
2022-07-29 09:51:10 -05:00
|
|
|
for blob := range repoBlob2Size {
|
|
|
|
repoSize += repoBlob2Size[blob]
|
|
|
|
}
|
|
|
|
|
|
|
|
size := strconv.FormatInt(repoSize, 10)
|
|
|
|
|
2023-01-09 15:37:44 -05:00
|
|
|
repoPlatforms := make([]OsArch, 0, len(repoPlatformsSet))
|
|
|
|
|
|
|
|
for _, osArch := range repoPlatformsSet {
|
|
|
|
repoPlatforms = append(repoPlatforms, osArch)
|
|
|
|
}
|
|
|
|
|
|
|
|
repoVendors := make([]string, 0, len(repoVendorsSet))
|
|
|
|
|
|
|
|
for vendor := range repoVendorsSet {
|
|
|
|
vendor := vendor
|
|
|
|
repoVendors = append(repoVendors, vendor)
|
|
|
|
}
|
|
|
|
|
2022-07-29 09:51:10 -05:00
|
|
|
summary := RepoSummary{
|
|
|
|
Name: name,
|
2022-09-13 09:20:44 -05:00
|
|
|
LastUpdated: lastUpdatedTag.Timestamp,
|
2022-07-29 09:51:10 -05:00
|
|
|
Size: size,
|
|
|
|
Platforms: repoPlatforms,
|
2022-09-13 09:20:44 -05:00
|
|
|
NewestImage: lastUpdatedImageSummary,
|
2022-07-29 09:51:10 -05:00
|
|
|
Vendors: repoVendors,
|
|
|
|
Score: -1,
|
|
|
|
}
|
|
|
|
|
|
|
|
repo.Summary = summary
|
|
|
|
|
2022-02-01 21:02:05 -05:00
|
|
|
return repo, nil
|
|
|
|
}
|