mirror of
https://github.com/containers/skopeo.git
synced 2025-09-05 16:50:45 +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
|
PREFIX ?= ${DESTDIR}/usr
|
||||||
INSTALLDIR=${PREFIX}/bin
|
INSTALLDIR=${PREFIX}/bin
|
||||||
MANINSTALLDIR=${PREFIX}/share/man
|
MANINSTALLDIR=${PREFIX}/share/man
|
||||||
|
CONTAINERSSYSCONFIGDIR=${DESTDIR}/etc/containers
|
||||||
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
|
BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
|
||||||
GO_MD2MAN ?= /usr/bin/go-md2man
|
GO_MD2MAN ?= /usr/bin/go-md2man
|
||||||
|
|
||||||
@@ -60,14 +61,13 @@ clean:
|
|||||||
rm -f skopeo docs/*.1
|
rm -f skopeo docs/*.1
|
||||||
|
|
||||||
install: install-binary install-docs install-completions
|
install: install-binary install-docs install-completions
|
||||||
|
install -D -m 644 default-policy.json ${CONTAINERSSYSCONFIGDIR}/policy.json
|
||||||
|
|
||||||
install-binary: ./skopeo
|
install-binary: ./skopeo
|
||||||
install -d -m 0755 ${INSTALLDIR}
|
install -D -m 755 skopeo ${INSTALLDIR}/skopeo
|
||||||
install -m 755 skopeo ${INSTALLDIR}
|
|
||||||
|
|
||||||
install-docs: docs/skopeo.1
|
install-docs: docs/skopeo.1
|
||||||
install -d -m 0755 ${MANINSTALLDIR}/man1
|
install -D -m 644 docs/skopeo.1 ${MANINSTALLDIR}/man1/skopeo.1
|
||||||
install -m 644 docs/skopeo.1 ${MANINSTALLDIR}/man1/
|
|
||||||
|
|
||||||
install-completions:
|
install-completions:
|
||||||
install -m 644 -T hack/make/bash_autocomplete ${BASHINSTALLDIR}/skopeo
|
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")
|
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])
|
dest, err := parseImageDestination(context, context.Args()[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error initializing %s: %v", context.Args()[1], err)
|
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")
|
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()
|
manifest, _, err := src.Manifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error reading manifest: %v", err)
|
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()
|
blobDigests, err := src.BlobDigests()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error parsing manifest: %v", err)
|
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 != "" {
|
if signBy != "" {
|
||||||
mech, err := signature.NewGPGSigningMechanism()
|
mech, err := signature.NewGPGSigningMechanism()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/containers/image/signature"
|
||||||
"github.com/projectatomic/skopeo/version"
|
"github.com/projectatomic/skopeo/version"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@@ -50,6 +51,11 @@ func createApp() *cli.App {
|
|||||||
Name: "tls-verify",
|
Name: "tls-verify",
|
||||||
Usage: "verify certificates",
|
Usage: "verify certificates",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "policy",
|
||||||
|
Value: "",
|
||||||
|
Usage: "Path to a signature verification policy file",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
app.Before = func(c *cli.Context) error {
|
app.Before = func(c *cli.Context) error {
|
||||||
if c.GlobalBool("debug") {
|
if c.GlobalBool("debug") {
|
||||||
@@ -75,3 +81,19 @@ func main() {
|
|||||||
logrus.Fatal(err)
|
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
|
**--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
|
**--tls-verify** _bool-value_ Verify certificates
|
||||||
|
|
||||||
**--help**|**-h** Show help
|
**--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.
|
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
|
_source-image_ use the "image name" format described above
|
||||||
|
|
||||||
_destination-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
|
## skopeo help
|
||||||
show help for `skopeo`
|
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
|
# EXAMPLES
|
||||||
|
|
||||||
## skopeo copy
|
## skopeo copy
|
||||||
|
@@ -9,7 +9,7 @@ bundle_test_integration() {
|
|||||||
# subshell so that we can export PATH without breaking other things
|
# subshell so that we can export PATH without breaking other things
|
||||||
(
|
(
|
||||||
make binary-local
|
make binary-local
|
||||||
make install-binary
|
make install
|
||||||
export GO15VENDOREXPERIMENT=1
|
export GO15VENDOREXPERIMENT=1
|
||||||
bundle_test_integration
|
bundle_test_integration
|
||||||
) 2>&1
|
) 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"
|
"github.com/docker/docker/reference"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transport is an ImageTransport for Docker references.
|
// Transport is an ImageTransport for Docker registry-hosted images.
|
||||||
var Transport = dockerTransport{}
|
var Transport = dockerTransport{}
|
||||||
|
|
||||||
type dockerTransport struct{}
|
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"
|
"github.com/docker/docker/reference"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transport is an ImageTransport for Docker references.
|
// Transport is an ImageTransport for OCI directories.
|
||||||
var Transport = ociTransport{}
|
var Transport = ociTransport{}
|
||||||
|
|
||||||
type ociTransport struct{}
|
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"
|
"github.com/docker/docker/reference"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transport is an ImageTransport for directory paths.
|
// Transport is an ImageTransport for OpenShift registry-hosted images.
|
||||||
var Transport = openshiftTransport{}
|
var Transport = openshiftTransport{}
|
||||||
|
|
||||||
type openshiftTransport struct{}
|
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"
|
"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.
|
// InvalidPolicyFormatError is returned when parsing an invalid policy configuration.
|
||||||
type InvalidPolicyFormatError string
|
type InvalidPolicyFormatError string
|
||||||
|
|
||||||
@@ -33,6 +42,24 @@ func (err InvalidPolicyFormatError) Error() string {
|
|||||||
|
|
||||||
// FIXME: NewDefaultPolicy, from default file (or environment if trusted?)
|
// 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.
|
// NewPolicyFromFile returns a policy configured in the specified file.
|
||||||
func NewPolicyFromFile(fileName string) (*Policy, error) {
|
func NewPolicyFromFile(fileName string) (*Policy, error) {
|
||||||
contents, err := ioutil.ReadFile(fileName)
|
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
|
Os string
|
||||||
Layers []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>
|
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
Reference in New Issue
Block a user