go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/connection/container/image/docker.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package image
     5  
     6  import (
     7  	"io"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/google/go-containerregistry/pkg/name"
    12  	v1 "github.com/google/go-containerregistry/pkg/v1"
    13  	"github.com/google/go-containerregistry/pkg/v1/daemon"
    14  	"github.com/google/go-containerregistry/pkg/v1/tarball"
    15  	"go.mondoo.com/cnquery/providers/os/connection/container/cache"
    16  )
    17  
    18  type ShaReference struct {
    19  	SHA string
    20  }
    21  
    22  func (r ShaReference) Name() string {
    23  	return r.SHA
    24  }
    25  
    26  func (r ShaReference) String() string {
    27  	return r.SHA
    28  }
    29  
    30  func (r ShaReference) Context() name.Repository {
    31  	return name.Repository{}
    32  }
    33  
    34  func (r ShaReference) Identifier() string {
    35  	return r.SHA
    36  }
    37  
    38  func (r ShaReference) Scope(scope string) string {
    39  	return ""
    40  }
    41  
    42  func LoadImageFromDockerEngine(sha string, disableBuffer bool) (v1.Image, io.ReadCloser, error) {
    43  	opts := []daemon.Option{}
    44  	if disableBuffer {
    45  		opts = append(opts, daemon.WithUnbufferedOpener())
    46  	}
    47  	img, err := daemon.Image(&ShaReference{SHA: strings.Replace(sha, "sha256:", "", -1)}, opts...)
    48  	if err != nil {
    49  		return nil, nil, err
    50  	}
    51  
    52  	// write image to disk (conmpressed, unflattened)
    53  	// Otherwise we can not later recognize it as a valid image
    54  	f, err := writeCompressedTarImage(img, sha)
    55  	if err != nil {
    56  		return nil, nil, err
    57  	}
    58  
    59  	return img, f, nil
    60  }
    61  
    62  // writeCompressedTarImage writes image including the metradata unflattened to disk
    63  func writeCompressedTarImage(img v1.Image, digest string) (*os.File, error) {
    64  	f, err := cache.RandomFile()
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	filename := f.Name()
    69  
    70  	ref, err := name.ParseReference(digest, name.WeakValidation)
    71  	if err != nil {
    72  		os.Remove(filename)
    73  		return nil, err
    74  	}
    75  
    76  	err = tarball.Write(ref, img, f)
    77  	if err != nil {
    78  		os.Remove(filename)
    79  		return nil, err
    80  	}
    81  
    82  	// Rewind, to later read the complete file for uncompress
    83  	f.Seek(0, io.SeekStart)
    84  
    85  	return f, nil
    86  }