Merge pull request #157 from mtrmac/verify-on-pull

Verify signatures on pull
This commit is contained in:
Miloslav Trmač
2016-08-25 20:02:45 +02:00
committed by GitHub
12 changed files with 101 additions and 13 deletions

View File

@@ -5,6 +5,7 @@ export GO15VENDOREXPERIMENT=1
PREFIX ?= ${DESTDIR}/usr
INSTALLDIR=${PREFIX}/bin
MANINSTALLDIR=${PREFIX}/share/man
CONTAINERSSYSCONFIGDIR=${DESTDIR}/etc/containers
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
GO_MD2MAN ?= /usr/bin/go-md2man
@@ -60,14 +61,13 @@ clean:
rm -f skopeo docs/*.1
install: install-binary install-docs install-completions
install -D -m 644 default-policy.json ${CONTAINERSSYSCONFIGDIR}/policy.json
install-binary: ./skopeo
install -d -m 0755 ${INSTALLDIR}
install -m 755 skopeo ${INSTALLDIR}
install -D -m 755 skopeo ${INSTALLDIR}/skopeo
install-docs: docs/skopeo.1
install -d -m 0755 ${MANINSTALLDIR}/man1
install -m 644 docs/skopeo.1 ${MANINSTALLDIR}/man1/
install -D -m 644 docs/skopeo.1 ${MANINSTALLDIR}/man1/skopeo.1
install-completions:
install -m 644 -T hack/make/bash_autocomplete ${BASHINSTALLDIR}/skopeo

View File

@@ -80,6 +80,12 @@ func copyHandler(context *cli.Context) error {
return errors.New("Usage: copy source destination")
}
policyContext, err := getPolicyContext(context)
if err != nil {
return fmt.Errorf("Error loading verification policy: %v", err)
}
defer policyContext.Destroy()
dest, err := parseImageDestination(context, context.Args()[1])
if err != nil {
return fmt.Errorf("Error initializing %s: %v", context.Args()[1], err)
@@ -93,11 +99,21 @@ func copyHandler(context *cli.Context) error {
signBy := context.String("sign-by")
// Please keep this policy check BEFORE reading any other information about the image.
if allowed, err := policyContext.IsRunningImageAllowed(src); !allowed || err != nil { // Be paranoid and fail if either return value indicates so.
return fmt.Errorf("Source image rejected: %v", err)
}
manifest, _, err := src.Manifest()
if err != nil {
return fmt.Errorf("Error reading manifest: %v", err)
}
sigs, err := src.Signatures()
if err != nil {
return fmt.Errorf("Error reading signatures: %v", err)
}
blobDigests, err := src.BlobDigests()
if err != nil {
return fmt.Errorf("Error parsing manifest: %v", err)
@@ -128,11 +144,6 @@ func copyHandler(context *cli.Context) error {
}
}
sigs, err := src.Signatures()
if err != nil {
return fmt.Errorf("Error reading signatures: %v", err)
}
if signBy != "" {
mech, err := signature.NewGPGSigningMechanism()
if err != nil {

View File

@@ -5,6 +5,7 @@ import (
"os"
"github.com/Sirupsen/logrus"
"github.com/containers/image/signature"
"github.com/projectatomic/skopeo/version"
"github.com/urfave/cli"
)
@@ -50,6 +51,11 @@ func createApp() *cli.App {
Name: "tls-verify",
Usage: "verify certificates",
},
cli.StringFlag{
Name: "policy",
Value: "",
Usage: "Path to a signature verification policy file",
},
}
app.Before = func(c *cli.Context) error {
if c.GlobalBool("debug") {
@@ -75,3 +81,19 @@ func main() {
logrus.Fatal(err)
}
}
// getPolicyContext handles the global "policy" flag.
func getPolicyContext(c *cli.Context) (*signature.PolicyContext, error) {
policyPath := c.GlobalString("policy")
var policy *signature.Policy // This could be cached across calls, if we had an application context.
var err error
if policyPath == "" {
policy, err = signature.DefaultPolicy(nil)
} else {
policy, err = signature.NewPolicyFromFile(policyPath)
}
if err != nil {
return nil, err
}
return signature.NewPolicyContext(policy)
}

7
default-policy.json Normal file
View File

@@ -0,0 +1,7 @@
{
"default": [
{
"type": "insecureAcceptAnything"
}
]
}

View File

@@ -43,6 +43,9 @@ Most commands refer to container images, using a _transport_`:`_details_ format.
**--cert-path** _path_ Use certificates at _path_ (cert.pem, key.pem) to connect to the registry
**--policy** _path-to-policy_ Path to a policy.json file to use for verifying signatures and
deciding whether an image is accepted, instead of the default policy.
**--tls-verify** _bool-value_ Verify certificates
**--help**|**-h** Show help
@@ -56,6 +59,8 @@ Most commands refer to container images, using a _transport_`:`_details_ format.
Copy an image (manifest, filesystem layers, signatures) from one location to another.
Uses the system's signature verification policy to validate images, refuses to copy images rejected by the policy.
_source-image_ use the "image name" format described above
_destination-image_ use the "image name" format described above
@@ -128,6 +133,11 @@ Verify a signature using local files, digest will be printed on success.
## skopeo help
show help for `skopeo`
# FILES
**/etc/containers/policy.json**
Default signature verification policy file, if **--policy** is not specified.
The policy format is documented in https://github.com/containers/image/blob/master/docs/policy.json.md .
# EXAMPLES
## skopeo copy

View File

@@ -9,7 +9,7 @@ bundle_test_integration() {
# subshell so that we can export PATH without breaking other things
(
make binary-local
make install-binary
make install
export GO15VENDOREXPERIMENT=1
bundle_test_integration
) 2>&1

View File

@@ -9,7 +9,7 @@ import (
"github.com/docker/docker/reference"
)
// Transport is an ImageTransport for Docker references.
// Transport is an ImageTransport for Docker registry-hosted images.
var Transport = dockerTransport{}
type dockerTransport struct{}

View File

@@ -12,7 +12,7 @@ import (
"github.com/docker/docker/reference"
)
// Transport is an ImageTransport for Docker references.
// Transport is an ImageTransport for OCI directories.
var Transport = ociTransport{}
type ociTransport struct{}

View File

@@ -12,7 +12,7 @@ import (
"github.com/docker/docker/reference"
)
// Transport is an ImageTransport for directory paths.
// Transport is an ImageTransport for OpenShift registry-hosted images.
var Transport = openshiftTransport{}
type openshiftTransport struct{}

View File

@@ -24,6 +24,15 @@ import (
"github.com/docker/docker/reference"
)
// systemDefaultPolicyPath is the policy path used for DefaultPolicy().
// You can override this at build time with
// -ldflags '-X github.com/containers/image/signature.systemDefaultPolicyPath=$your_path'
var systemDefaultPolicyPath = builtinDefaultPolicyPath
// builtinDefaultPolicyPath is the policy pat used for DefaultPolicy().
// DO NOT change this, instead see systemDefaultPolicyPath above.
const builtinDefaultPolicyPath = "/etc/containers/policy.json"
// InvalidPolicyFormatError is returned when parsing an invalid policy configuration.
type InvalidPolicyFormatError string
@@ -33,6 +42,24 @@ func (err InvalidPolicyFormatError) Error() string {
// FIXME: NewDefaultPolicy, from default file (or environment if trusted?)
// DefaultPolicy returns the default policy of the system.
// Most applications should be using this method to get the policy configured
// by the system administrator.
// ctx should usually be nil, can be set to override the default.
// NOTE: When this function returns an error, report it to the user and abort.
// DO NOT hard-code fallback policies in your application.
func DefaultPolicy(ctx *types.SystemContext) (*Policy, error) {
return NewPolicyFromFile(defaultPolicyPath(ctx))
}
// defaultPolicyPath returns a path to the default policy of the system.
func defaultPolicyPath(ctx *types.SystemContext) string {
if ctx != nil && ctx.SignaturePolicyPath != "" {
return ctx.SignaturePolicyPath
}
return systemDefaultPolicyPath
}
// NewPolicyFromFile returns a policy configured in the specified file.
func NewPolicyFromFile(fileName string) (*Policy, error) {
contents, err := ioutil.ReadFile(fileName)

View File

@@ -147,3 +147,12 @@ type ImageInspectInfo struct {
Os string
Layers []string
}
// SystemContext allows parametrizing access to implicitly-accessed resources,
// like configuration files in /etc and users' login state in their home directory.
// Various components can share the same field only if their semantics is exactly
// the same; if in doubt, add a new field.
// It is always OK to pass nil instead of a SystemContext.
type SystemContext struct {
SignaturePolicyPath string // If not "", overrides the system's default path for signature.Policy configuration.
}

View File

@@ -1,3 +1,5 @@
ISC License
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
Permission to use, copy, modify, and distribute this software for any