diff --git a/cmd/buildah/commit.go b/cmd/buildah/commit.go index 811aeec76..7108f15a8 100644 --- a/cmd/buildah/commit.go +++ b/cmd/buildah/commit.go @@ -19,11 +19,20 @@ var ( Name: "disable-compression, D", Usage: "don't compress layers", }, + cli.StringFlag{ + Name: "cert-dir", + Value: "", + Usage: "use certificates at the specified path to access the registry", + }, cli.StringFlag{ Name: "creds", Value: "", Usage: "use `username[:password]` for accessing the registry", }, + cli.BoolTFlag{ + Name: "tls-verify", + Usage: "Require HTTPS and verify certificates when accessing the registry", + }, cli.StringFlag{ Name: "signature-policy", Usage: "`pathname` of signature policy file (not usually used)", @@ -123,11 +132,17 @@ func commitCmd(c *cli.Context) error { dest = dest2 } + systemContext, err := systemContextFromOptions(c) + if err != nil { + return errors.Wrapf(err, "error building system context") + } + options := buildah.CommitOptions{ PreferredManifestType: format, Compression: compress, SignaturePolicyPath: signaturePolicy, HistoryTimestamp: ×tamp, + SystemContext: systemContext, } if !quiet { options.ReportWriter = os.Stderr diff --git a/cmd/buildah/from.go b/cmd/buildah/from.go index c98f5aca5..89d34027b 100644 --- a/cmd/buildah/from.go +++ b/cmd/buildah/from.go @@ -33,7 +33,7 @@ var ( Value: "", Usage: "use `username[:password]` for accessing the registry", }, - cli.StringFlag{ + cli.BoolTFlag{ Name: "tls-verify", Usage: "Require HTTPS and verify certificates when accessing the registry", }, @@ -72,7 +72,7 @@ func fromCmd(c *cli.Context) error { systemContext, err := systemContextFromOptions(c) if err != nil { - return errors.Errorf("error building system context [%v]", err) + return errors.Wrapf(err, "error building system context") } pull := true diff --git a/cmd/buildah/push.go b/cmd/buildah/push.go index 09f46d4ce..e61a0ed94 100644 --- a/cmd/buildah/push.go +++ b/cmd/buildah/push.go @@ -19,6 +19,20 @@ var ( Name: "disable-compression, D", Usage: "don't compress layers", }, + cli.StringFlag{ + Name: "cert-dir", + Value: "", + Usage: "use certificates at the specified path to access the registry", + }, + cli.StringFlag{ + Name: "creds", + Value: "", + Usage: "use `username[:password]` for accessing the registry", + }, + cli.BoolTFlag{ + Name: "tls-verify", + Usage: "Require HTTPS and verify certificates when accessing the registry", + }, cli.StringFlag{ Name: "signature-policy", Usage: "`pathname` of signature policy file (not usually used)", @@ -79,10 +93,16 @@ func pushCmd(c *cli.Context) error { return err } + systemContext, err := systemContextFromOptions(c) + if err != nil { + return errors.Wrapf(err, "error building system context") + } + options := buildah.PushOptions{ Compression: compress, SignaturePolicyPath: signaturePolicy, Store: store, + SystemContext: systemContext, } if !quiet { options.ReportWriter = os.Stderr diff --git a/commit.go b/commit.go index eba09664a..ee8e4a4be 100644 --- a/commit.go +++ b/commit.go @@ -54,6 +54,9 @@ type CommitOptions struct { // HistoryTimestamp is the timestamp used when creating new items in the // image's history. If unset, the current time will be used. HistoryTimestamp *time.Time + // github.com/containers/image/types SystemContext to hold credentials + // and other authentication/authorization information. + SystemContext *types.SystemContext } // PushOptions can be used to alter how an image is copied somewhere. @@ -73,6 +76,9 @@ type PushOptions struct { ReportWriter io.Writer // Store is the local storage store which holds the source image. Store storage.Store + // github.com/containers/image/types SystemContext to hold credentials + // and other authentication/authorization information. + SystemContext *types.SystemContext } // shallowCopy copies the most recent layer, the configuration, and the manifest from one image to another. @@ -249,8 +255,7 @@ func (b *Builder) Commit(dest types.ImageReference, options CommitOptions) error } if exporting { // Copy everything. - // TODO: add credsContext - err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, nil)) + err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, options.SystemContext)) if err != nil { return errors.Wrapf(err, "error copying layers and metadata") } @@ -322,8 +327,7 @@ func Push(image string, dest types.ImageReference, options PushOptions) error { return errors.Wrapf(err, "error recomputing layer digests and building metadata") } // Copy everything. - // TODO: add credsContext - err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, nil)) + err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, options.SystemContext)) if err != nil { return errors.Wrapf(err, "error copying layers and metadata") } diff --git a/contrib/completions/bash/buildah b/contrib/completions/bash/buildah index aafa93c93..9134486f9 100644 --- a/contrib/completions/bash/buildah +++ b/contrib/completions/bash/buildah @@ -291,9 +291,12 @@ return 1 --quiet -q --rm + --tls-verify " local options_with_args=" + --cert-dir + --creds --signature-policy --format -f @@ -471,9 +474,12 @@ return 1 -D --quiet -q + --tls-verify " local options_with_args=" + --cert-dir + --creds --signature-policy " @@ -614,6 +620,7 @@ return 1 --pull-always --quiet -q + --tls-verify " local options_with_args=" @@ -621,7 +628,6 @@ return 1 --creds --name --signature-policy - --tls-verify " diff --git a/docs/buildah-commit.md b/docs/buildah-commit.md index 489215bba..0c45d9502 100644 --- a/docs/buildah-commit.md +++ b/docs/buildah-commit.md @@ -13,6 +13,14 @@ specified, an ID is assigned, but no name is assigned to the image. ## OPTIONS +**--cert-dir** *path* + +Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry + +**--creds** *creds* + +The username[:password] to use to authenticate with the registry if required. + **--disable-compression, -D** Don't compress filesystem layers when building the image. @@ -23,6 +31,10 @@ Pathname of a signature policy file to use. It is not recommended that this option be used, as the default behavior of using the system-wide default policy (frequently */etc/containers/policy.json*) is most often preferred. +**--tls-verify** *bool-value* + +Require HTTPS and verify certificates when talking to container registries (defaults to true) + **--quiet** When writing the output image, suppress progress output. @@ -39,13 +51,24 @@ Default leaves the container and its content in place. ## EXAMPLE -buildah commit containerID +This example saves an image based on the container. + `buildah commit containerID` -buildah commit --rm containerID newImageName +This example saves an image named newImageName based on the container. + `buildah commit --rm containerID newImageName` -buildah commit --disable-compression --signature-policy '/etc/containers/policy.json' containerID -buildah commit --disable-compression --signature-policy '/etc/containers/policy.json' containerID newImageName +This example saves an image based on the container disabling compression. + `buildah commit --disable-compression containerID` + +This example saves an image named newImageName based on the container disabling compression. + `buildah commit --disable-compression containerID newImageName` + +This example commits the container to the image on the local registry while turning off tls verification. + `buildah commit --tls-verify=false containerID docker://localhost:5000/imageId` + +This example commits the container to the image on the local registry using credentials and certificates for authentication. + `buildah commit --cert-dir ~/auth --tls-verify=true --creds=username:password containerID docker://localhost:5000/imageId` ## SEE ALSO buildah(1) diff --git a/docs/buildah-from.md b/docs/buildah-from.md index 591a31fb2..92eba1845 100644 --- a/docs/buildah-from.md +++ b/docs/buildah-from.md @@ -42,7 +42,7 @@ Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry **--creds** *creds* -The username and password to use to authenticate with the registry if required. +The username[:password] to use to authenticate with the registry if required. **--name** *name* @@ -82,7 +82,9 @@ buildah from imagename --signature-policy /etc/containers/policy.json buildah from docker://myregistry.example.com/imagename --pull-always --name "mycontainer" -buildah from myregistry/myrepository/imagename:imagetag --creds=myusername:mypassword +buildah from myregistry/myrepository/imagename:imagetag --tls-verify=false + +buildah from myregistry/myrepository/imagename:imagetag --creds=myusername:mypassword --cert-dir ~/auth ## SEE ALSO buildah(1) diff --git a/docs/buildah-push.md b/docs/buildah-push.md index ca2e6393f..43c02905a 100644 --- a/docs/buildah-push.md +++ b/docs/buildah-push.md @@ -40,6 +40,14 @@ Image stored in local container/storage ## OPTIONS +**--cert-dir** *path* + +Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry + +**--creds** *creds* + +The username[:password] to use to authenticate with the registry if required. + **--disable-compression, -D** Don't compress copies of filesystem layers which will be pushed. @@ -50,6 +58,10 @@ Pathname of a signature policy file to use. It is not recommended that this option be used, as the default behavior of using the system-wide default policy (frequently */etc/containers/policy.json*) is most often preferred. +**--tls-verify** *bool-value* + +Require HTTPS and verify certificates when talking to container registries (defaults to true) + **--quiet** When writing the output image, suppress progress output. @@ -64,13 +76,19 @@ This example extracts the imageID image to a local directory in oci format. `# buildah push imageID oci:/path/to/layout` -This example extracts the imageID image to a container registry named registry.example.com +This example extracts the imageID image to a container registry named registry.example.com. `# buildah push imageID docker://registry.example.com/repository:tag` -This example extracts the imageID image and puts into the local docker container store +This example extracts the imageID image and puts into the local docker container store. `# buildah push imageID docker-daemon:image:tag` +This example extracts the imageID image and puts it into the registry on the localhost while turning off tls verification. + `# buildah push --tls-verify=false imageID docker://localhost:5000/my-imageID` + +This example extracts the imageID image and puts it into the registry on the localhost using credentials and certificates for authentication. + `# buildah push --cert-dir ~/auth --tls-verify=true --creds=username:password imageID docker://localhost:5000/my-imageID` + ## SEE ALSO buildah(1) diff --git a/tests/test_buildah_authentication.sh b/tests/test_buildah_authentication.sh new file mode 100644 index 000000000..e0d07273c --- /dev/null +++ b/tests/test_buildah_authentication.sh @@ -0,0 +1,180 @@ +#!/bin/bash +# test_buildah_authentication +# A script to be run at the command line with Buildah installed. +# This will test the code and should be run with this command: +# +# /bin/bash -v test_buildah_authentication.sh + +######## +# Create creds and store in /root/auth/htpasswd +######## +docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > /root/auth/htpasswd + +######## +# Create certificate via openssl +######## +openssl req -newkey rsa:4096 -nodes -sha256 -keyout /root/auth/domain.key -x509 -days 2 -out /root/auth/domain.crt -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost" + +######## +# Skopeo and buildah both require *.cert file +######## +cp /root/auth/domain.crt /root/auth/domain.cert + +######## +# Create a private registry that uses certificate and creds file +######## +docker run -d -p 5000:5000 --name registry -v /root/auth:/root/auth:Z -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/root/auth/htpasswd -e REGISTRY_HTTP_TLS_CERTIFICATE=/root/auth/domain.crt -e REGISTRY_HTTP_TLS_KEY=/root/auth/domain.key registry:2 + +######## +# Pull alpine +######## +buildah from alpine + +buildah containers + +buildah images + +######## +# Log into docker on local repo +######## +docker login localhost:5000 --username testuser --password testpassword + +######## +# Push to the local repo using cached Docker creds. +######## +buildah push --cert-dir /root/auth alpine docker://localhost:5000/my-alpine + +######## +# Show stuff +######## +docker ps --all + +docker images + +buildah containers + +buildah images + +######## +# Buildah pulls using certs and cached Docker creds. +# Should show two alpine images and containers when done. +######## +ctrid=$(buildah from localhost:5000/my-alpine --cert-dir /root/auth) + +buildah containers + +buildah images + +######## +# Clean up Buildah +######## +buildah rm $ctrid +buildah rmi -f localhost:5000/my-alpine:latest + +######## +# Show stuff +######## +docker ps --all + +docker images + +buildah containers + +buildah images + +######## +# Log out of local repo +######## +docker logout localhost:5000 + +######## +# Push using only certs, this should fail. +######## +buildah push --cert-dir /root/auth --tls-verify=true alpine docker://localhost:5000/my-alpine + +######## +# Push using creds and certs, this should work. +######## +buildah push --cert-dir ~/auth --tls-verify=true --creds=testuser:testpassword alpine docker://localhost:5000/my-alpine + +######## +# This should fail, no creds anywhere, only the certificate +######## +buildah from localhost:5000/my-alpine --cert-dir /root/auth --tls-verify=true + +######## +# Log in with creds, this should work +######## +ctrid=$(buildah from localhost:5000/my-alpine --cert-dir /root/auth --tls-verify=true --creds=testuser:testpassword) + +######## +# Show stuff +######## +docker ps --all + +docker images + +buildah containers + +buildah images + +######## +# Clean up Buildah +######## +buildah rm $ctrid +buildah rmi -f $(buildah --debug=false images -q) + +######## +# Pull alpine +######## +buildah from alpine + +######## +# Show stuff +######## +docker ps --all + +docker images + +buildah containers + +buildah images + +######## +# Let's test commit +######## + +######## +# No credentials, this should fail. +######## +buildah commit --cert-dir /root/auth --tls-verify=true alpine-working-container docker://localhost:5000/my-commit-alpine + +######## +# This should work, writing image in registry. Will not create an image locally. +######## +buildah commit --cert-dir /root/auth --tls-verify=true --creds=testuser:testpassword alpine-working-container docker://localhost:5000/my-commit-alpine + +######## +# Pull the new image that we just commited +######## +buildah from localhost:5000/my-commit-alpine --cert-dir /root/auth --tls-verify=true --creds=testuser:testpassword + +######## +# Show stuff +######## +docker ps --all + +docker images + +buildah containers + +buildah images + +######## +# Clean up +######## +rm -rf ${TESTDIR}/auth +docker rm -f $(docker ps --all -q) +docker rmi -f $(docker images -q) +buildah rm $(buildah containers -q) +buildah rmi -f $(buildah --debug=false images -q)