Skip to content

Commit

Permalink
* generate simple passwords for lts compatibility (this might be it)
Browse files Browse the repository at this point in the history
* by default run the oldest lts instead of ci image
* fixed gencert cli version mismatch
  • Loading branch information
RagingKore committed Nov 7, 2023
1 parent 477c03a commit 418e996
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 23 deletions.
4 changes: 2 additions & 2 deletions gencert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ chmod 0755 ./certs

docker pull eventstore/es-gencert-cli:1.0.2

docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.1 create-ca -out /tmp/ca
docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.2 create-ca -out /tmp/ca

docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.1 create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost
docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.2 create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost

chmod -R 0755 ./certs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
namespace EventStore.Client.Operations.Tests;

public class AuthenticationTests : IClassFixture<EventStoreFixture> {
public AuthenticationTests(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output));
public class AuthenticationTests : IClassFixture<InsecureClientTestFixture> {
public AuthenticationTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output));

EventStoreFixture Fixture { get; }
InsecureClientTestFixture Fixture { get; }

public enum CredentialsCase { None, TestUser, RootUser }

Expand Down Expand Up @@ -34,7 +34,7 @@ public async Task system_call_with_valid_credentials(int caseNr, CredentialsCase

async Task ExecuteTest(int caseNr, CredentialsCase defaultCredentials, CredentialsCase actualCredentials, bool shouldThrow) {
var testUser = await Fixture.CreateTestUser();

var defaultUserCredentials = GetCredentials(defaultCredentials);
var actualUserCredentials = GetCredentials(actualCredentials);

Expand Down
82 changes: 82 additions & 0 deletions test/EventStore.Client.Operations.Tests/AuthenticationTestsOld.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
namespace EventStore.Client;

public class AuthenticationTestsOld : IClassFixture<InsecureClientTestFixture> {
public AuthenticationTestsOld(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output));

InsecureClientTestFixture Fixture { get; }

private static readonly Dictionary<string, UserCredentials> _credentials =
new Dictionary<string, UserCredentials> {
{ nameof(TestCredentials.Root), TestCredentials.Root },
{ nameof(TestCredentials.TestUser1), TestCredentials.TestUser1 },
};

public static IEnumerable<object?[]> AuthenticationCases() {
var root = nameof(TestCredentials.Root);
var testUser = nameof(TestCredentials.TestUser1);

var shouldFail = false;
var shouldSucceed = true;

// no user credentials
yield return new object?[] {1, root, null, shouldSucceed};
yield return new object?[] {2, testUser, null, shouldFail};
yield return new object?[] {3, null, null, shouldFail};

// unprivileged user credentials
yield return new object?[] {4, root, testUser, shouldFail};
yield return new object?[] {5, testUser, testUser, shouldFail};
yield return new object?[] {6, null, testUser, shouldFail};

// root user credentials
yield return new object?[] {7, root, root, shouldSucceed};
yield return new object?[] {8, testUser, root, shouldSucceed};
yield return new object?[] {9, null, root, shouldSucceed};
}

[Theory, MemberData(nameof(AuthenticationCases))]
public async Task system_call_with_credentials_combination(int caseNr, string? defaultUser, string? user, bool succeeds) {
await Fixture.Users.CreateUserWithRetry(
loginName: TestCredentials.TestUser1.Username!,
fullName: nameof(TestCredentials.TestUser1),
groups: Array.Empty<string>(),
password: TestCredentials.TestUser1.Password!,
userCredentials: TestCredentials.Root
)
.WithTimeout(TimeSpan.FromMilliseconds(1000));

var settings = Fixture.ClientSettings;

settings.DefaultCredentials = defaultUser != null ? _credentials[defaultUser] : null;
settings.ConnectionName = $"Authentication case #{caseNr} {defaultUser}";

await using var client = new EventStoreOperationsClient(settings);

var result = await Record.ExceptionAsync(() =>
client.SetNodePriorityAsync(1, userCredentials: user != null ? _credentials[user] : null));

if (succeeds) {
Assert.Null(result);
return;
}

Assert.NotNull(result);
}

// public class Fixture : EventStoreClientFixture {
// protected override async Task Given() {
// var userManagementClient = new EventStoreUserManagementClient(Settings);
// await userManagementClient.WarmUpAsync();
//
// await userManagementClient.CreateUserWithRetry(
// loginName: TestCredentials.TestUser1.Username!,
// fullName: nameof(TestCredentials.TestUser1),
// groups: Array.Empty<string>(),
// password: TestCredentials.TestUser1.Password!,
// userCredentials: TestCredentials.Root)
// .WithTimeout(TimeSpan.FromMilliseconds(1000));
// }
//
// protected override Task When() => Task.CompletedTask;
// }
}
8 changes: 7 additions & 1 deletion test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public sealed class TestUserFaker : Faker<TestUser> {
RuleFor(x => x.LoginName, f => f.Person.UserName);
RuleFor(x => x.FullName, f => f.Person.FullName);
RuleFor(x => x.Groups, f => f.Lorem.Words());
RuleFor(x => x.Password, () => PasswordGenerator.GeneratePassword());
RuleFor(x => x.Password, () => PasswordGenerator.GenerateSimplePassword());
RuleFor(x => x.Credentials, (_, user) => new(user.LoginName, user.Password));
RuleFor(x => x.Details, (_, user) => new(user.LoginName, user.FullName, user.Groups, disabled: false, dateLastUpdated: default));
}
Expand All @@ -40,6 +40,12 @@ public TestUser WithInvalidCredentials(bool wrongLoginName = true, bool wrongPas
)
)
.Generate();

public TestUser WithNonAsciiPassword() =>
Instance
.RuleFor(x => x.Password, () => PasswordGenerator.GeneratePassword())
.RuleFor(x => x.Credentials, (_, user) => new (user.LoginName, user.Password))
.Generate();
}

public static partial class Fakers {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ public Task<TestUser[]> CreateTestUsers(int count = 3, bool withoutGroups = true
.Generate(count)
.Select(
async user => {
await Users.CreateUserAsync(
user.LoginName,
user.FullName,
user.Groups,
user.Password,
userCredentials: useUserCredentials ? user.Credentials : TestCredentials.Root
);
await Users.CreateUserAsync(
user.LoginName,
user.FullName,
user.Groups,
user.Password,
userCredentials: useUserCredentials ? user.Credentials : TestCredentials.Root
);

return user;
}
Expand Down
63 changes: 57 additions & 6 deletions test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using System.Net;
using System.Net.Sockets;
using Ductus.FluentDocker.Builders;
using Ductus.FluentDocker.Common;
using Ductus.FluentDocker.Model.Builders;
using Ductus.FluentDocker.Services;
using Ductus.FluentDocker.Services.Extensions;
using EventStore.Client.Tests.FluentDocker;
using Polly;
using Serilog;
using Serilog.Extensions.Logging;

Expand Down Expand Up @@ -30,7 +34,8 @@ public static EventStoreFixtureOptions DefaultOptions() {

var defaultEnvironment = new Dictionary<string, string?>(GlobalEnvironment.Variables) {
//["EVENTSTORE_NODE_PORT"] = port,
["EVENTSTORE_NODE_PORT_ADVERTISE_AS"] = port,
// ["EVENTSTORE_NODE_PORT_ADVERTISE_AS"] = port,
// ["EVENTSTORE_NODE_PORT_ADVERTISE_AS"] = port,
//["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = port,
["EVENTSTORE_ENABLE_EXTERNAL_TCP"] = "false",
["EVENTSTORE_MEM_DB"] = "true",
Expand All @@ -39,7 +44,7 @@ public static EventStoreFixtureOptions DefaultOptions() {
["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key",
["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000",
["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000",
["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "false",
["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true",
["EVENTSTORE_DISABLE_LOG_FILE"] = "true"
};

Expand All @@ -63,10 +68,56 @@ protected override ContainerBuilder Configure() {
.WithEnvironment(env)
.MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly)
.ExposePort(port, 2113)
.WaitForHealthy(TimeSpan.FromSeconds(60));
//.WaitForMessageInLog($"========== [\"0.0.0.0:{port}\"] IS LEADER... SPARTA!")
//.WaitForMessageInLog("'ops' user added to $users.")
//.WaitForMessageInLog("'admin' user added to $users.");
.WaitForMessageInLog("'admin' user added to $users.", TimeSpan.FromSeconds(60));
//.Wait("", (svc, count) => CheckConnection());
// .KeepContainer()
// .WaitForHealthy(TimeSpan.FromSeconds(60));
//.WaitForMessageInLog($"========== [\"0.0.0.0:{port}\"] IS LEADER... SPARTA!")
//.WaitForMessageInLog("'ops' user added to $users.")
//.WaitForMessageInLog("'admin' user added to $users.");
}

int CheckConnection() {
using var http = new HttpClient(
new SocketsHttpHandler {
SslOptions = { RemoteCertificateValidationCallback = delegate { return true; } }
}
) {
BaseAddress = Options.ClientSettings.ConnectivitySettings.Address
};

return Policy.Handle<Exception>()
.WaitAndRetryAsync(300, retryCount => TimeSpan.FromMilliseconds(100))
.ExecuteAsync(
async () => {
using var response = await http.GetAsync("/health/live", CancellationToken.None);

if (response.StatusCode >= HttpStatusCode.BadRequest)
throw new FluentDockerException($"Health check failed with status code: {response.StatusCode}.");

return 0;
}
).GetAwaiter().GetResult();
}

protected override async Task OnServiceStarted() {
using var http = new HttpClient(
new SocketsHttpHandler {
SslOptions = { RemoteCertificateValidationCallback = delegate { return true; } }
}
) {
BaseAddress = Options.ClientSettings.ConnectivitySettings.Address
};

await Policy.Handle<Exception>()
.WaitAndRetryAsync(200, retryCount => TimeSpan.FromMilliseconds(100))
.ExecuteAsync(
async () => {
using var response = await http.GetAsync("/health/live", CancellationToken.None);
if (response.StatusCode >= HttpStatusCode.BadRequest)
throw new FluentDockerException($"Health check failed with status code: {response.StatusCode}.");
}
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/EventStore.Client.Tests.Common/GlobalEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace EventStore.Client.Tests;
public static class GlobalEnvironment {
static GlobalEnvironment() {
EnsureDefaults(Application.Configuration);

UseCluster = Application.Configuration.GetValue<bool>("ES_USE_CLUSTER");
UseExternalServer = Application.Configuration.GetValue<bool>("ES_USE_EXTERNAL_SERVER");
DockerImage = Application.Configuration.GetValue<string>("ES_DOCKER_IMAGE")!;
Expand All @@ -24,7 +24,7 @@ static void EnsureDefaults(IConfiguration configuration) {
configuration.EnsureValue("ES_USE_EXTERNAL_SERVER", "false");

configuration.EnsureValue("ES_DOCKER_REGISTRY", "ghcr.io/eventstore/eventstore");
configuration.EnsureValue("ES_DOCKER_TAG", "ci");
configuration.EnsureValue("ES_DOCKER_TAG", "previous-lts");
configuration.EnsureValue("ES_DOCKER_IMAGE", $"{configuration["ES_DOCKER_REGISTRY"]}:{configuration["ES_DOCKER_TAG"]}");

configuration.EnsureValue("EVENTSTORE_MEM_DB", "false");
Expand Down
12 changes: 12 additions & 0 deletions test/EventStore.Client.Tests.Common/PasswordGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,16 @@ public static string GeneratePassword(int length = 8, int minNonAsciiChars = 1)

return new(password);
}

public static string GenerateSimplePassword(int length = 8) {
if (length <= 0)
throw new ArgumentException("Invalid input parameters.");

var password = new char[length];

for (var i = 0; i < length; i++)
password[i] = AsciiChars[Random.Next(AsciiChars.Length)];

return new(password);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class UserCredentialsTests {

[Fact]
public void from_username_and_password() {
var user = Fakers.Users.Generate();
var user = Fakers.Users.WithNonAsciiPassword();

var value = new AuthenticationHeaderValue(
Constants.Headers.BasicScheme,
Expand Down

0 comments on commit 418e996

Please sign in to comment.