Build Charac server and client with OIDC, SSH sessions, and packages
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
using System.Security.Cryptography;
|
||||
using Charac.Server.Authentication;
|
||||
using Charac.Server.Connections;
|
||||
using Charac.Client;
|
||||
|
||||
namespace Charac.Server.Tests;
|
||||
|
||||
public sealed class ActiveClientDevicesTests
|
||||
{
|
||||
private static readonly ExternalIdentity Alice = new("https://auth.example/", "alice");
|
||||
private static readonly ExternalIdentity Bob = new("https://auth.example/", "bob");
|
||||
|
||||
[Fact]
|
||||
public void SameInstallationCanHoldSeveralConnectionsWhileAnotherIsRejected()
|
||||
{
|
||||
var devices = new ActiveClientDevices();
|
||||
var first = Credential();
|
||||
var second = Credential();
|
||||
Assert.Equal(ClientDeviceStatus.Invalid, devices.Check(Alice, "spoofed"));
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Alice, first, out var one));
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Alice, first, out var two));
|
||||
Assert.Equal(ClientDeviceStatus.Occupied, devices.Check(Alice, second));
|
||||
Assert.Equal(ClientDeviceStatus.Occupied, devices.Acquire(Alice, second, out var rejected));
|
||||
Assert.Null(rejected);
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Bob, second, out var bob));
|
||||
one!.Dispose();
|
||||
Assert.Equal(ClientDeviceStatus.Occupied, devices.Check(Alice, second));
|
||||
two!.Dispose();
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Alice, second, out var replacement));
|
||||
replacement!.Dispose();
|
||||
bob!.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OperatorDisconnectReleasesDeviceAndStaleLeaseCannotReleaseReplacement()
|
||||
{
|
||||
var devices = new ActiveClientDevices();
|
||||
var first = Credential();
|
||||
var second = Credential();
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Alice, first, out var old));
|
||||
using (devices.BeginDisconnect(Alice))
|
||||
{
|
||||
Assert.Equal(ClientDeviceStatus.Occupied, devices.Check(Alice, second));
|
||||
Assert.False(devices.TryUse(old!, () => new object(), out _));
|
||||
}
|
||||
Assert.Equal(ClientDeviceStatus.Allowed, devices.Acquire(Alice, second, out var current));
|
||||
old!.Dispose();
|
||||
Assert.Equal(ClientDeviceStatus.Occupied, devices.Check(Alice, first));
|
||||
current!.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InstallationCredentialPersistsAndIsPrivate()
|
||||
{
|
||||
var directory = Path.Combine(Path.GetTempPath(), "rac-device-" + Guid.NewGuid().ToString("N"));
|
||||
try
|
||||
{
|
||||
var concurrent = await Task.WhenAll(Enumerable.Range(0, 8)
|
||||
.Select(_ => Task.Run(() => ClientDeviceCredential.LoadOrCreate(directory))));
|
||||
var first = concurrent[0];
|
||||
Assert.Equal(43, first.Length);
|
||||
Assert.Equal(first, ClientDeviceCredential.LoadOrCreate(directory));
|
||||
Assert.All(concurrent, value => Assert.Equal(first, value));
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
var mode = File.GetUnixFileMode(Path.Combine(directory, "device-key"));
|
||||
Assert.Equal(UnixFileMode.UserRead | UnixFileMode.UserWrite, mode &
|
||||
(UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.GroupRead |
|
||||
UnixFileMode.GroupWrite | UnixFileMode.OtherRead | UnixFileMode.OtherWrite));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(directory))
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Credential() => Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))
|
||||
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
||||
}
|
||||
Reference in New Issue
Block a user