oci-containers: consolidate capabilities interface (#363574)

* oci-containers: consolidate capabilities interface

* Update nixos/modules/virtualisation/oci-containers.nix

Improved wording

Co-authored-by: Benjamin Staffin <benley@zoiks.net>

---------

Co-authored-by: Benjamin Staffin <benley@zoiks.net>
This commit is contained in:
Yethal 2024-12-12 17:50:13 +01:00 committed by GitHub
parent d011002802
commit 91bb1c6d75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 61 additions and 64 deletions

View File

@ -295,28 +295,19 @@ let
''; '';
}; };
capAdd = mkOption { capabilities = mkOption {
type = with types; lazyAttrsOf (nullOr bool); type = with types; lazyAttrsOf (nullOr bool);
default = { }; default = { };
description = '' description = ''
Capabilities to add to container Capabilities to configure for the container.
''; When set to true, capability is added to the container.
example = literalExpression '' When set to false, capability is dropped from the container.
{ When null, default runtime settings apply.
SYS_ADMIN = true;
{
'';
};
capDrop = mkOption {
type = with types; lazyAttrsOf (nullOr bool);
default = { };
description = ''
Capabilities to drop from container
''; '';
example = literalExpression '' example = literalExpression ''
{ {
SYS_ADMIN = true; SYS_ADMIN = true;
SYS_WRITE = false;
{ {
''; '';
}; };
@ -441,10 +432,10 @@ let
++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}" ++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}"
++ optional (container.privileged) "--privileged" ++ optional (container.privileged) "--privileged"
++ mapAttrsToList (k: _: "--cap-add=${escapeShellArg k}") ( ++ mapAttrsToList (k: _: "--cap-add=${escapeShellArg k}") (
filterAttrs (_: v: v == true) container.capAdd filterAttrs (_: v: v == true) container.capabilities
) )
++ mapAttrsToList (k: _: "--cap-drop=${escapeShellArg k}") ( ++ mapAttrsToList (k: _: "--cap-drop=${escapeShellArg k}") (
filterAttrs (_: v: v == true) container.capDrop filterAttrs (_: v: v == false) container.capabilities
) )
++ map (d: "--device=${escapeShellArg d}") container.devices ++ map (d: "--device=${escapeShellArg d}") container.devices
++ map (n: "--network=${escapeShellArg n}") container.networks ++ map (n: "--network=${escapeShellArg n}") container.networks

View File

@ -1,32 +1,34 @@
{ system ? builtins.currentSystem {
, config ? {} system ? builtins.currentSystem,
, pkgs ? import ../.. { inherit system config; } config ? { },
, lib ? pkgs.lib pkgs ? import ../.. { inherit system config; },
lib ? pkgs.lib,
}: }:
let let
inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest; inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
mkOCITest = backend: makeTest { mkOCITest =
backend:
makeTest {
name = "oci-containers-${backend}"; name = "oci-containers-${backend}";
meta.maintainers = lib.teams.serokell.members meta.maintainers = lib.teams.serokell.members ++ (with lib.maintainers; [ benley ]);
++ (with lib.maintainers; [ benley ]);
nodes = { nodes = {
${backend} = { pkgs, ... }: { ${backend} =
{ pkgs, ... }:
{
virtualisation.oci-containers = { virtualisation.oci-containers = {
inherit backend; inherit backend;
containers.nginx = { containers.nginx = {
image = "nginx-container"; image = "nginx-container";
imageStream = pkgs.dockerTools.examples.nginxStream; imageStream = pkgs.dockerTools.examples.nginxStream;
ports = ["8181:80"]; ports = [ "8181:80" ];
capAdd = { capabilities = {
CAP_AUDIT_READ = true; CAP_AUDIT_READ = true;
}; CAP_AUDIT_WRITE = false;
capDrop = {
CAP_AUDIT_WRITE = true;
}; };
privileged = false; privileged = false;
devices = [ devices = [
@ -51,14 +53,18 @@ let
output = json.loads(${backend}.succeed("${backend} inspect nginx --format json").strip())[0] output = json.loads(${backend}.succeed("${backend} inspect nginx --format json").strip())[0]
${backend}.succeed("systemctl stop ${backend}-nginx.service", timeout=10) ${backend}.succeed("systemctl stop ${backend}-nginx.service", timeout=10)
assert output['HostConfig']['CapAdd'] == ["CAP_AUDIT_READ"] assert output['HostConfig']['CapAdd'] == ["CAP_AUDIT_READ"]
assert output['HostConfig']['CapDrop'] == ${if backend == "docker" then "[\"CAP_AUDIT_WRITE\"]" else "[]"} # Rootless podman runs with no capabilities so it cannot drop them assert output['HostConfig']['CapDrop'] == ${
if backend == "docker" then "[\"CAP_AUDIT_WRITE\"]" else "[]"
} # Rootless podman runs with no capabilities so it cannot drop them
assert output['HostConfig']['Privileged'] == False assert output['HostConfig']['Privileged'] == False
assert output['HostConfig']['Devices'] == [{'PathOnHost': '/dev/random', 'PathInContainer': '/dev/random', 'CgroupPermissions': '${if backend == "docker" then "rwm" else ""}'}] assert output['HostConfig']['Devices'] == [{'PathOnHost': '/dev/random', 'PathInContainer': '/dev/random', 'CgroupPermissions': '${
if backend == "docker" then "rwm" else ""
}'}]
''; '';
}; };
in in
lib.foldl' (attrs: backend: attrs // { ${backend} = mkOCITest backend; }) {} [ lib.foldl' (attrs: backend: attrs // { ${backend} = mkOCITest backend; }) { } [
"docker" "docker"
"podman" "podman"
] ]