mirror of
https://github.com/containers/skopeo.git
synced 2025-08-31 14:20:21 +00:00
Merge pull request #157 from mtrmac/verify-on-pull
Verify signatures on pull
This commit is contained in:
8
Makefile
8
Makefile
@@ -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
|
||||
|
@@ -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 {
|
||||
|
@@ -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
7
default-policy.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default": [
|
||||
{
|
||||
"type": "insecureAcceptAnything"
|
||||
}
|
||||
]
|
||||
}
|
@@ -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
|
||||
|
@@ -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
|
||||
|
2
vendor/github.com/containers/image/docker/docker_transport.go
generated
vendored
2
vendor/github.com/containers/image/docker/docker_transport.go
generated
vendored
@@ -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{}
|
||||
|
2
vendor/github.com/containers/image/oci/oci_transport.go
generated
vendored
2
vendor/github.com/containers/image/oci/oci_transport.go
generated
vendored
@@ -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{}
|
||||
|
2
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
2
vendor/github.com/containers/image/openshift/openshift_transport.go
generated
vendored
@@ -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{}
|
||||
|
27
vendor/github.com/containers/image/signature/policy_config.go
generated
vendored
27
vendor/github.com/containers/image/signature/policy_config.go
generated
vendored
@@ -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)
|
||||
|
9
vendor/github.com/containers/image/types/types.go
generated
vendored
9
vendor/github.com/containers/image/types/types.go
generated
vendored
@@ -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.
|
||||
}
|
||||
|
2
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
2
vendor/github.com/davecgh/go-spew/LICENSE
generated
vendored
@@ -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
|
||||
|
Reference in New Issue
Block a user