-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #49 from ngi-nix/algae-rosenpass
rosenpass: Add package, module and tests
- Loading branch information
Showing
15 changed files
with
683 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
{ | ||
config, | ||
lib, | ||
options, | ||
pkgs, | ||
... | ||
}: | ||
with builtins; | ||
with lib; let | ||
cfg = config.services.rosenpass; | ||
opt = options.services.rosenpass; | ||
in { | ||
options.services.rosenpass = with types; { | ||
enable = mkEnableOption "Whether to enable the Rosenpass service to provide post-quantum secure key exchange for WireGuard."; | ||
|
||
package = mkPackageOption pkgs "rosenpass" {}; | ||
|
||
user = mkOption { | ||
type = str; | ||
default = "rosenpass"; | ||
description = "User to run Rosenpass as."; | ||
}; | ||
|
||
group = mkOption { | ||
type = str; | ||
default = "rosenpass"; | ||
description = "Primary group of the user running Rosenpass."; | ||
}; | ||
|
||
publicKeyFile = mkOption { | ||
type = path; | ||
description = "Path to a file containing the public key of the local Rosenpass peer. Generate this by running `rosenpass gen-keys`."; | ||
}; | ||
|
||
secretKeyFile = mkOption { | ||
type = path; | ||
description = "Path to a file containing the secret key of the local Rosenpass peer. Generate this by running `rosenpass gen-keys`."; | ||
}; | ||
|
||
defaultDevice = mkOption { | ||
type = nullOr str; | ||
description = "Name of the network interface to use for all peers by default."; | ||
example = "wg0"; | ||
}; | ||
|
||
listen = mkOption { | ||
type = listOf str; | ||
description = "List of local endpoints to listen for connections."; | ||
default = []; | ||
example = literalExpression "[ \"0.0.0.0:10000\" ]"; | ||
}; | ||
|
||
verbosity = mkOption { | ||
type = enum ["Verbose" "Quiet"]; | ||
default = "Quiet"; | ||
description = "Verbosity of output produced by the service."; | ||
}; | ||
|
||
peers = let | ||
peer = submodule { | ||
options = { | ||
publicKeyFile = mkOption { | ||
type = path; | ||
description = "Path to a file containing the public key of the remote Rosenpass peer."; | ||
}; | ||
|
||
endpoint = mkOption { | ||
type = nullOr str; | ||
default = null; | ||
description = "Endpoint of the remote Rosenpass peer."; | ||
}; | ||
|
||
device = mkOption { | ||
type = str; | ||
default = cfg.defaultDevice; | ||
defaultText = literalExpression "config.${opt.defaultDevice}"; | ||
description = "Name of the local WireGuard interface to use for this peer."; | ||
}; | ||
|
||
wireguard = mkOption { | ||
type = submodule { | ||
options = { | ||
publicKey = mkOption { | ||
type = str; | ||
description = "WireGuard public key corresponding to the remote Rosenpass peer."; | ||
}; | ||
}; | ||
}; | ||
description = "WireGuard configuration for this peer."; | ||
}; | ||
}; | ||
}; | ||
in | ||
mkOption { | ||
type = listOf peer; | ||
description = "List of peers to exchange keys with."; | ||
default = []; | ||
}; | ||
|
||
extraConfig = mkOption { | ||
type = attrs; | ||
description = '' | ||
Extra configuration to be merged with the generated Rosenpass configuration file. | ||
''; | ||
default = {}; | ||
}; | ||
}; | ||
|
||
config = mkIf cfg.enable { | ||
warnings = let | ||
netdevsList = attrValues config.systemd.network.netdevs; | ||
publicKeyInNetdevs = peer: any (netdev: any (publicKeyInWireguardPeers peer) netdev.wireguardPeers) netdevsList; | ||
publicKeyInWireguardPeers = peer: x: x.wireguardPeerConfig ? PublicKey && x.wireguardPeerConfig.PublicKey == peer.wireguard.publicKey; | ||
|
||
# NOTE: In the message below, we tried to refer to | ||
# options.systemd.network.netdevs."<name>".wireguardPeers.*.PublicKey | ||
# directly, but don't know how to traverse "<name>" and * in this path. | ||
warningMsg = peer: "It appears that you have configured a Rosenpass peer with the Wireguard public key '${peer.wireguard.publicKey}' but there is no corresponding Wireguard peer configuration in any of `${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.PublicKey`. While this may work as expected, such a scenario is unusual. Please double-check your configuration."; | ||
in | ||
concatMap (peer: optional (!publicKeyInNetdevs peer) (warningMsg peer)) cfg.peers; | ||
|
||
environment.systemPackages = [cfg.package pkgs.wireguard-tools]; | ||
|
||
users.users."${cfg.user}" = { | ||
isSystemUser = true; | ||
createHome = false; | ||
group = cfg.group; | ||
}; | ||
|
||
users.groups."${cfg.group}" = {}; | ||
|
||
# NOTE: It would be possible to use systemd credentials for pqsk. | ||
# <https://systemd.io/CREDENTIALS/> | ||
systemd.services.rosenpass = let | ||
generatePeerConfig = { | ||
publicKeyFile, | ||
endpoint, | ||
device, | ||
wireguard, | ||
}: | ||
{ | ||
inherit device; | ||
public_key = publicKeyFile; | ||
peer = wireguard.publicKey; | ||
extra_params = []; | ||
} | ||
// (optionalAttrs (endpoint != null) {inherit endpoint;}); | ||
|
||
generateConfig = { | ||
publicKeyFile, | ||
secretKeyFile, | ||
listen, | ||
verbosity, | ||
peers, | ||
... | ||
}: { | ||
inherit listen verbosity; | ||
public_key = publicKeyFile; | ||
secret_key = secretKeyFile; | ||
peers = map generatePeerConfig peers; | ||
}; | ||
toml = pkgs.formats.toml {}; | ||
configFile = toml.generate "config.toml" (recursiveUpdate (generateConfig cfg) cfg.extraConfig); | ||
in { | ||
wantedBy = ["multi-user.target"]; | ||
after = ["network-online.target"]; | ||
path = [pkgs.wireguard-tools]; | ||
|
||
script = "${cfg.package}/bin/rosenpass exchange-config ${configFile}"; | ||
|
||
serviceConfig = { | ||
User = cfg.user; | ||
Group = cfg.group; | ||
AmbientCapabilities = ["CAP_NET_ADMIN"]; | ||
}; | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
lib, | ||
makeWrapper, | ||
stdenv, | ||
coreutils, | ||
findutils, | ||
gawk, | ||
rosenpass, | ||
wireguard-tools, | ||
}: | ||
stdenv.mkDerivation { | ||
pname = "rosenpass-tools"; | ||
inherit (rosenpass) version src; | ||
|
||
nativeBuildInputs = [makeWrapper]; | ||
|
||
postInstall = let | ||
rpDependencies = [ | ||
coreutils | ||
findutils | ||
gawk | ||
rosenpass | ||
wireguard-tools | ||
]; | ||
in '' | ||
install -D $src/rp $out/bin/rp | ||
install -D $src/doc/rp.1 $out/share/man/man1/rp.1 | ||
wrapProgram $out/bin/rp --prefix PATH : ${lib.makeBinPath rpDependencies} | ||
''; | ||
|
||
meta = { | ||
inherit (rosenpass.meta) homepage license maintainers; | ||
description = rosenpass.meta.description + " This package contains `rp`, which is a script that wraps the `rosenpass` binary."; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
{ | ||
lib, | ||
fetchFromGitHub, | ||
nixosTests, | ||
rustPlatform, | ||
targetPlatform, | ||
cmake, | ||
libsodium, | ||
pkg-config, | ||
}: | ||
rustPlatform.buildRustPackage rec { | ||
pname = "rosenpass"; | ||
version = "0.2.0"; | ||
src = fetchFromGitHub { | ||
owner = pname; | ||
repo = pname; | ||
rev = "v${version}"; | ||
hash = "sha256-r7/3C5DzXP+9w4rp9XwbP+/NK1axIP6s3Iiio1xRMbk="; | ||
}; | ||
|
||
cargoHash = "sha256-g2w3lZXQ3Kg3ydKdFs8P2lOPfIkfTbAF0MhxsJoX/E4="; | ||
|
||
nativeBuildInputs = [ | ||
cmake # for oqs build in the oqs-sys crate | ||
pkg-config # let libsodium-sys-stable find libsodium | ||
rustPlatform.bindgenHook # for C-bindings in the crypto libs | ||
]; | ||
|
||
buildInputs = [libsodium]; | ||
|
||
# liboqs requires quite a lot of stack memory, thus we adjust | ||
# Increase the default stack size picked for new threads (which is used | ||
# by `cargo test`) to be _big enough_. | ||
# Only set this value for the check phase (not as an environment variable for the derivation), | ||
# because it is only required in this phase. | ||
preCheck = "export RUST_MIN_STACK=${builtins.toString (8 * 1024 * 1024)}"; # 8 MiB | ||
|
||
# nix defaults to building for aarch64 _without_ the armv8-a | ||
# crypto extensions, but liboqs depends on these | ||
preBuild = | ||
lib.optionalString targetPlatform.isAarch | ||
''NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -march=armv8-a+crypto"''; | ||
|
||
preInstall = "install -D doc/rosenpass.1 $out/share/man/man1/rosenpass.1"; | ||
|
||
meta = with lib; { | ||
description = "Build post-quantum-secure VPNs with WireGuard!"; | ||
homepage = "https://rosenpass.eu/"; | ||
license = with licenses; [ | ||
mit | ||
/* | ||
or | ||
*/ | ||
asl20 | ||
]; | ||
platforms = platforms.all; | ||
maintainers = with maintainers; | ||
[ | ||
andresnav | ||
imincik | ||
lorenzleutgeb | ||
] | ||
++ (with (import ../../maintainers/maintainers-list.nix); [augustebaum kubaneko]); | ||
}; | ||
|
||
passthru.tests = { | ||
inherit (nixosTests) rosenpass; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
keys: | ||
- &andres-nav age12qdlu87t3sh0m02eh5n3kx75d98h2evgme4uue2ucl4e4acg8ffszzlkss | ||
- &augustebaum age16xvvc22xm35xzgc2yx6cpcz6wnww8tf6rwfmrag4vnem7nq6h9pqr33epg | ||
- &imincik age1przhvgd5gy3kvcmlmsu47qmauhdwzzez7z89xyv623em72e9mfzskefwcl | ||
- &lorenzleutgeb age1c0g6s6daxy79dlm9uqczwlkh0hvjpghw5h8zzljc3vs275rvvqus30hv9l | ||
- &test age1fdlfm8xh97fwpf8fls9245wre9aktg6dzhhrr02s028kz4g38ajss2guwx | ||
creation_rules: | ||
- path_regex: ^(client|server)\/.*\.(yaml|bin)$ | ||
key_groups: | ||
- age: | ||
- *andres-nav | ||
- *augustebaum | ||
- *imincik | ||
- *lorenzleutgeb | ||
- *test |
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
wireguard: | ||
wgsk: ENC[AES256_GCM,data:k+45ywsKGgTelWa3tjFZyaRzKya/yLVPTM2CwwQNzJ9fx54olcfzLlwpxi8=,iv:YoLWrnVZSEFyGmC2k7KmAiWOrtjtBEhR5cwX6ehWnVc=,tag:SkJh7vGBwL2nmIwJx++b7g==,type:str] | ||
sops: | ||
kms: [] | ||
gcp_kms: [] | ||
azure_kv: [] | ||
hc_vault: [] | ||
age: | ||
- recipient: age12qdlu87t3sh0m02eh5n3kx75d98h2evgme4uue2ucl4e4acg8ffszzlkss | ||
enc: | | ||
-----BEGIN AGE ENCRYPTED FILE----- | ||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBISXREQ2tlVUtVUHNkSCsz | ||
b2NBOG00UmZjZkVCQ2pyK3lQblRCMlBHQUJZCmFEcVVZNDZYWGZrcVl6RDZYVnAw | ||
aTlmWTNsbkVaNC9FMVBlQW9OYmNpcDAKLS0tIEw1SThDcEJmSnpQYVBueHRLZFRr | ||
NlVmQ3JXUTd6dStCSHlITW04WllyUjgKKLk6KAZV2496O+LiZNSXDSm92VSyT22y | ||
wsiHb9wzuKP5qUqPsbNezSsyRUbgPpn3HTO+v7JBuYqu5GLJj3RIfA== | ||
-----END AGE ENCRYPTED FILE----- | ||
- recipient: age16xvvc22xm35xzgc2yx6cpcz6wnww8tf6rwfmrag4vnem7nq6h9pqr33epg | ||
enc: | | ||
-----BEGIN AGE ENCRYPTED FILE----- | ||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZZndSaWd0cktaL2dFbWxW | ||
UWZHTk44V3Y1bzBSUnRhbFloVlpRWXJIU0c0Cng2ZmN3YnJWSitSWnNjUUhGeENS | ||
SG1iQzkwaVUvUFZGVEF5VUhEaHpqNlUKLS0tIG5kV1Z3ODJmdEFNSm14N3IzblJq | ||
eDltbkNNc0g5eVk4a1dMSTQ5VjRoRVUKs+Pxd0W6MRIjSsS2IFHdX4Q4m84v7K0H | ||
JoY+r4I1NxAJWt6uoDhc9JIiagwPABjzN5nfe1+4o0nYmwmndG4XiQ== | ||
-----END AGE ENCRYPTED FILE----- | ||
- recipient: age1przhvgd5gy3kvcmlmsu47qmauhdwzzez7z89xyv623em72e9mfzskefwcl | ||
enc: | | ||
-----BEGIN AGE ENCRYPTED FILE----- | ||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2dGI4Mk9yc3RXL2FEdFBH | ||
RjRmalliZ0ZVTUJuQkUrQ1BSdHQraFo4L2wwCkVNdjM4QVpEZGoyMEllWjRpOW5u | ||
TjJHOVFXeGxYYVNyZjBRMGd1amFLOEUKLS0tIHNhU0QrYUwwYXBZZjFKT29vMVpy | ||
NTRaSFdhR05qMitNcEZGRkMwd0g1d28KYInWBN/Qmp1y8A0gCk9LDXshkf27/xzj | ||
7Tdk57u52E7MqAcWUO8R8EbI79ePH2j4VXzhVNKsnjKODZ2MrcGvRg== | ||
-----END AGE ENCRYPTED FILE----- | ||
- recipient: age1c0g6s6daxy79dlm9uqczwlkh0hvjpghw5h8zzljc3vs275rvvqus30hv9l | ||
enc: | | ||
-----BEGIN AGE ENCRYPTED FILE----- | ||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxT1Z3MzlxMjgrY1VHR2xt | ||
aFNreEszNFBUZGRoSEJ5QVRRMVc4Ty9FYnhzCkdzT2tWNXNKclQzVGJHMEtGR01E | ||
ejlWbDAwTmYxNUgxL2dXbVg5ankwRTgKLS0tIHpvWUJ0UGhWMlgxMjk5Tko3Skdq | ||
V05aR2JyU2hac2F1UWx6VnpxekF6UGsK9iBYVAkMCvmCIcxCkGU3Bq9t7kFs2gyz | ||
uiUBUxgLTyfdmxZ4HDQFpMm66O6SHc5Zx0738/AClU89fhvtANJeyw== | ||
-----END AGE ENCRYPTED FILE----- | ||
- recipient: age1fdlfm8xh97fwpf8fls9245wre9aktg6dzhhrr02s028kz4g38ajss2guwx | ||
enc: | | ||
-----BEGIN AGE ENCRYPTED FILE----- | ||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJUTFQZzljQ3hCUHFESUlm | ||
aGJOeXUvc0ZDTm1jOGlnMnM0QzFOOGRuODI0CjdlM2ZXWnJFUFFqVXFZRGFsZ2V2 | ||
SmxHUGhtM2Y2d016V0ZYZkp1cXFMSFkKLS0tIGlvRjNHWDFEUEY1bXRqaWtjOXpi | ||
RWhubmtWdVZwbml6QzlMcXVwL0RZa1EKcBXzTtmaB4Rg+qHVQilx8jPVjHbJ366r | ||
OOYx12stTCvAcbrLCUhZRhsm9mLEmudFQcC36QxqxJfhYB3tKukLaQ== | ||
-----END AGE ENCRYPTED FILE----- | ||
lastmodified: "2023-09-05T18:39:18Z" | ||
mac: ENC[AES256_GCM,data:ZLevHXqYLBzz9F+UDHWGXCv9gjgoWRlhOyPB2hDXbmTptiDwoeJ1AAyXWCXCmgdR4zsNv9UuIpY++Q7zY1r2TEsQSfdCH1sELcBfn41QidLvrQDo5Ua1k08SiNyAeytsDAXRCr0YuOSA7gKydKt40RXCAo9FYNpr6iII7XWHLyI=,iv:fqt6TaPKgZyxn+NqXeH1i5kV2i6nprAlkvmRGkRU7V4=,tag:nZLc9jdY5kKeQ+JoX8eWeA==,type:str] | ||
pgp: [] | ||
unencrypted_suffix: _unencrypted | ||
version: 3.7.3 |
Oops, something went wrong.