Skip to content

Commit

Permalink
only perform signing actions in cosign.Signer
Browse files Browse the repository at this point in the history
Signed-off-by: Jake Sanders <jsand@google.com>
  • Loading branch information
Jake Sanders committed Nov 29, 2021
1 parent 3f5bf27 commit a99d528
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 168 deletions.
46 changes: 25 additions & 21 deletions cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"net/url"
Expand Down Expand Up @@ -209,11 +208,6 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO
defer out.Close()
}

req := &icos.SigningRequest{
SignaturePayload: payload,
SignedEntity: se,
}

var s icos.Signer
s = &icos.PayloadSigner{
PayloadSigner: sv,
Expand All @@ -229,31 +223,41 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO
RekorURL: ko.RekorURL,
}
}
s = &icos.OCISignatureBuilder{
Inner: s,

ociSig, _, err := s.Sign(ctx, bytes.NewReader(payload))
if err != nil {
return err
}
s = &icos.OCISignatureAttacher{
DD: dd,
Inner: s,

b64sig, err := ociSig.Base64Signature()
if err != nil {
return err
}
if _, err := out.Write([]byte(b64sig)); err != nil {
return errors.Wrap(err, "write signature to file")
}
if upload {
s = &icos.RemoteSignerWrapper{
SignatureRepo: digest.Repository,
RegOpts: regOpts,

Inner: s,
}
if !upload {
return nil
}

results, err := s.Sign(ctx, req)
// Attach the signature to the entity.
newSE, err := mutate.AttachSignatureToEntity(se, ociSig, mutate.WithDupeDetector(dd))
if err != nil {
return err
}

b64sig := base64.StdEncoding.EncodeToString(results.Signature)
if _, err := out.Write([]byte(b64sig)); err != nil {
return errors.Wrap(err, "write signature to file")
// Publish the signatures associated with this entity
walkOpts, err := regOpts.ClientOpts(ctx)
if err != nil {
return errors.Wrap(err, "constructing client options")
}

// Publish the signatures associated with this entity
if err := ociremote.WriteSignatures(digest.Repository, newSE, walkOpts...); err != nil {
return err
}

return nil
}

Expand Down
75 changes: 75 additions & 0 deletions internal/pkg/cosign/fulcio.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2021 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cosign

import (
"context"
"crypto"
"io"

"github.com/sigstore/cosign/pkg/oci"
"github.com/sigstore/cosign/pkg/oci/static"
)

// FulcioSignerWrapper implements `Signer`
type FulcioSignerWrapper struct {
Inner Signer

Cert, Chain []byte
}

func (fs *FulcioSignerWrapper) Sign(ctx context.Context, payload io.Reader) (oci.Signature, crypto.PublicKey, error) {
sig, pub, err := fs.Inner.Sign(ctx, payload)
if err != nil {
return nil, nil, err
}

payloadBytes, err := sig.Payload()
if err != nil {
return nil, nil, err
}
b64Sig, err := sig.Base64Signature()
if err != nil {
return nil, nil, err
}

// TODO(dekkagaijin): move the fulcio SignerVerififer logic here

opts := []static.Option{static.WithCertChain(fs.Cert, fs.Chain)}

// Copy over the other attributes:
if annotations, err := sig.Annotations(); err != nil {
return nil, nil, err
} else if len(annotations) > 0 {
opts = append(opts, static.WithAnnotations(annotations))
}
if bundle, err := sig.Bundle(); err != nil {
return nil, nil, err
} else if bundle != nil {
opts = append(opts, static.WithBundle(bundle))
}
if mt, err := sig.MediaType(); err != nil {
return nil, nil, err
} else if mt != "" {
opts = append(opts, static.WithLayerMediaType(mt))
}

newSig, err := static.NewSignature(payloadBytes, b64Sig, opts...)
if err != nil {
return nil, nil, err
}

return newSig, pub, nil
}
80 changes: 67 additions & 13 deletions internal/pkg/cosign/tlog.go → internal/pkg/cosign/rekor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ package cosign

import (
"context"
"crypto"
"encoding/base64"
"fmt"
"io"
"os"

cosignv1 "github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/oci"
"github.com/sigstore/cosign/pkg/oci/static"
rekPkgClient "github.com/sigstore/rekor/pkg/client"
rekGenClient "github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/models"
Expand Down Expand Up @@ -65,28 +69,78 @@ type RekorSignerWrapper struct {
}

// Sign calls a wrapped, inner signer then uploads either the Cert or Pub(licKey) of the results to Rekor, then adds the resulting `Bundle`
func (rs *RekorSignerWrapper) Sign(ctx context.Context, req *SigningRequest) (*SigningResults, error) {
results, err := rs.Inner.Sign(ctx, req)
func (rs *RekorSignerWrapper) Sign(ctx context.Context, payload io.Reader) (oci.Signature, crypto.PublicKey, error) {
sig, pub, err := rs.Inner.Sign(ctx, payload)
if err != nil {
return nil, err
return nil, nil, err
}

payloadBytes, err := sig.Payload()
if err != nil {
return nil, nil, err
}
b64Sig, err := sig.Base64Signature()
if err != nil {
return nil, nil, err
}
sigBytes, err := base64.StdEncoding.DecodeString(b64Sig)
if err != nil {
return nil, nil, err
}

// Upload the cert or the public key, depending on what we have
rekorBytes := results.Cert
if rekorBytes == nil {
rekorBytes, err = cryptoutils.MarshalPublicKeyToPEM(results.Pub)
if err != nil {
return nil, err
}
cert, err := sig.Cert()
if err != nil {
return nil, nil, err
}

var rekorBytes []byte
if cert != nil {
rekorBytes, err = cryptoutils.MarshalCertificateToPEM(cert)
} else {
rekorBytes, err = cryptoutils.MarshalPublicKeyToPEM(pub)
}
if err != nil {
return nil, nil, err
}

bundle, err := uploadToTlog(rekorBytes, rs.RekorURL, func(r *rekGenClient.Rekor, b []byte) (*models.LogEntryAnon, error) {
return cosignv1.TLogUpload(ctx, r, results.Signature, results.SignedPayload, b)
return cosignv1.TLogUpload(ctx, r, sigBytes, payloadBytes, b)
})
if err != nil {
return nil, err
return nil, nil, err
}

opts := []static.Option{static.WithBundle(bundle)}

// Copy over the other attributes:

if cert != nil {
chain, err := sig.Chain()
if err != nil {
return nil, nil, err
}
chainBytes, err := cryptoutils.MarshalCertificatesToPEM(chain)
if err != nil {
return nil, nil, err
}
opts = append(opts, static.WithCertChain(rekorBytes, chainBytes))
}
if annotations, err := sig.Annotations(); err != nil {
return nil, nil, err
} else if len(annotations) > 0 {
opts = append(opts, static.WithAnnotations(annotations))
}
if mt, err := sig.MediaType(); err != nil {
return nil, nil, err
} else if mt != "" {
opts = append(opts, static.WithLayerMediaType(mt))
}

newSig, err := static.NewSignature(payloadBytes, b64Sig, opts...)
if err != nil {
return nil, nil, err
}

results.Bundle = bundle
return results, nil
return newSig, pub, nil
}
Loading

0 comments on commit a99d528

Please sign in to comment.