...

Source file src/github.com/sigstore/cosign/v2/pkg/oci/mutate/signature.go

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

     1  // Copyright 2021 The Sigstore Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package mutate
    16  
    17  import (
    18  	"bytes"
    19  	"crypto/x509"
    20  	"encoding/json"
    21  	"fmt"
    22  	"io"
    23  
    24  	v1 "github.com/google/go-containerregistry/pkg/v1"
    25  	"github.com/google/go-containerregistry/pkg/v1/types"
    26  	"github.com/sigstore/cosign/v2/pkg/cosign/bundle"
    27  	"github.com/sigstore/cosign/v2/pkg/oci"
    28  	"github.com/sigstore/cosign/v2/pkg/oci/static"
    29  	"github.com/sigstore/sigstore/pkg/cryptoutils"
    30  )
    31  
    32  type sigWrapper struct {
    33  	wrapped oci.Signature
    34  
    35  	annotations      map[string]string
    36  	bundle           *bundle.RekorBundle
    37  	rfc3161Timestamp *bundle.RFC3161Timestamp
    38  	cert             *x509.Certificate
    39  	chain            []*x509.Certificate
    40  	mediaType        types.MediaType
    41  }
    42  
    43  var _ v1.Layer = (*sigWrapper)(nil)
    44  var _ oci.Signature = (*sigWrapper)(nil)
    45  
    46  func copyAnnotations(ann map[string]string) map[string]string {
    47  	new := make(map[string]string, len(ann)) //nolint: revive
    48  	for k, v := range ann {
    49  		new[k] = v
    50  	}
    51  	return new
    52  }
    53  
    54  // Annotations implements oci.Signature.
    55  func (sw *sigWrapper) Annotations() (map[string]string, error) {
    56  	if sw.annotations != nil {
    57  		return copyAnnotations(sw.annotations), nil
    58  	}
    59  	return sw.wrapped.Annotations()
    60  }
    61  
    62  // Payload implements oci.Signature.
    63  func (sw *sigWrapper) Payload() ([]byte, error) {
    64  	return sw.wrapped.Payload()
    65  }
    66  
    67  // Signature implements oci.Signature
    68  func (sw *sigWrapper) Signature() ([]byte, error) {
    69  	return sw.wrapped.Signature()
    70  }
    71  
    72  // Base64Signature implements oci.Signature.
    73  func (sw *sigWrapper) Base64Signature() (string, error) {
    74  	return sw.wrapped.Base64Signature()
    75  }
    76  
    77  // Cert implements oci.Signature.
    78  func (sw *sigWrapper) Cert() (*x509.Certificate, error) {
    79  	if sw.cert != nil {
    80  		return sw.cert, nil
    81  	}
    82  	return sw.wrapped.Cert()
    83  }
    84  
    85  // Chain implements oci.Signature.
    86  func (sw *sigWrapper) Chain() ([]*x509.Certificate, error) {
    87  	if sw.chain != nil {
    88  		return sw.chain, nil
    89  	}
    90  	return sw.wrapped.Chain()
    91  }
    92  
    93  // Bundle implements oci.Signature.
    94  func (sw *sigWrapper) Bundle() (*bundle.RekorBundle, error) {
    95  	if sw.bundle != nil {
    96  		return sw.bundle, nil
    97  	}
    98  	return sw.wrapped.Bundle()
    99  }
   100  
   101  // RFC3161Timestamp implements oci.Signature.
   102  func (sw *sigWrapper) RFC3161Timestamp() (*bundle.RFC3161Timestamp, error) {
   103  	if sw.rfc3161Timestamp != nil {
   104  		return sw.rfc3161Timestamp, nil
   105  	}
   106  	return sw.wrapped.RFC3161Timestamp()
   107  }
   108  
   109  // MediaType implements v1.Layer
   110  func (sw *sigWrapper) MediaType() (types.MediaType, error) {
   111  	if sw.mediaType != "" {
   112  		return sw.mediaType, nil
   113  	}
   114  	return sw.wrapped.MediaType()
   115  }
   116  
   117  // Digest implements v1.Layer
   118  func (sw *sigWrapper) Digest() (v1.Hash, error) {
   119  	return sw.wrapped.Digest()
   120  }
   121  
   122  // DiffID implements v1.Layer
   123  func (sw *sigWrapper) DiffID() (v1.Hash, error) {
   124  	return sw.wrapped.DiffID()
   125  }
   126  
   127  // Compressed implements v1.Layer
   128  func (sw *sigWrapper) Compressed() (io.ReadCloser, error) {
   129  	return sw.wrapped.Compressed()
   130  }
   131  
   132  // Uncompressed implements v1.Layer
   133  func (sw *sigWrapper) Uncompressed() (io.ReadCloser, error) {
   134  	return sw.wrapped.Uncompressed()
   135  }
   136  
   137  // Size implements v1.Layer
   138  func (sw *sigWrapper) Size() (int64, error) {
   139  	return sw.wrapped.Size()
   140  }
   141  
   142  // Signature returns a new oci.Signature based on the provided original, plus the requested mutations.
   143  func Signature(original oci.Signature, opts ...SignatureOption) (oci.Signature, error) {
   144  	newSig := sigWrapper{wrapped: original}
   145  
   146  	so := makeSignatureOption(opts...)
   147  	oldAnn, err := original.Annotations()
   148  	if err != nil {
   149  		return nil, fmt.Errorf("could not get annotations from signature to mutate: %w", err)
   150  	}
   151  
   152  	var newAnn map[string]string
   153  	if so.annotations != nil {
   154  		newAnn = copyAnnotations(so.annotations)
   155  		newAnn[static.SignatureAnnotationKey] = oldAnn[static.SignatureAnnotationKey]
   156  		for _, key := range []string{static.BundleAnnotationKey, static.CertificateAnnotationKey, static.ChainAnnotationKey, static.RFC3161TimestampAnnotationKey} {
   157  			if val, isSet := oldAnn[key]; isSet {
   158  				newAnn[key] = val
   159  			} else {
   160  				delete(newAnn, key)
   161  			}
   162  		}
   163  	} else {
   164  		newAnn = copyAnnotations(oldAnn)
   165  	}
   166  
   167  	if so.bundle != nil {
   168  		newSig.bundle = so.bundle
   169  		b, err := json.Marshal(so.bundle)
   170  		if err != nil {
   171  			return nil, err
   172  		}
   173  		newAnn[static.BundleAnnotationKey] = string(b)
   174  	}
   175  
   176  	if so.rfc3161Timestamp != nil {
   177  		newSig.rfc3161Timestamp = so.rfc3161Timestamp
   178  		b, err := json.Marshal(so.rfc3161Timestamp)
   179  		if err != nil {
   180  			return nil, err
   181  		}
   182  		newAnn[static.RFC3161TimestampAnnotationKey] = string(b)
   183  	}
   184  
   185  	if so.cert != nil {
   186  		var cert *x509.Certificate
   187  		var chain []*x509.Certificate
   188  
   189  		certs, err := cryptoutils.LoadCertificatesFromPEM(bytes.NewReader(so.cert))
   190  		if err != nil {
   191  			return nil, err
   192  		}
   193  		newAnn[static.CertificateAnnotationKey] = string(so.cert)
   194  		cert = certs[0]
   195  
   196  		delete(newAnn, static.ChainAnnotationKey)
   197  		if so.chain != nil {
   198  			chain, err = cryptoutils.LoadCertificatesFromPEM(bytes.NewReader(so.chain))
   199  			if err != nil {
   200  				return nil, err
   201  			}
   202  			newAnn[static.ChainAnnotationKey] = string(so.chain)
   203  		}
   204  
   205  		newSig.cert = cert
   206  		newSig.chain = chain
   207  	}
   208  
   209  	if so.mediaType != "" {
   210  		newSig.mediaType = so.mediaType
   211  	}
   212  
   213  	newSig.annotations = newAnn
   214  
   215  	return &newSig, nil
   216  }
   217  

View as plain text