diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index 678ce3c2880..ca9c6f9a7f9 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -120,8 +120,8 @@ in rec { (all nixos.tests.networking.scripted.macvlan) (all nixos.tests.networking.scripted.sit) (all nixos.tests.networking.scripted.vlan) - (all nixos.tests.nfs3) - (all nixos.tests.nfs4) + (all nixos.tests.nfs3.simple) + (all nixos.tests.nfs4.simple) (all nixos.tests.openssh) (all nixos.tests.php-pcre) (all nixos.tests.predictable-interface-names.predictable) diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 23ad22ee5a1..7ef48589de4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -189,8 +189,9 @@ in networkingProxy = handleTest ./networking-proxy.nix {}; nextcloud = handleTest ./nextcloud {}; nexus = handleTest ./nexus.nix {}; - nfs3 = handleTest ./nfs.nix { version = 3; }; - nfs4 = handleTest ./nfs.nix { version = 4; }; + # TODO: Test nfsv3 + Kerberos + nfs3 = handleTest ./nfs { version = 3; }; + nfs4 = handleTest ./nfs { version = 4; }; nghttpx = handleTest ./nghttpx.nix {}; nginx = handleTest ./nginx.nix {}; nginx-sso = handleTest ./nginx-sso.nix {}; diff --git a/nixos/tests/nfs/default.nix b/nixos/tests/nfs/default.nix new file mode 100644 index 00000000000..6bc803c91b4 --- /dev/null +++ b/nixos/tests/nfs/default.nix @@ -0,0 +1,9 @@ +{ version ? 4 +, system ? builtins.currentSystem +, pkgs ? import ../../.. { inherit system; } +}: { + simple = import ./simple.nix { inherit version system pkgs; }; +} // pkgs.lib.optionalAttrs (version == 4) { + # TODO: Test kerberos + nfsv3 + kerberos = import ./kerberos.nix { inherit version system pkgs; }; +} diff --git a/nixos/tests/nfs/kerberos.nix b/nixos/tests/nfs/kerberos.nix new file mode 100644 index 00000000000..1c45b6542fd --- /dev/null +++ b/nixos/tests/nfs/kerberos.nix @@ -0,0 +1,140 @@ +import ../make-test-python.nix ({ pkgs, lib, ... }: + +with lib; + +let + krb5 = + { enable = true; + domain_realm."nfs.test" = "NFS.TEST"; + libdefaults.default_realm = "NFS.TEST"; + realms."NFS.TEST" = + { admin_server = "server.nfs.test"; + kdc = "server.nfs.test"; + }; + }; + + hosts = + '' + 192.168.1.1 client.nfs.test + 192.168.1.2 server.nfs.test + ''; + + users = { + users.alice = { + isNormalUser = true; + name = "alice"; + uid = 1000; + }; + }; + + environment = { + etc."request-key.conf".text = '' + create id_resolver * * ${pkgs.nfs-utils}/bin/nfsidmap -t 600 %k %d + ''; + systemPackages = with pkgs; [ keyutils ]; + }; + +in + +{ + name = "nfsv4-with-kerberos"; + + nodes = { + client = { lib, ... }: + { inherit krb5 users environment; + + networking.extraHosts = hosts; + networking.domain = "nfs.test"; + networking.hostName = "client"; + + fileSystems = lib.mkVMOverride + { "/data" = { + device = "server.nfs.test:/"; + fsType = "nfs"; + options = [ "nfsvers=4" "sec=krb5p" "noauto" ]; + }; + }; + }; + + server = { lib, ...}: + { inherit krb5 users environment; + + networking.extraHosts = hosts; + networking.domain = "nfs.test"; + networking.hostName = "server"; + + networking.firewall.allowedTCPPorts = [ + 111 # rpc + 2049 # nfs + 88 # kerberos + 749 # kerberos admin + ]; + + services.kerberos_server.enable = true; + services.kerberos_server.realms = + { "NFS.TEST".acl = + [ { access = "all"; principal = "admin/admin"; } ]; + }; + + services.nfs.server.enable = true; + services.nfs.server.createMountPoints = true; + services.nfs.server.exports = + '' + /data *(rw,no_root_squash,fsid=0,sec=krb5p) + ''; + }; + }; + + testScript = + '' + server.succeed("mkdir -p /data/alice") + server.succeed("chown alice:users /data/alice") + + # set up kerberos database + server.succeed( + "kdb5_util create -s -r NFS.TEST -P master_key", + "systemctl restart kadmind.service kdc.service", + ) + server.wait_for_unit(f"kadmind.service") + server.wait_for_unit(f"kdc.service") + + # create principals + server.succeed( + "kadmin.local add_principal -randkey nfs/server.nfs.test", + "kadmin.local add_principal -randkey nfs/client.nfs.test", + "kadmin.local add_principal -pw admin_pw admin/admin", + "kadmin.local add_principal -pw alice_pw alice", + ) + + # add principals to server keytab + server.succeed("kadmin.local ktadd nfs/server.nfs.test") + server.succeed("systemctl start rpc-gssd.service rpc-svcgssd.service") + server.wait_for_unit(f"rpc-gssd.service") + server.wait_for_unit(f"rpc-svcgssd.service") + + client.wait_for_unit("network-online.target") + + # add principals to client keytab + client.succeed("echo admin_pw | kadmin -p admin/admin ktadd nfs/client.nfs.test") + client.succeed("systemctl start rpc-gssd.service") + client.wait_for_unit("rpc-gssd.service") + + with subtest("nfs share mounts"): + client.succeed("systemctl restart data.mount") + client.wait_for_unit("data.mount") + + with subtest("permissions on nfs share are enforced"): + client.fail("su alice -c 'ls /data'") + client.succeed("su alice -c 'echo alice_pw | kinit'") + client.succeed("su alice -c 'ls /data'") + + client.fail("su alice -c 'echo bla >> /data/foo'") + client.succeed("su alice -c 'echo bla >> /data/alice/foo'") + server.succeed("test -e /data/alice/foo") + + with subtest("uids/gids are mapped correctly on nfs share"): + ids = client.succeed("stat -c '%U %G' /data/alice").split() + expected = ["alice", "users"] + assert ids == expected, f"ids incorrect: got {ids} expected {expected}" + ''; +}) diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs/simple.nix similarity index 97% rename from nixos/tests/nfs.nix rename to nixos/tests/nfs/simple.nix index fd0e39adc09..a1a09ee0f45 100644 --- a/nixos/tests/nfs.nix +++ b/nixos/tests/nfs/simple.nix @@ -1,4 +1,4 @@ -import ./make-test-python.nix ({ pkgs, version ? 4, ... }: +import ../make-test-python.nix ({ pkgs, version ? 4, ... }: let