Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegate to targets/releases per extended MVP #80

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 2 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,67 +101,13 @@ INFO[0000] The SHA sums are equal: 540cc4dc213548ebbdffb2ab0ef58729e089d1887edbc
- Add in-toto metadata when signing a thin bundle:

```
$ ./scripts/signy-sign.sh testdata/cnab/bundle.json localhost:5000/thin-intoto:v2 --in-toto --layout testdata/intoto/root.layout --links testdata/intoto --layout-key testdata/intoto/alice.pub
INFO[0000] Adding In-Toto layout and links metadata to TUF
INFO[0000] Pushed trust data for localhost:5000/thin-intoto:v2: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] Starting to copy image cnab/helloworld:0.1.1
INFO[0001] Completed image cnab/helloworld:0.1.1 copy
INFO[0001] Generated relocation map: relocation.ImageRelocationMap{"cnab/helloworld:0.1.1":"localhost:5000/thin-intoto@sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6"}
INFO[0001] Pushed successfully, with digest "sha256:b4936e42304c184bafc9b06dde9ea1f979129e09a021a8f40abc07f736de9268"
$ ./scripts/signy-sign.sh testdata/intoto/minimal/bundle.json localhost:5000/minimal:latest --in-toto --layout testdata/intoto/minimal/root.layout --links testdata/intoto/minimal/d374df2f6946233546bb4ca97dcee3a01fe07aaef11be1fb09abd37ceb4ecfb7/ --layout-key testdata/intoto/minimal/root.layout.pub
```

- verifying the signature of a thin bundle and running the in-toto verifications in a container:

```
$ ./scripts/signy-verify.sh localhost:5000/thin-intoto:v2 --in-toto
INFO[0000] Pulled trust data for localhost:5000/thin-intoto:v2, with role targets - SHA256: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] Pulling bundle from registry: localhost:5000/thin-intoto:v2
INFO[0000] Computed SHA: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] The SHA sums are equal: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] Writing In-Toto metadata files into /tmp/intoto-verification169227773
INFO[0000] copying file /in-toto/layout.template in container for verification...
INFO[0000] copying file /in-toto/key.pub in container for verification...
INFO[0000] copying file in-toto/package.2f89b927.link in container for verification...
INFO[0000] copying file in-toto/write-code.776a00e2.link in container for verification...
INFO[0000] copying file in-toto/foo.tar.gz in container for verification...
INFO[0000] Loading layout...
INFO[0000] Loading layout key(s)...
INFO[0000] Verifying layout signatures...
INFO[0001] Verifying layout expiration...
INFO[0001] Reading link metadata files...
INFO[0001] Verifying link metadata signatures...
INFO[0001] Verifying sublayouts...
INFO[0001] Verifying alignment of reported commands...
INFO[0001] Verifying command alignment for 'write-code.776a00e2.link'...
INFO[0001] Verifying command alignment for 'package.2f89b927.link'...
INFO[0001] Verifying threshold constraints...
INFO[0001] Skipping threshold verification for step 'write-code' with threshold '1'...
INFO[0001] Skipping threshold verification for step 'package' with threshold '1'...
INFO[0001] Verifying Step rules...
INFO[0001] Verifying material rules for 'write-code'...
INFO[0001] Verifying product rules for 'write-code'...
INFO[0001] Verifying 'ALLOW foo.py'...
INFO[0001] Verifying material rules for 'package'...
INFO[0001] Verifying 'MATCH foo.py WITH PRODUCTS FROM write-code'...
INFO[0001] Verifying 'DISALLOW *'...
INFO[0001] Verifying product rules for 'package'...
INFO[0001] Verifying 'ALLOW foo.tar.gz'...
INFO[0001] Verifying 'ALLOW foo.py'...
INFO[0001] Executing Inspection commands...
INFO[0001] Executing command for inspection 'untar'...
INFO[0001] Running 'untar'...
INFO[0001] Recording materials '.'...
INFO[0001] Running command 'tar xfz foo.tar.gz'...
INFO[0001] Recording products '.'...
INFO[0001] Creating link metadata...
INFO[0001] Verifying Inspection rules...
INFO[0001] Verifying material rules for 'untar'...
INFO[0001] Verifying 'MATCH foo.tar.gz WITH PRODUCTS FROM package'...
INFO[0001] Verifying 'DISALLOW foo.tar.gz'...
INFO[0001] Verifying product rules for 'untar'...
INFO[0001] Verifying 'MATCH foo.py WITH PRODUCTS FROM write-code'...
INFO[0001] Verifying 'DISALLOW foo.py'...
INFO[0001] The software product passed all verification.
$ ./scripts/signy-verify.sh localhost:5000/minimal:latest --in-toto
```

- similarly for a thick bundle:
Expand Down
40 changes: 29 additions & 11 deletions cmd/sign.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package main

import (
"encoding/hex"
"fmt"

canonicaljson "github.com/docker/go/canonical/json"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"github.com/cnabio/signy/pkg/cnab"
"github.com/cnabio/signy/pkg/docker"
"github.com/cnabio/signy/pkg/intoto"
"github.com/cnabio/signy/pkg/tuf"
)
Expand Down Expand Up @@ -89,40 +88,59 @@ INFO[0001] Pushed successfully, with digest "sha256:b4936e42304c184bafc9b06dde9e
}

func (s *signCmd) run() error {
var cm *canonicaljson.RawMessage
var publicKeys intoto.PublicKeys
radu-matei marked this conversation as resolved.
Show resolved Hide resolved
var rootLayout intoto.RootLayout
var links intoto.Links
var bundleCustom intoto.Custom

gun, err := docker.GetGUN(s.ref)
if err != nil {
return fmt.Errorf("cannot initialize GUN from %s: %v", s.ref, err)
}

if s.intoto {
if s.layout == "" || s.layoutKey == "" || s.linkDir == "" {
return fmt.Errorf("required in-toto metadata not found")
}
log.Infof("Adding In-Toto layout and links metadata to TUF")

err := intoto.ValidateFromPath(s.layout)
if err != nil {
return fmt.Errorf("validation for in-toto metadata failed: %v", err)
}
custom, err := intoto.GetMetadataRawMessage(s.layout, s.linkDir, s.layoutKey)

publicKeys, err = intoto.GetPublicKeys(gun, s.layoutKey)
if err != nil {
return fmt.Errorf("cannot read public keys: %v", err)
}

rootLayout, err = intoto.GetRootLayout(gun, s.layout, publicKeys)
if err != nil {
return fmt.Errorf("cannot get metadata message: %v", err)
return fmt.Errorf("cannot read root layout: %v", err)
}
// TODO: Radu M
// Refactor GetMatedataRawMessage to return a pointer to a raw message
cm = &custom

links, err = intoto.GetLinks(gun, s.linkDir)
if err != nil {
return fmt.Errorf("cannot read links: %v", err)
}

bundleCustom = intoto.GetBundleCustom(rootLayout, links)
}

// NOTE: We first push to the Registry, and then Notary. This is so that if we modify the bundle locally,
// we will not invalidate its signature by first pushing to Notary, and then the Registry.

// We push only thin bundles to the Registry.
if !s.thick {
if err := cnab.Push(s.file, s.ref); err != nil {
return err
}
}

target, err := tuf.SignAndPublish(trustDir, trustServer, s.ref, s.file, tlscacert, s.rootKey, timeout, cm)
bundleDigest, err := tuf.SignAndPublish(trustDir, trustServer, s.ref, s.file, tlscacert, s.rootKey, timeout, rootLayout, publicKeys, links, bundleCustom)
if err != nil {
return fmt.Errorf("cannot sign and publish trust data: %v", err)
}

log.Infof("Pushed trust data for %v: %v\n", s.ref, hex.EncodeToString(target.Hashes["sha256"]))
log.Infof("Pushed trust data for %v: %v\n", s.ref, bundleDigest)
return nil
}
13 changes: 13 additions & 0 deletions pkg/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ const (
workingDir = "/in-toto" // Where we expect to copy in-toto artifacts to
)

// GetGUN returns the Globally Unique Name for a reference image name
func GetGUN(name string) (string, error) {
r, err := reference.ParseNormalizedNamed(name)
if err != nil {
return "", err
}
repo, err := registry.ParseRepositoryInfo(r)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this second function call does for you? It seems that you can return r.Name directly and the test still passes.

if err != nil {
return "", err
}
return repo.Name.Name(), nil
}

// Run will start a container, copy all In-Toto metadata in /in-toto
// then run in-toto-verification
func Run(verificationImage, verificationDir, logLevel string) error {
Expand Down
33 changes: 32 additions & 1 deletion pkg/docker/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,42 @@ import (
"github.com/stretchr/testify/assert"
)

var testDir = "../../testdata/intoto"
var testDir = "../../testdata/intoto/minimal"

func TestRun(t *testing.T) {
// NOTE: Tag will be empty since we cannot inject build-time variables during testing.
// Therefore, we shall use the "latest" tag.
err := Run(VerificationImage+"latest", testDir, log.InfoLevel.String())
assert.NoError(t, err)
}

func TestParseReference(t *testing.T) {
tests := []struct {
input string
gun string
}{
{
input: "localhost:5000/local-test-simple:v1",
gun: "localhost:5000/local-test-simple",
},
{
input: "localhost:5000/multi-path/some/bundle:v1",
gun: "localhost:5000/multi-path/some/bundle",
},
{
input: "dockerhubusername/bundle:v3",
gun: "docker.io/dockerhubusername/bundle",
},
{
input: "mycnabregistry.azurecr.io/org/sub-org/bundle:latest",
gun: "mycnabregistry.azurecr.io/org/sub-org/bundle",
},
}

is := assert.New(t)
for _, test := range tests {
gun, err := GetGUN(test.input)
is.NoError(err)
is.Equal(test.gun, gun)
}
}
Loading