diff --git a/src/CommunityToolkit.Aspire.Hosting.Zitadel/ZitadelHostingExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.Zitadel/ZitadelHostingExtensions.cs index 3ceb4e05d..708db7199 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Zitadel/ZitadelHostingExtensions.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Zitadel/ZitadelHostingExtensions.cs @@ -35,7 +35,7 @@ public static IResourceBuilder AddZitadel( ArgumentNullException.ThrowIfNull(name); var usernameParameter = username?.Resource ?? new ParameterResource($"{name}-username", _ => "admin", false); - var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-password", minSpecial: 1); + var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-password", minLower: 1, minUpper: 1, minNumeric: 1, minSpecial: 1); var masterKeyParameter = masterKey?.Resource ?? ParameterResourceBuilderExtensions.CreateGeneratedParameter(builder, $"{name}-masterKey", true, new GenerateParameterDefault { MinLength = 32, // Zitadel requires 32, CreateDefaultPasswordParameter generates 22 diff --git a/tests/CommunityToolkit.Aspire.Hosting.Zitadel.Tests/ZitadelHostingExtensionsTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Zitadel.Tests/ZitadelHostingExtensionsTests.cs index bcb62bf15..caf533b31 100644 --- a/tests/CommunityToolkit.Aspire.Hosting.Zitadel.Tests/ZitadelHostingExtensionsTests.cs +++ b/tests/CommunityToolkit.Aspire.Hosting.Zitadel.Tests/ZitadelHostingExtensionsTests.cs @@ -70,6 +70,28 @@ public async Task AddZitadel_Sets_Admin_Username_And_Password() Assert.True(env.ContainsKey("ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD")); } + [Fact] + public void AddZitadel_Default_Password_Meets_Complexity_Requirements() + { + // Publish mode exposes the generator without wrapping it in persisted user secrets. + var builder = DistributedApplication.CreateBuilder(["Publishing:Publisher=manifest"]); + var zitadel = builder.AddZitadel("zitadel"); + + // Check the guarantees so this test cannot pass by chance if a minimum is removed. + var generation = Assert.IsType(zitadel.Resource.AdminPasswordParameter.Default); + Assert.True(generation.MinLower >= 1); + Assert.True(generation.MinUpper >= 1); + Assert.True(generation.MinNumeric >= 1); + Assert.True(generation.MinSpecial >= 1); + + var password = generation.GetDefaultValue(); + + Assert.Contains(password, char.IsLower); + Assert.Contains(password, char.IsUpper); + Assert.Contains(password, char.IsDigit); + Assert.Contains(password, c => !char.IsLetterOrDigit(c)); + } + [Fact] public void AddZitadel_Uses_Custom_Username_And_Password() {