mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
Try to read the authorized keys file from the configuration
This commit is contained in:
parent
a8e2a99faa
commit
9e107b1eb1
@ -245,6 +245,7 @@ namespace BTCPayServer.Configuration
|
||||
}
|
||||
settings.Password = conf.GetOrDefault<string>("sshpassword", "");
|
||||
settings.KeyFile = conf.GetOrDefault<string>("sshkeyfile", "");
|
||||
settings.AuthorizedKeysFile = conf.GetOrDefault<string>("sshauthorizedkeys", "");
|
||||
settings.KeyFilePassword = conf.GetOrDefault<string>("sshkeyfilepassword", "");
|
||||
return settings;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ namespace BTCPayServer.Configuration
|
||||
app.Option("--sshpassword", "SSH password to manage BTCPay (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--sshkeyfile", "SSH private key file to manage BTCPay (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--sshkeyfilepassword", "Password of the SSH keyfile (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--sshauthorizedkeys", "Path to a authorized_keys file that BTCPayServer can modify from the website (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue);
|
||||
app.Option("--torrcfile", "Path to torrc file containing hidden services directories (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--socksendpoint", "Socks endpoint to connect to onion urls (default: empty)", CommandOptionType.SingleValue);
|
||||
|
@ -474,7 +474,8 @@ namespace BTCPayServer.Controllers
|
||||
if (appIdsToFetch.Any())
|
||||
{
|
||||
var apps = (await _AppService.GetApps(appIdsToFetch.ToArray()))
|
||||
.ToDictionary(data => data.Id, data => Enum.Parse<AppType>(data.AppType));;
|
||||
.ToDictionary(data => data.Id, data => Enum.Parse<AppType>(data.AppType));
|
||||
;
|
||||
if (!string.IsNullOrEmpty(settings.RootAppId))
|
||||
{
|
||||
settings.RootAppType = apps[settings.RootAppId];
|
||||
@ -504,7 +505,7 @@ namespace BTCPayServer.Controllers
|
||||
Link = this.Request.GetAbsoluteUriNoPathBase(externalService.Value).AbsoluteUri
|
||||
});
|
||||
}
|
||||
if (_sshState.CanUseSSH)
|
||||
if (CanShowSSHService())
|
||||
{
|
||||
result.OtherExternalServices.Add(new ServicesViewModel.OtherExternalService()
|
||||
{
|
||||
@ -900,10 +901,10 @@ namespace BTCPayServer.Controllers
|
||||
[Route("server/services/ssh")]
|
||||
public async Task<IActionResult> SSHService()
|
||||
{
|
||||
var settings = _Options.SSHSettings;
|
||||
if (settings == null)
|
||||
if (!CanShowSSHService())
|
||||
return NotFound();
|
||||
|
||||
var settings = _Options.SSHSettings;
|
||||
var server = Extensions.IsLocalNetwork(settings.Server) ? this.Request.Host.Host : settings.Server;
|
||||
SSHServiceViewModel vm = new SSHServiceViewModel();
|
||||
string port = settings.Port == 22 ? "" : $" -p {settings.Port}";
|
||||
@ -911,8 +912,19 @@ namespace BTCPayServer.Controllers
|
||||
vm.Password = settings.Password;
|
||||
vm.KeyFilePassword = settings.KeyFilePassword;
|
||||
vm.HasKeyFile = !string.IsNullOrEmpty(settings.KeyFile);
|
||||
vm.CanConnect = _sshState.CanUseSSH;
|
||||
if (vm.CanConnect)
|
||||
|
||||
// Let's try to just read the authorized key file
|
||||
if (CanAccessAuthorizedKeyFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
vm.SSHKeyFileContent = await System.IO.File.ReadAllTextAsync(settings.AuthorizedKeysFile);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If that fail, just fallback to ssh
|
||||
if (vm.SSHKeyFileContent == null && _sshState.CanUseSSH)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -922,31 +934,68 @@ namespace BTCPayServer.Controllers
|
||||
vm.SSHKeyFileContent = result.Output;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
bool CanShowSSHService()
|
||||
{
|
||||
return _Options.SSHSettings != null && (_sshState.CanUseSSH || CanAccessAuthorizedKeyFile());
|
||||
}
|
||||
|
||||
private bool CanAccessAuthorizedKeyFile()
|
||||
{
|
||||
return _Options.SSHSettings.AuthorizedKeysFile != null && System.IO.File.Exists(_Options.SSHSettings.AuthorizedKeysFile);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("server/services/ssh")]
|
||||
public async Task<IActionResult> SSHService(SSHServiceViewModel viewModel)
|
||||
{
|
||||
string newContent = viewModel?.SSHKeyFileContent ?? string.Empty;
|
||||
newContent = newContent.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase);
|
||||
try
|
||||
|
||||
Exception exception = null;
|
||||
|
||||
// Let's try to just write the file
|
||||
if (CanAccessAuthorizedKeyFile())
|
||||
{
|
||||
using (var sshClient = await _Options.SSHSettings.ConnectAsync())
|
||||
try
|
||||
{
|
||||
await sshClient.RunBash($"mkdir -p ~/.ssh && echo '{newContent.EscapeSingleQuotes()}' > ~/.ssh/authorized_keys", TimeSpan.FromSeconds(10));
|
||||
await System.IO.File.WriteAllTextAsync(_Options.SSHSettings.AuthorizedKeysFile, newContent);
|
||||
StatusMessage = "authorized_keys has been updated";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
// If that fail, fallback to ssh
|
||||
if (exception != null && _sshState.CanUseSSH)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var sshClient = await _Options.SSHSettings.ConnectAsync())
|
||||
{
|
||||
await sshClient.RunBash($"mkdir -p ~/.ssh && echo '{newContent.EscapeSingleQuotes()}' > ~/.ssh/authorized_keys", TimeSpan.FromSeconds(10));
|
||||
}
|
||||
exception = null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception is null)
|
||||
{
|
||||
StatusMessage = "authorized_keys has been updated";
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
StatusMessage = $"Error: {ex.Message}";
|
||||
StatusMessage = $"Error: {exception.Message}";
|
||||
}
|
||||
return RedirectToAction(nameof(SSHService));
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ namespace BTCPayServer.Models.ServerViewModels
|
||||
public string Password { get; set; }
|
||||
public string KeyFilePassword { get; set; }
|
||||
public bool HasKeyFile { get; set; }
|
||||
public bool CanConnect { get; set; }
|
||||
public string SSHKeyFileContent { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace BTCPayServer.SSH
|
||||
public int Port { get; set; } = 22;
|
||||
public string KeyFile { get; set; }
|
||||
public string KeyFilePassword { get; set; }
|
||||
public string AuthorizedKeysFile { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public List<SSHFingerprint> TrustedFingerprints { get; set; } = new List<SSHFingerprint>();
|
||||
|
@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.CanConnect)
|
||||
@if (Model.SSHKeyFileContent != null)
|
||||
{
|
||||
<h4>Authorized keys</h4>
|
||||
<div class="row">
|
||||
|
Loading…
Reference in New Issue
Block a user