Files
WorkspaceAccessHost/tests/WorkspaceAccessServer.Tests/SshHostKeyTrustTests.cs
T
Nitload 0ea679932e
Verify / verify (ubuntu-latest, linux-bionic-arm64) (push) Canceled after 0s
Verify / verify (ubuntu-latest, linux-x64) (push) Canceled after 0s
Verify / verify (windows-latest, win-x64) (push) Canceled after 0s
Verify / postgres (push) Canceled after 0s
Build Charac server and client with OIDC, SSH sessions, and packages
2026-10-05 14:02:50 +08:00

72 lines
2.6 KiB
C#

using System.Buffers.Binary;
using System.Text;
using Microsoft.Extensions.Configuration;
using Charac.Server.Ssh;
using Charac.Server.Data;
namespace Charac.Server.Tests;
public sealed class SshHostKeyTrustTests
{
[Fact]
public void ExactPinnedBlobIsTrustedButDifferentBlobIsRejected()
{
var first = MakeKey(1);
var second = MakeKey(2);
var trust = new SshHostKeyTrust([first.PublicKey]);
Assert.True(trust.IsTrusted(first.Blob));
Assert.False(trust.IsTrusted(second.Blob));
}
[Fact]
public void MissingOrMalformedPinsFailClosed()
{
Assert.Throws<InvalidOperationException>(() => new SshHostKeyTrust([]));
Assert.Throws<InvalidOperationException>(() => new SshHostKeyTrust(["ssh-ed25519 invalid-base64"]));
Assert.Throws<InvalidOperationException>(() => new SshHostKeyTrust(["ssh-rsa " + MakeKey(1).PublicKey.Split(' ')[1]]));
}
[Fact]
public void ProbeConfigurationAcceptsQuotedHostPublicKey()
{
var key = MakeKey(1);
var ini = $"[ssh_probe]\naddress=10.10.0.101\nport=22\naccount=test\nhost_public_key=\"{key.PublicKey}\"\n";
using var input = new MemoryStream(Encoding.UTF8.GetBytes(ini));
var configuration = new ConfigurationBuilder().AddIniStream(input).Build();
var settings = SshProbeSettings.FromConfiguration(configuration);
Assert.Equal(key.PublicKey, settings.HostPublicKey);
}
[Fact]
public void RegistrationAcceptsOneTrustedHostKeyLineAndRejectsMultipleKeys()
{
var path = Path.Combine(Path.GetTempPath(), "rac-host-key-" + Guid.NewGuid().ToString("N") + ".pub");
try
{
var key = MakeKey(3);
File.WriteAllText(path, key.PublicKey + " host-comment\n");
Assert.Equal(key.PublicKey, AccessRegistrationCommand.ReadHostKey(path));
File.AppendAllText(path, MakeKey(4).PublicKey + "\n");
Assert.Throws<InvalidOperationException>(() => AccessRegistrationCommand.ReadHostKey(path));
}
finally
{
if (File.Exists(path))
File.Delete(path);
}
}
private static (string PublicKey, byte[] Blob) MakeKey(byte marker)
{
const string algorithm = "ssh-ed25519";
var name = Encoding.ASCII.GetBytes(algorithm);
var blob = new byte[4 + name.Length + 32];
BinaryPrimitives.WriteUInt32BigEndian(blob, (uint)name.Length);
name.CopyTo(blob, 4);
blob.AsSpan(4 + name.Length).Fill(marker);
return ($"{algorithm} {Convert.ToBase64String(blob)}", blob);
}
}