Add credentials to buildah from
Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com> Add credentials to buildah from Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com> Closes: #204 Approved by: nalind
This commit is contained in:
parent
ee91e6b981
commit
498f0ae9d7
|
@ -5,6 +5,8 @@ go:
|
|||
- tip
|
||||
dist: trusty
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:duggan/bats
|
||||
- sudo apt-get -qq update
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
@ -122,6 +123,9 @@ type BuilderOptions struct {
|
|||
// ReportWriter is an io.Writer which will be used to log the reading
|
||||
// of the source image from a registry, if we end up pulling the image.
|
||||
ReportWriter io.Writer
|
||||
// github.com/containers/image/types SystemContext to hold credentials
|
||||
// and other authentication/authorization information.
|
||||
SystemContext *types.SystemContext
|
||||
}
|
||||
|
||||
// ImportOptions are used to initialize a Builder from an existing container
|
||||
|
|
|
@ -19,6 +19,11 @@ var (
|
|||
Name: "disable-compression, D",
|
||||
Usage: "don't compress layers",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Value: "",
|
||||
Usage: "use `username[:password]` for accessing the registry",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`pathname` of signature policy file (not usually used)",
|
||||
|
|
|
@ -2,9 +2,12 @@ package main
|
|||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
is "github.com/containers/image/storage"
|
||||
"github.com/containers/image/types"
|
||||
"github.com/containers/storage"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -108,3 +111,50 @@ func getDateAndDigestAndSize(image storage.Image, store storage.Store) (time.Tim
|
|||
}
|
||||
return created, manifestDigest, imgSize, err
|
||||
}
|
||||
|
||||
// systemContextFromOptions returns a SystemContext populated with values
|
||||
// per the input parameters provided by the caller for the use in authentication.
|
||||
func systemContextFromOptions(c *cli.Context) (*types.SystemContext, error) {
|
||||
ctx := &types.SystemContext{
|
||||
DockerCertPath: c.String("cert-dir"),
|
||||
}
|
||||
if c.IsSet("tls-verify") {
|
||||
ctx.DockerInsecureSkipTLSVerify = !c.BoolT("tls-verify")
|
||||
}
|
||||
if c.IsSet("creds") {
|
||||
var err error
|
||||
ctx.DockerAuthConfig, err = getDockerAuth(c.String("creds"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if c.IsSet("signature-policy") {
|
||||
ctx.SignaturePolicyPath = c.String("signature-policy")
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func parseCreds(creds string) (string, string, error) {
|
||||
if creds == "" {
|
||||
return "", "", errors.Wrapf(syscall.EINVAL, "credentials can't be empty")
|
||||
}
|
||||
up := strings.SplitN(creds, ":", 2)
|
||||
if len(up) == 1 {
|
||||
return up[0], "", nil
|
||||
}
|
||||
if up[0] == "" {
|
||||
return "", "", errors.Wrapf(syscall.EINVAL, "username can't be empty")
|
||||
}
|
||||
return up[0], up[1], nil
|
||||
}
|
||||
|
||||
func getDockerAuth(creds string) (*types.DockerAuthConfig, error) {
|
||||
username, password, err := parseCreds(creds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.DockerAuthConfig{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -35,6 +35,20 @@ var (
|
|||
Usage: "`prefix` to prepend to the image name in order to pull the image",
|
||||
Value: DefaultTransport,
|
||||
},
|
||||
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.StringFlag{
|
||||
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)",
|
||||
|
@ -65,12 +79,18 @@ func fromCmd(c *cli.Context) error {
|
|||
if len(args) > 1 {
|
||||
return errors.Errorf("too many arguments specified")
|
||||
}
|
||||
image := args[0]
|
||||
|
||||
image := args[0]
|
||||
transport := DefaultTransport
|
||||
if c.IsSet("transport") {
|
||||
transport = c.String("transport")
|
||||
}
|
||||
|
||||
systemContext, err := systemContextFromOptions(c)
|
||||
if err != nil {
|
||||
return errors.Errorf("error building system context [%v]", err)
|
||||
}
|
||||
|
||||
pull := true
|
||||
if c.IsSet("pull") {
|
||||
pull = c.BoolT("pull")
|
||||
|
@ -113,6 +133,7 @@ func fromCmd(c *cli.Context) error {
|
|||
PullPolicy: pullPolicy,
|
||||
Transport: transport,
|
||||
SignaturePolicyPath: signaturePolicy,
|
||||
SystemContext: systemContext,
|
||||
}
|
||||
if !quiet {
|
||||
options.ReportWriter = os.Stderr
|
||||
|
|
|
@ -249,7 +249,8 @@ func (b *Builder) Commit(dest types.ImageReference, options CommitOptions) error
|
|||
}
|
||||
if exporting {
|
||||
// Copy everything.
|
||||
err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter))
|
||||
// TODO: add credsContext
|
||||
err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, nil))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error copying layers and metadata")
|
||||
}
|
||||
|
@ -321,7 +322,8 @@ func Push(image string, dest types.ImageReference, options PushOptions) error {
|
|||
return errors.Wrapf(err, "error recomputing layer digests and building metadata")
|
||||
}
|
||||
// Copy everything.
|
||||
err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter))
|
||||
// TODO: add credsContext
|
||||
err = cp.Image(policyContext, dest, src, getCopyOptions(options.ReportWriter, nil, nil))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error copying layers and metadata")
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ import (
|
|||
"github.com/containers/image/types"
|
||||
)
|
||||
|
||||
func getCopyOptions(reportWriter io.Writer) *cp.Options {
|
||||
func getCopyOptions(reportWriter io.Writer, sourceSystemContext *types.SystemContext, destinationSystemContext *types.SystemContext) *cp.Options {
|
||||
return &cp.Options{
|
||||
ReportWriter: reportWriter,
|
||||
ReportWriter: reportWriter,
|
||||
SourceCtx: sourceSystemContext,
|
||||
DestinationCtx: destinationSystemContext,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -618,9 +618,12 @@ return 1
|
|||
"
|
||||
|
||||
local options_with_args="
|
||||
--cert-dir
|
||||
--creds
|
||||
--name
|
||||
--transport
|
||||
--signature-policy
|
||||
--tls-verify
|
||||
"
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,14 @@ The container ID of the container that was created. On error, -1 is returned an
|
|||
|
||||
## OPTIONS
|
||||
|
||||
**--cert-dir** *path*
|
||||
|
||||
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.
|
||||
|
||||
**--name** *name*
|
||||
|
||||
A *name* for the working container
|
||||
|
@ -41,6 +49,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**
|
||||
|
||||
If an image needs to be pulled from the registry, suppress progress output.
|
||||
|
@ -55,5 +67,7 @@ buildah from imagename --signature-policy /etc/containers/policy.json
|
|||
|
||||
buildah from imagename --pull-always --transport "docker://myregistry.example.com/" --name "mycontainer"
|
||||
|
||||
buildah from myregistry/myrepository/imagename:imagetag --creds=myusername:mypassword
|
||||
|
||||
## SEE ALSO
|
||||
buildah(1)
|
||||
|
|
2
pull.go
2
pull.go
|
@ -109,6 +109,6 @@ func pullImage(store storage.Store, options BuilderOptions, sc *types.SystemCont
|
|||
|
||||
logrus.Debugf("copying %q to %q", spec, name)
|
||||
|
||||
err = cp.Image(policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter))
|
||||
err = cp.Image(policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, options.SystemContext, nil))
|
||||
return destRef, err
|
||||
}
|
||||
|
|
|
@ -34,3 +34,81 @@ load helpers
|
|||
buildah rmi ${elsewhere}
|
||||
[ "$cid" = `basename ${elsewhere}`-working-container ]
|
||||
}
|
||||
|
||||
@test "from-authenticate-cert" {
|
||||
|
||||
mkdir -p ${TESTDIR}/auth
|
||||
# Create certifcate via openssl
|
||||
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ${TESTDIR}/auth/domain.key -x509 -days 2 -out ${TESTDIR}/auth/domain.crt -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
|
||||
# Skopeo and buildah both require *.cert file
|
||||
cp ${TESTDIR}/auth/domain.crt ${TESTDIR}/auth/domain.cert
|
||||
|
||||
# Create a private registry that uses certificate and creds file
|
||||
# docker run -d -p 5000:5000 --name registry -v ${TESTDIR}/auth:${TESTDIR}/auth:Z -e REGISTRY_HTTP_TLS_CERTIFICATE=${TESTDIR}/auth/domain.crt -e REGISTRY_HTTP_TLS_KEY=${TESTDIR}/auth/domain.key registry:2
|
||||
|
||||
# When more buildah auth is in place convert the below.
|
||||
# docker pull alpine
|
||||
# docker tag alpine localhost:5000/my-alpine
|
||||
# docker push localhost:5000/my-alpine
|
||||
|
||||
# ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth)
|
||||
# buildah rm $ctrid
|
||||
# buildah rmi -f $(buildah --debug=false images -q)
|
||||
|
||||
# This should work
|
||||
# ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth --tls-verify true)
|
||||
|
||||
rm -rf ${TESTDIR}/auth
|
||||
|
||||
# This should fail
|
||||
run ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth --tls-verify true)
|
||||
[ "$status" -ne 0 ]
|
||||
|
||||
# Clean up
|
||||
# docker rm -f $(docker ps --all -q)
|
||||
# docker rmi -f localhost:5000/my-alpine
|
||||
# docker rmi -f $(docker images -q)
|
||||
# buildah rm $ctrid
|
||||
# buildah rmi -f $(buildah --debug=false images -q)
|
||||
}
|
||||
|
||||
@test "from-authenticate-cert-and-creds" {
|
||||
|
||||
mkdir -p ${TESTDIR}/auth
|
||||
# Create creds and store in ${TESTDIR}/auth/htpasswd
|
||||
# docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > ${TESTDIR}/auth/htpasswd
|
||||
# Create certifcate via openssl
|
||||
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ${TESTDIR}/auth/domain.key -x509 -days 2 -out ${TESTDIR}/auth/domain.crt -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
|
||||
# Skopeo and buildah both require *.cert file
|
||||
cp ${TESTDIR}/auth/domain.crt ${TESTDIR}/auth/domain.cert
|
||||
|
||||
# Create a private registry that uses certificate and creds file
|
||||
# docker run -d -p 5000:5000 --name registry -v ${TESTDIR}/auth:${TESTDIR}/auth:Z -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=${TESTDIR}/auth/htpasswd -e REGISTRY_HTTP_TLS_CERTIFICATE=${TESTDIR}/auth/domain.crt -e REGISTRY_HTTP_TLS_KEY=${TESTDIR}/auth/domain.key registry:2
|
||||
|
||||
# When more buildah auth is in place convert the below.
|
||||
# docker pull alpine
|
||||
# docker login localhost:5000 --username testuser --password testpassword
|
||||
# docker tag alpine localhost:5000/my-alpine
|
||||
# docker push localhost:5000/my-alpine
|
||||
|
||||
# ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth)
|
||||
# buildah rm $ctrid
|
||||
# buildah rmi -f $(buildah --debug=false images -q)
|
||||
|
||||
# docker logout localhost:5000
|
||||
|
||||
# This should fail
|
||||
run ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth --tls-verify true)
|
||||
[ "$status" -ne 0 ]
|
||||
|
||||
# This should work
|
||||
# ctrid=$(buildah from localhost:5000/my-alpine --cert-dir ${TESTDIR}/auth --tls-verify true --creds=testuser:testpassword)
|
||||
|
||||
# Clean up
|
||||
rm -rf ${TESTDIR}/auth
|
||||
# docker rm -f $(docker ps --all -q)
|
||||
# docker rmi -f localhost:5000/my-alpine
|
||||
# docker rmi -f $(docker images -q)
|
||||
# buildah rm $ctrid
|
||||
# buildah rmi -f $(buildah --debug=false images -q)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue