From 32c5e04919862b40b4048402a0f395750b2df906 Mon Sep 17 00:00:00 2001 From: zowoq <59103226+zowoq@users.noreply.github.com> Date: Thu, 27 May 2021 09:59:49 +1000 Subject: [PATCH 01/17] docker: add clientOnly / docker-client Currently the docker client is only available on non-linux platforms as `docker`, this makes the client available on linux and other platforms as `docker-client`. (cherry picked from commit 7233acd515546107e5902a8fef6832f4f319390c) --- pkgs/applications/virtualization/docker/default.nix | 9 +++++---- pkgs/top-level/all-packages.nix | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/applications/virtualization/docker/default.nix b/pkgs/applications/virtualization/docker/default.nix index 954404e5268..6b72653c347 100644 --- a/pkgs/applications/virtualization/docker/default.nix +++ b/pkgs/applications/virtualization/docker/default.nix @@ -17,6 +17,7 @@ rec { , btrfs-progs, iptables, e2fsprogs, xz, util-linux, xfsprogs, git , procps, libseccomp , nixosTests + , clientOnly ? !stdenv.isLinux }: let docker-runc = runc.overrideAttrs (oldAttrs: { @@ -116,7 +117,7 @@ rec { ++ optional (libseccomp != null) "seccomp"; }); in - buildGoPackage ((optionalAttrs (stdenv.isLinux) { + buildGoPackage ((optionalAttrs (!clientOnly) { inherit docker-runc docker-containerd docker-proxy docker-tini moby; @@ -137,7 +138,7 @@ rec { nativeBuildInputs = [ makeWrapper pkg-config go-md2man go libtool installShellFiles ]; - buildInputs = optionals (stdenv.isLinux) [ + buildInputs = optionals (!clientOnly) [ sqlite lvm2 btrfs-progs systemd libseccomp ] ++ optionals (buildxSupport) [ docker-buildx ]; @@ -177,7 +178,7 @@ rec { makeWrapper $out/libexec/docker/docker $out/bin/docker \ --prefix PATH : "$out/libexec/docker:$extraPath" - '' + optionalString (stdenv.isLinux) '' + '' + optionalString (!clientOnly) '' # symlink docker daemon to docker cli derivation ln -s ${moby}/bin/dockerd $out/bin/dockerd @@ -204,7 +205,7 @@ rec { installManPage man/*/*.[1-9] ''; - passthru.tests = { inherit (nixosTests) docker; }; + passthru.tests = lib.optionals (!clientOnly) { inherit (nixosTests) docker; }; meta = { homepage = "https://www.docker.com/"; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 9b9a0199fd6..6b690c6ccab 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -23020,6 +23020,7 @@ in docker = docker_20_10; docker-edge = docker_20_10; + docker-client = docker.override { clientOnly = true; }; docker-proxy = callPackage ../applications/virtualization/docker/proxy.nix { }; From 73f566b2add5839924107c92715d886e59df833d Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Mon, 24 May 2021 14:03:37 +0300 Subject: [PATCH 02/17] maintainers: add mikroskeem (cherry picked from commit f830b000fc8aafd14bf3151178919378584e87c9) --- maintainers/maintainer-list.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 202e166443a..e979e9efcf5 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -6587,6 +6587,16 @@ githubId = 1387206; name = "Mike Sperber"; }; + mikroskeem = { + email = "mikroskeem@mikroskeem.eu"; + github = "mikroskeem"; + githubId = 3490861; + name = "Mark Vainomaa"; + keys = [{ + longkeyid = "rsa4096/0xDA015B05B5A11B22"; + fingerprint = "DB43 2895 CF68 F0CE D4B7 EF60 DA01 5B05 B5A1 1B22"; + }]; + }; milesbreslin = { email = "milesbreslin@gmail.com"; github = "milesbreslin"; From d33aa3d0d34953152123c05d70dcfdab79617c10 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa Date: Mon, 24 May 2021 14:29:16 +0300 Subject: [PATCH 03/17] dnsname-cni: init at 1.1.1 (cherry picked from commit 5826e9020636c8ba3bc311294ce78b6466fd2b24) --- .../cluster/dnsname-cni/default.nix | 32 +++++++++++++++++++ .../dnsname-cni/hardcode-dnsmasq-path.patch | 19 +++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 3 files changed, 53 insertions(+) create mode 100644 pkgs/applications/networking/cluster/dnsname-cni/default.nix create mode 100644 pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch diff --git a/pkgs/applications/networking/cluster/dnsname-cni/default.nix b/pkgs/applications/networking/cluster/dnsname-cni/default.nix new file mode 100644 index 00000000000..91ef8b68fb6 --- /dev/null +++ b/pkgs/applications/networking/cluster/dnsname-cni/default.nix @@ -0,0 +1,32 @@ +{ buildGoModule, fetchFromGitHub, lib, dnsmasq }: + +buildGoModule rec { + pname = "cni-plugin-dnsname"; + version = "1.1.1"; + + src = fetchFromGitHub { + owner = "containers"; + repo = "dnsname"; + rev = "v${version}"; + sha256 = "090kpq2ppan9ayajdk5vwbvww30nphylgajn2p3441d4jg2nvsm3"; + }; + + patches = [ ./hardcode-dnsmasq-path.patch ]; + + postPatch = '' + substituteInPlace plugins/meta/dnsname/service.go --replace '@DNSMASQ@' '${dnsmasq}/bin/dnsmasq' + ''; + + vendorSha256 = null; + subPackages = [ "plugins/meta/dnsname" ]; + + doCheck = false; # NOTE: requires root privileges + + meta = with lib; { + description = "DNS name resolution for containers"; + homepage = "https://github.com/containers/dnsname"; + license = licenses.asl20; + platforms = platforms.linux; + maintainers = with maintainers; [ mikroskeem ]; + }; +} diff --git a/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch b/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch new file mode 100644 index 00000000000..24ef5eb85d1 --- /dev/null +++ b/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch @@ -0,0 +1,19 @@ +diff --git a/plugins/meta/dnsname/service.go b/plugins/meta/dnsname/service.go +index fc05f75..f6b4caf 100644 +--- a/plugins/meta/dnsname/service.go ++++ b/plugins/meta/dnsname/service.go +@@ -16,10 +16,14 @@ import ( + + // newDNSMasqFile creates a new instance of a dnsNameFile + func newDNSMasqFile(domainName, networkInterface, networkName string) (dnsNameFile, error) { ++ /* + dnsMasqBinary, err := exec.LookPath("dnsmasq") + if err != nil { + return dnsNameFile{}, errors.Errorf("the dnsmasq cni plugin requires the dnsmasq binary be in PATH") + } ++ */ ++ _ = errors.Errorf // XXX(mikroskeem): reduce diff ++ dnsMasqBinary := "@DNSMASQ@" + masqConf := dnsNameFile{ + ConfigFile: makePath(networkName, confFileName), + Domain: domainName, diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 6b690c6ccab..abc4aee9dab 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -22851,6 +22851,8 @@ in cni = callPackage ../applications/networking/cluster/cni {}; cni-plugins = callPackage ../applications/networking/cluster/cni/plugins.nix {}; + dnsname-cni = callPackage ../applications/networking/cluster/dnsname-cni {}; + cntr = callPackage ../applications/virtualization/cntr { }; communi = libsForQt5.callPackage ../applications/networking/irc/communi { }; From 0919b5c41961a5c5e70114694e149f9859f01649 Mon Sep 17 00:00:00 2001 From: Nick Cao Date: Wed, 26 May 2021 23:56:20 +0800 Subject: [PATCH 04/17] podman: add systemd to rpath (cherry picked from commit ada45ac3aee664265759611d09443d549250bd70) --- pkgs/applications/virtualization/podman/default.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/applications/virtualization/podman/default.nix b/pkgs/applications/virtualization/podman/default.nix index c8b8467def5..f392fd98c43 100644 --- a/pkgs/applications/virtualization/podman/default.nix +++ b/pkgs/applications/virtualization/podman/default.nix @@ -75,6 +75,11 @@ buildGoModule rec { runHook postInstall ''; + postFixup = lib.optionalString stdenv.isLinux '' + RPATH=$(patchelf --print-rpath $out/bin/podman) + patchelf --set-rpath "${lib.makeLibraryPath [ systemd ]}":$RPATH $out/bin/podman + ''; + passthru.tests = { inherit (nixosTests) podman; }; meta = with lib; { From 17ba99dd686395191c4876049145c7801ccb4bb8 Mon Sep 17 00:00:00 2001 From: zowoq <59103226+zowoq@users.noreply.github.com> Date: Sun, 30 May 2021 11:14:03 +1000 Subject: [PATCH 05/17] podman: install cni config (cherry picked from commit fd59022ee9eb8d08b65df563c65e4218a68fca3c) --- pkgs/applications/virtualization/podman/default.nix | 1 + pkgs/applications/virtualization/podman/wrapper.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/pkgs/applications/virtualization/podman/default.nix b/pkgs/applications/virtualization/podman/default.nix index f392fd98c43..c72a3577bf8 100644 --- a/pkgs/applications/virtualization/podman/default.nix +++ b/pkgs/applications/virtualization/podman/default.nix @@ -69,6 +69,7 @@ buildGoModule rec { installShellCompletion --zsh completions/zsh/* MANDIR=$man/share/man make install.man-nobuild '' + lib.optionalString stdenv.isLinux '' + install -Dm644 cni/87-podman-bridge.conflist -t $out/etc/cni/net.d install -Dm644 contrib/tmpfile/podman.conf -t $out/lib/tmpfiles.d install -Dm644 contrib/systemd/system/podman.{socket,service} -t $out/lib/systemd/system '' + '' diff --git a/pkgs/applications/virtualization/podman/wrapper.nix b/pkgs/applications/virtualization/podman/wrapper.nix index ae163583e69..9f3e1943b56 100644 --- a/pkgs/applications/virtualization/podman/wrapper.nix +++ b/pkgs/applications/virtualization/podman/wrapper.nix @@ -48,6 +48,7 @@ in runCommand podman.name { ln -s ${podman.man} $man mkdir -p $out/bin + ln -s ${podman-unwrapped}/etc $out/etc ln -s ${podman-unwrapped}/lib $out/lib ln -s ${podman-unwrapped}/share $out/share makeWrapper ${podman-unwrapped}/bin/podman $out/bin/podman \ From f63aff597b99ebf9c132dc01a712b0c54376ca5d Mon Sep 17 00:00:00 2001 From: zowoq <59103226+zowoq@users.noreply.github.com> Date: Sun, 30 May 2021 11:15:02 +1000 Subject: [PATCH 06/17] nixos/podman: install cni config from package (cherry picked from commit 30ae7e4ba983de461c7b71d02274d184ab55244d) --- nixos/modules/virtualisation/podman.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index d6421d488b8..d485f993fb3 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, utils, ... }: +{ config, lib, pkgs, ... }: let cfg = config.virtualisation.podman; toml = pkgs.formats.toml { }; @@ -92,7 +92,7 @@ in environment.systemPackages = [ cfg.package ] ++ lib.optional cfg.dockerCompat dockerCompat; - environment.etc."cni/net.d/87-podman-bridge.conflist".source = utils.copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist"; + environment.etc."cni/net.d/87-podman-bridge.conflist".source = "${cfg.package}/etc/cni/net.d/87-podman-bridge.conflist"; virtualisation.containers = { enable = true; # Enable common /etc/containers configuration From db05ed8b0d87d11535514e5b9853652bf33e7aca Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 25 May 2021 10:22:29 +0200 Subject: [PATCH 07/17] nixos/podman: Change podman socket to new podman group (cherry picked from commit fb8b0a38433c8e83a53c1dc0a739c5a7ad64e2fc) --- nixos/modules/virtualisation/podman.nix | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index d485f993fb3..05c9075fa73 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -111,8 +111,19 @@ in }; systemd.sockets.podman.wantedBy = [ "sockets.target" ]; + systemd.sockets.podman.socketConfig.SocketGroup = "podman"; - systemd.tmpfiles.packages = [ cfg.package ]; + systemd.tmpfiles.packages = [ + # The /run/podman rule interferes with our podman group, so we remove + # it and let the systemd socket logic take care of it. + (pkgs.runCommand "podman-tmpfiles-nixos" { package = cfg.package; } '' + mkdir -p $out/lib/tmpfiles.d/ + grep -v 'D! /run/podman 0700 root root' \ + <$package/lib/tmpfiles.d/podman.conf \ + >$out/lib/tmpfiles.d/podman.conf + '') ]; + + users.groups.podman = {}; assertions = [ { From 0c5e6d0beab9c41c4795eb721fbd9d60889b9563 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 25 May 2021 10:26:28 +0200 Subject: [PATCH 08/17] nixos/podman: Add dockerSocket.enable (cherry picked from commit ff4d83a66727ad13da0f51d00db4eda8a8c50590) --- nixos/modules/virtualisation/podman.nix | 25 +++++++++++++++++ nixos/tests/podman.nix | 37 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index 05c9075fa73..076d28eb5ba 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -46,6 +46,20 @@ in ''; }; + dockerSocket.enable = mkOption { + type = types.bool; + default = false; + description = '' + Make the Podman socket available in place of the Docker socket, so + Docker tools can find the Podman socket. + + Podman implements the Docker API. + + Users must be in the podman group in order to connect. As + with Docker, members of this group can gain root access. + ''; + }; + dockerCompat = mkOption { type = types.bool; default = false; @@ -123,6 +137,11 @@ in >$out/lib/tmpfiles.d/podman.conf '') ]; + systemd.tmpfiles.rules = + lib.optionals cfg.dockerSocket.enable [ + "L! /run/docker.sock - - - - /run/podman/podman.sock" + ]; + users.groups.podman = {}; assertions = [ @@ -130,6 +149,12 @@ in assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable; message = "Option dockerCompat conflicts with docker"; } + { + assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable; + message = '' + The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket. + ''; + } ]; } ]); diff --git a/nixos/tests/podman.nix b/nixos/tests/podman.nix index 6078a936ede..343ecbe14b2 100644 --- a/nixos/tests/podman.nix +++ b/nixos/tests/podman.nix @@ -13,10 +13,23 @@ import ./make-test-python.nix ( { virtualisation.podman.enable = true; + # To test docker socket support + virtualisation.podman.dockerSocket.enable = true; + environment.systemPackages = [ + pkgs.docker-client + ]; + users.users.alice = { isNormalUser = true; home = "/home/alice"; description = "Alice Foobar"; + extraGroups = [ "podman" ]; + }; + + users.users.mallory = { + isNormalUser = true; + home = "/home/mallory"; + description = "Mallory Foobar"; }; }; @@ -26,9 +39,9 @@ import ./make-test-python.nix ( import shlex - def su_cmd(cmd): + def su_cmd(cmd, user = "alice"): cmd = shlex.quote(cmd) - return f"su alice -l -c {cmd}" + return f"su {user} -l -c {cmd}" podman.wait_for_unit("sockets.target") @@ -105,6 +118,26 @@ import ./make-test-python.nix ( assert pid == "1" pid = podman.succeed("podman run --rm --init busybox readlink /proc/self").strip() assert pid == "2" + + with subtest("A podman member can use the docker cli"): + podman.succeed(su_cmd("docker version")) + + with subtest("Run container via docker cli"): + podman.succeed("docker network create default") + podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg") + podman.succeed( + "docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10" + ) + podman.succeed("docker ps | grep sleeping") + podman.succeed("podman ps | grep sleeping") + podman.succeed("docker stop sleeping") + podman.succeed("docker rm sleeping") + + with subtest("A podman non-member can not use the docker cli"): + podman.fail(su_cmd("docker version", user="mallory")) + + # TODO: add docker-compose test + ''; } ) From ffde2bb4a1cafa60290364cb9d2233d1af983bed Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 25 May 2021 10:16:30 +0200 Subject: [PATCH 09/17] nixos/podman: Add generic networkSocket interface (cherry picked from commit 52844efcd67028a481a24103d8e93c7ef2bf4f08) --- .../virtualisation/podman-network-socket.nix | 91 +++++++++++++++++++ nixos/modules/virtualisation/podman.nix | 1 + 2 files changed, 92 insertions(+) create mode 100644 nixos/modules/virtualisation/podman-network-socket.nix diff --git a/nixos/modules/virtualisation/podman-network-socket.nix b/nixos/modules/virtualisation/podman-network-socket.nix new file mode 100644 index 00000000000..1429164630b --- /dev/null +++ b/nixos/modules/virtualisation/podman-network-socket.nix @@ -0,0 +1,91 @@ +{ config, lib, pkg, ... }: +let + inherit (lib) + mkOption + types + ; + + cfg = config.virtualisation.podman.networkSocket; + +in +{ + options.virtualisation.podman.networkSocket = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Make the Podman and Docker compatibility API available over the network + with TLS client certificate authentication. + + This allows Docker clients to connect with the equivalents of the Docker + CLI -H and --tls* family of options. + + For certificate setup, see https://docs.docker.com/engine/security/protect-access/ + + This option is independent of . + ''; + }; + + server = mkOption { + type = types.enum []; + description = '' + Choice of TLS proxy server. + ''; + example = "ghostunnel"; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open the port in the firewall. + ''; + }; + + tls.cacert = mkOption { + type = types.path; + description = '' + Path to CA certificate to use for client authentication. + ''; + }; + + tls.cert = mkOption { + type = types.path; + description = '' + Path to certificate describing the server. + ''; + }; + + tls.key = mkOption { + type = types.path; + description = '' + Path to the private key corresponding to the server certificate. + + Use a string for this setting. Otherwise it will be copied to the Nix + store first, where it is readable by any system process. + ''; + }; + + port = mkOption { + type = types.port; + default = 2376; + description = '' + TCP port number for receiving TLS connections. + ''; + }; + listenAddress = mkOption { + type = types.str; + default = "0.0.0.0"; + description = '' + Interface address for receiving TLS connections. + ''; + }; + }; + + config = { + networking.firewall.allowedTCPPorts = + lib.optional (cfg.enable && cfg.openFirewall) cfg.port; + }; + + meta.maintainers = lib.teams.podman.members ++ [ lib.maintainers.roberth ]; +} diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index 076d28eb5ba..b16afb66894 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -25,6 +25,7 @@ let in { imports = [ + ./podman-network-socket.nix (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ]) ]; From 833b005e3796ebd3ca7985d19d7ad458b4d891e5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 25 May 2021 10:15:22 +0200 Subject: [PATCH 10/17] nixos/podman-network-socket-ghostunnel: init (cherry picked from commit b6570e723836167640c9b7efc63f327ff17b0755) --- nixos/modules/module-list.nix | 1 + .../podman-network-socket-ghostunnel.nix | 34 ++++ nixos/tests/all-tests.nix | 1 + nixos/tests/podman-tls-ghostunnel.nix | 150 ++++++++++++++++++ .../virtualization/podman/default.nix | 6 +- 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix create mode 100644 nixos/tests/podman-tls-ghostunnel.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7a0a90f4bd2..326428b95c3 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1111,6 +1111,7 @@ ./virtualisation/openvswitch.nix ./virtualisation/parallels-guest.nix ./virtualisation/podman.nix + ./virtualisation/podman-network-socket-ghostunnel.nix ./virtualisation/qemu-guest-agent.nix ./virtualisation/railcar.nix ./virtualisation/spice-usb-redirection.nix diff --git a/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix b/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix new file mode 100644 index 00000000000..1f1ada7f089 --- /dev/null +++ b/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix @@ -0,0 +1,34 @@ +{ config, lib, pkg, ... }: +let + inherit (lib) + mkOption + types + ; + + cfg = config.virtualisation.podman.networkSocket; + +in +{ + options.virtualisation.podman.networkSocket = { + server = mkOption { + type = types.enum [ "ghostunnel" ]; + }; + }; + + config = { + + services.ghostunnel = lib.mkIf (cfg.enable && cfg.server == "ghostunnel") { + enable = true; + servers."podman-socket" = { + inherit (cfg.tls) cert key cacert; + listen = "${cfg.listenAddress}:${toString cfg.port}"; + target = "unix:/run/podman/podman.sock"; + allowAll = lib.mkDefault true; + }; + }; + systemd.services.ghostunnel-server-podman-socket.serviceConfig.SupplementaryGroups = ["podman"]; + + }; + + meta.maintainers = lib.teams.podman.members ++ [ lib.maintainers.roberth ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e3f92ce451c..7f0a987f89c 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -334,6 +334,7 @@ in plotinus = handleTest ./plotinus.nix {}; podgrab = handleTest ./podgrab.nix {}; podman = handleTestOn ["x86_64-linux"] ./podman.nix {}; + podman-tls-ghostunnel = handleTestOn ["x86_64-linux"] ./podman-tls-ghostunnel.nix {}; pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {}; postfix = handleTest ./postfix.nix {}; postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {}; diff --git a/nixos/tests/podman-tls-ghostunnel.nix b/nixos/tests/podman-tls-ghostunnel.nix new file mode 100644 index 00000000000..0e687b199b2 --- /dev/null +++ b/nixos/tests/podman-tls-ghostunnel.nix @@ -0,0 +1,150 @@ +/* + This test runs podman as a backend for the Docker CLI. + */ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + + let gen-ca = pkgs.writeScript "gen-ca" '' + # Create CA + PATH="${pkgs.openssl}/bin:$PATH" + openssl genrsa -out ca-key.pem 4096 + openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -subj '/C=NL/ST=Zuid-Holland/L=The Hague/O=Stevige Balken en Planken B.V./OU=OpSec/CN=Certificate Authority' -out ca.pem + + # Create service + openssl genrsa -out podman-key.pem 4096 + openssl req -subj '/CN=podman' -sha256 -new -key podman-key.pem -out service.csr + echo subjectAltName = DNS:podman,IP:127.0.0.1 >> extfile.cnf + echo extendedKeyUsage = serverAuth >> extfile.cnf + openssl x509 -req -days 365 -sha256 -in service.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out podman-cert.pem -extfile extfile.cnf + + # Create client + openssl genrsa -out client-key.pem 4096 + openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr + echo extendedKeyUsage = clientAuth > extfile-client.cnf + openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile-client.cnf + + # Create CA 2 + PATH="${pkgs.openssl}/bin:$PATH" + openssl genrsa -out ca-2-key.pem 4096 + openssl req -new -x509 -days 365 -key ca-2-key.pem -sha256 -subj '/C=NL/ST=Zuid-Holland/L=The Hague/O=Stevige Balken en Planken B.V./OU=OpSec/CN=Certificate Authority' -out ca-2.pem + + # Create client signed by CA 2 + openssl genrsa -out client-2-key.pem 4096 + openssl req -subj '/CN=client' -new -key client-2-key.pem -out client-2.csr + echo extendedKeyUsage = clientAuth > extfile-client.cnf + openssl x509 -req -days 365 -sha256 -in client-2.csr -CA ca-2.pem -CAkey ca-2-key.pem -CAcreateserial -out client-2-cert.pem -extfile extfile-client.cnf + + ''; + in + { + name = "podman-tls-ghostunnel"; + meta = { + maintainers = lib.teams.podman.members ++ [ lib.maintainers.roberth ]; + }; + + nodes = { + podman = + { pkgs, ... }: + { + virtualisation.podman.enable = true; + virtualisation.podman.dockerSocket.enable = true; + virtualisation.podman.networkSocket = { + enable = true; + openFirewall = true; + server = "ghostunnel"; + tls.cert = "/root/podman-cert.pem"; + tls.key = "/root/podman-key.pem"; + tls.cacert = "/root/ca.pem"; + }; + + environment.systemPackages = [ + pkgs.docker-client + ]; + + users.users.alice = { + isNormalUser = true; + home = "/home/alice"; + description = "Alice Foobar"; + extraGroups = ["podman"]; + }; + + }; + + client = { ... }: { + environment.systemPackages = [ + # Installs the docker _client_ only + # Normally, you'd want `virtualisation.docker.enable = true;`. + pkgs.docker-client + ]; + environment.variables.DOCKER_HOST = "podman:2376"; + environment.variables.DOCKER_TLS_VERIFY = "1"; + }; + }; + + testScript = '' + import shlex + + + def su_cmd(user, cmd): + cmd = shlex.quote(cmd) + return f"su {user} -l -c {cmd}" + + def cmd(command): + print(f"+{command}") + r = os.system(command) + if r != 0: + raise Exception(f"Command {command} failed with exit code {r}") + + start_all() + cmd("${gen-ca}") + + podman.copy_from_host("ca.pem", "/root/ca.pem") + podman.copy_from_host("podman-cert.pem", "/root/podman-cert.pem") + podman.copy_from_host("podman-key.pem", "/root/podman-key.pem") + + client.copy_from_host("ca.pem", "/root/.docker/ca.pem") + # client.copy_from_host("podman-cert.pem", "/root/podman-cert.pem") + client.copy_from_host("client-cert.pem", "/root/.docker/cert.pem") + client.copy_from_host("client-key.pem", "/root/.docker/key.pem") + + # TODO (ghostunnel): add file watchers so the restart isn't necessary + podman.succeed("systemctl reset-failed && systemctl restart ghostunnel-server-podman-socket.service") + + podman.wait_for_unit("sockets.target") + podman.wait_for_unit("ghostunnel-server-podman-socket.service") + + with subtest("Create default network"): + podman.succeed("docker network create default") + + with subtest("Root docker cli also works"): + podman.succeed("docker version") + + with subtest("A podman member can also still use the docker cli"): + podman.succeed(su_cmd("alice", "docker version")) + + with subtest("Run container remotely via docker cli"): + client.succeed("docker version") + + # via socket would be nicer + podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg") + + client.succeed( + "docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10" + ) + client.succeed("docker ps | grep sleeping") + podman.succeed("docker ps | grep sleeping") + client.succeed("docker stop sleeping") + client.succeed("docker rm sleeping") + + with subtest("Clients without cert will be denied"): + client.succeed("rm /root/.docker/{cert,key}.pem") + client.fail("docker version") + + with subtest("Clients with wrong cert will be denied"): + client.copy_from_host("client-2-cert.pem", "/root/.docker/cert.pem") + client.copy_from_host("client-2-key.pem", "/root/.docker/key.pem") + client.fail("docker version") + + ''; + } +) diff --git a/pkgs/applications/virtualization/podman/default.nix b/pkgs/applications/virtualization/podman/default.nix index c72a3577bf8..6c518ab8934 100644 --- a/pkgs/applications/virtualization/podman/default.nix +++ b/pkgs/applications/virtualization/podman/default.nix @@ -81,7 +81,11 @@ buildGoModule rec { patchelf --set-rpath "${lib.makeLibraryPath [ systemd ]}":$RPATH $out/bin/podman ''; - passthru.tests = { inherit (nixosTests) podman; }; + passthru.tests = { + inherit (nixosTests) podman; + # related modules + inherit (nixosTests) podman-tls-ghostunnel; + }; meta = with lib; { homepage = "https://podman.io/"; From 29ee113277541edadc946b8f3c3dbce388195b7f Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Tue, 25 May 2021 17:39:23 +0200 Subject: [PATCH 11/17] podman: Add iproute2, fixing docker network rm (cherry picked from commit db31d8354d9c1988968f076c4e01843330162e03) --- nixos/tests/podman.nix | 1 + pkgs/applications/virtualization/podman/wrapper.nix | 2 ++ 2 files changed, 3 insertions(+) diff --git a/nixos/tests/podman.nix b/nixos/tests/podman.nix index 343ecbe14b2..7eae575fd7f 100644 --- a/nixos/tests/podman.nix +++ b/nixos/tests/podman.nix @@ -132,6 +132,7 @@ import ./make-test-python.nix ( podman.succeed("podman ps | grep sleeping") podman.succeed("docker stop sleeping") podman.succeed("docker rm sleeping") + podman.succeed("docker network rm default") with subtest("A podman non-member can not use the docker cli"): podman.fail(su_cmd("docker version", user="mallory")) diff --git a/pkgs/applications/virtualization/podman/wrapper.nix b/pkgs/applications/virtualization/podman/wrapper.nix index 9f3e1943b56..c9ec18593df 100644 --- a/pkgs/applications/virtualization/podman/wrapper.nix +++ b/pkgs/applications/virtualization/podman/wrapper.nix @@ -12,6 +12,7 @@ , util-linux # nsenter , cni-plugins # not added to path , iptables +, iproute2 }: let @@ -25,6 +26,7 @@ let fuse-overlayfs util-linux iptables + iproute2 ] ++ extraPackages); in runCommand podman.name { From 03e08759f7bb0dc34e2df35a2bb952f20b780fb5 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 31 May 2021 08:32:21 +0200 Subject: [PATCH 12/17] dnsname-cni: Use wrapper instead of patch for dnsmasq The patch proved to be an incomplete solution while developing nixosTests.podman-dnsname (cherry picked from commit 651777934941480a36f7df9c434e6044957d045d) --- .../cluster/dnsname-cni/default.nix | 16 +++++++++++----- .../dnsname-cni/hardcode-dnsmasq-path.patch | 19 ------------------- 2 files changed, 11 insertions(+), 24 deletions(-) delete mode 100644 pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch diff --git a/pkgs/applications/networking/cluster/dnsname-cni/default.nix b/pkgs/applications/networking/cluster/dnsname-cni/default.nix index 91ef8b68fb6..2770617db7e 100644 --- a/pkgs/applications/networking/cluster/dnsname-cni/default.nix +++ b/pkgs/applications/networking/cluster/dnsname-cni/default.nix @@ -1,4 +1,11 @@ -{ buildGoModule, fetchFromGitHub, lib, dnsmasq }: +{ + buildGoModule, + dnsmasq, + fetchFromGitHub, + lib, + nixosTests, + makeWrapper, +}: buildGoModule rec { pname = "cni-plugin-dnsname"; @@ -11,10 +18,9 @@ buildGoModule rec { sha256 = "090kpq2ppan9ayajdk5vwbvww30nphylgajn2p3441d4jg2nvsm3"; }; - patches = [ ./hardcode-dnsmasq-path.patch ]; - - postPatch = '' - substituteInPlace plugins/meta/dnsname/service.go --replace '@DNSMASQ@' '${dnsmasq}/bin/dnsmasq' + nativeBuildInputs = [ makeWrapper ]; + postInstall = '' + wrapProgram $out/bin/dnsname --prefix PATH : ${lib.makeBinPath [ dnsmasq ]} ''; vendorSha256 = null; diff --git a/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch b/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch deleted file mode 100644 index 24ef5eb85d1..00000000000 --- a/pkgs/applications/networking/cluster/dnsname-cni/hardcode-dnsmasq-path.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/plugins/meta/dnsname/service.go b/plugins/meta/dnsname/service.go -index fc05f75..f6b4caf 100644 ---- a/plugins/meta/dnsname/service.go -+++ b/plugins/meta/dnsname/service.go -@@ -16,10 +16,14 @@ import ( - - // newDNSMasqFile creates a new instance of a dnsNameFile - func newDNSMasqFile(domainName, networkInterface, networkName string) (dnsNameFile, error) { -+ /* - dnsMasqBinary, err := exec.LookPath("dnsmasq") - if err != nil { - return dnsNameFile{}, errors.Errorf("the dnsmasq cni plugin requires the dnsmasq binary be in PATH") - } -+ */ -+ _ = errors.Errorf // XXX(mikroskeem): reduce diff -+ dnsMasqBinary := "@DNSMASQ@" - masqConf := dnsNameFile{ - ConfigFile: makePath(networkName, confFileName), - Domain: domainName, From f28df17dfa98b32737bd309e71d7ca04bf6722e7 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 27 May 2021 13:00:09 +0200 Subject: [PATCH 13/17] nixos/containers: Add virtualisation.containers.containersConf.cniPlugins (cherry picked from commit efba949352271ec77d9d5e7d54f2d16b9c53ee4f) --- nixos/modules/virtualisation/containers.nix | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 3974caf2233..45d4f877ae5 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -48,6 +48,23 @@ in description = "containers.conf configuration"; }; + containersConf.cniPlugins = mkOption { + type = types.listOf types.package; + defaultText = '' + [ + pkgs.cni-plugins + ] + ''; + example = lib.literalExample '' + [ + pkgs.cniPlugins.dnsname + ] + ''; + description = '' + CNI plugins to install on the system. + ''; + }; + registries = { search = mkOption { type = types.listOf types.str; @@ -97,8 +114,11 @@ in }; config = lib.mkIf cfg.enable { + + virtualisation.containers.containersConf.cniPlugins = [ pkgs.cni-plugins ]; + virtualisation.containers.containersConf.settings = { - network.cni_plugin_dirs = [ "${pkgs.cni-plugins}/bin/" ]; + network.cni_plugin_dirs = map (p: "${lib.getBin p}/bin") cfg.containersConf.cniPlugins; engine = { init_path = "${pkgs.catatonit}/bin/catatonit"; } // lib.optionalAttrs cfg.ociSeccompBpfHook.enable { From 9e4729617b0c2b47ca1ef8b256cd361e6cee5f04 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 27 May 2021 16:19:01 +0200 Subject: [PATCH 14/17] nixos/podman: Add defaultNetwork.extraPlugins (cherry picked from commit d81631fb98ea35b107d86f5de287cf727d0dfc18) --- nixos/modules/virtualisation/podman.nix | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index b16afb66894..ee9565abc24 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -2,6 +2,7 @@ let cfg = config.virtualisation.podman; toml = pkgs.formats.toml { }; + json = pkgs.formats.json { }; inherit (lib) mkOption types; @@ -22,6 +23,19 @@ let done ''; + net-conflist = pkgs.runCommand "87-podman-bridge.conflist" { + nativeBuildInputs = [ pkgs.jq ]; + extraPlugins = builtins.toJSON cfg.defaultNetwork.extraPlugins; + jqScript = '' + . + { "plugins": (.plugins + $extraPlugins) } + ''; + } '' + jq <${cfg.package}/etc/cni/net.d/87-podman-bridge.conflist \ + --argjson extraPlugins "$extraPlugins" \ + "$jqScript" \ + >$out + ''; + in { imports = [ @@ -99,6 +113,13 @@ in ''; }; + defaultNetwork.extraPlugins = lib.mkOption { + type = types.listOf json.type; + default = []; + description = '' + Extra CNI plugin configurations to add to podman's default network. + ''; + }; }; @@ -107,7 +128,7 @@ in environment.systemPackages = [ cfg.package ] ++ lib.optional cfg.dockerCompat dockerCompat; - environment.etc."cni/net.d/87-podman-bridge.conflist".source = "${cfg.package}/etc/cni/net.d/87-podman-bridge.conflist"; + environment.etc."cni/net.d/87-podman-bridge.conflist".source = net-conflist; virtualisation.containers = { enable = true; # Enable common /etc/containers configuration From c758b6937516cbd761a53ba90deb60b16d9cd568 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Thu, 27 May 2021 16:22:28 +0200 Subject: [PATCH 15/17] nixos/podman-dnsname: init (cherry picked from commit 54f2f1e5f1c7fd34e564a84443e8490477e26eb7) --- .../modules/virtualisation/podman-dnsname.nix | 36 ++++++++++++++++ nixos/modules/virtualisation/podman.nix | 1 + nixos/tests/all-tests.nix | 1 + nixos/tests/podman-dnsname.nix | 42 +++++++++++++++++++ .../cluster/dnsname-cni/default.nix | 4 ++ 5 files changed, 84 insertions(+) create mode 100644 nixos/modules/virtualisation/podman-dnsname.nix create mode 100644 nixos/tests/podman-dnsname.nix diff --git a/nixos/modules/virtualisation/podman-dnsname.nix b/nixos/modules/virtualisation/podman-dnsname.nix new file mode 100644 index 00000000000..beef1975507 --- /dev/null +++ b/nixos/modules/virtualisation/podman-dnsname.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: +let + inherit (lib) + mkOption + mkIf + types + ; + + cfg = config.virtualisation.podman; + +in +{ + options = { + virtualisation.podman = { + + defaultNetwork.dnsname.enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable DNS resolution in the default podman network. + ''; + }; + + }; + }; + + config = { + virtualisation.containers.containersConf.cniPlugins = mkIf cfg.defaultNetwork.dnsname.enable [ pkgs.dnsname-cni ]; + virtualisation.podman.defaultNetwork.extraPlugins = + lib.optional cfg.defaultNetwork.dnsname.enable { + type = "dnsname"; + domainName = "dns.podman"; + capabilities.aliases = true; + }; + }; +} diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index ee9565abc24..e245004e04a 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -39,6 +39,7 @@ let in { imports = [ + ./podman-dnsname.nix ./podman-network-socket.nix (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ]) ]; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7f0a987f89c..917d2f54efe 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -334,6 +334,7 @@ in plotinus = handleTest ./plotinus.nix {}; podgrab = handleTest ./podgrab.nix {}; podman = handleTestOn ["x86_64-linux"] ./podman.nix {}; + podman-dnsname = handleTestOn ["x86_64-linux"] ./podman-dnsname.nix {}; podman-tls-ghostunnel = handleTestOn ["x86_64-linux"] ./podman-tls-ghostunnel.nix {}; pomerium = handleTestOn ["x86_64-linux"] ./pomerium.nix {}; postfix = handleTest ./postfix.nix {}; diff --git a/nixos/tests/podman-dnsname.nix b/nixos/tests/podman-dnsname.nix new file mode 100644 index 00000000000..dd352f754dc --- /dev/null +++ b/nixos/tests/podman-dnsname.nix @@ -0,0 +1,42 @@ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + let + inherit (pkgs) writeTextDir python3 curl; + webroot = writeTextDir "index.html" "

Hi

"; + in + { + name = "podman-dnsname"; + meta = { + maintainers = with lib.maintainers; [ roberth ] ++ lib.teams.podman.members; + }; + + nodes = { + podman = { pkgs, ... }: { + virtualisation.podman.enable = true; + virtualisation.podman.defaultNetwork.dnsname.enable = true; + }; + }; + + testScript = '' + podman.wait_for_unit("sockets.target") + + with subtest("DNS works"): # also tests inter-container tcp routing + podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg") + podman.succeed( + "podman run -d --name=webserver -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin -w ${webroot} scratchimg ${python3}/bin/python -m http.server 8000" + ) + podman.succeed("podman ps | grep webserver") + podman.succeed(""" + for i in `seq 0 120`; do + podman run --rm --name=client -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg ${curl}/bin/curl http://webserver:8000 >/dev/console \ + && exit 0 + sleep 0.5 + done + exit 1 + """) + podman.succeed("podman stop webserver") + podman.succeed("podman rm webserver") + + ''; + } +) diff --git a/pkgs/applications/networking/cluster/dnsname-cni/default.nix b/pkgs/applications/networking/cluster/dnsname-cni/default.nix index 2770617db7e..27b37fdee0c 100644 --- a/pkgs/applications/networking/cluster/dnsname-cni/default.nix +++ b/pkgs/applications/networking/cluster/dnsname-cni/default.nix @@ -28,6 +28,10 @@ buildGoModule rec { doCheck = false; # NOTE: requires root privileges + passthru.tests = { + inherit (nixosTests) podman-dnsname; + }; + meta = with lib; { description = "DNS name resolution for containers"; homepage = "https://github.com/containers/dnsname"; From eeefa0a65d69e9761a18e58f25b91f08e65686ad Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 31 May 2021 09:40:04 +0200 Subject: [PATCH 16/17] podman: Add nixosTests.podman-dnsname to tests (cherry picked from commit 1d781e5c80d3c392933479a114e9e3857a1d9529) --- pkgs/applications/virtualization/podman/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/applications/virtualization/podman/default.nix b/pkgs/applications/virtualization/podman/default.nix index 6c518ab8934..10a6d726aef 100644 --- a/pkgs/applications/virtualization/podman/default.nix +++ b/pkgs/applications/virtualization/podman/default.nix @@ -84,7 +84,10 @@ buildGoModule rec { passthru.tests = { inherit (nixosTests) podman; # related modules - inherit (nixosTests) podman-tls-ghostunnel; + inherit (nixosTests) + podman-tls-ghostunnel + podman-dnsname + ; }; meta = with lib; { From 0684f78698e9f565254f8ce0d737b544cb892bf8 Mon Sep 17 00:00:00 2001 From: zowoq <59103226+zowoq@users.noreply.github.com> Date: Mon, 31 May 2021 22:57:39 +1000 Subject: [PATCH 17/17] nixos/podman-network-socket-ghostunnel: move condition to include socket (cherry picked from commit 72f54c32a6114a69caec30170a29837c91434aff) --- .../virtualisation/podman-network-socket-ghostunnel.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix b/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix index 1f1ada7f089..a0e7e433164 100644 --- a/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix +++ b/nixos/modules/virtualisation/podman-network-socket-ghostunnel.nix @@ -15,9 +15,9 @@ in }; }; - config = { + config = lib.mkIf (cfg.enable && cfg.server == "ghostunnel") { - services.ghostunnel = lib.mkIf (cfg.enable && cfg.server == "ghostunnel") { + services.ghostunnel = { enable = true; servers."podman-socket" = { inherit (cfg.tls) cert key cacert;