Some checks failed
		
		
	
	Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
			
				
	
	
		
			138 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.IO;
 | |
| using System.Linq;
 | |
| using System.Text.Json;
 | |
| using Microsoft.Extensions.Logging;
 | |
| using StellaOps.Cli.Configuration;
 | |
| using StellaOps.Cli.Services;
 | |
| using Xunit;
 | |
| 
 | |
| namespace StellaOps.Cli.Tests.Services;
 | |
| 
 | |
| public sealed class AuthorityDiagnosticsReporterTests : IDisposable
 | |
| {
 | |
|     private readonly string _originalDirectory = Directory.GetCurrentDirectory();
 | |
|     private readonly string _tempDirectory = Path.Combine(Path.GetTempPath(), $"stellaops-cli-tests-{Guid.NewGuid():N}");
 | |
| 
 | |
|     public AuthorityDiagnosticsReporterTests()
 | |
|     {
 | |
|         Directory.CreateDirectory(_tempDirectory);
 | |
|         Directory.SetCurrentDirectory(_tempDirectory);
 | |
|     }
 | |
| 
 | |
|     [Fact]
 | |
|     public void Emit_LogsWarning_WhenPasswordPolicyWeakened()
 | |
|     {
 | |
|         WriteAuthorityConfiguration(minimumLength: 8);
 | |
| 
 | |
|         var (_, configuration) = CliBootstrapper.Build(Array.Empty<string>());
 | |
|         var logger = new ListLogger();
 | |
| 
 | |
|         AuthorityDiagnosticsReporter.Emit(configuration, logger);
 | |
| 
 | |
|         var warning = Assert.Single(logger.Entries, entry => entry.Level == LogLevel.Warning);
 | |
|         Assert.Contains("minimum length 8 < 12", warning.Message, StringComparison.OrdinalIgnoreCase);
 | |
|         Assert.Contains("standard.yaml", warning.Message, StringComparison.OrdinalIgnoreCase);
 | |
|     }
 | |
| 
 | |
|     [Fact]
 | |
|     public void Emit_EmitsNoWarnings_WhenPasswordPolicyMeetsBaseline()
 | |
|     {
 | |
|         WriteAuthorityConfiguration(minimumLength: 12);
 | |
| 
 | |
|         var (_, configuration) = CliBootstrapper.Build(Array.Empty<string>());
 | |
|         var logger = new ListLogger();
 | |
| 
 | |
|         AuthorityDiagnosticsReporter.Emit(configuration, logger);
 | |
| 
 | |
|         Assert.DoesNotContain(logger.Entries, entry => entry.Level >= LogLevel.Warning);
 | |
|     }
 | |
| 
 | |
|     public void Dispose()
 | |
|     {
 | |
|         Directory.SetCurrentDirectory(_originalDirectory);
 | |
|         try
 | |
|         {
 | |
|             if (Directory.Exists(_tempDirectory))
 | |
|             {
 | |
|                 Directory.Delete(_tempDirectory, recursive: true);
 | |
|             }
 | |
|         }
 | |
|         catch
 | |
|         {
 | |
|             // Ignored.
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private static void WriteAuthorityConfiguration(int minimumLength)
 | |
|     {
 | |
|         var payload = new
 | |
|         {
 | |
|             Authority = new
 | |
|             {
 | |
|                 Plugins = new
 | |
|                 {
 | |
|                     ConfigurationDirectory = "plugins",
 | |
|                     Descriptors = new
 | |
|                     {
 | |
|                         standard = new
 | |
|                         {
 | |
|                             AssemblyName = "StellaOps.Authority.Plugin.Standard",
 | |
|                             Enabled = true,
 | |
|                             ConfigFile = "standard.yaml"
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true });
 | |
|         File.WriteAllText("appsettings.json", json);
 | |
| 
 | |
|         var pluginDirectory = Path.Combine(Directory.GetCurrentDirectory(), "plugins");
 | |
|         Directory.CreateDirectory(pluginDirectory);
 | |
| 
 | |
|         var pluginConfig = $"""
 | |
| bootstrapUser:
 | |
|   username: "admin"
 | |
|   password: "changeme"
 | |
| 
 | |
| passwordPolicy:
 | |
|   minimumLength: {minimumLength}
 | |
|   requireUppercase: true
 | |
|   requireLowercase: true
 | |
|   requireDigit: true
 | |
|   requireSymbol: true
 | |
| """;
 | |
| 
 | |
|         File.WriteAllText(Path.Combine(pluginDirectory, "standard.yaml"), pluginConfig);
 | |
|     }
 | |
| 
 | |
|     private sealed class ListLogger : ILogger
 | |
|     {
 | |
|         public readonly record struct LogEntry(LogLevel Level, string Message);
 | |
| 
 | |
|         public List<LogEntry> Entries { get; } = new();
 | |
| 
 | |
|         public IDisposable? BeginScope<TState>(TState state) where TState : notnull => NullScope.Instance;
 | |
| 
 | |
|         public bool IsEnabled(LogLevel logLevel) => true;
 | |
| 
 | |
|         public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
 | |
|         {
 | |
|             var message = formatter(state, exception);
 | |
|             Entries.Add(new LogEntry(logLevel, message));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private sealed class NullScope : IDisposable
 | |
|     {
 | |
|         public static NullScope Instance { get; } = new();
 | |
| 
 | |
|         public void Dispose()
 | |
|         {
 | |
|         }
 | |
|     }
 | |
| }
 |