Skip to content

Commit

Permalink
Merge pull request #16237 from alexlarsson/quadlet-updates
Browse files Browse the repository at this point in the history
Various quadlet updates
  • Loading branch information
openshift-merge-robot authored Oct 26, 2022
2 parents 02fc9eb + bac907a commit ac8b401
Show file tree
Hide file tree
Showing 16 changed files with 157 additions and 41 deletions.
8 changes: 7 additions & 1 deletion cmd/quadlet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

var (
verboseFlag bool // True if -v passed
noKmsgFlag bool
isUser bool // True if run as quadlet-user-generator executable
)

Expand Down Expand Up @@ -134,7 +135,7 @@ func generateServiceFile(service *parser.UnitFile) error {
Debugf("writing '%s'", service.Path)

service.PrependComment("",
"Automatically generated by quadlet-generator",
fmt.Sprintf("Automatically generated by %s", os.Args[0]),
"")

f, err := os.Create(service.Path)
Expand Down Expand Up @@ -219,6 +220,10 @@ func main() {
enableDebug()
}

if noKmsgFlag {
noKmsg = true
}

if flag.NArg() < 1 {
Logf("Missing output directory argument")
os.Exit(1)
Expand Down Expand Up @@ -270,4 +275,5 @@ func main() {

func init() {
flag.BoolVar(&verboseFlag, "v", false, "Print debug information")
flag.BoolVar(&noKmsgFlag, "no-kmsg-log", false, "Don't log to kmsg")
}
3 changes: 2 additions & 1 deletion docs/source/markdown/options/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Valid _mode_ values are:
- **mac=MAC**: Specify a static mac address for this container.
- **interface_name**: Specify a name for the created network interface inside the container.

For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.
For example to set a static ipv4 address and a static mac address, use `--network bridge:ip=10.88.0.10,mac=44:33:22:11:00:99`.

- \<network name or ID\>[:OPTIONS,...]: Connect to a user-defined network; this is the network name or ID from a network created by **[podman network create](podman-network-create.1.md)**. Using the network name implies the bridge network mode. It is possible to specify the same options described under the bridge mode above. You can use the **--network** option multiple times to specify additional networks.
- **none**: Create a network namespace for the container but do not configure network interfaces for it, thus the container has no network connectivity.
- **container:**_id_: Reuse another container's network stack.
Expand Down
45 changes: 40 additions & 5 deletions docs/source/markdown/podman-systemd.unit.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,39 @@ setuid and file capabilities.

#### `DropCapability=` (defaults to `all`)

Drop these capabilities from the default container capability set. The default is `all`, allowing
addition of capabilities with `AddCapability`. Set this to empty to drop no capabilities.
This can be listed multiple times.
Drop these capabilities from the default podman capability set, or `all` for all capabilities. The default if no
`DropCapability` is set is `all`. Set this to empty (i.e. `DropCapability=`) to use the default podman capability set.

This is a space separated list of capabilities. This key can be listed multiple times.

For example:
```
DropCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
```

#### `AddCapability=`

By default, the container runs with no capabilities (due to DropCapabilities='all'). If any specific
caps are needed, then add them with this key. For example using `AddCapability=CAP_DAC_OVERRIDE`.
This can be listed multiple times.

#### `ReadOnly=` (defaults to `no`)
This is a space separated list of capabilities. This key can be listed multiple times.

For example:
```
AddCapability=CAP_DAC_OVERRIDE CAP_IPC_OWNER
```

#### `ReadOnly=` (defaults to `yes`)

If enabled, makes image read-only, with /var/tmp, /tmp and /run a tmpfs (unless disabled by `VolatileTmp=no`).

**NOTE:** Podman will automatically copy any content from the image onto the tmpfs

#### `SeccompProfile=`

Set the seccomp profile to use in the container. If unset, the default podman profile is used.
Set to either the pathname of a json file, or `unconfined` to disable the seccomp filters.

#### `RemapUsers=` (defaults to `no`)

If this is enabled, then host user and group ids are remapped in the container, such that all the uids
Expand Down Expand Up @@ -217,6 +234,14 @@ created by using a `$name.volume` quadlet file.

This key can be listed multiple times.

#### `Network=`

Specify a custom network for the container. This has the same format as the `--network` option
to `podman run`. For example, use `host` to use the host network in the container, or `none` to
not set up networking in the container.

This key can be listed multiple times.

#### `ExposeHostPort=`

Exposes a port, or a range of ports (e.g. `50-59`), from the host to the container. Equivalent
Expand All @@ -241,6 +266,16 @@ allocated port can be found with the `podman port` command.

This key can be listed multiple times.

#### `AddDevice=`

Adds a device node from the host into the container. The format of this is
`HOST-DEVICE[:CONTAINER-DEVICE][:PERMISSIONS]`, where `HOST-DEVICE` is the path of
the device node on the host, `CONTAINER-DEVICE` is the path of the device node in
the container, and `PERMISSIONS` is a list of permissions combining 'r' for read,
'w' for write, and 'm' for mknod(2).

This key can be listed multiple times.

#### `PodmanArgs=`

This key contains a list of arguments passed directly to the end of the `podman run` command
Expand Down
48 changes: 29 additions & 19 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const (
KeyRemapUIDRanges = "RemapUidRanges"
KeyRemapGIDRanges = "RemapGidRanges"
KeyNotify = "Notify"
KeySocketActivated = "SocketActivated"
KeyExposeHostPort = "ExposeHostPort"
KeyPublishPort = "PublishPort"
KeyKeepID = "KeepId"
Expand All @@ -71,6 +70,9 @@ const (
KeyRunInit = "RunInit"
KeyVolatileTmp = "VolatileTmp"
KeyTimezone = "Timezone"
KeySeccompProfile = "SeccompProfile"
KeyAddDevice = "AddDevice"
KeyNetwork = "Network"
)

// Supported keys in "Container" group
Expand All @@ -89,7 +91,6 @@ var supportedContainerKeys = map[string]bool{
KeyRemapUIDRanges: true,
KeyRemapGIDRanges: true,
KeyNotify: true,
KeySocketActivated: true,
KeyExposeHostPort: true,
KeyPublishPort: true,
KeyKeepID: true,
Expand All @@ -104,6 +105,9 @@ var supportedContainerKeys = map[string]bool{
KeyRunInit: true,
KeyVolatileTmp: true,
KeyTimezone: true,
KeySeccompProfile: true,
KeyAddDevice: true,
KeyNetwork: true,
}

// Supported keys in "Volume" group
Expand Down Expand Up @@ -353,8 +357,7 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
"-d",

// But we still want output to the journal, so use the log driver.
// TODO: Once available we want to use the passthrough log-driver instead.
"--log-driver", "journald",
"--log-driver", "passthrough",

// Never try to pull the image during service start
"--pull=never")
Expand All @@ -370,6 +373,13 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podman.addf("--tz=%s", timezone)
}

networks := container.LookupAll(ContainerGroup, KeyNetwork)
for _, network := range networks {
if len(network) > 0 {
podman.addf("--network=%s", network)
}
}

// Run with a pid1 init to reap zombies by default (as most apps don't do that)
runInit := container.LookupBoolean(ContainerGroup, KeyRunInit, true)
if runInit {
Expand Down Expand Up @@ -397,22 +407,34 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podman.add("--security-opt=no-new-privileges")
}

// But allow overrides with AddCapability
devices := container.LookupAllStrv(ContainerGroup, KeyAddDevice)
for _, device := range devices {
podman.addf("--device=%s", device)
}

// Default to no higher level privileges or caps
seccompProfile, hasSeccompProfile := container.Lookup(ContainerGroup, KeySeccompProfile)
if hasSeccompProfile {
podman.add("--security-opt", fmt.Sprintf("seccomp=%s", seccompProfile))
}

dropCaps := []string{"all"} // Default
if container.HasKey(ContainerGroup, KeyDropCapability) {
dropCaps = container.LookupAll(ContainerGroup, KeyDropCapability)
dropCaps = container.LookupAllStrv(ContainerGroup, KeyDropCapability)
}

for _, caps := range dropCaps {
podman.addf("--cap-drop=%s", strings.ToLower(caps))
}

// But allow overrides with AddCapability
addCaps := container.LookupAll(ContainerGroup, KeyAddCapability)
addCaps := container.LookupAllStrv(ContainerGroup, KeyAddCapability)
for _, caps := range addCaps {
podman.addf("--cap-add=%s", strings.ToLower(caps))
}

readOnly := container.LookupBoolean(ContainerGroup, KeyReadOnly, false)
readOnly := container.LookupBoolean(ContainerGroup, KeyReadOnly, true)
if readOnly {
podman.add("--read-only")
}
Expand All @@ -429,18 +451,6 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile
podman.add("--read-only-tmpfs=false")
}

socketActivated := container.LookupBoolean(ContainerGroup, KeySocketActivated, false)
if socketActivated {
// TODO: This will not be needed with later podman versions that support activation directly:
// https://github.com/containers/podman/pull/11316
podman.add("--preserve-fds=1")
podmanEnv["LISTEN_FDS"] = "1"

// TODO: This will not be 2 when catatonit forwards fds:
// https://github.com/openSUSE/catatonit/pull/15
podmanEnv["LISTEN_PID"] = "2"
}

defaultContainerUID := uint32(0)
defaultContainerGID := uint32(0)

Expand Down
4 changes: 2 additions & 2 deletions test/e2e/quadlet/basepodman.container
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
## assert-podman-final-args run --name=systemd-%N --cidfile=%t/%N.cid --replace --rm -d --log-driver journald --pull=never --runtime /usr/bin/crun --cgroups=split --sdnotify=conmon imagename
## assert-podman-final-args run --name=systemd-%N --cidfile=%t/%N.cid --replace --rm -d --log-driver passthrough --pull=never --runtime /usr/bin/crun --cgroups=split --sdnotify=conmon imagename

[Container]
Image=imagename

# Disable all default features to get as empty podman run command as we can
RemapUsers=no
ReadOnly=no
NoNewPrivileges=no
DropCapability=
RunInit=no
Expand Down
5 changes: 3 additions & 2 deletions test/e2e/quadlet/basic.container
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
## assert-podman-args "--rm"
## assert-podman-args "--replace"
## assert-podman-args "-d"
## assert-podman-args "--log-driver" "journald"
## assert-podman-args "--log-driver" "passthrough"
## assert-podman-args "--pull=never"
## assert-podman-args "--init"
## assert-podman-args "--runtime" "/usr/bin/crun"
## assert-podman-args "--cgroups=split"
## assert-podman-args "--sdnotify=conmon"
## assert-podman-args "--security-opt=no-new-privileges"
## assert-podman-args "--cap-drop=all"
## assert-podman-args "--tmpfs" "/tmp:rw,size=512M,mode=1777"
## assert-podman-args "--read-only"
## !assert-podman-args "--read-only-tmpfs=false"
## assert-key-is "Unit" "RequiresMountsFor" "%t/containers"
## assert-key-is "Service" "KillMode" "mixed"
## assert-key-is "Service" "Delegate" "yes"
Expand Down
7 changes: 5 additions & 2 deletions test/e2e/quadlet/capabilities.container
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
## assert-podman-args "--cap-drop=all"
## !assert-podman-args "--cap-drop=all"
## assert-podman-args "--cap-add=cap_dac_override"
## assert-podman-args "--cap-add=cap_audit_write"
## assert-podman-args "--cap-add=cap_ipc_owner"

[Container]
Image=imagename
AddCapability=CAP_DAC_OVERRIDE
# Verify that we can reset to the default cap set
DropCapability=
AddCapability=CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
AddCapability=CAP_IPC_OWNER
9 changes: 9 additions & 0 deletions test/e2e/quadlet/capabilities2.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## !assert-podman-args "--cap-drop=all"
## assert-podman-args "--cap-drop=cap_dac_override"
## assert-podman-args "--cap-drop=cap_audit_write"
## assert-podman-args "--cap-drop=cap_ipc_owner"

[Container]
Image=localhost/imagename
DropCapability=CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
DropCapability=CAP_IPC_OWNER
7 changes: 7 additions & 0 deletions test/e2e/quadlet/devices.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## assert-podman-args --device=/dev/fuse
## assert-podman-args --device=/dev/loop0:r

[Container]
Image=localhost/imagename
AddDevice=/dev/fuse
AddDevice=/dev/loop0:r
5 changes: 5 additions & 0 deletions test/e2e/quadlet/network.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-podman-args "--network=host"

[Container]
Image=localhost/imagename
Network=host
2 changes: 1 addition & 1 deletion test/e2e/quadlet/noimage.container
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## assert-failed
## assert-stderr-contains "No Image key specified"
## assert-stderr-contains "no Image key specified"

[Container]
6 changes: 6 additions & 0 deletions test/e2e/quadlet/readonly-notmpfs.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## assert-podman-args "--read-only-tmpfs=false"
## assert-podman-args "--read-only"

[Container]
Image=localhost/imagename
VolatileTmp=no
7 changes: 7 additions & 0 deletions test/e2e/quadlet/readwrite-notmpfs.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## !assert-podman-args "--read-only"
## !assert-podman-args "--tmpfs" "/tmp:rw,size=512M,mode=1777"

[Container]
Image=localhost/imagename
VolatileTmp=no
ReadOnly=no
6 changes: 6 additions & 0 deletions test/e2e/quadlet/readwrite.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## !assert-podman-args "--read-only"
## assert-podman-args "--tmpfs" "/tmp:rw,size=512M,mode=1777"

[Container]
Image=localhost/imagename
ReadOnly=no
5 changes: 5 additions & 0 deletions test/e2e/quadlet/seccomp.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-podman-args --security-opt seccomp=unconfined

[Container]
Image=localhost/imagename
SeccompProfile=unconfined
Loading

0 comments on commit ac8b401

Please sign in to comment.