diff --git a/checks/admin/default.nix b/checks/admin/default.nix new file mode 100644 index 000000000..84475e5c1 --- /dev/null +++ b/checks/admin/default.nix @@ -0,0 +1,59 @@ +{ + pkgs, + self, + clanLib, + ... +}: + +let + public-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII6zj7ubTg6z/aDwRNwvM/WlQdUocMprQ8E92NWxl6t+ test@test"; +in + +clanLib.test.makeTestClan { + inherit pkgs self; + nixosTest = ( + { ... }: + + { + name = "admin"; + + clan = { + directory = ./.; + inventory = { + modules."@clan/admin" = import ../../clanServices/admin/default.nix; + + machines.client = { }; + machines.server = { }; + + instances = { + ssh-test-one = { + module.name = "@clan/admin"; + roles.default.machines."server".settings = { + allowedKeys = {testkey = public-key;}; + }; + }; + }; + }; + }; + + nodes = { + client.environment.etc.private-test-key.source = ./private-test-key; + }; + + testScript = '' + start_all() + + # Show all addresses + machines = [client, server] + for m in machines: + m.systemctl("start network-online.target") + + for m in machines: + m.wait_for_unit("network-online.target") + + client.succeed(f"&>2") + client.succeed(f"ssh -F /dev/null -i /etc/private-test-key -o BatchMode=yes root@server true &>/dev/null") + ''; + } + ); +} diff --git a/checks/admin/private-test-key b/checks/admin/private-test-key new file mode 100644 index 000000000..b8d6845ae --- /dev/null +++ b/checks/admin/private-test-key @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCOs4+7m04Os/2g8ETcLzP1pUHVKHDKa0PBPdjVsZerfgAAAJDXdRkm13UZ +JgAAAAtzc2gtZWQyNTUxOQAAACCOs4+7m04Os/2g8ETcLzP1pUHVKHDKa0PBPdjVsZerfg +AAAECIgb2FQcgBKMniA+6zm2cwGre60ATu3Sg1GivgAqVJlI6zj7ubTg6z/aDwRNwvM/Wl +QdUocMprQ8E92NWxl6t+AAAAC3BpbnBveEBraXdpAQI= +-----END OPENSSH PRIVATE KEY----- + diff --git a/checks/admin/sops/machines/server/key.json b/checks/admin/sops/machines/server/key.json new file mode 100755 index 000000000..5eb135c60 --- /dev/null +++ b/checks/admin/sops/machines/server/key.json @@ -0,0 +1,6 @@ +[ + { + "publickey": "age1q4e7nsw5z6mqeqk5u5kug8lwhpq3f276s0t0npwfffwdkfh58gkqxknhjg", + "type": "age" + } +] diff --git a/checks/admin/sops/secrets/server-age.key/secret b/checks/admin/sops/secrets/server-age.key/secret new file mode 100644 index 000000000..27431d83c --- /dev/null +++ b/checks/admin/sops/secrets/server-age.key/secret @@ -0,0 +1,15 @@ +{ + "data": "ENC[AES256_GCM,data:ET/FggP6t7L60krfVRvtMjv++xr3zqRsJ58AfnPS1zjTovV5tE9RgnboGY1ieS7fCs4VOL2S6ELtwV1+BTLDQX9s0c5A9cKqjnc=,iv:6EQ6DOqxUdHcOziTxf8kl0sp1Pggu720s5BJ8zA9Je0=,tag:hQMPWaWb4igqDYjwNehlqQ==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRWjhuZkgwNEZTL3JXZHFE\nTC9jSXJGcVd2bnkvOE1qV0d6TzNobFZobndvCmF1UmhVUWtKeVVwS29NY21ONkRn\nZU5sM01kTU9rQVNENi9paUFWbERoWnMKLS0tIEdjZzgwQjFtWlVtRGZwdW9GY0FK\nSER1TTFNVGxFa0ZrclR4MitWVERiSGMK9DNLzlJZelcpP0klwSDMggTAy5ZVOmsZ\niuu8dXMSdIeTd7l8rpZZN27BaKUm8yEDpUmot5Vq9rbZl6SO3ncX+A==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-05-07T11:45:41Z", + "mac": "ENC[AES256_GCM,data:m8eTnPtMzrooEah43mvjwHxQIwR/aq+A1wYyG/rQ75COq/TQepfMiDSrCJKW8x+OKmN/3HZs1b9k659jNNMF+RtMag0+/ovTmr7PQux3IkzWl+R2kU3Y7WDOMweBKY3mTMu6reICE1YVME8vJwhDDbA5JCXJv64rkTz2tfGt4CQ=,iv:/vrwJyEVsfm1cUK//TesY24Makt8YI8mwx5GIhn4038=,tag:H2tS9ohvWJ4TWB6LghcZNg==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/admin/sops/secrets/server-age.key/users/admin b/checks/admin/sops/secrets/server-age.key/users/admin new file mode 120000 index 000000000..9e21a9938 --- /dev/null +++ b/checks/admin/sops/secrets/server-age.key/users/admin @@ -0,0 +1 @@ +../../../users/admin \ No newline at end of file diff --git a/checks/admin/sops/users/admin/key.json b/checks/admin/sops/users/admin/key.json new file mode 100644 index 000000000..e408aa96b --- /dev/null +++ b/checks/admin/sops/users/admin/key.json @@ -0,0 +1,4 @@ +{ + "publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "type": "age" +} diff --git a/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519.pub/value b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519.pub/value new file mode 100644 index 000000000..cb337d528 --- /dev/null +++ b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519.pub/value @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICVVQjCEuryZii1LmJyjx9DX44eJh3qwTTEWlahYONsz nixbld@kiwi diff --git a/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/machines/server b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/machines/server new file mode 120000 index 000000000..2bd819ecb --- /dev/null +++ b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/machines/server @@ -0,0 +1 @@ +../../../../../../sops/machines/server \ No newline at end of file diff --git a/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/secret b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/secret new file mode 100644 index 000000000..4245371ad --- /dev/null +++ b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/secret @@ -0,0 +1,19 @@ +{ + "data": "ENC[AES256_GCM,data:yH7IQixe4nudnK4QOsr7VYoJ1YrVLP0Ufvgu7TNWSJnc55khKZHvQiDIlxzCIrAyMgUYwPNmrrZn9PZhgjAQZm7/o6SmP91Efb0yWM55o861El6v59yw0fseo3z6xAisjlg3KwTd5KMrRhzT0HzrjLn89SYRVh7DAWK+Cs7HVGvKVJ1E6AWiJmFPXIB7YaqJ7P4jZW9u7bEMCZabsRRqgS8dWXVXw9VS5ll4bNYQY4x5p2eg6e81zdeY2Y9Gbi5ty1Whqpzko2Pvggu6K4zUDXikM4lWggvIXzfrJA7HNE3xzXw94J45woj1y5FVOzn1Ve5kCc8PjVGaJ32poGkZiiD07kd5PxZuyVexREJpgz29lyB6nRJJeau4gpSG1VHOyNdwwBsBBm+zn6v2rlVzJPTlqmCV1+5UKf8JZKziIDFfi/78kSdtaeX+miJJvyDRkqNpQ7htEI0TAS8yQrkjWEIyaPAWQ2Usa8g1UrEftTlGUi/aMC2ob0qTLQQbhNhlSV/dImzI/qRMqSy2RWeS,iv:EuprKOFKzNLZrGlPtU2mEjmtNPNOcuVDbuvrtYyrerc=,tag:ny/q1AMHIQ8OgUNEE0Cc8w==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1q4e7nsw5z6mqeqk5u5kug8lwhpq3f276s0t0npwfffwdkfh58gkqxknhjg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLODFxUjREa2tOYW9xaHYw\nQlhWZ282UVhiOGRndk0xYnlCQWRYR01qS2hJCllySUZyblJmTkgyZXd5bjVINDBo\nbEhIWmxycVdOVW0xTUxkalF5Y1k2bXcKLS0tIGRRS1VqOG5sanh2dXR5a2FGeXRs\nK3ZUdERCdEkvMmt3ZndPZEM3QUxJZzAKutOr9jHPCL86zEdMWJ6YZmplcr4tDAcN\nncQfC5rddYDW+0y/crwepKTa2FZjQheOY7jobZanU19ai521hqDSVw==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxc3NxNGhRYmU3eFNodDZ4\ndnNTeHFnNXBKbUxmNHBjRlFpNG0zdVNpS2d3CjhrOUlSQU5BZVlSdWR3dnNyODZO\nRFBKZWpwWHlOUW03OGlVZlRQUmMrMzQKLS0tIEd6ei9LU3ZFTzlWTUk1c3huS1RQ\nbG1vQzI4ODJkeFcyRnJaQWp1Wk9zSkUKXefMOk/ZT4P6DItfnM82RoOvX4SBn7Fn\nlAoMnSzaRCunDwq7ha05G45gcI2Wjv3urjt0tmdmrmTnFtBSSt23TQ==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-05-07T11:45:47Z", + "mac": "ENC[AES256_GCM,data:ORCANHbEX13O+zBVLOYyPxYIr1RS3NybTBb23ES7RbiGhSl2t/TXcfPWU5Smuqee0tfcrxL0u1FELZta4IysySW54JlD2907E9OUJWlQ6seOxADla4TMukW2pwhSsUJ9XfjEwC07zYB0alHzO3pY+LG3OAWzyhAlWzHlB5+WqIA=,iv:As+CjAJxKht0PJs3S2WWzho7UBqaUUltBIrYvlzBAbM=,tag:PSyUKaPZZNCxqd6XLPJSCw==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/users/admin b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/users/admin new file mode 120000 index 000000000..ca714e122 --- /dev/null +++ b/checks/admin/vars/per-machine/server/openssh/ssh.id_ed25519/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/checks/admin/vars/per-machine/server/root-password/password-hash/machines/server b/checks/admin/vars/per-machine/server/root-password/password-hash/machines/server new file mode 120000 index 000000000..2bd819ecb --- /dev/null +++ b/checks/admin/vars/per-machine/server/root-password/password-hash/machines/server @@ -0,0 +1 @@ +../../../../../../sops/machines/server \ No newline at end of file diff --git a/checks/admin/vars/per-machine/server/root-password/password-hash/secret b/checks/admin/vars/per-machine/server/root-password/password-hash/secret new file mode 100644 index 000000000..6373988b4 --- /dev/null +++ b/checks/admin/vars/per-machine/server/root-password/password-hash/secret @@ -0,0 +1,19 @@ +{ + "data": "ENC[AES256_GCM,data:5Fa0TQN/Whj311JZuVWXnp+2KJaNZPb/TOnP23T+KktulabcBA9go+/F+8wJbsEH2mf6UDq656p6C+kLIvfBFl2O/WwSOhsl23as9TLbgB6gBq73GjyV81VFsnLYNLHKMq+8nfJHM/WekA==,iv:n5vz3q5N6DplLWibdiCcYDdiN7q1VggzPoIYy9r2ZJw=,tag:FoGXrrJfjHZCUVTS2RESmw==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1q4e7nsw5z6mqeqk5u5kug8lwhpq3f276s0t0npwfffwdkfh58gkqxknhjg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBheXZvUW9YbjBFMi9mZnVk\ncGFPQzFOZkNPMU1HckhtSGtDWExpWVNYRlV3CjdDaDlSd2wzVnhKZGU0aFY0UnZY\nQStPSkxuSmlyOU9aeUdRaEJ2UTRRSm8KLS0tIFd3SG9YdEU5T2tzNk16b2s1SUNj\nWkh2cng5eWd3ZmxVZDhSR2Y1QnFySDgKGb/t+8NqiSGgmFOJc1NmDYZ+PXlANy8V\nuFwUTeqWAv7pOiGC8oessfyTPaJ7gWjz+XfKV5JVVikK2l3J4eAGxg==\n-----END AGE ENCRYPTED FILE-----\n" + }, + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWM0daWmxCTjAyQStwQ2lM\nNkcyZW9hRmpDelRJR0VVTWhNTGFuZWhCc1RJCm81ZXowZjBhWGpIQTBhQnZLSmQy\nVUNNYjI0bVpqQ21YZS95TW53OUx1YUkKLS0tIDRUUE1zczBDeFJTOTQyVXVkMkYy\ncVVTN3J6TWtwcXVpM0M5c0gxUXpmV2cKwlWrbGLtkO2+PXKoMoHTV5aJpnfVy3RP\n6i8DDpLPGYfVUtWxHx+L+NmMxmw1AvmKSbdB4Y7aSbBW2mea3j1YCg==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-05-07T11:45:50Z", + "mac": "ENC[AES256_GCM,data:rwdbGOg8l8fWT2GYFx+PgV3oPxt5+NCHJf3PhG3V2lrRMPRisyf1nKwDsYavTuhv+bZC/qo4LrGylcXsHWdkCe/xBX+/jYLMf6nJZPk8BPzfUpiDnEKwRl05qfRfkIDusnQrlBrE+tqtcool65js7hYIzSi92O/hxbzzfsCUpqk=,iv:lUTNJkr6Zh3MQm/h7Ven4N6xVn4VeTXOEKzxd0HSsCk=,tag:Bwbi4HD9vzso6306y7EZOg==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/admin/vars/per-machine/server/root-password/password-hash/users/admin b/checks/admin/vars/per-machine/server/root-password/password-hash/users/admin new file mode 120000 index 000000000..ca714e122 --- /dev/null +++ b/checks/admin/vars/per-machine/server/root-password/password-hash/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/checks/admin/vars/per-machine/server/root-password/password/secret b/checks/admin/vars/per-machine/server/root-password/password/secret new file mode 100644 index 000000000..6703b01ff --- /dev/null +++ b/checks/admin/vars/per-machine/server/root-password/password/secret @@ -0,0 +1,15 @@ +{ + "data": "ENC[AES256_GCM,data:sPh+BuT2we+d/GaMv4zPWc3rPhlMsJQC,iv:VwcHUOMaNiao+R8RBtUINffEUhutktKD6KEWLkFxyp4=,tag:SNVKLjjDv+u5XTVczs2/Uw==,type:str]", + "sops": { + "age": [ + { + "recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJVWNYRGEwVWxDSmE4bTNL\nRlZPeGZabFZZNGFsMEwzV1ZmT1pqNVk4STMwCkg5UER0Vjk3K1RMazVVYjF3SDc2\ndDZHa3VtYjRiWUJET25weXprc0JNUjAKLS0tIDdVb2xNdWxCcjhpSGtGWDV0d2ti\nZENkZGNpSTNzMVVTZVN0ZktLc2VackEKdexhI37pwcnbZbcy30k9Uo5Z7z3NLqlx\nspxJ87SzEwdStTMhiH1iYf62vcyAOTa4HwfXu97MGVPFNw13/VfgCw==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-05-07T11:45:50Z", + "mac": "ENC[AES256_GCM,data:tZRh8qj7JUnhXCfqCHJKWEFQ8XLtmo/p0C+eFIK+34enxfB5lG5Lq83wBXLa0D/nqrr58z1rLO+UVDOI5LH1jFxARBZZnUKrVJNTDHa5pUnlnVOFEOoc+R0h2E5Xw9OHaq7aDUh4fT9+gNDpguKggI5fS9KqRnmZ4VrpNccjnkw=,iv:2yI25fcWMog91EMD7bYQy3GS30a7gZHnif93MaE3sZo=,tag:tYqa6zssiU3BCFU5xmDYZQ==,type:str]", + "unencrypted_suffix": "_unencrypted", + "version": "3.10.2" + } +} diff --git a/checks/admin/vars/per-machine/server/root-password/password/users/admin b/checks/admin/vars/per-machine/server/root-password/password/users/admin new file mode 120000 index 000000000..ca714e122 --- /dev/null +++ b/checks/admin/vars/per-machine/server/root-password/password/users/admin @@ -0,0 +1 @@ +../../../../../../sops/users/admin \ No newline at end of file diff --git a/checks/flake-module.nix b/checks/flake-module.nix index 6bde03bf0..18805f3f6 100644 --- a/checks/flake-module.nix +++ b/checks/flake-module.nix @@ -52,6 +52,7 @@ in # Clan Tests dummy-inventory-test = import ./dummy-inventory-test nixosTestArgs; + admin = import ./admin nixosTestArgs; data-mesher = import ./data-mesher nixosTestArgs; syncthing = import ./syncthing nixosTestArgs; } diff --git a/clanModules/admin/default.nix b/clanModules/admin/default.nix deleted file mode 100644 index ed6af3368..000000000 --- a/clanModules/admin/default.nix +++ /dev/null @@ -1,6 +0,0 @@ -# Dont import this file -# It is only here for backwards compatibility. -# Dont author new modules with this file. -{ - imports = [ ./roles/default.nix ]; -} diff --git a/clanModules/admin/roles/default.nix b/clanModules/admin/roles/default.nix deleted file mode 100644 index 84a1bde4c..000000000 --- a/clanModules/admin/roles/default.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ lib, config, ... }: -{ - options.clan.admin = { - allowedKeys = lib.mkOption { - default = { }; - type = lib.types.attrsOf lib.types.str; - description = "The allowed public keys for ssh access to the admin user"; - example = { - "key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD..."; - }; - }; - }; - # Bad practice. - # Should we add 'clanModules' to specialArgs? - imports = [ - ../../sshd - ../../root-password - ]; - config = { - users.users.root.openssh.authorizedKeys.keys = builtins.attrValues config.clan.admin.allowedKeys; - }; -} diff --git a/clanModules/admin/README.md b/clanServices/admin/README.md similarity index 100% rename from clanModules/admin/README.md rename to clanServices/admin/README.md diff --git a/clanServices/admin/default.nix b/clanServices/admin/default.nix new file mode 100644 index 000000000..239bbfd24 --- /dev/null +++ b/clanServices/admin/default.nix @@ -0,0 +1,37 @@ +{ ... }: +{ + _class = "clan.service"; + manifest.name = "clan-core/admin"; + + roles.default = { + interface = + { lib, ... }: + { + options.allowedKeys = lib.mkOption { + default = { }; + type = lib.types.attrsOf lib.types.str; + description = "The allowed public keys for ssh access to the admin user"; + example = { + "key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD..."; + }; + }; + + }; + + perInstance = + { settings, ... }: + { + nixosModule = + { ... }: + { + + imports = [ + ../../clanModules/sshd + ../../clanModules/root-password + ]; + + users.users.root.openssh.authorizedKeys.keys = builtins.attrValues settings.allowedKeys; + }; + }; + }; +} diff --git a/clanServices/admin/flake-module.nix b/clanServices/admin/flake-module.nix new file mode 100644 index 000000000..0c85e0630 --- /dev/null +++ b/clanServices/admin/flake-module.nix @@ -0,0 +1,58 @@ +{ + self, + inputs, + lib, + ... +}: +let + module = lib.modules.importApply ./default.nix { + inherit (self) packages; + }; +in +{ + clan.inventory.modules = { + hello-world = module; + }; + clan.modules = { + hello-world = module; + }; + perSystem = + { pkgs, ... }: + let + # Module that contains the tests + # This module adds: + # - legacyPackages..eval-tests-hello-world + # - checks..eval-tests-hello-world + unit-test-module = ( + self.clanLib.test.flakeModules.makeEvalChecks { + inherit module; + inherit self inputs; + testName = "hello-world"; + tests = ./tests/eval-tests.nix; + # Optional arguments passed to the test + testArgs = { }; + } + ); + in + { + imports = [ unit-test-module ]; + + /** + 1. Prepare the test vars + nix run .#generate-test-vars -- clanServices/hello-world/tests/vm hello-service + + 2. To run the test + nix build .#checks.x86_64-linux.hello-service + */ + checks = + # Currently we don't support nixos-integration tests on darwin + lib.optionalAttrs (pkgs.stdenv.isLinux) { + hello-service = import ./tests/vm/default.nix { + inherit module; + inherit self inputs pkgs; + # clanLib is exposed from inputs.clan-core + clanLib = self.clanLib; + }; + }; + }; +} diff --git a/clanServices/flake-module.nix b/clanServices/flake-module.nix index e107c2a98..8ba506b8b 100644 --- a/clanServices/flake-module.nix +++ b/clanServices/flake-module.nix @@ -1,5 +1,13 @@ +{ lib, ... }: { imports = [ ./hello-world/flake-module.nix ]; + + clan.inventory.modules = { + admin = lib.modules.importApply ./admin/default.nix { + # inherit (self) packages; + }; + }; + }