mirror of
https://github.com/containers/podman.git
synced 2025-07-15 03:02:52 +08:00
Error on rootless mac and ip addresses
When creating a pod or container where a static MAC or IP address is provided, we should return a proper error and exit as 125. Fixes: #6972 Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -28,6 +28,15 @@ func exclusiveOptions(opt1, opt2 string) error {
|
|||||||
// input for creating a container.
|
// input for creating a container.
|
||||||
func (s *SpecGenerator) Validate() error {
|
func (s *SpecGenerator) Validate() error {
|
||||||
|
|
||||||
|
if rootless.IsRootless() {
|
||||||
|
if s.StaticIP != nil || s.StaticIPv6 != nil {
|
||||||
|
return ErrNoStaticIPRootless
|
||||||
|
}
|
||||||
|
if s.StaticMAC != nil {
|
||||||
|
return ErrNoStaticMACRootless
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// ContainerBasicConfig
|
// ContainerBasicConfig
|
||||||
//
|
//
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package specgen
|
package specgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/containers/libpod/v2/pkg/rootless"
|
||||||
"github.com/containers/libpod/v2/pkg/util"
|
"github.com/containers/libpod/v2/pkg/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -18,6 +19,16 @@ func exclusivePodOptions(opt1, opt2 string) error {
|
|||||||
|
|
||||||
// Validate verifies the input is valid
|
// Validate verifies the input is valid
|
||||||
func (p *PodSpecGenerator) Validate() error {
|
func (p *PodSpecGenerator) Validate() error {
|
||||||
|
|
||||||
|
if rootless.IsRootless() {
|
||||||
|
if p.StaticIP != nil {
|
||||||
|
return ErrNoStaticIPRootless
|
||||||
|
}
|
||||||
|
if p.StaticMAC != nil {
|
||||||
|
return ErrNoStaticMACRootless
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PodBasicConfig
|
// PodBasicConfig
|
||||||
if p.NoInfra {
|
if p.NoInfra {
|
||||||
if len(p.InfraCommand) > 0 {
|
if len(p.InfraCommand) > 0 {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package specgen
|
package specgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@ -469,6 +470,15 @@ type PortMapping struct {
|
|||||||
Protocol string `json:"protocol,omitempty"`
|
Protocol string `json:"protocol,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoStaticIPRootless is used when a rootless user requests to assign a static IP address
|
||||||
|
// to a pod or container
|
||||||
|
ErrNoStaticIPRootless error = errors.New("rootless containers and pods cannot be assigned static IP addresses")
|
||||||
|
// ErrNoStaticMACRootless is used when a rootless user requests to assign a static MAC address
|
||||||
|
// to a pod or container
|
||||||
|
ErrNoStaticMACRootless error = errors.New("rootless containers and pods cannot be assigned static MAC addresses")
|
||||||
|
)
|
||||||
|
|
||||||
// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
|
// NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs
|
||||||
func NewSpecGenerator(arg string, rootfs bool) *SpecGenerator {
|
func NewSpecGenerator(arg string, rootfs bool) *SpecGenerator {
|
||||||
csc := ContainerStorageConfig{}
|
csc := ContainerStorageConfig{}
|
||||||
|
@ -595,3 +595,7 @@ func SkipIfNotFedora() {
|
|||||||
ginkgo.Skip("Test can only run on Fedora")
|
ginkgo.Skip("Test can only run on Fedora")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRootless() bool {
|
||||||
|
return os.Geteuid() != 0
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/v2/pkg/rootless"
|
||||||
. "github.com/containers/libpod/v2/test/utils"
|
. "github.com/containers/libpod/v2/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -19,7 +20,6 @@ var _ = Describe("Podman create with --ip flag", func() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
SkipIfRootless()
|
|
||||||
tempdir, err = CreateTempDirInTempDir()
|
tempdir, err = CreateTempDirInTempDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -39,18 +39,21 @@ var _ = Describe("Podman create with --ip flag", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("Podman create --ip with garbage address", func() {
|
It("Podman create --ip with garbage address", func() {
|
||||||
|
SkipIfRootless()
|
||||||
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "114232346", ALPINE, "ls"})
|
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "114232346", ALPINE, "ls"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).To(ExitWithError())
|
Expect(result).To(ExitWithError())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Podman create --ip with v6 address", func() {
|
It("Podman create --ip with v6 address", func() {
|
||||||
|
SkipIfRootless()
|
||||||
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "2001:db8:bad:beef::1", ALPINE, "ls"})
|
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "2001:db8:bad:beef::1", ALPINE, "ls"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).To(ExitWithError())
|
Expect(result).To(ExitWithError())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Podman create --ip with non-allocatable IP", func() {
|
It("Podman create --ip with non-allocatable IP", func() {
|
||||||
|
SkipIfRootless()
|
||||||
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "203.0.113.124", ALPINE, "ls"})
|
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", "203.0.113.124", ALPINE, "ls"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
@ -64,19 +67,25 @@ var _ = Describe("Podman create with --ip flag", func() {
|
|||||||
ip := GetRandomIPAddress()
|
ip := GetRandomIPAddress()
|
||||||
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", ip, ALPINE, "ip", "addr"})
|
result := podmanTest.Podman([]string{"create", "--name", "test", "--ip", ip, ALPINE, "ip", "addr"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
// Rootless static ip assignment should error
|
||||||
|
if rootless.IsRootless() {
|
||||||
|
Expect(result.ExitCode()).To(Equal(125))
|
||||||
|
} else {
|
||||||
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"start", "test"})
|
result = podmanTest.Podman([]string{"start", "test"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"logs", "test"})
|
result = podmanTest.Podman([]string{"logs", "test"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
Expect(result.OutputToString()).To(ContainSubstring(ip + "/16"))
|
Expect(result.OutputToString()).To(ContainSubstring(ip + "/16"))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Podman create two containers with the same IP", func() {
|
It("Podman create two containers with the same IP", func() {
|
||||||
|
SkipIfRootless()
|
||||||
ip := GetRandomIPAddress()
|
ip := GetRandomIPAddress()
|
||||||
result := podmanTest.Podman([]string{"create", "--name", "test1", "--ip", ip, ALPINE, "sleep", "999"})
|
result := podmanTest.Podman([]string{"create", "--name", "test1", "--ip", ip, ALPINE, "sleep", "999"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// +build !remote
|
|
||||||
|
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/v2/pkg/rootless"
|
||||||
. "github.com/containers/libpod/v2/test/utils"
|
. "github.com/containers/libpod/v2/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -18,7 +17,6 @@ var _ = Describe("Podman run with --mac-address flag", func() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
SkipIfRootless()
|
|
||||||
tempdir, err = CreateTempDirInTempDir()
|
tempdir, err = CreateTempDirInTempDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -40,7 +38,11 @@ var _ = Describe("Podman run with --mac-address flag", func() {
|
|||||||
It("Podman run --mac-address", func() {
|
It("Podman run --mac-address", func() {
|
||||||
result := podmanTest.Podman([]string{"run", "--mac-address", "92:d0:c6:0a:29:34", ALPINE, "ip", "addr"})
|
result := podmanTest.Podman([]string{"run", "--mac-address", "92:d0:c6:0a:29:34", ALPINE, "ip", "addr"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
if rootless.IsRootless() {
|
||||||
Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:0a:29:34"))
|
Expect(result.ExitCode()).To(Equal(125))
|
||||||
|
} else {
|
||||||
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
|
Expect(result.OutputToString()).To(ContainSubstring("92:d0:c6:0a:29:34"))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -28,11 +28,6 @@ func SkipIfRootless() {
|
|||||||
ginkgo.Skip("This function is not enabled for rootless podman")
|
ginkgo.Skip("This function is not enabled for rootless podman")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func SkipIfRootlessV2() {
|
|
||||||
if os.Geteuid() != 0 {
|
|
||||||
ginkgo.Skip("This function is not enabled for v2 rootless podman")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Podman is the exec call to podman on the filesystem
|
// Podman is the exec call to podman on the filesystem
|
||||||
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
||||||
|
@ -41,12 +41,6 @@ func SkipIfRootless() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SkipIfRootlessV2() {
|
|
||||||
if os.Geteuid() != 0 {
|
|
||||||
Skip("This function is not enabled for v2 rootless podman")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Podman is the exec call to podman on the filesystem
|
// Podman is the exec call to podman on the filesystem
|
||||||
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
|
||||||
podmanSession := p.PodmanBase(args, false, false)
|
podmanSession := p.PodmanBase(args, false, false)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/v2/pkg/rootless"
|
||||||
. "github.com/containers/libpod/v2/test/utils"
|
. "github.com/containers/libpod/v2/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -238,17 +239,20 @@ var _ = Describe("Podman pod create", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("podman create pod with IP address", func() {
|
It("podman create pod with IP address", func() {
|
||||||
SkipIfRootless()
|
|
||||||
name := "test"
|
name := "test"
|
||||||
ip := GetRandomIPAddress()
|
ip := GetRandomIPAddress()
|
||||||
podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name})
|
podCreate := podmanTest.Podman([]string{"pod", "create", "--ip", ip, "--name", name})
|
||||||
podCreate.WaitWithDefaultTimeout()
|
podCreate.WaitWithDefaultTimeout()
|
||||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
// Rootless should error
|
||||||
|
if rootless.IsRootless() {
|
||||||
podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
|
Expect(podCreate.ExitCode()).To(Equal(125))
|
||||||
podResolvConf.WaitWithDefaultTimeout()
|
} else {
|
||||||
Expect(podResolvConf.ExitCode()).To(Equal(0))
|
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||||
Expect(strings.Contains(podResolvConf.OutputToString(), ip)).To(BeTrue())
|
podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
|
||||||
|
podResolvConf.WaitWithDefaultTimeout()
|
||||||
|
Expect(podResolvConf.ExitCode()).To(Equal(0))
|
||||||
|
Expect(strings.Contains(podResolvConf.OutputToString(), ip)).To(BeTrue())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman create pod with IP address and no infra should fail", func() {
|
It("podman create pod with IP address and no infra should fail", func() {
|
||||||
@ -262,17 +266,20 @@ var _ = Describe("Podman pod create", func() {
|
|||||||
|
|
||||||
It("podman create pod with MAC address", func() {
|
It("podman create pod with MAC address", func() {
|
||||||
SkipIfRemote()
|
SkipIfRemote()
|
||||||
SkipIfRootless()
|
|
||||||
name := "test"
|
name := "test"
|
||||||
mac := "92:d0:c6:0a:29:35"
|
mac := "92:d0:c6:0a:29:35"
|
||||||
podCreate := podmanTest.Podman([]string{"pod", "create", "--mac-address", mac, "--name", name})
|
podCreate := podmanTest.Podman([]string{"pod", "create", "--mac-address", mac, "--name", name})
|
||||||
podCreate.WaitWithDefaultTimeout()
|
podCreate.WaitWithDefaultTimeout()
|
||||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
// Rootless should error
|
||||||
|
if rootless.IsRootless() {
|
||||||
podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
|
Expect(podCreate.ExitCode()).To(Equal(125))
|
||||||
podResolvConf.WaitWithDefaultTimeout()
|
} else {
|
||||||
Expect(podResolvConf.ExitCode()).To(Equal(0))
|
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||||
Expect(strings.Contains(podResolvConf.OutputToString(), mac)).To(BeTrue())
|
podResolvConf := podmanTest.Podman([]string{"run", "--pod", name, "-ti", "--rm", ALPINE, "ip", "addr"})
|
||||||
|
podResolvConf.WaitWithDefaultTimeout()
|
||||||
|
Expect(podResolvConf.ExitCode()).To(Equal(0))
|
||||||
|
Expect(strings.Contains(podResolvConf.OutputToString(), mac)).To(BeTrue())
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman create pod with MAC address and no infra should fail", func() {
|
It("podman create pod with MAC address and no infra should fail", func() {
|
||||||
|
@ -165,9 +165,13 @@ function random_ip() {
|
|||||||
# Create a pod with all the desired options
|
# Create a pod with all the desired options
|
||||||
# FIXME: --ip=$ip fails:
|
# FIXME: --ip=$ip fails:
|
||||||
# Error adding network: failed to allocate all requested IPs
|
# Error adding network: failed to allocate all requested IPs
|
||||||
|
local mac_option="--mac-address=$mac"
|
||||||
|
if is_rootless; then
|
||||||
|
mac_option=
|
||||||
|
fi
|
||||||
run_podman pod create --name=mypod \
|
run_podman pod create --name=mypod \
|
||||||
--pod-id-file=$pod_id_file \
|
--pod-id-file=$pod_id_file \
|
||||||
--mac-address=$mac \
|
$mac_option \
|
||||||
--hostname=$hostname \
|
--hostname=$hostname \
|
||||||
--add-host "$add_host_n:$add_host_ip" \
|
--add-host "$add_host_n:$add_host_ip" \
|
||||||
--dns "$dns_server" \
|
--dns "$dns_server" \
|
||||||
@ -181,7 +185,7 @@ function random_ip() {
|
|||||||
is "$(<$pod_id_file)" "$pod_id" "contents of pod-id-file"
|
is "$(<$pod_id_file)" "$pod_id" "contents of pod-id-file"
|
||||||
|
|
||||||
# Check each of the options
|
# Check each of the options
|
||||||
if ! is_rootless; then
|
if [ -n "$mac_option" ]; then
|
||||||
run_podman run --rm --pod mypod $IMAGE ip link show
|
run_podman run --rm --pod mypod $IMAGE ip link show
|
||||||
# 'ip' outputs hex in lower-case, ${expr,,} converts UC to lc
|
# 'ip' outputs hex in lower-case, ${expr,,} converts UC to lc
|
||||||
is "$output" ".* link/ether ${mac,,} " "requested MAC address was set"
|
is "$output" ".* link/ether ${mac,,} " "requested MAC address was set"
|
||||||
|
Reference in New Issue
Block a user