...

Source file src/github.com/sigstore/cosign/v2/pkg/oci/layout/index.go

Documentation: github.com/sigstore/cosign/v2/pkg/oci/layout

     1  //
     2  // Copyright 2021 The Sigstore Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package layout
    17  
    18  import (
    19  	"fmt"
    20  
    21  	v1 "github.com/google/go-containerregistry/pkg/v1"
    22  	"github.com/google/go-containerregistry/pkg/v1/layout"
    23  	"github.com/sigstore/cosign/v2/pkg/oci"
    24  	"github.com/sigstore/cosign/v2/pkg/oci/signed"
    25  )
    26  
    27  const (
    28  	kindAnnotation       = "kind"
    29  	imageAnnotation      = "dev.cosignproject.cosign/image"
    30  	imageIndexAnnotation = "dev.cosignproject.cosign/imageIndex"
    31  	sigsAnnotation       = "dev.cosignproject.cosign/sigs"
    32  	attsAnnotation       = "dev.cosignproject.cosign/atts"
    33  )
    34  
    35  // SignedImageIndex provides access to a local index reference, and its signatures.
    36  func SignedImageIndex(path string) (oci.SignedImageIndex, error) {
    37  	p, err := layout.FromPath(path)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	ii, err := p.ImageIndex()
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	return &index{
    46  		v1Index: ii,
    47  	}, nil
    48  }
    49  
    50  // We alias ImageIndex so that we can inline it without the type
    51  // name colliding with the name of a method it had to implement.
    52  type v1Index v1.ImageIndex
    53  
    54  type index struct {
    55  	v1Index
    56  }
    57  
    58  var _ oci.SignedImageIndex = (*index)(nil)
    59  
    60  // Signatures implements oci.SignedImageIndex
    61  func (i *index) Signatures() (oci.Signatures, error) {
    62  	img, err := i.imageByAnnotation(sigsAnnotation)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	if img == nil {
    67  		return nil, nil
    68  	}
    69  	return &sigs{img}, nil
    70  }
    71  
    72  // Attestations implements oci.SignedImageIndex
    73  func (i *index) Attestations() (oci.Signatures, error) {
    74  	img, err := i.imageByAnnotation(attsAnnotation)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	if img == nil {
    79  		return nil, nil
    80  	}
    81  	return &sigs{img}, nil
    82  }
    83  
    84  // Attestations implements oci.SignedImage
    85  func (i *index) Attachment(name string) (oci.File, error) { //nolint: revive
    86  	return nil, fmt.Errorf("not yet implemented")
    87  }
    88  
    89  // SignedImage implements oci.SignedImageIndex
    90  // if an empty hash is passed in, return the original image that was signed
    91  func (i *index) SignedImage(h v1.Hash) (oci.SignedImage, error) {
    92  	var img v1.Image
    93  	var err error
    94  	if h.String() == ":" {
    95  		img, err = i.imageByAnnotation(imageAnnotation)
    96  	} else {
    97  		img, err = i.Image(h)
    98  	}
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	if img == nil {
   103  		return nil, nil
   104  	}
   105  	return signed.Image(img), nil
   106  }
   107  
   108  // imageByAnnotation searches through all manifests in the index.json
   109  // and returns the image that has the matching annotation
   110  func (i *index) imageByAnnotation(annotation string) (v1.Image, error) {
   111  	manifest, err := i.IndexManifest()
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	for _, m := range manifest.Manifests {
   116  		if val, ok := m.Annotations[kindAnnotation]; ok && val == annotation {
   117  			return i.Image(m.Digest)
   118  		}
   119  	}
   120  	return nil, nil
   121  }
   122  
   123  func (i *index) imageIndexByAnnotation(annotation string) (v1.ImageIndex, error) {
   124  	manifest, err := i.IndexManifest()
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	for _, m := range manifest.Manifests {
   129  		if val, ok := m.Annotations[kindAnnotation]; ok && val == annotation {
   130  			return i.ImageIndex(m.Digest)
   131  		}
   132  	}
   133  	return nil, nil
   134  }
   135  
   136  // SignedImageIndex implements oci.SignedImageIndex
   137  func (i *index) SignedImageIndex(h v1.Hash) (oci.SignedImageIndex, error) {
   138  	var ii v1.ImageIndex
   139  	var err error
   140  	if h.String() == ":" {
   141  		ii, err = i.imageIndexByAnnotation(imageIndexAnnotation)
   142  	} else {
   143  		ii, err = i.ImageIndex(h)
   144  	}
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	if ii == nil {
   149  		return nil, nil
   150  	}
   151  	return &index{
   152  		v1Index: ii,
   153  	}, nil
   154  }
   155  

View as plain text