Skip to content

Commit

Permalink
Image encryption/decryption support in skopeo
Browse files Browse the repository at this point in the history
Signed-off-by: Harshal Patil <harshal.patil@in.ibm.com>
Signed-off-by: Brandon Lum <lumjjb@gmail.com>
  • Loading branch information
Harshal Patil committed Oct 1, 2019
1 parent fa6e580 commit 9a17dc6
Show file tree
Hide file tree
Showing 604 changed files with 84,402 additions and 9,431 deletions.
62 changes: 61 additions & 1 deletion cmd/skopeo/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/containers/image/manifest"
"github.com/containers/image/transports"
"github.com/containers/image/transports/alltransports"
encconfig "github.com/containers/ocicrypt/config"
enchelpers "github.com/containers/ocicrypt/helpers"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/urfave/cli"
)
Expand All @@ -24,7 +26,8 @@ type copyOptions struct {
signByFingerprint string // Sign the image using a GPG key with the specified fingerprint
format optionalString // Force conversion of the image to a specified format
quiet bool // Suppress output information when copying images

encryptionKeys string // Keys needed to encrypt the image
decryptionKeys string // Keys needed to decrypt the image
}

func copyCmd(global *globalOptions) cli.Command {
Expand Down Expand Up @@ -77,6 +80,16 @@ func copyCmd(global *globalOptions) cli.Command {
Usage: "`MANIFEST TYPE` (oci, v2s1, or v2s2) to use when saving image to directory using the 'dir:' transport (default is manifest type of source)",
Value: newOptionalStringValue(&opts.format),
},
cli.StringFlag{
Name: "encryption-keys",
Usage: "keys (comma separated) with the encryption protocol to use needed to encrypt the image (e.g. jwe:/path/to/key.pem)",
Destination: &opts.encryptionKeys,
},
cli.StringFlag{
Name: "decryption-keys",
Usage: "keys (comma separated) needed to decrypt the image",
Destination: &opts.decryptionKeys,
},
}, sharedFlags...), srcFlags...), destFlags...),
}
}
Expand Down Expand Up @@ -147,13 +160,60 @@ func (opts *copyOptions) run(args []string, stdout io.Writer) error {
if opts.quiet {
stdout = nil
}

var ccs []encconfig.CryptoConfig

if opts.encryptionKeys != "" {
// encryption
if opts.decryptionKeys != "" {
return fmt.Errorf("--encryption-keys and --decryption-keys cannot be specified together")
}
encryptionKeys := strings.Split(opts.encryptionKeys, ",")
ecc, err := enchelpers.CreateCryptoConfig(encryptionKeys, []string{})
if err != nil {
return err
}
ccs = append(ccs, ecc)
}

if opts.decryptionKeys != "" {
// decryption
if opts.encryptionKeys != "" {
return fmt.Errorf("--encryption-keys and --decryption-keys cannot be specified together")
}
decryptionKeys := strings.Split(opts.decryptionKeys, ",")
dcc, err := enchelpers.CreateCryptoConfig([]string{}, decryptionKeys)
if err != nil {
return err
}
ccs = append(ccs, dcc)
}

var encConfig *encconfig.EncryptConfig
var encLayers *[]int
if len(ccs) > 0 {
cc := encconfig.CombineCryptoConfigs(ccs)
if opts.decryptionKeys != "" {
sourceCtx.CryptoConfig = &cc
destinationCtx.CryptoConfig = nil
}

if opts.encryptionKeys != "" {
encLayers = &[]int{}
encConfig = cc.EncryptConfig
sourceCtx.CryptoConfig = nil
}
}

_, err = copy.Image(ctx, policyContext, destRef, srcRef, &copy.Options{
RemoveSignatures: opts.removeSignatures,
SignBy: opts.signByFingerprint,
ReportWriter: stdout,
SourceCtx: sourceCtx,
DestinationCtx: destinationCtx,
ForceManifestMIMEType: manifestType,
EncryptLayers: encLayers,
EncryptConfig: encConfig,
})
return err
}
3 changes: 2 additions & 1 deletion cmd/skopeo/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package main

import (
"context"
"errors"
"io"
"strings"

"github.com/containers/image/pkg/compression"
"github.com/containers/image/transports/alltransports"
"github.com/containers/image/types"
"github.com/pkg/errors"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -145,6 +145,7 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
return nil, err
}
}

if opts.noCreds {
ctx.DockerAuthConfig = &types.DockerAuthConfig{}
}
Expand Down
19 changes: 19 additions & 0 deletions docs/skopeo-copy.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec

**--sign-by=**_key-id_ add a signature using that key ID for an image name corresponding to _destination-image_

**--encryption-keys** _Keys_ a comma deli-metered list of key references prefixed with the encryption protocol to use. e.g. jwe:/path/to/key.pem or pgp:admin@example.com or pkcs7:/path/to/x509-file

**--decryption-keys** _Keys_ a comma deli-metered list of key references required to perform decryption of container images. this should point to files which represent keys and/or certificates that can be used for decryption. Decryption will be tried with all keys.

**--src-creds** _username[:password]_ for accessing the source registry

**--dest-compress** _bool-value_ Compress tarball image layers when saving to directory using the 'dir' transport. (default is same compression type as source)
Expand Down Expand Up @@ -80,6 +84,21 @@ To copy and sign an image:
$ skopeo copy --sign-by dev@example.com atomic:example/busybox:streaming atomic:example/busybox:gold
```

To encrypt an image:
```sh
./skopeo copy docker://docker.io/library/nginx:latest oci:local_nginx:latest

openssl genrsa -out private.key 1024
openssl rsa -in private.key -pubout > public.key

./skopeo copy --encryption-keys jwe:./public.key oci:local_nginx:latest oci:try-encrypt:enc
```

To decrypt an image:
```sh
./skopeo copy --decryption-keys ./private.key oci:try-encrypt:enc oci:try-decrypt:dec
```

## SEE ALSO
skopeo(1), podman-login(1), docker-login(1)

Expand Down
49 changes: 22 additions & 27 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,39 @@ module github.com/containers/skopeo
go 1.12

require (
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/containerd/continuity v0.0.0-20180216233310-d8fb8589b0e8 // indirect
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 // indirect
github.com/containers/buildah v1.8.4
github.com/containers/image v1.5.2-0.20190821161828-0cc0e97405db
github.com/containers/storage v1.13.0
github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65 // indirect
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741
github.com/containers/storage v1.13.4
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v0.0.0-20180522102801-da99009bbb11
github.com/docker/docker-credential-helpers v0.6.0 // indirect
github.com/docker/go-connections v0.0.0-20180212134524-7beb39f0b969 // indirect
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
github.com/etcd-io/bbolt v1.3.2 // indirect
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 // indirect
github.com/docker/docker-credential-helpers v0.6.3 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-check/check v0.0.0-20180628173108-788fd7840127
github.com/gogo/protobuf v0.0.0-20170815085658-fcdc5011193f // indirect
github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 // indirect
github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e // indirect
github.com/imdario/mergo v0.0.0-20141206190957-6633656539c1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c // indirect
github.com/gogo/protobuf v1.3.0 // indirect
github.com/gorilla/mux v1.7.3 // indirect
github.com/imdario/mergo v0.3.7 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/image-spec v1.0.0-rc6.0.20190823105129-775207bd45b6
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/image-tools v0.0.0-20170926011501-6d941547fa1d
github.com/opencontainers/runtime-spec v1.0.0 // indirect
github.com/pborman/uuid v0.0.0-20160209185913-a97ce2ca70fa // indirect
github.com/pkg/errors v0.8.1
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.3.0
github.com/stretchr/testify v1.4.0
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/ulikunitz/xz v0.5.4 // indirect
github.com/urfave/cli v1.20.0
github.com/vbauerster/mpb v3.4.0+incompatible // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/urfave/cli v1.22.1
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonschema v1.1.0 // indirect
go4.org v0.0.0-20190218023631-ce4c26f7be8e // indirect
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e // indirect
gopkg.in/yaml.v2 v2.0.0-20141029210843-d466437aa4ad // indirect
k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083 // indirect
)

replace github.com/containers/image => github.com/lumjjb/image v1.5.2-0.20191001141258-431a18503daf
Loading

0 comments on commit 9a17dc6

Please sign in to comment.