diff --git a/BTCPayServer/Controllers/Macaroons.cs b/BTCPayServer/Controllers/Macaroons.cs new file mode 100644 index 000000000..0a87fd6e6 --- /dev/null +++ b/BTCPayServer/Controllers/Macaroons.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace BTCPayServer.Controllers +{ + public class Macaroons + { + public class Macaroon + { + public Macaroon(byte[] bytes) + { + Bytes = bytes; + Hex = NBitcoin.DataEncoders.Encoders.Hex.EncodeData(bytes); + } + + public string Hex { get; set; } + public byte[] Bytes { get; set; } + } + public static async Task GetFromDirectoryAsync(string directoryPath) + { + if (directoryPath == null) + throw new ArgumentNullException(nameof(directoryPath)); + Macaroons macaroons = new Macaroons(); + if (!Directory.Exists(directoryPath)) + return macaroons; + foreach(var file in Directory.GetFiles("*.macaroon")) + { + try + { + switch (Path.GetFileName(file)) + { + case "admin.macaroon": + macaroons.AdminMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + case "readonly.macaroon": + macaroons.ReadonlyMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + case "invoice.macaroon": + macaroons.InvoiceMacaroon = new Macaroon(await File.ReadAllBytesAsync(file)); + break; + default: + break; + } + } + catch { } + } + return macaroons; + } + public Macaroon ReadonlyMacaroon { get; set; } + + public Macaroon InvoiceMacaroon { get; set; } + public Macaroon AdminMacaroon { get; set; } + } +} diff --git a/BTCPayServer/Controllers/ServerController.cs b/BTCPayServer/Controllers/ServerController.cs index 96d6774f0..7aab0c07b 100644 --- a/BTCPayServer/Controllers/ServerController.cs +++ b/BTCPayServer/Controllers/ServerController.cs @@ -504,7 +504,7 @@ namespace BTCPayServer.Controllers } [Route("server/services/lnd/{cryptoCode}/{index}")] - public IActionResult LndServices(string cryptoCode, int index, uint? nonce) + public async Task LndServices(string cryptoCode, int index, uint? nonce) { if (!_dashBoard.IsFullySynched(cryptoCode, out var unusud)) { @@ -536,6 +536,10 @@ namespace BTCPayServer.Controllers { model.Macaroon = Encoders.Hex.EncodeData(external.Macaroon); } + var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath); + model.AdminMacaroon = macaroons?.AdminMacaroon?.Hex; + model.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex; + model.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex; if (nonce != null) { @@ -568,36 +572,40 @@ namespace BTCPayServer.Controllers [Route("server/services/lnd/{cryptoCode}/{index}")] [HttpPost] - public IActionResult LndServicesPost(string cryptoCode, int index) + public async Task LndServicesPost(string cryptoCode, int index) { var external = GetExternalLndConnectionString(cryptoCode, index); if (external == null) return NotFound(); LightningConfigurations confs = new LightningConfigurations(); + var macaroons = external.MacaroonDirectoryPath == null ? null : await Macaroons.GetFromDirectoryAsync(external.MacaroonDirectoryPath); if (external.ConnectionType == LightningConnectionType.LndGRPC) { - LightningConfiguration conf = new LightningConfiguration(); - conf.Type = "grpc"; - conf.ChainType = _Options.NetworkType.ToString(); - conf.CryptoCode = cryptoCode; - conf.Host = external.BaseUri.DnsSafeHost; - conf.Port = external.BaseUri.Port; - conf.SSL = external.BaseUri.Scheme == "https"; - conf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - conf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); - confs.Configurations.Add(conf); + LightningConfiguration grpcConf = new LightningConfiguration(); + grpcConf.Type = "grpc"; + grpcConf.Host = external.BaseUri.DnsSafeHost; + grpcConf.Port = external.BaseUri.Port; + grpcConf.SSL = external.BaseUri.Scheme == "https"; + confs.Configurations.Add(grpcConf); } else if (external.ConnectionType == LightningConnectionType.LndREST) { var restconf = new LNDRestConfiguration(); restconf.Type = "lnd-rest"; - restconf.ChainType = _Options.NetworkType.ToString(); - restconf.CryptoCode = cryptoCode; restconf.Uri = external.BaseUri.AbsoluteUri; - restconf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); - restconf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); confs.Configurations.Add(restconf); } + else + throw new NotSupportedException(external.ConnectionType.ToString()); + var commonConf = (LNDConfiguration)confs.Configurations[confs.Configurations.Count - 1]; + commonConf.ChainType = _Options.NetworkType.ToString(); + commonConf.CryptoCode = cryptoCode; + commonConf.Macaroon = external.Macaroon == null ? null : Encoders.Hex.EncodeData(external.Macaroon); + commonConf.CertificateThumbprint = external.CertificateThumbprint == null ? null : Encoders.Hex.EncodeData(external.CertificateThumbprint); + commonConf.AdminMacaroon = macaroons?.AdminMacaroon?.Hex; + commonConf.ReadonlyMacaroon = macaroons?.ReadonlyMacaroon?.Hex; + commonConf.InvoiceMacaroon = macaroons?.InvoiceMacaroon?.Hex; + var nonce = RandomUtils.GetUInt32(); var configKey = GetConfigKey("lnd", cryptoCode, index, nonce); _LnConfigProvider.KeepConfig(configKey, confs); diff --git a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs index 619463f35..54f33dbd8 100644 --- a/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs +++ b/BTCPayServer/Models/ServerViewModels/LndGrpcServicesViewModel.cs @@ -11,7 +11,9 @@ namespace BTCPayServer.Models.ServerViewModels public string Host { get; set; } public bool SSL { get; set; } public string Macaroon { get; set; } - public string RestrictedMacaroon { get; set; } + public string AdminMacaroon { get; set; } + public string ReadonlyMacaroon { get; set; } + public string InvoiceMacaroon { get; set; } public string CertificateThumbprint { get; set; } [Display(Name = "GRPC SSL Cipher suite (GRPC_SSL_CIPHER_SUITES)")] public string GRPCSSLCipherSuites { get; set; } diff --git a/BTCPayServer/Services/LightningConfigurationProvider.cs b/BTCPayServer/Services/LightningConfigurationProvider.cs index 87bedef1d..8bd98bdd4 100644 --- a/BTCPayServer/Services/LightningConfigurationProvider.cs +++ b/BTCPayServer/Services/LightningConfigurationProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NBitcoin; +using NBitcoin.DataEncoders; namespace BTCPayServer.Services { @@ -27,9 +28,9 @@ namespace BTCPayServer.Services private void CleanExpired() { - foreach(var item in _Map) + foreach (var item in _Map) { - if(item.Value.expiration < DateTimeOffset.UtcNow) + if (item.Value.expiration < DateTimeOffset.UtcNow) { _Map.TryRemove(item.Key, out var unused); } @@ -41,24 +42,29 @@ namespace BTCPayServer.Services { public List Configurations { get; set; } = new List(); } - public class LightningConfiguration + + public class LNDConfiguration { public string ChainType { get; set; } public string Type { get; set; } public string CryptoCode { get; set; } + public string CertificateThumbprint { get; set; } + public string Macaroon { get; set; } + public string AdminMacaroon { get; set; } + public string ReadonlyMacaroon { get; set; } + public string InvoiceMacaroon { get; set; } + } + public class LightningConfiguration : LNDConfiguration + { public string Host { get; set; } public int Port { get; set; } public bool SSL { get; set; } - public string CertificateThumbprint { get; set; } - public string Macaroon { get; set; } } - public class LNDRestConfiguration + public class LNDRestConfiguration : LNDConfiguration { public string ChainType { get; set; } public string Type { get; set; } public string CryptoCode { get; set; } public string Uri { get; set; } - public string Macaroon { get; set; } - public string CertificateThumbprint { get; set; } } } diff --git a/BTCPayServer/Views/Server/LndServices.cshtml b/BTCPayServer/Views/Server/LndServices.cshtml index 258ac1149..dd644359e 100644 --- a/BTCPayServer/Views/Server/LndServices.cshtml +++ b/BTCPayServer/Views/Server/LndServices.cshtml @@ -86,12 +86,26 @@ } - @if (Model.RestrictedMacaroon != null) + @if (Model.AdminMacaroon != null) { - @*
- - -
*@ +
+ + +
+ } + @if (Model.InvoiceMacaroon != null) + { +
+ + +
+ } + @if (Model.ReadonlyMacaroon != null) + { +
+ + +
} @if (Model.GRPCSSLCipherSuites != null) {