lnd: generate custom macaroons

Create new `macaroon` option that allows any module to place its own
custom macaroon in the lnd RuntimeDirectory `/run/lnd`.
This commit is contained in:
nixbitcoin 2020-08-26 08:22:23 +00:00
parent 6f032e3c40
commit 46d681a17e
No known key found for this signature in database
GPG Key ID: DD11F9AD5308B3BA

View File

@ -7,6 +7,7 @@ let
inherit (config) nix-bitcoin-services; inherit (config) nix-bitcoin-services;
onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []);
secretsDir = config.nix-bitcoin.secretsDir; secretsDir = config.nix-bitcoin.secretsDir;
mainnetDir = "${cfg.dataDir}/chain/bitcoin/mainnet";
configFile = pkgs.writeText "lnd.conf" '' configFile = pkgs.writeText "lnd.conf" ''
datadir=${cfg.dataDir} datadir=${cfg.dataDir}
logdir=${cfg.dataDir}/logs logdir=${cfg.dataDir}/logs
@ -97,6 +98,27 @@ in {
default = false; default = false;
description = "Announce LND Tor Hidden Service"; description = "Announce LND Tor Hidden Service";
}; };
macaroons = mkOption {
default = {};
type = with types; attrsOf (submodule {
options = {
user = mkOption {
type = types.str;
description = "User who owns the macaroon.";
};
permissions = mkOption {
type = types.str;
example = ''
{"entity":"info","action":"read"},{"entity":"onchain","action":"read"}
'';
description = "List of granted macaroon permissions.";
};
};
});
description = ''
Extra macaroon definitions.
'';
};
extraConfig = mkOption { extraConfig = mkOption {
type = types.lines; type = types.lines;
default = ""; default = "";
@ -155,6 +177,8 @@ in {
${optionalString cfg.announce-tor "echo externalip=$(cat /var/lib/onion-chef/lnd/lnd) >> '${cfg.dataDir}/lnd.conf'"} ${optionalString cfg.announce-tor "echo externalip=$(cat /var/lib/onion-chef/lnd/lnd) >> '${cfg.dataDir}/lnd.conf'"}
''; '';
serviceConfig = nix-bitcoin-services.defaultHardening // { serviceConfig = nix-bitcoin-services.defaultHardening // {
RuntimeDirectory = "lnd"; # Only used to store custom macaroons
RuntimeDirectoryMode = "711";
ExecStart = "${cfg.package}/bin/lnd --configfile=${cfg.dataDir}/lnd.conf"; ExecStart = "${cfg.package}/bin/lnd --configfile=${cfg.dataDir}/lnd.conf";
User = "lnd"; User = "lnd";
Restart = "on-failure"; Restart = "on-failure";
@ -181,9 +205,7 @@ in {
fi fi
chown lnd: "$mnemonic" chown lnd: "$mnemonic"
''}" ''}"
"${let "${nix-bitcoin-services.script ''
mainnetDir = "${cfg.dataDir}/chain/bitcoin/mainnet";
in nix-bitcoin-services.script ''
if [[ ! -f ${mainnetDir}/wallet.db ]]; then if [[ ! -f ${mainnetDir}/wallet.db ]]; then
echo Create lnd wallet echo Create lnd wallet
@ -213,6 +235,23 @@ in {
while ! { exec 3>/dev/tcp/127.0.0.1/${toString cfg.rpcPort}; } &>/dev/null; do while ! { exec 3>/dev/tcp/127.0.0.1/${toString cfg.rpcPort}; } &>/dev/null; do
sleep 0.1 sleep 0.1
done done
''}"
# Run fully privileged for chown
"+${nix-bitcoin-services.script ''
umask ug=r,o=
${lib.concatMapStrings (macaroon: ''
echo "Create custom macaroon ${macaroon}"
macaroonPath="$RUNTIME_DIRECTORY/${macaroon}.macaroon"
${pkgs.curl}/bin/curl -s \
-H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${mainnetDir}/admin.macaroon')" \
--cacert ${secretsDir}/lnd-cert \
-X POST \
-d '{"permissions":[${cfg.macaroons.${macaroon}.permissions}]}' \
https://127.0.0.1:${restPort}/v1/macaroon |\
${pkgs.jq}/bin/jq -c '.macaroon' | ${pkgs.xxd}/bin/xxd -p -r > "$macaroonPath"
chown ${cfg.macaroons.${macaroon}.user}: "$macaroonPath"
'') (attrNames cfg.macaroons)}
''}" ''}"
]; ];
} // (if cfg.enforceTor } // (if cfg.enforceTor
@ -231,6 +270,7 @@ in {
lnd-wallet-password.user = "lnd"; lnd-wallet-password.user = "lnd";
lnd-key.user = "lnd"; lnd-key.user = "lnd";
lnd-cert.user = "lnd"; lnd-cert.user = "lnd";
lnd-cert.permissions = "0444"; # world readable
}; };
}; };
} }