diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go index 6a04464225..07a1a0c03e 100644 --- a/cmd/podman/auto-update.go +++ b/cmd/podman/auto-update.go @@ -8,6 +8,7 @@ import ( "github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/report" + "github.com/containers/image/v5/types" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/pkg/domain/entities" @@ -17,7 +18,8 @@ import ( type cliAutoUpdateOptions struct { entities.AutoUpdateOptions - format string + format string + tlsVerify bool } var ( @@ -56,6 +58,8 @@ func init() { flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template") _ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(&autoUpdateOutput{})) + + flags.BoolVarP(&autoUpdateOptions.tlsVerify, "tls-verify", "", true, "Require HTTPS and verify certificates when contacting registries") } func autoUpdate(cmd *cobra.Command, args []string) error { @@ -64,6 +68,10 @@ func autoUpdate(cmd *cobra.Command, args []string) error { return fmt.Errorf("`%s` takes no arguments", cmd.CommandPath()) } + if cmd.Flags().Changed("tls-verify") { + autoUpdateOptions.InsecureSkipTLSVerify = types.NewOptionalBool(!autoUpdateOptions.tlsVerify) + } + allReports, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions.AutoUpdateOptions) if allReports == nil { return errorhandling.JoinErrors(failures) diff --git a/docs/source/markdown/options/tls-verify.md b/docs/source/markdown/options/tls-verify.md index d694bab26d..13c2a6e634 100644 --- a/docs/source/markdown/options/tls-verify.md +++ b/docs/source/markdown/options/tls-verify.md @@ -1,5 +1,5 @@ ####> This option file is used in: -####> podman build, container runlabel, create, kube play, login, manifest add, manifest create, manifest inspect, manifest push, pull, push, run, search +####> podman auto update, build, container runlabel, create, kube play, login, manifest add, manifest create, manifest inspect, manifest push, pull, push, run, search ####> If file is edited, make sure the changes ####> are applicable to all of those. #### **--tls-verify** diff --git a/docs/source/markdown/podman-auto-update.1.md.in b/docs/source/markdown/podman-auto-update.1.md.in index b44999496b..c615567ff9 100644 --- a/docs/source/markdown/podman-auto-update.1.md.in +++ b/docs/source/markdown/podman-auto-update.1.md.in @@ -79,6 +79,7 @@ Please note that detecting if a systemd unit has failed is best done by the cont For a container to send the READY message via SDNOTIFY it must be created with the `--sdnotify=container` option (see podman-run(1)). The application running inside the container can then execute `systemd-notify --ready` when ready or use the sdnotify bindings of the specific programming language (e.g., sd_notify(3)). +@@option tls-verify ## EXAMPLES Autoupdate with registry policy diff --git a/go.mod b/go.mod index 63b6b7374b..0e9dac5ef9 100644 --- a/go.mod +++ b/go.mod @@ -180,3 +180,5 @@ require ( ) replace github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc + +replace github.com/containers/common => github.com/containers/common v0.55.1-0.20230703090011-0ab70cf5664d diff --git a/go.sum b/go.sum index 99c59d9b66..c7c1accf84 100644 --- a/go.sum +++ b/go.sum @@ -241,8 +241,8 @@ github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= github.com/containers/buildah v1.31.0 h1:NgVtEyTsR7e/XLTSJElbInnGPjdDGNHqLKADPHzaUGg= github.com/containers/buildah v1.31.0/go.mod h1:tcgXcGhqw3kw49RapUS7tskEhxKLG4eVFJKA/QzgwNU= -github.com/containers/common v0.55.1 h1:sOlcIxEYXoR3OSHufew7CuSeOWr7a2jHGYw3r+xKA1k= -github.com/containers/common v0.55.1/go.mod h1:ZKPllYOZ2xj2rgWRdnHHVvWg6ru4BT28En8mO8DMMPk= +github.com/containers/common v0.55.1-0.20230703090011-0ab70cf5664d h1:qtrq0ZsAAd+lI9eYBpq/1Fz9cxE1D95AvoB6g4ES0wg= +github.com/containers/common v0.55.1-0.20230703090011-0ab70cf5664d/go.mod h1:c+q6NRSLy4pKMYzb7Hsu6NPy0LnIjH2CJnplR5w3Bk8= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.26.1 h1:8y3xq8GO/6y8FR+nAedHPsAFiAtOrab9qHTBpbqaX8g= diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go index 4f2a4a0770..dd8c7b80c6 100644 --- a/pkg/autoupdate/autoupdate.go +++ b/pkg/autoupdate/autoupdate.go @@ -282,7 +282,10 @@ func (t *task) registryUpdateAvailable(ctx context.Context) (bool, error) { if err != nil { return false, err } - options := &libimage.HasDifferentDigestOptions{AuthFilePath: t.authfile} + options := &libimage.HasDifferentDigestOptions{ + AuthFilePath: t.authfile, + InsecureSkipTLSVerify: t.auto.options.InsecureSkipTLSVerify, + } return t.image.HasDifferentDigest(ctx, remoteRef, options) } @@ -296,6 +299,7 @@ func (t *task) registryUpdate(ctx context.Context) error { pullOptions := &libimage.PullOptions{} pullOptions.AuthFilePath = t.authfile pullOptions.Writer = os.Stderr + pullOptions.InsecureSkipTLSVerify = t.auto.options.InsecureSkipTLSVerify if _, err := t.auto.runtime.LibimageRuntime().Pull(ctx, t.rawImageName, config.PullPolicyAlways, pullOptions); err != nil { return err } @@ -416,8 +420,14 @@ func (u *updater) assembleTasks(ctx context.Context) []error { continue } + // Use user-specified auth file (CLI or env variable) unless + // the container was created with the auth-file label. + authfile := u.options.Authfile + if fromContainer, ok := labels[define.AutoUpdateAuthfileLabel]; ok { + authfile = fromContainer + } t := task{ - authfile: labels[define.AutoUpdateAuthfileLabel], + authfile: authfile, auto: u, container: ctr, policy: policy, diff --git a/pkg/domain/entities/auto-update.go b/pkg/domain/entities/auto-update.go index 5ea2cdf150..195f27f84a 100644 --- a/pkg/domain/entities/auto-update.go +++ b/pkg/domain/entities/auto-update.go @@ -1,5 +1,7 @@ package entities +import "github.com/containers/image/v5/types" + // AutoUpdateOptions are the options for running auto-update. type AutoUpdateOptions struct { // Authfile to use when contacting registries. @@ -11,6 +13,9 @@ type AutoUpdateOptions struct { // If restarting the service with the new image failed, restart it // another time with the previous image. Rollback bool + // Allow contacting registries over HTTP, or HTTPS with failed TLS + // verification. Note that this does not affect other TLS connections. + InsecureSkipTLSVerify types.OptionalBool } // AutoUpdateReport contains the results from running auto-update. diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 7fef945299..be5b282c8d 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -4,6 +4,8 @@ # load helpers +load helpers.network +load helpers.registry load helpers.systemd SNAME_FILE=$BATS_TMPDIR/services @@ -47,6 +49,7 @@ function teardown() { # 4. Generate the service file from the container # 5. Remove the origin container # 6. Start the container from service +# 7. Use this fully-qualified image instead of 2) function generate_service() { local target_img_basename=$1 local autoupdate=$2 @@ -64,6 +67,9 @@ function generate_service() { # IMPORTANT: variable 'cname' is passed (out of scope) up to caller! cname=c_${autoupdate//\'/}_$(random_string) target_img="quay.io/libpod/$target_img_basename:latest" + if [[ -n "$7" ]]; then + target_img="$7" + fi if [[ -z "$noTag" ]]; then run_podman tag $IMAGE $target_img @@ -623,4 +629,62 @@ EOF systemctl daemon-reload } +@test "podman-auto-update --authfile" { + # Test the three supported ways of using authfiles with auto updates + # 1) Passed via --authfile CLI flag + # 2) Passed via the REGISTRY_AUTH_FILE env variable + # 3) Via a label at container creation where 1) and 2) will be ignored + + registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT} + image_on_local_registry=$registry/name:tag + authfile=$PODMAN_TMPDIR/authfile.json + + # First, start the registry and populate the authfile that we can use for the test. + start_registry + run_podman login --authfile=$authfile \ + --tls-verify=false \ + --username ${PODMAN_LOGIN_USER} \ + --password ${PODMAN_LOGIN_PASS} \ + $registry + + run_podman tag $IMAGE $image_on_local_registry + run_podman push --tls-verify=false --creds "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" $image_on_local_registry + + # Generate a systemd service with the "registry" auto-update policy running + # "top" inside the image we just pushed to the local registry. + generate_service "" registry top "" "" "" $image_on_local_registry + ctr=$cname + _wait_service_ready container-$ctr.service + + run_podman 125 auto-update + is "$output" \ + ".*Error: checking image updates for container .*: x509: .*" + + run_podman 125 auto-update --tls-verify=false + is "$output" \ + ".*Error: checking image updates for container .*: authentication required" + + # Test 1) + run_podman auto-update --authfile=$authfile --tls-verify=false --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" "container-$ctr.service,$image_on_local_registry,false,registry" "auto-update works with authfile" + + # Test 2) + REGISTRY_AUTH_FILE=$authfile run_podman auto-update --tls-verify=false --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" "container-$ctr.service,$image_on_local_registry,false,registry" "auto-update works with env var" + systemctl stop container-$ctr.service + run_podman rm -f -t0 --ignore $ctr + + # Create a container with the auth-file label + generate_service "" registry top "--label io.containers.autoupdate.authfile=$authfile" "" "" $image_on_local_registry + ctr=$cname + _wait_service_ready container-$ctr.service + + # Test 3) + # Also make sure that the label takes precedence over the CLI flag. + run_podman auto-update --authfile=/dev/null --tls-verify=false --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" "container-$ctr.service,$image_on_local_registry,false,registry" "auto-update works with authfile container label" + run_podman rm -f -t0 --ignore $ctr + run_podman rmi $image_on_local_registry +} + # vim: filetype=sh diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index da4ff8b7a4..e8e095afe8 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -806,6 +806,9 @@ type HasDifferentDigestOptions struct { // containers-auth.json(5) file to use when authenticating against // container registries. AuthFilePath string + // Allow contacting registries over HTTP, or HTTPS with failed TLS + // verification. Note that this does not affect other TLS connections. + InsecureSkipTLSVerify types.OptionalBool } // HasDifferentDigest returns true if the image specified by `remoteRef` has a @@ -831,8 +834,15 @@ func (i *Image) HasDifferentDigest(ctx context.Context, remoteRef types.ImageRef sys.VariantChoice = inspectInfo.Variant } - if options != nil && options.AuthFilePath != "" { - sys.AuthFilePath = options.AuthFilePath + if options != nil { + if options.AuthFilePath != "" { + sys.AuthFilePath = options.AuthFilePath + } + if options.InsecureSkipTLSVerify != types.OptionalBoolUndefined { + sys.DockerInsecureSkipTLSVerify = options.InsecureSkipTLSVerify + sys.OCIInsecureSkipTLSVerify = options.InsecureSkipTLSVerify == types.OptionalBoolTrue + sys.DockerDaemonInsecureSkipTLSVerify = options.InsecureSkipTLSVerify == types.OptionalBoolTrue + } } return i.hasDifferentDigestWithSystemContext(ctx, remoteRef, sys) diff --git a/vendor/github.com/containers/common/pkg/secrets/secrets.go b/vendor/github.com/containers/common/pkg/secrets/secrets.go index 61ab9be986..535d576593 100644 --- a/vendor/github.com/containers/common/pkg/secrets/secrets.go +++ b/vendor/github.com/containers/common/pkg/secrets/secrets.go @@ -217,9 +217,12 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti } if options.Replace { - err = driver.Delete(secr.ID) - if err != nil { - return "", fmt.Errorf("replacing secret %s: %w", name, err) + if err := driver.Delete(secr.ID); err != nil { + return "", fmt.Errorf("deleting secret %s: %w", secr.ID, err) + } + + if err := s.delete(secr.ID); err != nil { + return "", fmt.Errorf("deleting secret %s: %w", secr.ID, err) } } diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 9a370a898c..219aae7ae3 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.55.1" +const Version = "0.56.0-dev" diff --git a/vendor/modules.txt b/vendor/modules.txt index 552fe93549..26bb0c40ab 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -128,7 +128,7 @@ github.com/containers/buildah/pkg/rusage github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/util github.com/containers/buildah/util -# github.com/containers/common v0.55.1 +# github.com/containers/common v0.55.1 => github.com/containers/common v0.55.1-0.20230703090011-0ab70cf5664d ## explicit; go 1.18 github.com/containers/common/libimage github.com/containers/common/libimage/define @@ -1154,3 +1154,4 @@ gopkg.in/yaml.v3 ## explicit; go 1.12 sigs.k8s.io/yaml # github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20220617142545-8b9452f75cbc +# github.com/containers/common => github.com/containers/common v0.55.1-0.20230703090011-0ab70cf5664d