mirror of
https://github.com/containers/buildah.git
synced 2025-07-31 15:24:26 +03:00
Implement commit for encryption
Signed-off-by: Brandon Lum <lumjjb@gmail.com>
This commit is contained in:
@ -35,6 +35,8 @@ type commitInputOptions struct {
|
|||||||
signBy string
|
signBy string
|
||||||
squash bool
|
squash bool
|
||||||
tlsVerify bool
|
tlsVerify bool
|
||||||
|
encryptionKeys []string
|
||||||
|
encryptLayers []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -59,6 +61,8 @@ func init() {
|
|||||||
|
|
||||||
flags.StringVar(&opts.authfile, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
flags.StringVar(&opts.authfile, "authfile", auth.GetDefaultAuthFile(), "path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
|
||||||
flags.StringVar(&opts.blobCache, "blob-cache", "", "assume image blobs in the specified directory will be available for pushing")
|
flags.StringVar(&opts.blobCache, "blob-cache", "", "assume image blobs in the specified directory will be available for pushing")
|
||||||
|
flags.StringSliceVar(&opts.encryptionKeys, "encryption-key", nil, "key with the encryption protocol to use needed to encrypt the image (e.g. jwe:/path/to/key.pem)")
|
||||||
|
flags.IntSliceVar(&opts.encryptLayers, "encrypt-layer", nil, "layers to encrypt, 0-indexed layer indices with support for negative indexing (e.g. 0 is the first layer, -1 is the last layer). If not defined, will encrypt all layers if encryption-key flag is specified")
|
||||||
|
|
||||||
if err := flags.MarkHidden("blob-cache"); err != nil {
|
if err := flags.MarkHidden("blob-cache"); err != nil {
|
||||||
panic(fmt.Sprintf("error marking blob-cache as hidden: %v", err))
|
panic(fmt.Sprintf("error marking blob-cache as hidden: %v", err))
|
||||||
@ -168,6 +172,11 @@ func commitCmd(c *cobra.Command, args []string, iopts commitInputOptions) error
|
|||||||
// Add builder identity information.
|
// Add builder identity information.
|
||||||
builder.SetLabel(buildah.BuilderIdentityAnnotation, buildah.Version)
|
builder.SetLabel(buildah.BuilderIdentityAnnotation, buildah.Version)
|
||||||
|
|
||||||
|
encConfig, encLayers, err := getEncryptConfig(iopts.encryptionKeys, iopts.encryptLayers)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "unable to obtain encryption config")
|
||||||
|
}
|
||||||
|
|
||||||
options := buildah.CommitOptions{
|
options := buildah.CommitOptions{
|
||||||
PreferredManifestType: format,
|
PreferredManifestType: format,
|
||||||
Compression: compress,
|
Compression: compress,
|
||||||
@ -179,6 +188,8 @@ func commitCmd(c *cobra.Command, args []string, iopts commitInputOptions) error
|
|||||||
BlobDirectory: iopts.blobCache,
|
BlobDirectory: iopts.blobCache,
|
||||||
OmitTimestamp: iopts.omitTimestamp,
|
OmitTimestamp: iopts.omitTimestamp,
|
||||||
SignBy: iopts.signBy,
|
SignBy: iopts.signBy,
|
||||||
|
OciEncryptConfig: encConfig,
|
||||||
|
OciEncryptLayers: encLayers,
|
||||||
}
|
}
|
||||||
if !iopts.quiet {
|
if !iopts.quiet {
|
||||||
options.ReportWriter = os.Stderr
|
options.ReportWriter = os.Stderr
|
||||||
|
17
commit.go
17
commit.go
@ -89,6 +89,17 @@ type CommitOptions struct {
|
|||||||
// RetryDelay is how long to wait before retrying a commit attempt to a
|
// RetryDelay is how long to wait before retrying a commit attempt to a
|
||||||
// registry.
|
// registry.
|
||||||
RetryDelay time.Duration
|
RetryDelay time.Duration
|
||||||
|
// OciEncryptConfig when non-nil indicates that an image should be encrypted.
|
||||||
|
// The encryption options is derived from the construction of EncryptConfig object.
|
||||||
|
// Note: During initial encryption process of a layer, the resultant digest is not known
|
||||||
|
// during creation, so newDigestingReader has to be set with validateDigest = false
|
||||||
|
OciEncryptConfig *encconfig.EncryptConfig
|
||||||
|
// OciEncryptLayers represents the list of layers to encrypt.
|
||||||
|
// If nil, don't encrypt any layers.
|
||||||
|
// If non-nil and len==0, denotes encrypt all layers.
|
||||||
|
// integers in the slice represent 0-indexed layer indices, with support for negative
|
||||||
|
// indexing. i.e. 0 is the first layer, -1 is the last (top-most) layer.
|
||||||
|
OciEncryptLayers *[]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushOptions can be used to alter how an image is copied somewhere.
|
// PushOptions can be used to alter how an image is copied somewhere.
|
||||||
@ -284,7 +295,9 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
|||||||
// Check if the base image is already in the destination and it's some kind of local
|
// Check if the base image is already in the destination and it's some kind of local
|
||||||
// storage. If so, we can skip recompressing any layers that come from the base image.
|
// storage. If so, we can skip recompressing any layers that come from the base image.
|
||||||
exportBaseLayers := true
|
exportBaseLayers := true
|
||||||
if transport, destIsStorage := dest.Transport().(is.StoreTransport); destIsStorage && b.FromImageID != "" {
|
if transport, destIsStorage := dest.Transport().(is.StoreTransport); destIsStorage && options.OciEncryptConfig != nil {
|
||||||
|
return imgID, nil, "", errors.New("unable to use local storage with image encryption")
|
||||||
|
} else if destIsStorage && b.FromImageID != "" {
|
||||||
if baseref, err := transport.ParseReference(b.FromImageID); baseref != nil && err == nil {
|
if baseref, err := transport.ParseReference(b.FromImageID); baseref != nil && err == nil {
|
||||||
if img, err := transport.GetImage(baseref); img != nil && err == nil {
|
if img, err := transport.GetImage(baseref); img != nil && err == nil {
|
||||||
logrus.Debugf("base image %q is already present in local storage, no need to copy its layers", b.FromImageID)
|
logrus.Debugf("base image %q is already present in local storage, no need to copy its layers", b.FromImageID)
|
||||||
@ -333,7 +346,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options
|
|||||||
}
|
}
|
||||||
|
|
||||||
var manifestBytes []byte
|
var manifestBytes []byte
|
||||||
if manifestBytes, err = retryCopyImage(ctx, policyContext, maybeCachedDest, maybeCachedSrc, dest, "push", getCopyOptions(b.store, options.ReportWriter, nil, systemContext, "", false, options.SignBy, nil, nil, nil), options.MaxRetries, options.RetryDelay); err != nil {
|
if manifestBytes, err = retryCopyImage(ctx, policyContext, maybeCachedDest, maybeCachedSrc, dest, "push", getCopyOptions(b.store, options.ReportWriter, nil, systemContext, "", false, options.SignBy, options.OciEncryptLayers, options.OciEncryptConfig, nil), options.MaxRetries, options.RetryDelay); err != nil {
|
||||||
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
|
return imgID, nil, "", errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID)
|
||||||
}
|
}
|
||||||
// If we've got more names to attach, and we know how to do that for
|
// If we've got more names to attach, and we know how to do that for
|
||||||
|
@ -174,3 +174,29 @@ load helpers
|
|||||||
run_buildah commit --signature-policy ${TESTSDIR}/policy.json --tls-verify=false --creds testuser:testpassword busyboxc docker://localhost:5000/commit/busybox
|
run_buildah commit --signature-policy ${TESTSDIR}/policy.json --tls-verify=false --creds testuser:testpassword busyboxc docker://localhost:5000/commit/busybox
|
||||||
run_buildah from --signature-policy ${TESTSDIR}/policy.json --name fromdocker --tls-verify=false --creds testuser:testpassword docker://localhost:5000/commit/busybox
|
run_buildah from --signature-policy ${TESTSDIR}/policy.json --name fromdocker --tls-verify=false --creds testuser:testpassword docker://localhost:5000/commit/busybox
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "commit encrypted local oci image" {
|
||||||
|
_prefetch busybox
|
||||||
|
mkdir ${TESTDIR}/tmp
|
||||||
|
openssl genrsa -out ${TESTDIR}/tmp/mykey.pem 1024
|
||||||
|
openssl rsa -in ${TESTDIR}/tmp/mykey.pem -pubout > ${TESTDIR}/tmp/mykey.pub
|
||||||
|
run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json busybox
|
||||||
|
cid=$output
|
||||||
|
run_buildah commit --iidfile /dev/null --signature-policy ${TESTSDIR}/policy.json --encryption-key jwe:${TESTDIR}/tmp/mykey.pub -q $cid oci:${TESTDIR}/tmp/busybox_enc
|
||||||
|
imgtype -show-manifest oci:${TESTDIR}/tmp/busybox_enc | grep "+encrypted"
|
||||||
|
rm -rf ${TESTDIR}/tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@test "commit oci encrypt to registry" {
|
||||||
|
_prefetch busybox
|
||||||
|
mkdir ${TESTDIR}/tmp
|
||||||
|
openssl genrsa -out ${TESTDIR}/tmp/mykey.pem 1024
|
||||||
|
openssl rsa -in ${TESTDIR}/tmp/mykey.pem -pubout > ${TESTDIR}/tmp/mykey.pub
|
||||||
|
run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json busybox
|
||||||
|
cid=$output
|
||||||
|
run_buildah commit --iidfile /dev/null --tls-verify=false --creds testuser:testpassword --signature-policy ${TESTSDIR}/policy.json --encryption-key jwe:${TESTDIR}/tmp/mykey.pub -q $cid docker://localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
# this test, just checks the ability to commit an image to a registry
|
||||||
|
# there is no good way to test the details of the image unless with ./buildah pull, test will be in pull.bats
|
||||||
|
rm -rf ${TESTDIR}/tmp
|
||||||
|
}
|
||||||
|
@ -204,3 +204,23 @@ load helpers
|
|||||||
|
|
||||||
rm -rf ${TESTDIR}/tmp
|
rm -rf ${TESTDIR}/tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "pull encrypted registry image from commit" {
|
||||||
|
_prefetch busybox
|
||||||
|
mkdir ${TESTDIR}/tmp
|
||||||
|
openssl genrsa -out ${TESTDIR}/tmp/mykey.pem 1024
|
||||||
|
openssl rsa -in ${TESTDIR}/tmp/mykey.pem -pubout > ${TESTDIR}/tmp/mykey.pub
|
||||||
|
run_buildah from --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json busybox
|
||||||
|
cid=$output
|
||||||
|
run_buildah commit --iidfile /dev/null --tls-verify=false --creds testuser:testpassword --signature-policy ${TESTSDIR}/policy.json --encryption-key jwe:${TESTDIR}/tmp/mykey.pub -q $cid docker://localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
|
||||||
|
# Try to pull encrypted image without key should fail
|
||||||
|
run_buildah 1 pull --signature-policy ${TESTSDIR}/policy.json --tls-verify=false --creds testuser:testpassword docker://localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
# Try to pull encrypted image with wrong key should fail
|
||||||
|
run_buildah 1 pull --signature-policy ${TESTSDIR}/policy.json --tls-verify=false --creds testuser:testpassword --decryption-key ${TESTDIR}/tmp/mykey2.pem docker://localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
# Providing the right key should succeed
|
||||||
|
run_buildah pull --signature-policy ${TESTSDIR}/policy.json --tls-verify=false --creds testuser:testpassword --decryption-key ${TESTDIR}/tmp/mykey.pem docker://localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
run_buildah rmi localhost:5000/buildah/busybox_encrypted:latest
|
||||||
|
|
||||||
|
rm -rf ${TESTDIR}/tmp
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user