Skip to content

Commit

Permalink
feat: improve the verification message
Browse files Browse the repository at this point in the history
Signed-off-by: Batuhan Apaydın <batuhan.apaydin@trendyol.com>
  • Loading branch information
developer-guy committed Sep 22, 2022
1 parent 0baa044 commit 8cf81ab
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 16 deletions.
16 changes: 11 additions & 5 deletions cmd/cosign/cli/verify/verify.go
Expand Up @@ -261,22 +261,22 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) {
}

if githubWorkflowTrigger := ce.GetCertExtensionGithubWorkflowTrigger(); githubWorkflowTrigger != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Trigger:", githubWorkflowTrigger)
fmt.Fprintln(os.Stderr, "GitHub Workflow Trigger:", githubWorkflowTrigger)
}

if githubWorkflowSha := ce.GetExtensionGithubWorkflowSha(); githubWorkflowSha != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow SHA:", githubWorkflowSha)
fmt.Fprintln(os.Stderr, "GitHub Workflow SHA:", githubWorkflowSha)
}
if githubWorkflowName := ce.GetCertExtensionGithubWorkflowName(); githubWorkflowName != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Name:", githubWorkflowName)
fmt.Fprintln(os.Stderr, "GitHub Workflow Name:", githubWorkflowName)
}

if githubWorkflowRepository := ce.GetCertExtensionGithubWorkflowRepository(); githubWorkflowRepository != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Trigger", githubWorkflowRepository)
fmt.Fprintln(os.Stderr, "GitHub Workflow Trigger", githubWorkflowRepository)
}

if githubWorkflowRef := ce.GetCertExtensionGithubWorkflowRef(); githubWorkflowRef != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Ref:", githubWorkflowRef)
fmt.Fprintln(os.Stderr, "GitHub Workflow Ref:", githubWorkflowRef)
}
}

Expand Down Expand Up @@ -311,23 +311,29 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) {
ss.Optional["Subject"] = sigs.CertSubject(cert)
if issuerURL := ce.GetIssuer(); issuerURL != "" {
ss.Optional["Issuer"] = issuerURL
ss.Optional[cosign.CertExtensionOIDCIssuer] = issuerURL
}
if githubWorkflowTrigger := ce.GetCertExtensionGithubWorkflowTrigger(); githubWorkflowTrigger != "" {
ss.Optional[cosign.CertExtensionMap[cosign.CertExtensionGithubWorkflowTrigger]] = githubWorkflowTrigger
ss.Optional[cosign.CertExtensionGithubWorkflowTrigger] = githubWorkflowTrigger
}

if githubWorkflowSha := ce.GetExtensionGithubWorkflowSha(); githubWorkflowSha != "" {
ss.Optional[cosign.CertExtensionMap[cosign.CertExtensionGithubWorkflowSha]] = githubWorkflowSha
ss.Optional[cosign.CertExtensionGithubWorkflowSha] = githubWorkflowSha
}
if githubWorkflowName := ce.GetCertExtensionGithubWorkflowName(); githubWorkflowName != "" {
ss.Optional[cosign.CertExtensionMap[cosign.CertExtensionGithubWorkflowName]] = githubWorkflowName
ss.Optional[cosign.CertExtensionGithubWorkflowName] = githubWorkflowName
}

if githubWorkflowRepository := ce.GetCertExtensionGithubWorkflowRepository(); githubWorkflowRepository != "" {
ss.Optional[cosign.CertExtensionMap[cosign.CertExtensionGithubWorkflowRepository]] = githubWorkflowRepository
ss.Optional[cosign.CertExtensionGithubWorkflowRepository] = githubWorkflowRepository
}

if githubWorkflowRef := ce.GetCertExtensionGithubWorkflowRef(); githubWorkflowRef != "" {
ss.Optional[cosign.CertExtensionMap[cosign.CertExtensionGithubWorkflowRef]] = githubWorkflowRef
ss.Optional[cosign.CertExtensionGithubWorkflowRef] = githubWorkflowRef
}
}
Expand Down
145 changes: 145 additions & 0 deletions cmd/cosign/cli/verify/verify_test.go
@@ -0,0 +1,145 @@
package verify

import (
"bytes"
"crypto"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"github.com/google/go-containerregistry/pkg/name"
"github.com/sigstore/cosign/pkg/oci"
"github.com/sigstore/cosign/pkg/oci/static"
"github.com/sigstore/cosign/test"
"github.com/sigstore/sigstore/pkg/signature/payload"
"github.com/stretchr/testify/assert"
"io"
"log"
"os"
"sync"
"testing"
)

func TestPrintVerification(t *testing.T) {
wantPayload := `
[
{
"critical": {
"identity": {
"docker-reference": "gcr.io/baz/baz"
},
"image": {
"docker-manifest-digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"type": "cosign container image signature"
},
"optional": {
"1.3.6.1.4.1.57264.1.1": "oidc-issuer",
"1.3.6.1.4.1.57264.1.2": "myWorkflowTrigger",
"1.3.6.1.4.1.57264.1.3": "myWorkflowSha",
"1.3.6.1.4.1.57264.1.4": "myWorkflowName",
"1.3.6.1.4.1.57264.1.5": "myWorkflowRepository",
"1.3.6.1.4.1.57264.1.6": "myWorkflowRef",
"Issuer": "oidc-issuer",
"Subject": "subject",
"githubWorkflowName": "myWorkflowName",
"githubWorkflowRef": "myWorkflowRef",
"githubWorkflowRepository": "myWorkflowRepository",
"githubWorkflowSha": "myWorkflowSha",
"githubWorkflowTrigger": "myWorkflowTrigger"
}
}
]
`
eexts := []pkix.Extension{
{Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 2}, Value: []byte("myWorkflowTrigger")},
{Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 3}, Value: []byte("myWorkflowSha")},
{Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 4}, Value: []byte("myWorkflowName")},
{Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 5}, Value: []byte("myWorkflowRepository")},
{Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 6}, Value: []byte("myWorkflowRef")},
}
rootCert, rootKey, _ := test.GenerateRootCa()
subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", subCert, subKey, eexts...)
pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw})
pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})

rootPool := x509.NewCertPool()
rootPool.AddCert(rootCert)

// Generate the payload for the image, and check the digest.
b := bytes.Buffer{}
dig3, err := name.NewDigest("gcr.io/baz/baz@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", name.StrictValidation)
if err != nil {
t.Fatalf("Error creating test dig3.")
}
pp, err := (&payload.Cosign{Image: dig3, Annotations: map[string]interface{}{}}).MarshalJSON()
if err != nil {
t.Fatalf("Error creating cosign payload")
}
fmt.Fprintln(&b, string(pp))

p := b.Bytes()
h := sha256.Sum256(p)
signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)

ociSig, _ := static.NewSignature(p,
base64.StdEncoding.EncodeToString(signature),
static.WithCertChain(pemLeaf, appendSlices([][]byte{pemSub, pemRoot})))

captureOutput := func(imgRef string, sigs []oci.Signature, output string, f func(string, []oci.Signature, string)) string {
reader, writer, err := os.Pipe()
if err != nil {
panic(err)
}
stdout := os.Stdout
stderr := os.Stderr
defer func() {
os.Stdout = stdout
os.Stderr = stderr
log.SetOutput(os.Stderr)
}()
os.Stdout = writer
os.Stderr = writer
log.SetOutput(writer)
out := make(chan string)
wg := new(sync.WaitGroup)
wg.Add(1)
go func() {
var buf bytes.Buffer
wg.Done()
io.Copy(&buf, reader)
out <- buf.String()
}()
wg.Wait()
f(imgRef, sigs, output)
writer.Close()
return <-out
}

out := captureOutput("", []oci.Signature{ociSig}, "json", PrintVerification)
prettyPrint := func(b []byte) ([]byte, error) {
var out bytes.Buffer
err := json.Indent(&out, b, "", " ")
return out.Bytes(), err
}
i, err := prettyPrint([]byte(out))
if err != nil {
t.Fatal(err.Error())
}
assert.JSONEq(t, wantPayload, string(i))
}

func appendSlices(slices [][]byte) []byte {
var tmp []byte
for _, s := range slices {
tmp = append(tmp, s...)
}
return tmp
}
25 changes: 14 additions & 11 deletions test/cert_utils.go
Expand Up @@ -145,22 +145,25 @@ func GenerateLeafCertWithExpiration(subject string, oidcIssuer string, expiratio
return cert, nil
}

func GenerateLeafCert(subject string, oidcIssuer string, parentTemplate *x509.Certificate, parentPriv crypto.Signer) (*x509.Certificate, *ecdsa.PrivateKey, error) {
certTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1),
EmailAddresses: []string{subject},
NotBefore: time.Now().Add(-1 * time.Minute),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning},
IsCA: false,
ExtraExtensions: []pkix.Extension{{
func GenerateLeafCert(subject string, oidcIssuer string, parentTemplate *x509.Certificate, parentPriv crypto.Signer, eexts ...pkix.Extension) (*x509.Certificate, *ecdsa.PrivateKey, error) {
exts := []pkix.Extension{
{
// OID for OIDC Issuer extension
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1},
Critical: false,
Value: []byte(oidcIssuer),
},
},
}
exts = append(exts, eexts...)
certTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1),
EmailAddresses: []string{subject},
NotBefore: time.Now().Add(-1 * time.Minute),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning},
IsCA: false,
ExtraExtensions: exts,
}

priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expand Down

0 comments on commit 8cf81ab

Please sign in to comment.