mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-10-26 08:48:38 +03:00
nixos/tang: create module for tang server (#247037)
This commit adds a module for the tang server and the related nixos test.
This commit is contained in:
parent
301949dcf0
commit
fb3723fe52
@ -1164,6 +1164,7 @@
|
|||||||
./services/security/sshguard.nix
|
./services/security/sshguard.nix
|
||||||
./services/security/sslmate-agent.nix
|
./services/security/sslmate-agent.nix
|
||||||
./services/security/step-ca.nix
|
./services/security/step-ca.nix
|
||||||
|
./services/security/tang.nix
|
||||||
./services/security/tor.nix
|
./services/security/tor.nix
|
||||||
./services/security/torify.nix
|
./services/security/torify.nix
|
||||||
./services/security/torsocks.nix
|
./services/security/torsocks.nix
|
||||||
|
95
nixos/modules/services/security/tang.nix
Normal file
95
nixos/modules/services/security/tang.nix
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services.tang;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.tang = {
|
||||||
|
enable = mkEnableOption "tang";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.tang;
|
||||||
|
defaultText = literalExpression "pkgs.tang";
|
||||||
|
description = mdDoc "The tang package to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
listenStream = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ "7654" ];
|
||||||
|
example = [ "198.168.100.1:7654" "[2001:db8::1]:7654" "7654" ];
|
||||||
|
description = mdDoc ''
|
||||||
|
Addresses and/or ports on which tang should listen.
|
||||||
|
For detailed syntax see ListenStream in {manpage}`systemd.socket(5)`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
ipAddressAllow = mkOption {
|
||||||
|
example = [ "192.168.1.0/24" ];
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = ''
|
||||||
|
Whitelist a list of address prefixes.
|
||||||
|
Preferably, internal addresses should be used.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
|
||||||
|
systemd.services."tangd@" = {
|
||||||
|
description = "Tang server";
|
||||||
|
path = [ cfg.package ];
|
||||||
|
serviceConfig = {
|
||||||
|
StandardInput = "socket";
|
||||||
|
StandardOutput = "socket";
|
||||||
|
StandardError = "journal";
|
||||||
|
DynamicUser = true;
|
||||||
|
StateDirectory = "tang";
|
||||||
|
RuntimeDirectory = "tang";
|
||||||
|
StateDirectoryMode = "700";
|
||||||
|
UMask = "0077";
|
||||||
|
CapabilityBoundingSet = [ "" ];
|
||||||
|
ExecStart = "${cfg.package}/libexec/tangd %S/tang";
|
||||||
|
LockPersonality = true;
|
||||||
|
MemoryDenyWriteExecute = true;
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
DeviceAllow = [ "/dev/stdin" ];
|
||||||
|
RestrictAddressFamilies = [ "AF_UNIX" ];
|
||||||
|
DevicePolicy = "strict";
|
||||||
|
PrivateDevices = true;
|
||||||
|
PrivateTmp = true;
|
||||||
|
PrivateUsers = true;
|
||||||
|
ProcSubset = "pid";
|
||||||
|
ProtectClock = true;
|
||||||
|
ProtectControlGroups = true;
|
||||||
|
ProtectHome = true;
|
||||||
|
ProtectHostname = true;
|
||||||
|
ProtectKernelLogs = true;
|
||||||
|
ProtectKernelModules = true;
|
||||||
|
ProtectKernelTunables = true;
|
||||||
|
ProtectProc = "invisible";
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
RestrictNamespaces = true;
|
||||||
|
RestrictRealtime = true;
|
||||||
|
RestrictSUIDSGID = true;
|
||||||
|
SystemCallArchitectures = "native";
|
||||||
|
SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ];
|
||||||
|
IPAddressDeny = "any";
|
||||||
|
IPAddressAllow = cfg.ipAddressAllow;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.sockets.tangd = {
|
||||||
|
description = "Tang server";
|
||||||
|
wantedBy = [ "sockets.target" ];
|
||||||
|
socketConfig = {
|
||||||
|
ListenStream = cfg.listenStream;
|
||||||
|
Accept = "yes";
|
||||||
|
IPAddressDeny = "any";
|
||||||
|
IPAddressAllow = cfg.ipAddressAllow;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
meta.maintainers = with lib.maintainers; [ jfroche julienmalka ];
|
||||||
|
}
|
@ -807,6 +807,7 @@ in {
|
|||||||
systemd-userdbd = handleTest ./systemd-userdbd.nix {};
|
systemd-userdbd = handleTest ./systemd-userdbd.nix {};
|
||||||
systemd-homed = handleTest ./systemd-homed.nix {};
|
systemd-homed = handleTest ./systemd-homed.nix {};
|
||||||
tandoor-recipes = handleTest ./tandoor-recipes.nix {};
|
tandoor-recipes = handleTest ./tandoor-recipes.nix {};
|
||||||
|
tang = handleTest ./tang.nix {};
|
||||||
taskserver = handleTest ./taskserver.nix {};
|
taskserver = handleTest ./taskserver.nix {};
|
||||||
tayga = handleTest ./tayga.nix {};
|
tayga = handleTest ./tayga.nix {};
|
||||||
teeworlds = handleTest ./teeworlds.nix {};
|
teeworlds = handleTest ./teeworlds.nix {};
|
||||||
|
81
nixos/tests/tang.nix
Normal file
81
nixos/tests/tang.nix
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
|
name = "tang";
|
||||||
|
meta = with pkgs.lib.maintainers; {
|
||||||
|
maintainers = [ jfroche ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.server =
|
||||||
|
{ config
|
||||||
|
, pkgs
|
||||||
|
, modulesPath
|
||||||
|
, ...
|
||||||
|
}: {
|
||||||
|
imports = [
|
||||||
|
"${modulesPath}/../tests/common/auto-format-root-device.nix"
|
||||||
|
];
|
||||||
|
virtualisation = {
|
||||||
|
emptyDiskImages = [ 512 ];
|
||||||
|
useBootLoader = true;
|
||||||
|
useEFIBoot = true;
|
||||||
|
# This requires to have access
|
||||||
|
# to a host Nix store as
|
||||||
|
# the new root device is /dev/vdb
|
||||||
|
# an empty 512MiB drive, containing no Nix store.
|
||||||
|
mountHostNixStore = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
|
||||||
|
networking.interfaces.eth1.ipv4.addresses = [
|
||||||
|
{ address = "192.168.0.1"; prefixLength = 24; }
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [ clevis tang cryptsetup ];
|
||||||
|
services.tang = {
|
||||||
|
enable = true;
|
||||||
|
ipAddressAllow = [ "127.0.0.1/32" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
machine.wait_for_unit("sockets.target")
|
||||||
|
|
||||||
|
with subtest("Check keys are generated"):
|
||||||
|
machine.wait_until_succeeds("curl -v http://127.0.0.1:7654/adv")
|
||||||
|
key = machine.wait_until_succeeds("tang-show-keys 7654")
|
||||||
|
|
||||||
|
with subtest("Check systemd access list"):
|
||||||
|
machine.succeed("ping -c 3 192.168.0.1")
|
||||||
|
machine.fail("curl -v --connect-timeout 3 http://192.168.0.1:7654/adv")
|
||||||
|
|
||||||
|
with subtest("Check basic encrypt and decrypt message"):
|
||||||
|
machine.wait_until_succeeds(f"""echo 'Hello World' | clevis encrypt tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}"}}' > /tmp/encrypted""")
|
||||||
|
decrypted = machine.wait_until_succeeds("clevis decrypt < /tmp/encrypted")
|
||||||
|
assert decrypted.strip() == "Hello World"
|
||||||
|
machine.wait_until_succeeds("tang-show-keys 7654")
|
||||||
|
|
||||||
|
with subtest("Check encrypt and decrypt disk"):
|
||||||
|
machine.succeed("cryptsetup luksFormat --force-password --batch-mode /dev/vdb <<<'password'")
|
||||||
|
machine.succeed(f"""clevis luks bind -s1 -y -f -d /dev/vdb tang '{{ "url": "http://127.0.0.1:7654", "thp":"{key}" }}' <<< 'password' """)
|
||||||
|
clevis_luks = machine.succeed("clevis luks list -d /dev/vdb")
|
||||||
|
assert clevis_luks.strip() == """1: tang '{"url":"http://127.0.0.1:7654"}'"""
|
||||||
|
machine.succeed("clevis luks unlock -d /dev/vdb")
|
||||||
|
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
|
||||||
|
machine.succeed("clevis luks unlock -d /dev/vdb")
|
||||||
|
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
|
||||||
|
# without tang available, unlock should fail
|
||||||
|
machine.succeed("systemctl stop tangd.socket")
|
||||||
|
machine.fail("clevis luks unlock -d /dev/vdb")
|
||||||
|
machine.succeed("systemctl start tangd.socket")
|
||||||
|
|
||||||
|
with subtest("Rotate server keys"):
|
||||||
|
machine.succeed("${pkgs.tang}/libexec/tangd-rotate-keys -d /var/lib/tang")
|
||||||
|
machine.succeed("clevis luks unlock -d /dev/vdb")
|
||||||
|
machine.succeed("find /dev/mapper -name 'luks*' -exec cryptsetup close {} +")
|
||||||
|
|
||||||
|
with subtest("Test systemd service security"):
|
||||||
|
output = machine.succeed("systemd-analyze security tangd@.service")
|
||||||
|
machine.log(output)
|
||||||
|
assert output[-9:-1] == "SAFE :-}"
|
||||||
|
'';
|
||||||
|
})
|
@ -13,6 +13,7 @@
|
|||||||
, testers
|
, testers
|
||||||
, tang
|
, tang
|
||||||
, gitUpdater
|
, gitUpdater
|
||||||
|
, nixosTests
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
@ -53,11 +54,14 @@ stdenv.mkDerivation rec {
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
passthru = {
|
passthru = {
|
||||||
tests.version = testers.testVersion {
|
tests = {
|
||||||
|
inherit (nixosTests) tang;
|
||||||
|
version = testers.testVersion {
|
||||||
package = tang;
|
package = tang;
|
||||||
command = "${tang}/libexec/tangd --version";
|
command = "${tang}/libexec/tangd --version";
|
||||||
version = "tangd ${version}";
|
version = "tangd ${version}";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
updateScript = gitUpdater { };
|
updateScript = gitUpdater { };
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,5 +71,6 @@ stdenv.mkDerivation rec {
|
|||||||
changelog = "https://github.com/latchset/tang/releases/tag/v${version}";
|
changelog = "https://github.com/latchset/tang/releases/tag/v${version}";
|
||||||
maintainers = with lib.maintainers; [ fpletz ];
|
maintainers = with lib.maintainers; [ fpletz ];
|
||||||
license = lib.licenses.gpl3Plus;
|
license = lib.licenses.gpl3Plus;
|
||||||
|
mainProgram = "tangd";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user