Skip to content

Commit

Permalink
Remove standalone commands for in-toto and integrate with sign an… (#32)
Browse files Browse the repository at this point in the history
Remove standalone commands for in-toto and integrate with sign and verify
  • Loading branch information
Radu M committed Oct 16, 2019
2 parents e910ef0 + 9a8fffd commit 8984425
Show file tree
Hide file tree
Showing 27 changed files with 1,493 additions and 488 deletions.
13 changes: 10 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

273 changes: 149 additions & 124 deletions README.md

Large diffs are not rendered by default.

37 changes: 0 additions & 37 deletions cmd/intoto_sign.go

This file was deleted.

37 changes: 0 additions & 37 deletions cmd/intoto_verify.go

This file was deleted.

2 changes: 0 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ func init() {
newListCmd(),
newSignCmd(),
newVerifyCmd(),
newIntotoSignCmd(),
newIntotoVerifyCmd(),
)

rootCmd.PersistentFlags().StringVarP(&trustServer, "server", "", "https://notary.docker.io", "The trust server used")
Expand Down
78 changes: 52 additions & 26 deletions cmd/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"encoding/hex"
"fmt"

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

"github.com/engineerd/signy/pkg/cnab"
"github.com/engineerd/signy/pkg/intoto"
"github.com/engineerd/signy/pkg/tuf"
)

Expand All @@ -16,6 +18,12 @@ type signCmd struct {
thick bool
file string
rootKey string

intoto bool
layout string
// TODO: figure out a way to pass layout root key to TUF (not in the custom object)
layoutKey string
linkDir string
}

func newSignCmd() *cobra.Command {
Expand All @@ -34,35 +42,29 @@ For more info on managing the signing keys, see https://docs.docker.com/notary/a
Example: computes the SHA256 digest of a canonical CNAB bundle, pushes it to the trust server, then pushes the bundle using CNAB-TO-OCI
$ signy sign bundle.json docker.io/<user>/<repo>:<tag>
Root key found, using: d701ba005e6d217c7eb6cb56dbc6cf0bd81f41347927acbca1318131cc693fc9
Pushed trust data for docker.io/<user>/<repo>:<tag>: 607ddb1d998e2155104067f99065659b202b0b19fa9ae52349ba3e9248635475
Starting to copy image cnab/helloworld:0.1.1...
Completed image cnab/helloworld:0.1.1 copy
Generated relocation map: bundle.ImageRelocationMap{"cnab/helloworld:0.1.1":"docker.io/radumatei/signed-cnab-bundle@sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6"}
Pushed successfully, with digest "sha256:086ef83113475d4582a7431b4b9bc98634d4f71ad1289cca45e661153fc9a46e"
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 sign testdata/cnab/bundle.json localhost:5000/thin-bundle:v1
INFO[0000] Pushed trust data for localhost:5000/thin-bundle:v1: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] Starting to copy image cnab/helloworld:0.1.1
INFO[0002] Completed image cnab/helloworld:0.1.1 copy
INFO[0002] Generated relocation map: relocation.ImageRelocationMap{"cnab/helloworld:0.1.1":"localhost:5000/thin-bundle@sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6"}
INFO[0002] Pushed successfully, with digest "sha256:b4936e42304c184bafc9b06dde9ea1f979129e09a021a8f40abc07f736de9268"
Example: computes the SHA256 digest of a thick bundle, pushes it to a trust sever
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 sign helloworld-0.1.1.tgz --thick localhost:5000/thick-bundle-signature:v1
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 sign --thick testdata/cnab/helloworld-0.1.1.tgz localhost:5000/thick-bundle:v1
INFO[0000] Pushed trust data for localhost:5000/thick-bundle:v1: 540cc4dc213548ebbdffb2ab0ef58729e089d1887edbcde6eeca851de624da70
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
In order to also push in-toto metadata to the TUF collection, use the --in-toto flag, together with --layout, --links, and (temporarily?) --layout-key.
Enter passphrase for new root key with ID d701ba0:
Repeat passphrase for new root key with ID d701ba0:
Enter passphrase for new targets key with ID 5113934:
Repeat passphrase for new targets key with ID 5113934:
Enter passphrase for new snapshot key with ID d12e8e4:
Repeat passphrase for new snapshot key with ID d12e8e4:
Example:
Pushed trust data for localhost:5000/thick-bundle-signature:v1: cd205919129bff138a3402b4de5abbbc1d310ec982e83a780ffee1879adda678
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 sign testdata/cnab/bundle.json localhost:5000/thin-intoto:v2 --in-toto --layout testdata/intoto/demo.layout.template --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"
`
sign := signCmd{}
cmd := &cobra.Command{
Expand All @@ -76,14 +78,38 @@ Pushed trust data for localhost:5000/thick-bundle-signature:v1: cd205919129bff13
return sign.run()
},
}
cmd.Flags().StringVarP(&sign.rootKey, "rootkey", "", "", "Root key to initialize the repository with")
cmd.Flags().BoolVarP(&sign.thick, "thick", "", false, "Signs a thick bundle. If passed, only the signature is pushed to the trust server, not the bundle file.")
cmd.Flags().StringVarP(&sign.rootKey, "root-key", "", "", "Root key to initialize the repository with")
cmd.Flags().BoolVarP(&sign.thick, "thick", "", false, "Signs a thick bundle. If passed, only the signature is pushed to the trust server, not the bundle file")

cmd.Flags().BoolVarP(&sign.intoto, "in-toto", "", false, "Adds in-toto metadata to TUF. If passed, the root layout, links directory, and root kyes must be supplied")
cmd.Flags().StringVarP(&sign.layout, "layout", "", "", "Path to the in-toto root layout file")
cmd.Flags().StringVarP(&sign.linkDir, "links", "", "", "Path to the in-toto links directory")
cmd.Flags().StringVarP(&sign.layoutKey, "layout-key", "", "", "Path to the in-toto root layout public keys")

return cmd
}

func (s *signCmd) run() error {
target, err := tuf.SignAndPublish(trustDir, trustServer, s.ref, s.file, tlscacert, s.rootKey, nil)
var cm *canonicaljson.RawMessage
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)
if err != nil {
return fmt.Errorf("cannot get metadata message: %v", err)
}
// TODO: Radu M
// Refactor GetMatedataRawMessage to return a pointer to a raw message
cm = &custom
}

target, err := tuf.SignAndPublish(trustDir, trustServer, s.ref, s.file, tlscacert, s.rootKey, cm)
if err != nil {
return fmt.Errorf("cannot sign and publish trust data: %v", err)
}
Expand Down
67 changes: 50 additions & 17 deletions cmd/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"fmt"

"github.com/engineerd/signy/pkg/trust"

"github.com/spf13/cobra"

"github.com/engineerd/signy/pkg/tuf"
Expand All @@ -12,47 +14,70 @@ type verifyCmd struct {
ref string
thick bool
localFile string

intoto bool
keepTempDir bool
verificationImage string
// TODO: remove this
targetFiles []string
}

func newVerifyCmd() *cobra.Command {
const verifyDesc = `
Pulls the metadata for a target from a trusted collection and checks that the trusted digest
equals the digest of the existing artifact.
For CNAB, the bundle is pulled from the OCI registry, and the two digests are compared. Optionally, the digests
can also be validated against a local bundle.json file in canonical form, passed through the --local flag.
For canonical CNAB bundes, the bundle is pulled from the OCI registry, and the two digests are compared.
For plaintext artifacts, the target from the trusted collection must be validated against a local file passed
through the --local flag.
For thick bundles, the --thick flag is required, together with the --local <path-to-thick-bundle>.
Example: verifies the metadata in the trusted collection for a CNAB bundle against the bundle pushed to an OCI registry
$ signy verify docker.io/<user>/<repo>:<tag>
Pulled trust data for docker.io/<user>/<repo>:<tag>, with role targets - SHA256: 607ddb1d998e2155104067f99065659b202b0b19fa9ae52349ba3e9248635475
Pulling bundle from registry: docker.io/<user>/<repo>:<tag>
Relocation map map[cnab/helloworld:0.1.1:radumatei/signed-cnab@sha256:a59a4e74d9cc89e4e75dfb2cc7ea5c108e4236ba6231b53081a9e2506d1197b6]
Computed SHA: 607ddb1d998e2155104067f99065659b202b0b19fa9ae52349ba3e9248635475
The SHA sums are equal: 607ddb1d998e2155104067f99065659b202b0b19fa9ae52349ba3e9248635475
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 verify localhost:5000/thin-bundle:v1
INFO[0000] Pulled trust data for localhost:5000/thin-bundle:v1, with role targets - SHA256: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] Pulling bundle from registry: localhost:5000/thin-bundle:v1
INFO[0000] Computed SHA: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
INFO[0000] The SHA sums are equal: c7e92bd51f059d60b15ad456edf194648997d739f60799b37e08edafd88a81b5
Example: verifies the metadata for a local thick bundle:
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 verify --thick --local helloworld-0.1.1.tgz localhost:5000/thick-bundle-signature:v1
Pulled trust data for localhost:5000/thick-bundle-signature:v1, with role targets - SHA256: cd205919129bff138a3402b4de5abbbc1d310ec982e83a780ffee1879adda678
Computed SHA: cd205919129bff138a3402b4de5abbbc1d310ec982e83a780ffee1879adda678
The SHA sums are equal: cd205919129bff138a3402b4de5abbbc1d310ec982e83a780ffee1879adda678
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 verify --thick --local testdata/cnab/helloworld-0.1.1.tgz localhost:5000/thick-bundle:v1
INFO[0000] Pulled trust data for localhost:5000/thick-bundle:v1, with role targets - SHA256: 540cc4dc213548ebbdffb2ab0ef58729e089d1887edbcde6eeca851de624da70
INFO[0000] Computed SHA: 540cc4dc213548ebbdffb2ab0ef58729e089d1887edbcde6eeca851de624da70
INFO[0000] The SHA sums are equal: 540cc4dc213548ebbdffb2ab0ef58729e089d1887edbcde6eeca851de624da70
In order to also verify in-toto metadata from the TUF collection, use the --in-toto flag (and, if the verification requires, --target, to indicate target files used by the verification).
Example:
$ signy --tlscacert=$NOTARY_CA --server https://localhost:4443 verify localhost:5000/thin-intoto:v2 --in-toto --target testdata/intoto/foo.tar.gz
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] Loading layout...
INFO[0000] Loading layout key(s)...
INFO[0001] The software product passed all verification.
`
verify := verifyCmd{}
cmd := &cobra.Command{
Use: "verify [target reference]",
Short: "Verifies the trust data for an artifact",
Long: verifyDesc,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
verify.ref = args[0]
return verify.run()
},
}
cmd.Flags().BoolVarP(&verify.thick, "thick", "", false, "Verifies a thick bundle. If passed, only the signature is pulled from the trust server, and is verified against a local thick bundle.")
cmd.Flags().StringVarP(&verify.localFile, "local", "", "", "Local file to validate the SHA256 against (mandatory for thick bundles).")
cmd.Flags().BoolVarP(&verify.thick, "thick", "", false, "Verifies a thick bundle. If passed, only the signature is pulled from the trust server, and is verified against a local thick bundle")
cmd.Flags().StringVarP(&verify.localFile, "local", "", "", "Local file to validate the SHA256 against (mandatory for thick bundles)")

cmd.Flags().BoolVarP(&verify.intoto, "in-toto", "", false, "If passed, will try to fetch in-toto metadata from TUF and perform the verification")
cmd.Flags().StringVarP(&verify.verificationImage, "image", "", "docker.pkg.github.com/engineerd/in-toto-container/verification:v1", "container image to run the in-toto verification")
cmd.Flags().BoolVarP(&verify.keepTempDir, "keep", "", false, "if passed, the temporary directory where the in-toto metadata is pulled is not deleted")
cmd.Flags().StringArrayVarP(&verify.targetFiles, "target", "", nil, "target files to copy in container for in-toto verifications")

return cmd
}
Expand All @@ -62,8 +87,16 @@ func (v *verifyCmd) run() error {
if v.localFile == "" {
return fmt.Errorf("no local file provided for thick bundle verification")
}
if v.intoto {
return trust.ValidateThickBundle(v.ref, v.localFile, trustServer, tlscacert, trustDir, v.verificationImage, logLevel, v.targetFiles, v.keepTempDir)
}

return tuf.VerifyFileTrust(v.ref, v.localFile, trustServer, tlscacert, trustDir)
}

if v.intoto {
return trust.ValidateThinBundle(v.ref, trustServer, tlscacert, trustDir, v.verificationImage, logLevel, v.targetFiles, v.keepTempDir)
}

return tuf.VerifyCNABTrust(v.ref, trustServer, tlscacert, trustDir)
}
8 changes: 4 additions & 4 deletions pkg/cnab/helpers.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package cnab

import (
"fmt"
"os"
"strings"

containerdRemotes "github.com/containerd/containerd/remotes"
"github.com/docker/cli/cli/config"
"github.com/docker/cnab-to-oci/remotes"
log "github.com/sirupsen/logrus"
)

func createResolver(insecureRegistries []string) containerdRemotes.Resolver {
Expand All @@ -17,12 +17,12 @@ func createResolver(insecureRegistries []string) containerdRemotes.Resolver {
func displayEvent(ev remotes.FixupEvent) {
switch ev.EventType {
case remotes.FixupEventTypeCopyImageStart:
fmt.Fprintf(os.Stderr, "Starting to copy image %s...\n", ev.SourceImage)
log.Infof("Starting to copy image %s", ev.SourceImage)
case remotes.FixupEventTypeCopyImageEnd:
if ev.Error != nil {
fmt.Fprintf(os.Stderr, "Failed to copy image %s: %s\n", ev.SourceImage, ev.Error)
log.Infof("Failed to copy image %s: %s", ev.SourceImage, ev.Error)
} else {
fmt.Fprintf(os.Stderr, "Completed image %s copy\n", ev.SourceImage)
log.Infof("Completed image %s copy", ev.SourceImage)
}
}
}
Expand Down
Loading

0 comments on commit 8984425

Please sign in to comment.