diff options
25 files changed, 57 insertions, 1377 deletions
diff --git a/Dockerfile.fedora b/Dockerfile.fedora index 0f82fdc5c..429597f4f 100644 --- a/Dockerfile.fedora +++ b/Dockerfile.fedora @@ -27,36 +27,24 @@ RUN dnf -y install btrfs-progs-devel \ xz \ slirp4netns \ container-selinux \ + containernetworking-plugins \ iptables && dnf clean all -# Install CNI plugins -ENV CNI_COMMIT 485be65581341430f9106a194a98f0f2412245fb -ENV -RUN set -x \ - && export GOPATH="$(mktemp -d)" GOCACHE="$(mktemp -d)" \ - && git clone https://github.com/containernetworking/plugins.git "$GOPATH/src/github.com/containernetworking/plugins" \ - && cd "$GOPATH/src/github.com/containernetworking/plugins" \ - && git checkout -q "$CNI_COMMIT" \ - && ./build_linux.sh \ - && mkdir -p /usr/libexec/cni \ - && cp bin/* /usr/libexec/cni \ - && rm -rf "$GOPATH" - # Install ginkgo RUN set -x \ - && export GOPATH=/go \ + && export GOPATH=/go GOCACHE="$(mktemp -d)" \ && go get -u github.com/onsi/ginkgo/ginkgo \ && install -D -m 755 "$GOPATH"/bin/ginkgo /usr/bin/ # Install gomega RUN set -x \ - && export GOPATH=/go \ + && export GOPATH=/go GOCACHE="$(mktemp -d)" \ && go get github.com/onsi/gomega/... # Install conmon ENV CONMON_COMMIT 6f3572558b97bc60dd8f8c7f0807748e6ce2c440 RUN set -x \ - && export GOPATH="$(mktemp -d)" \ + && export GOPATH="$(mktemp -d)" GOCACHE="$(mktemp -d)" \ && git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \ && cd "$GOPATH/src/github.com/containers/conmon.git" \ && git fetch origin --tags \ diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index e7ad921da..8075baf34 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -423,6 +423,7 @@ type PushValues struct { CertDir string Compress bool Creds string + Digestfile string Format string Quiet bool RemoveSignatures bool diff --git a/cmd/podman/push.go b/cmd/podman/push.go index 43df8c2de..13ebe8a1f 100644 --- a/cmd/podman/push.go +++ b/cmd/podman/push.go @@ -51,6 +51,7 @@ func init() { pushCommand.SetUsageTemplate(UsageTemplate()) flags := pushCommand.Flags() flags.StringVar(&pushCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") + flags.StringVar(&pushCommand.Digestfile, "digestfile", "", "After copying the image, write the digest of the resulting image to the file") flags.StringVarP(&pushCommand.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir:' transport (default is manifest type of source)") flags.BoolVarP(&pushCommand.Quiet, "quiet", "q", false, "Don't output progress information when pushing images") flags.BoolVar(&pushCommand.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image") @@ -143,5 +144,5 @@ func pushCmd(c *cliconfig.PushValues) error { SignBy: signBy, } - return runtime.Push(getContext(), srcName, destName, manifestType, c.Authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil) + return runtime.Push(getContext(), srcName, destName, manifestType, c.Authfile, c.String("digestfile"), c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil) } diff --git a/cni/87-podman-bridge.conflist b/cni/87-podman-bridge.conflist index a5e241c80..729d543ec 100644 --- a/cni/87-podman-bridge.conflist +++ b/cni/87-podman-bridge.conflist @@ -1,5 +1,5 @@ { - "cniVersion": "0.3.0", + "cniVersion": "0.4.0", "name": "podman", "plugins": [ { @@ -20,6 +20,10 @@ "capabilities": { "portMappings": true } + }, + { + "type": "firewall", + "backend": "iptables" } ] } diff --git a/completions/bash/podman b/completions/bash/podman index 962c15a95..7280f4040 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -1758,6 +1758,7 @@ _podman_mount() { _podman_push() { local boolean_options=" --compress + --digestflag --help -h --quiet diff --git a/docs/podman-push.1.md b/docs/podman-push.1.md index 2058a432c..29e4044a3 100644 --- a/docs/podman-push.1.md +++ b/docs/podman-push.1.md @@ -61,13 +61,17 @@ value can be entered. The password is entered without echo. **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. -Default certificates directory is _/etc/containers/certs.d_. (Not available for remote commands) (Not available for remote commands) +Default certificates directory is _/etc/containers/certs.d_. (Not available for remote commands) **--compress** Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source) Note: This flag can only be set when using the **dir** transport +**--digestfile** *Digestfile* + +After copying the image, write the digest of the resulting image to the file. (Not available for remote commands) + **--format**, **-f**=*format* Manifest Type (oci, v2s1, or v2s2) to use when pushing an image to a directory using the 'dir:' transport (default is manifest type of source) @@ -93,19 +97,23 @@ TLS verification will be used unless the target registry is listed as an insecur ## EXAMPLE -This example extracts the imageID image to a local directory in docker format. +This example pushes the image specified by the imageID to a local directory in docker format. `# podman push imageID dir:/path/to/image` -This example extracts the imageID image to a local directory in oci format. +This example pushes the image specified by the imageID to a local directory in oci format. `# podman push imageID oci-archive:/path/to/layout:image:tag` -This example extracts the imageID image to a container registry named registry.example.com +This example pushes the image specified by the imageID to a container registry named registry.example.com `# podman push imageID docker://registry.example.com/repository:tag` -This example extracts the imageID image and puts into the local docker container store +This example pushes the image specified by the imageID to a container registry named registry.example.com and saves the digest in the specified digestfile. + + `# podman push --digestfile=/tmp/mydigest imageID docker://registry.example.com/repository:tag` + +This example pushes the image specified by the imageID and puts it into the local docker container store `# podman push imageID docker-daemon:image:tag` @@ -20,7 +20,6 @@ require ( github.com/containers/storage v1.13.2 github.com/coreos/bbolt v1.3.3 // indirect github.com/coreos/etcd v3.3.13+incompatible // indirect - github.com/coreos/go-iptables v0.4.1 github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a github.com/cri-o/ocicni v0.1.1-0.20190702175919-7762645d18ca diff --git a/libpod/image/image.go b/libpod/image/image.go index cb7c390c6..1ff271a4d 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "os" "path/filepath" "strings" @@ -555,7 +556,7 @@ func (i *Image) UntagImage(tag string) error { // PushImageToHeuristicDestination pushes the given image to "destination", which is heuristically parsed. // Use PushImageToReference if the destination is known precisely. -func (i *Image) PushImageToHeuristicDestination(ctx context.Context, destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { +func (i *Image) PushImageToHeuristicDestination(ctx context.Context, destination, manifestMIMEType, authFile, digestFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { if destination == "" { return errors.Wrapf(syscall.EINVAL, "destination image name must be specified") } @@ -573,11 +574,11 @@ func (i *Image) PushImageToHeuristicDestination(ctx context.Context, destination return err } } - return i.PushImageToReference(ctx, dest, manifestMIMEType, authFile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, additionalDockerArchiveTags) + return i.PushImageToReference(ctx, dest, manifestMIMEType, authFile, digestFile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, additionalDockerArchiveTags) } // PushImageToReference pushes the given image to a location described by the given path -func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageReference, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { +func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageReference, manifestMIMEType, authFile, digestFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { sc := GetSystemContext(signaturePolicyPath, authFile, forceCompress) sc.BlobInfoCacheDir = filepath.Join(i.imageruntime.store.GraphRoot(), "cache") @@ -599,10 +600,22 @@ func (i *Image) PushImageToReference(ctx context.Context, dest types.ImageRefere copyOptions := getCopyOptions(sc, writer, nil, dockerRegistryOptions, signingOptions, manifestMIMEType, additionalDockerArchiveTags) copyOptions.DestinationCtx.SystemRegistriesConfPath = registries.SystemRegistriesConfPath() // FIXME: Set this more globally. Probably no reason not to have it in every types.SystemContext, and to compute the value just once in one place. // Copy the image to the remote destination - _, err = cp.Image(ctx, policyContext, dest, src, copyOptions) + manifestBytes, err := cp.Image(ctx, policyContext, dest, src, copyOptions) if err != nil { return errors.Wrapf(err, "Error copying image to the remote destination") } + digest, err := manifest.Digest(manifestBytes) + if err != nil { + return errors.Wrapf(err, "error computing digest of manifest of new image %q", transports.ImageName(dest)) + } + + logrus.Debugf("Successfully pushed %s with digest %s", transports.ImageName(dest), digest.String()) + + if digestFile != "" { + if err = ioutil.WriteFile(digestFile, []byte(digest.String()), 0644); err != nil { + return errors.Wrapf(err, "failed to write digest to file %q", digestFile) + } + } i.newImageEvent(events.Push) return nil } @@ -1358,7 +1371,7 @@ func (i *Image) Save(ctx context.Context, source, format, output string, moreTag return err } } - if err := i.PushImageToReference(ctx, destRef, manifestType, "", "", writer, compress, SigningOptions{}, &DockerRegistryOptions{}, additionaltags); err != nil { + if err := i.PushImageToReference(ctx, destRef, manifestType, "", "", "", writer, compress, SigningOptions{}, &DockerRegistryOptions{}, additionaltags); err != nil { return errors.Wrapf(err, "unable to save %q", source) } i.newImageEvent(events.Save) diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index bef3f7739..fd14b2f73 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -17,7 +17,6 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" "github.com/containers/libpod/pkg/errorhandling" - "github.com/containers/libpod/pkg/firewall" "github.com/containers/libpod/pkg/netns" "github.com/containers/libpod/pkg/rootless" "github.com/cri-o/ocicni/pkg/ocicni" @@ -86,18 +85,6 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re networkStatus = append(networkStatus, resultCurrent) } - // Add firewall rules to ensure the container has network access. - // Will not be necessary once CNI firewall plugin merges upstream. - // https://github.com/containernetworking/plugins/pull/75 - for _, netStatus := range networkStatus { - firewallConf := &firewall.FirewallNetConf{ - PrevResult: netStatus, - } - if err := r.firewallBackend.Add(firewallConf); err != nil { - return nil, errors.Wrapf(err, "error adding firewall rules for container %s", ctr.ID()) - } - } - return networkStatus, nil } @@ -390,26 +377,12 @@ func (r *Runtime) closeNetNS(ctr *Container) error { } // Tear down a network namespace, undoing all state associated with it. -// The CNI firewall rules will be removed, the namespace will be unmounted, -// and the file descriptor associated with it closed. func (r *Runtime) teardownNetNS(ctr *Container) error { if ctr.state.NetNS == nil { // The container has no network namespace, we're set return nil } - // Remove firewall rules we added on configuring the container. - // Will not be necessary once CNI firewall plugin merges upstream. - // https://github.com/containernetworking/plugins/pull/75 - for _, netStatus := range ctr.state.NetworkStatus { - firewallConf := &firewall.FirewallNetConf{ - PrevResult: netStatus, - } - if err := r.firewallBackend.Del(firewallConf); err != nil { - return errors.Wrapf(err, "error removing firewall rules for container %s", ctr.ID()) - } - } - logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID()) var requestedIP net.IP diff --git a/libpod/runtime.go b/libpod/runtime.go index cbbf667db..4d6a80d0b 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -23,7 +23,6 @@ import ( "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/lock" - "github.com/containers/libpod/pkg/firewall" sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" @@ -108,7 +107,6 @@ type Runtime struct { netPlugin ocicni.CNIPlugin conmonPath string imageRuntime *image.Runtime - firewallBackend firewall.FirewallBackend lockManager lock.Manager configuredFrom *runtimeConfiguredFrom @@ -1110,17 +1108,6 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { runtime.netPlugin = netPlugin } - // Set up a firewall backend - backendType := "" - if rootless.IsRootless() { - backendType = "none" - } - fwBackend, err := firewall.GetBackend(backendType) - if err != nil { - return err - } - runtime.firewallBackend = fwBackend - // We now need to see if the system has restarted // We check for the presence of a file in our tmp directory to verify this // This check must be locked to prevent races diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 7d4f97b28..0537308f8 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -201,12 +201,12 @@ func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmV } // Push is a wrapper to push an image to a registry -func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { +func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { newImage, err := r.ImageRuntime().NewFromLocal(srcName) if err != nil { return err } - return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil) + return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil) } // InspectVolumes returns a slice of volumes based on an arg list or --all diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 683bf1d35..8588966b6 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -619,7 +619,7 @@ func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmV return iopodman.VolumeRemove().Call(r.Conn, rmOpts) } -func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { +func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error { reply, err := iopodman.PushImage().Send(r.Conn, varlink.More, srcName, destination, forceCompress, manifestMIMEType, signingOptions.RemoveSignatures, signingOptions.SignBy) if err != nil { diff --git a/pkg/firewall/common.go b/pkg/firewall/common.go deleted file mode 100644 index a65d4f03d..000000000 --- a/pkg/firewall/common.go +++ /dev/null @@ -1,55 +0,0 @@ -package firewall - -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "net" - - "github.com/containernetworking/cni/pkg/types/current" -) - -// FirewallNetConf represents the firewall configuration. -// Nolint applied for firewall.Firewall... name duplication notice. -//nolint -type FirewallNetConf struct { - //types.NetConf - - // IptablesAdminChainName is an optional name to use instead of the default - // admin rules override chain name that includes the interface name. - IptablesAdminChainName string - - // FirewalldZone is an optional firewalld zone to place the interface into. If - // the firewalld backend is used but the zone is not given, it defaults - // to 'trusted' - FirewalldZone string - - PrevResult *current.Result -} - -// FirewallBackend is an interface to the system firewall, allowing addition and -// removal of firewall rules. -// Nolint applied for firewall.Firewall... name duplication notice. -//nolint -type FirewallBackend interface { - Add(*FirewallNetConf) error - Del(*FirewallNetConf) error -} - -func ipString(ip net.IPNet) string { - if ip.IP.To4() == nil { - return ip.IP.String() + "/128" - } - return ip.IP.String() + "/32" -} diff --git a/pkg/firewall/firewall_linux.go b/pkg/firewall/firewall_linux.go deleted file mode 100644 index 4ac45427b..000000000 --- a/pkg/firewall/firewall_linux.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build linux - -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package firewall - -import ( - "fmt" -) - -// GetBackend retrieves a firewall backend for adding or removing firewall rules -// on the system. -// Valid backend names are firewalld, iptables, and none. -// If the empty string is given, a firewalld backend will be returned if -// firewalld is running, and an iptables backend will be returned otherwise. -func GetBackend(backend string) (FirewallBackend, error) { - switch backend { - case "firewalld": - return newFirewalldBackend() - case "iptables": - return newIptablesBackend() - case "none": - return newNoneBackend() - case "": - // Default to firewalld if it's running - if isFirewalldRunning() { - return newFirewalldBackend() - } - - // Otherwise iptables - return newIptablesBackend() - default: - return nil, fmt.Errorf("unrecognized firewall backend %q", backend) - } -} diff --git a/pkg/firewall/firewall_none.go b/pkg/firewall/firewall_none.go deleted file mode 100644 index 9add24842..000000000 --- a/pkg/firewall/firewall_none.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package firewall - -import ( - "fmt" -) - -// FirewallNone is a firewall backend for environments where manipulating the -// system firewall is unsupported (for example, when running without root). -// Nolint applied to avoid firewall.FirewallNone name duplication notes. -//nolint -type FirewallNone struct{} - -func newNoneBackend() (FirewallBackend, error) { - return &FirewallNone{}, nil -} - -// Add adds a rule to the system firewall. -// No action is taken and an error is unconditionally returned as this backend -// does not support manipulating the firewall. -func (f *FirewallNone) Add(conf *FirewallNetConf) error { - return fmt.Errorf("cannot modify system firewall rules") -} - -// Del deletes a rule from the system firewall. -// No action is taken and an error is unconditionally returned as this backend -// does not support manipulating the firewall. -func (f *FirewallNone) Del(conf *FirewallNetConf) error { - return fmt.Errorf("cannot modify system firewall rules") -} diff --git a/pkg/firewall/firewall_unsupported.go b/pkg/firewall/firewall_unsupported.go deleted file mode 100644 index 24c07a8a9..000000000 --- a/pkg/firewall/firewall_unsupported.go +++ /dev/null @@ -1,27 +0,0 @@ -// +build !linux - -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package firewall - -import ( - "fmt" -) - -// GetBackend retrieves a firewall backend for adding or removing firewall rules -// on the system. -func GetBackend(backend string) (FirewallBackend, error) { - return nil, fmt.Errorf("firewall backends are not presently supported on this OS") -} diff --git a/pkg/firewall/firewalld.go b/pkg/firewall/firewalld.go deleted file mode 100644 index 15e845cb7..000000000 --- a/pkg/firewall/firewalld.go +++ /dev/null @@ -1,122 +0,0 @@ -// +build linux - -// Copyright 2018 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package firewall - -import ( - "fmt" - "github.com/sirupsen/logrus" - "strings" - - "github.com/godbus/dbus" -) - -const ( - dbusName = "org.freedesktop.DBus" - dbusPath = "/org/freedesktop/DBus" - dbusGetNameOwnerMethod = "GetNameOwner" - - firewalldName = "org.fedoraproject.FirewallD1" - firewalldPath = "/org/fedoraproject/FirewallD1" - firewalldZoneInterface = "org.fedoraproject.FirewallD1.zone" - firewalldAddSourceMethod = "addSource" - firewalldRemoveSourceMethod = "removeSource" - - errZoneAlreadySet = "ZONE_ALREADY_SET" -) - -// Only used for testcases to override the D-Bus connection -var testConn *dbus.Conn - -type fwdBackend struct { - conn *dbus.Conn -} - -// fwdBackend implements the FirewallBackend interface -var _ FirewallBackend = &fwdBackend{} - -func getConn() (*dbus.Conn, error) { - if testConn != nil { - return testConn, nil - } - return dbus.SystemBus() -} - -// isFirewalldRunning checks whether firewalld is running. -func isFirewalldRunning() bool { - conn, err := getConn() - if err != nil { - return false - } - - dbusObj := conn.Object(dbusName, dbusPath) - var res string - if err := dbusObj.Call(dbusName+"."+dbusGetNameOwnerMethod, 0, firewalldName).Store(&res); err != nil { - return false - } - - return true -} - -func newFirewalldBackend() (FirewallBackend, error) { - conn, err := getConn() - if err != nil { - return nil, err - } - - backend := &fwdBackend{ - conn: conn, - } - return backend, nil -} - -func getFirewalldZone(conf *FirewallNetConf) string { - if conf.FirewalldZone != "" { - return conf.FirewalldZone - } - - return "trusted" -} - -func (fb *fwdBackend) Add(conf *FirewallNetConf) error { - zone := getFirewalldZone(conf) - - for _, ip := range conf.PrevResult.IPs { - ipStr := ipString(ip.Address) - // Add a firewalld rule which assigns the given source IP to the given zone - firewalldObj := fb.conn.Object(firewalldName, firewalldPath) - var res string - if err := firewalldObj.Call(firewalldZoneInterface+"."+firewalldAddSourceMethod, 0, zone, ipStr).Store(&res); err != nil { - if !strings.Contains(err.Error(), errZoneAlreadySet) { - return fmt.Errorf("failed to add the address %v to %v zone: %v", ipStr, zone, err) - } - } - } - return nil -} - -func (fb *fwdBackend) Del(conf *FirewallNetConf) error { - for _, ip := range conf.PrevResult.IPs { - ipStr := ipString(ip.Address) - // Remove firewalld rules which assigned the given source IP to the given zone - firewalldObj := fb.conn.Object(firewalldName, firewalldPath) - var res string - if err := firewalldObj.Call(firewalldZoneInterface+"."+firewalldRemoveSourceMethod, 0, getFirewalldZone(conf), ipStr).Store(&res); err != nil { - logrus.Errorf("unable to store firewallobj") - } - } - return nil -} diff --git a/pkg/firewall/iptables.go b/pkg/firewall/iptables.go deleted file mode 100644 index 169ddc1d7..000000000 --- a/pkg/firewall/iptables.go +++ /dev/null @@ -1,195 +0,0 @@ -// +build linux - -// Copyright 2016 CNI authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This is a "meta-plugin". It reads in its own netconf, it does not create -// any network interface but just changes the network sysctl. - -package firewall - -import ( - "fmt" - "github.com/sirupsen/logrus" - "net" - - "github.com/coreos/go-iptables/iptables" -) - -func getPrivChainRules(ip string) [][]string { - var rules [][]string - rules = append(rules, []string{"-d", ip, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}) - rules = append(rules, []string{"-s", ip, "-j", "ACCEPT"}) - return rules -} - -func ensureChain(ipt *iptables.IPTables, table, chain string) error { - chains, err := ipt.ListChains(table) - if err != nil { - return fmt.Errorf("failed to list iptables chains: %v", err) - } - for _, ch := range chains { - if ch == chain { - return nil - } - } - - return ipt.NewChain(table, chain) -} - -func generateFilterRule(privChainName string) []string { - return []string{"-m", "comment", "--comment", "CNI firewall plugin rules", "-j", privChainName} -} - -func cleanupRules(ipt *iptables.IPTables, privChainName string, rules [][]string) { - for _, rule := range rules { - if err := ipt.Delete("filter", privChainName, rule...); err != nil { - logrus.Errorf("failed to delete iptables rule %s", privChainName) - } - } -} - -func ensureFirstChainRule(ipt *iptables.IPTables, chain string, rule []string) error { - exists, err := ipt.Exists("filter", chain, rule...) - if !exists && err == nil { - err = ipt.Insert("filter", chain, 1, rule...) - } - return err -} - -func (ib *iptablesBackend) setupChains(ipt *iptables.IPTables) error { - privRule := generateFilterRule(ib.privChainName) - adminRule := generateFilterRule(ib.adminChainName) - - // Ensure our private chains exist - if err := ensureChain(ipt, "filter", ib.privChainName); err != nil { - return err - } - if err := ensureChain(ipt, "filter", ib.adminChainName); err != nil { - return err - } - - // Ensure our filter rule exists in the forward chain - if err := ensureFirstChainRule(ipt, "FORWARD", privRule); err != nil { - return err - } - - // Ensure our admin override chain rule exists in our private chain - if err := ensureFirstChainRule(ipt, ib.privChainName, adminRule); err != nil { - return err - } - - return nil -} - -func protoForIP(ip net.IPNet) iptables.Protocol { - if ip.IP.To4() != nil { - return iptables.ProtocolIPv4 - } - return iptables.ProtocolIPv6 -} - -func (ib *iptablesBackend) addRules(conf *FirewallNetConf, ipt *iptables.IPTables, proto iptables.Protocol) error { - rules := make([][]string, 0) - for _, ip := range conf.PrevResult.IPs { - if protoForIP(ip.Address) == proto { - rules = append(rules, getPrivChainRules(ipString(ip.Address))...) - } - } - - if len(rules) > 0 { - if err := ib.setupChains(ipt); err != nil { - return err - } - - // Clean up on any errors - var err error - defer func() { - if err != nil { - cleanupRules(ipt, ib.privChainName, rules) - } - }() - - for _, rule := range rules { - err = ipt.AppendUnique("filter", ib.privChainName, rule...) - if err != nil { - return err - } - } - } - - return nil -} - -func (ib *iptablesBackend) delRules(conf *FirewallNetConf, ipt *iptables.IPTables, proto iptables.Protocol) error { - rules := make([][]string, 0) - for _, ip := range conf.PrevResult.IPs { - if protoForIP(ip.Address) == proto { - rules = append(rules, getPrivChainRules(ipString(ip.Address))...) - } - } - - if len(rules) > 0 { - cleanupRules(ipt, ib.privChainName, rules) - } - - return nil -} - -type iptablesBackend struct { - protos map[iptables.Protocol]*iptables.IPTables - privChainName string - adminChainName string -} - -// iptablesBackend implements the FirewallBackend interface -var _ FirewallBackend = &iptablesBackend{} - -func newIptablesBackend() (FirewallBackend, error) { - adminChainName := "CNI-ADMIN" - - backend := &iptablesBackend{ - privChainName: "CNI-FORWARD", - adminChainName: adminChainName, - protos: make(map[iptables.Protocol]*iptables.IPTables), - } - - for _, proto := range []iptables.Protocol{iptables.ProtocolIPv4, iptables.ProtocolIPv6} { - ipt, err := iptables.NewWithProtocol(proto) - if err != nil { - return nil, fmt.Errorf("could not initialize iptables protocol %v: %v", proto, err) - } - backend.protos[proto] = ipt - } - - return backend, nil -} - -func (ib *iptablesBackend) Add(conf *FirewallNetConf) error { - for proto, ipt := range ib.protos { - if err := ib.addRules(conf, ipt, proto); err != nil { - return err - } - } - return nil -} - -func (ib *iptablesBackend) Del(conf *FirewallNetConf) error { - for proto, ipt := range ib.protos { - if err := ib.delRules(conf, ipt, proto); err != nil { - logrus.Errorf("failed to delete iptables backend rule %s", conf.IptablesAdminChainName) - } - } - return nil -} diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index fe7f11b4d..a1fdf5955 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -353,7 +353,7 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compr output := bytes.NewBuffer([]byte{}) c := make(chan error) go func() { - err := newImage.PushImageToHeuristicDestination(getContext(), destname, manifestType, "", "", output, compress, so, &dockerRegistryOptions, nil) + err := newImage.PushImageToHeuristicDestination(getContext(), destname, manifestType, "", "", "", output, compress, so, &dockerRegistryOptions, nil) c <- err close(c) }() @@ -615,7 +615,7 @@ func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination str return err } - if err := newImage.PushImageToHeuristicDestination(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, additionalTags); err != nil { + if err := newImage.PushImageToHeuristicDestination(getContext(), destination, "", "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, additionalTags); err != nil { return call.ReplyErrorOccurred(err.Error()) } return call.ReplyExportImage(newImage.ID()) diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index cf6279f2f..4360eeece 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -76,6 +76,14 @@ var _ = Describe("Podman push", func() { push := podmanTest.PodmanNoCache([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"}) push.WaitWithDefaultTimeout() Expect(push.ExitCode()).To(Equal(0)) + + // Test --digestfile option + push2 := podmanTest.PodmanNoCache([]string{"push", "--tls-verify=false", "--digestfile=/tmp/digestfile.txt", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"}) + push2.WaitWithDefaultTimeout() + fi, err := os.Lstat("/tmp/digestfile.txt") + Expect(err).To(BeNil()) + Expect(fi.Name()).To(Equal("digestfile.txt")) + Expect(push2.ExitCode()).To(Equal(0)) }) It("podman push to local registry with authorization", func() { diff --git a/vendor/github.com/coreos/go-iptables/LICENSE b/vendor/github.com/coreos/go-iptables/LICENSE deleted file mode 100644 index 37ec93a14..000000000 --- a/vendor/github.com/coreos/go-iptables/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/coreos/go-iptables/NOTICE b/vendor/github.com/coreos/go-iptables/NOTICE deleted file mode 100644 index 23a0ada2f..000000000 --- a/vendor/github.com/coreos/go-iptables/NOTICE +++ /dev/null @@ -1,5 +0,0 @@ -CoreOS Project -Copyright 2018 CoreOS, Inc - -This product includes software developed at CoreOS, Inc. -(http://www.coreos.com/). diff --git a/vendor/github.com/coreos/go-iptables/iptables/iptables.go b/vendor/github.com/coreos/go-iptables/iptables/iptables.go deleted file mode 100644 index 9601bc78a..000000000 --- a/vendor/github.com/coreos/go-iptables/iptables/iptables.go +++ /dev/null @@ -1,532 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package iptables - -import ( - "bytes" - "fmt" - "io" - "net" - "os/exec" - "regexp" - "strconv" - "strings" - "syscall" -) - -// Adds the output of stderr to exec.ExitError -type Error struct { - exec.ExitError - cmd exec.Cmd - msg string - proto Protocol - exitStatus *int //for overriding -} - -func (e *Error) ExitStatus() int { - if e.exitStatus != nil { - return *e.exitStatus - } - return e.Sys().(syscall.WaitStatus).ExitStatus() -} - -func (e *Error) Error() string { - return fmt.Sprintf("running %v: exit status %v: %v", e.cmd.Args, e.ExitStatus(), e.msg) -} - -// IsNotExist returns true if the error is due to the chain or rule not existing -func (e *Error) IsNotExist() bool { - return e.ExitStatus() == 1 && - (e.msg == fmt.Sprintf("%s: Bad rule (does a matching rule exist in that chain?).\n", getIptablesCommand(e.proto)) || - e.msg == fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(e.proto))) -} - -// Protocol to differentiate between IPv4 and IPv6 -type Protocol byte - -const ( - ProtocolIPv4 Protocol = iota - ProtocolIPv6 -) - -type IPTables struct { - path string - proto Protocol - hasCheck bool - hasWait bool - hasRandomFully bool - v1 int - v2 int - v3 int - mode string // the underlying iptables operating mode, e.g. nf_tables -} - -// New creates a new IPTables. -// For backwards compatibility, this always uses IPv4, i.e. "iptables". -func New() (*IPTables, error) { - return NewWithProtocol(ProtocolIPv4) -} - -// New creates a new IPTables for the given proto. -// The proto will determine which command is used, either "iptables" or "ip6tables". -func NewWithProtocol(proto Protocol) (*IPTables, error) { - path, err := exec.LookPath(getIptablesCommand(proto)) - if err != nil { - return nil, err - } - vstring, err := getIptablesVersionString(path) - v1, v2, v3, mode, err := extractIptablesVersion(vstring) - - checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3) - - ipt := IPTables{ - path: path, - proto: proto, - hasCheck: checkPresent, - hasWait: waitPresent, - hasRandomFully: randomFullyPresent, - v1: v1, - v2: v2, - v3: v3, - mode: mode, - } - return &ipt, nil -} - -// Proto returns the protocol used by this IPTables. -func (ipt *IPTables) Proto() Protocol { - return ipt.proto -} - -// Exists checks if given rulespec in specified table/chain exists -func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) { - if !ipt.hasCheck { - return ipt.existsForOldIptables(table, chain, rulespec) - - } - cmd := append([]string{"-t", table, "-C", chain}, rulespec...) - err := ipt.run(cmd...) - eerr, eok := err.(*Error) - switch { - case err == nil: - return true, nil - case eok && eerr.ExitStatus() == 1: - return false, nil - default: - return false, err - } -} - -// Insert inserts rulespec to specified table/chain (in specified pos) -func (ipt *IPTables) Insert(table, chain string, pos int, rulespec ...string) error { - cmd := append([]string{"-t", table, "-I", chain, strconv.Itoa(pos)}, rulespec...) - return ipt.run(cmd...) -} - -// Append appends rulespec to specified table/chain -func (ipt *IPTables) Append(table, chain string, rulespec ...string) error { - cmd := append([]string{"-t", table, "-A", chain}, rulespec...) - return ipt.run(cmd...) -} - -// AppendUnique acts like Append except that it won't add a duplicate -func (ipt *IPTables) AppendUnique(table, chain string, rulespec ...string) error { - exists, err := ipt.Exists(table, chain, rulespec...) - if err != nil { - return err - } - - if !exists { - return ipt.Append(table, chain, rulespec...) - } - - return nil -} - -// Delete removes rulespec in specified table/chain -func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error { - cmd := append([]string{"-t", table, "-D", chain}, rulespec...) - return ipt.run(cmd...) -} - -// List rules in specified table/chain -func (ipt *IPTables) List(table, chain string) ([]string, error) { - args := []string{"-t", table, "-S", chain} - return ipt.executeList(args) -} - -// List rules (with counters) in specified table/chain -func (ipt *IPTables) ListWithCounters(table, chain string) ([]string, error) { - args := []string{"-t", table, "-v", "-S", chain} - return ipt.executeList(args) -} - -// ListChains returns a slice containing the name of each chain in the specified table. -func (ipt *IPTables) ListChains(table string) ([]string, error) { - args := []string{"-t", table, "-S"} - - result, err := ipt.executeList(args) - if err != nil { - return nil, err - } - - // Iterate over rules to find all default (-P) and user-specified (-N) chains. - // Chains definition always come before rules. - // Format is the following: - // -P OUTPUT ACCEPT - // -N Custom - var chains []string - for _, val := range result { - if strings.HasPrefix(val, "-P") || strings.HasPrefix(val, "-N") { - chains = append(chains, strings.Fields(val)[1]) - } else { - break - } - } - return chains, nil -} - -// Stats lists rules including the byte and packet counts -func (ipt *IPTables) Stats(table, chain string) ([][]string, error) { - args := []string{"-t", table, "-L", chain, "-n", "-v", "-x"} - lines, err := ipt.executeList(args) - if err != nil { - return nil, err - } - - appendSubnet := func(addr string) string { - if strings.IndexByte(addr, byte('/')) < 0 { - if strings.IndexByte(addr, '.') < 0 { - return addr + "/128" - } - return addr + "/32" - } - return addr - } - - ipv6 := ipt.proto == ProtocolIPv6 - - rows := [][]string{} - for i, line := range lines { - // Skip over chain name and field header - if i < 2 { - continue - } - - // Fields: - // 0=pkts 1=bytes 2=target 3=prot 4=opt 5=in 6=out 7=source 8=destination 9=options - line = strings.TrimSpace(line) - fields := strings.Fields(line) - - // The ip6tables verbose output cannot be naively split due to the default "opt" - // field containing 2 single spaces. - if ipv6 { - // Check if field 6 is "opt" or "source" address - dest := fields[6] - ip, _, _ := net.ParseCIDR(dest) - if ip == nil { - ip = net.ParseIP(dest) - } - - // If we detected a CIDR or IP, the "opt" field is empty.. insert it. - if ip != nil { - f := []string{} - f = append(f, fields[:4]...) - f = append(f, " ") // Empty "opt" field for ip6tables - f = append(f, fields[4:]...) - fields = f - } - } - - // Adjust "source" and "destination" to include netmask, to match regular - // List output - fields[7] = appendSubnet(fields[7]) - fields[8] = appendSubnet(fields[8]) - - // Combine "options" fields 9... into a single space-delimited field. - options := fields[9:] - fields = fields[:9] - fields = append(fields, strings.Join(options, " ")) - rows = append(rows, fields) - } - return rows, nil -} - -func (ipt *IPTables) executeList(args []string) ([]string, error) { - var stdout bytes.Buffer - if err := ipt.runWithOutput(args, &stdout); err != nil { - return nil, err - } - - rules := strings.Split(stdout.String(), "\n") - - // strip trailing newline - if len(rules) > 0 && rules[len(rules)-1] == "" { - rules = rules[:len(rules)-1] - } - - // nftables mode doesn't return an error code when listing a non-existent - // chain. Patch that up. - if len(rules) == 0 && ipt.mode == "nf_tables" { - v := 1 - return nil, &Error{ - cmd: exec.Cmd{Args: args}, - msg: fmt.Sprintf("%s: No chain/target/match by that name.\n", getIptablesCommand(ipt.proto)), - proto: ipt.proto, - exitStatus: &v, - } - } - - for i, rule := range rules { - rules[i] = filterRuleOutput(rule) - } - - return rules, nil -} - -// NewChain creates a new chain in the specified table. -// If the chain already exists, it will result in an error. -func (ipt *IPTables) NewChain(table, chain string) error { - return ipt.run("-t", table, "-N", chain) -} - -// ClearChain flushed (deletes all rules) in the specified table/chain. -// If the chain does not exist, a new one will be created -func (ipt *IPTables) ClearChain(table, chain string) error { - err := ipt.NewChain(table, chain) - - // the exit code for "this table already exists" is different for - // different iptables modes - existsErr := 1 - if ipt.mode == "nf_tables" { - existsErr = 4 - } - - eerr, eok := err.(*Error) - switch { - case err == nil: - return nil - case eok && eerr.ExitStatus() == existsErr: - // chain already exists. Flush (clear) it. - return ipt.run("-t", table, "-F", chain) - default: - return err - } -} - -// RenameChain renames the old chain to the new one. -func (ipt *IPTables) RenameChain(table, oldChain, newChain string) error { - return ipt.run("-t", table, "-E", oldChain, newChain) -} - -// DeleteChain deletes the chain in the specified table. -// The chain must be empty -func (ipt *IPTables) DeleteChain(table, chain string) error { - return ipt.run("-t", table, "-X", chain) -} - -// ChangePolicy changes policy on chain to target -func (ipt *IPTables) ChangePolicy(table, chain, target string) error { - return ipt.run("-t", table, "-P", chain, target) -} - -// Check if the underlying iptables command supports the --random-fully flag -func (ipt *IPTables) HasRandomFully() bool { - return ipt.hasRandomFully -} - -// Return version components of the underlying iptables command -func (ipt *IPTables) GetIptablesVersion() (int, int, int) { - return ipt.v1, ipt.v2, ipt.v3 -} - -// run runs an iptables command with the given arguments, ignoring -// any stdout output -func (ipt *IPTables) run(args ...string) error { - return ipt.runWithOutput(args, nil) -} - -// runWithOutput runs an iptables command with the given arguments, -// writing any stdout output to the given writer -func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error { - args = append([]string{ipt.path}, args...) - if ipt.hasWait { - args = append(args, "--wait") - } else { - fmu, err := newXtablesFileLock() - if err != nil { - return err - } - ul, err := fmu.tryLock() - if err != nil { - return err - } - defer ul.Unlock() - } - - var stderr bytes.Buffer - cmd := exec.Cmd{ - Path: ipt.path, - Args: args, - Stdout: stdout, - Stderr: &stderr, - } - - if err := cmd.Run(); err != nil { - switch e := err.(type) { - case *exec.ExitError: - return &Error{*e, cmd, stderr.String(), ipt.proto, nil} - default: - return err - } - } - - return nil -} - -// getIptablesCommand returns the correct command for the given protocol, either "iptables" or "ip6tables". -func getIptablesCommand(proto Protocol) string { - if proto == ProtocolIPv6 { - return "ip6tables" - } else { - return "iptables" - } -} - -// Checks if iptables has the "-C" and "--wait" flag -func getIptablesCommandSupport(v1 int, v2 int, v3 int) (bool, bool, bool) { - return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), iptablesHasRandomFully(v1, v2, v3) -} - -// getIptablesVersion returns the first three components of the iptables version -// and the operating mode (e.g. nf_tables or legacy) -// e.g. "iptables v1.3.66" would return (1, 3, 66, legacy, nil) -func extractIptablesVersion(str string) (int, int, int, string, error) { - versionMatcher := regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\s+\((\w+))?`) - result := versionMatcher.FindStringSubmatch(str) - if result == nil { - return 0, 0, 0, "", fmt.Errorf("no iptables version found in string: %s", str) - } - - v1, err := strconv.Atoi(result[1]) - if err != nil { - return 0, 0, 0, "", err - } - - v2, err := strconv.Atoi(result[2]) - if err != nil { - return 0, 0, 0, "", err - } - - v3, err := strconv.Atoi(result[3]) - if err != nil { - return 0, 0, 0, "", err - } - - mode := "legacy" - if result[4] != "" { - mode = result[4] - } - return v1, v2, v3, mode, nil -} - -// Runs "iptables --version" to get the version string -func getIptablesVersionString(path string) (string, error) { - cmd := exec.Command(path, "--version") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return "", err - } - return out.String(), nil -} - -// Checks if an iptables version is after 1.4.11, when --check was added -func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool { - if v1 > 1 { - return true - } - if v1 == 1 && v2 > 4 { - return true - } - if v1 == 1 && v2 == 4 && v3 >= 11 { - return true - } - return false -} - -// Checks if an iptables version is after 1.4.20, when --wait was added -func iptablesHasWaitCommand(v1 int, v2 int, v3 int) bool { - if v1 > 1 { - return true - } - if v1 == 1 && v2 > 4 { - return true - } - if v1 == 1 && v2 == 4 && v3 >= 20 { - return true - } - return false -} - -// Checks if an iptables version is after 1.6.2, when --random-fully was added -func iptablesHasRandomFully(v1 int, v2 int, v3 int) bool { - if v1 > 1 { - return true - } - if v1 == 1 && v2 > 6 { - return true - } - if v1 == 1 && v2 == 6 && v3 >= 2 { - return true - } - return false -} - -// Checks if a rule specification exists for a table -func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string) (bool, error) { - rs := strings.Join(append([]string{"-A", chain}, rulespec...), " ") - args := []string{"-t", table, "-S"} - var stdout bytes.Buffer - err := ipt.runWithOutput(args, &stdout) - if err != nil { - return false, err - } - return strings.Contains(stdout.String(), rs), nil -} - -// counterRegex is the regex used to detect nftables counter format -var counterRegex = regexp.MustCompile(`^\[([0-9]+):([0-9]+)\] `) - -// filterRuleOutput works around some inconsistencies in output. -// For example, when iptables is in legacy vs. nftables mode, it produces -// different results. -func filterRuleOutput(rule string) string { - out := rule - - // work around an output difference in nftables mode where counters - // are output in iptables-save format, rather than iptables -S format - // The string begins with "[0:0]" - // - // Fixes #49 - if groups := counterRegex.FindStringSubmatch(out); groups != nil { - // drop the brackets - out = out[len(groups[0]):] - out = fmt.Sprintf("%s -c %s %s", out, groups[1], groups[2]) - } - - return out -} diff --git a/vendor/github.com/coreos/go-iptables/iptables/lock.go b/vendor/github.com/coreos/go-iptables/iptables/lock.go deleted file mode 100644 index a88e92b4e..000000000 --- a/vendor/github.com/coreos/go-iptables/iptables/lock.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package iptables - -import ( - "os" - "sync" - "syscall" -) - -const ( - // In earlier versions of iptables, the xtables lock was implemented - // via a Unix socket, but now flock is used via this lockfile: - // http://git.netfilter.org/iptables/commit/?id=aa562a660d1555b13cffbac1e744033e91f82707 - // Note the LSB-conforming "/run" directory does not exist on old - // distributions, so assume "/var" is symlinked - xtablesLockFilePath = "/var/run/xtables.lock" - - defaultFilePerm = 0600 -) - -type Unlocker interface { - Unlock() error -} - -type nopUnlocker struct{} - -func (_ nopUnlocker) Unlock() error { return nil } - -type fileLock struct { - // mu is used to protect against concurrent invocations from within this process - mu sync.Mutex - fd int -} - -// tryLock takes an exclusive lock on the xtables lock file without blocking. -// This is best-effort only: if the exclusive lock would block (i.e. because -// another process already holds it), no error is returned. Otherwise, any -// error encountered during the locking operation is returned. -// The returned Unlocker should be used to release the lock when the caller is -// done invoking iptables commands. -func (l *fileLock) tryLock() (Unlocker, error) { - l.mu.Lock() - err := syscall.Flock(l.fd, syscall.LOCK_EX|syscall.LOCK_NB) - switch err { - case syscall.EWOULDBLOCK: - l.mu.Unlock() - return nopUnlocker{}, nil - case nil: - return l, nil - default: - l.mu.Unlock() - return nil, err - } -} - -// Unlock closes the underlying file, which implicitly unlocks it as well. It -// also unlocks the associated mutex. -func (l *fileLock) Unlock() error { - defer l.mu.Unlock() - return syscall.Close(l.fd) -} - -// newXtablesFileLock opens a new lock on the xtables lockfile without -// acquiring the lock -func newXtablesFileLock() (*fileLock, error) { - fd, err := syscall.Open(xtablesLockFilePath, os.O_CREATE, defaultFilePerm) - if err != nil { - return nil, err - } - return &fileLock{fd: fd}, nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4b992352c..3acff38c9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -144,8 +144,6 @@ github.com/containers/storage/drivers/quota github.com/containers/storage/pkg/fsutils github.com/containers/storage/pkg/ostree github.com/containers/storage/drivers/copy -# github.com/coreos/go-iptables v0.4.1 -github.com/coreos/go-iptables/iptables # github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a github.com/coreos/go-systemd/activation github.com/coreos/go-systemd/dbus |