(refactor): codebase review, small syntax fixes

This commit is contained in:
Maksym Sadovnychyy 2023-08-01 12:31:24 +02:00
parent 23fa0d9826
commit 767b4f2fc6
29 changed files with 1368 additions and 1410 deletions

View File

@ -8,7 +8,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Abstractions\" /> <Compile Remove="Abstractions\**" />
<EmbeddedResource Remove="Abstractions\**" />
<None Remove="Abstractions\**" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,7 +1,7 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Text.Json; using System.Text.Json;
namespace MaksIT.Core.Extensions { namespace MaksIT.Core.Extensions;
public static class ObjectExtensions { public static class ObjectExtensions {
/// <summary> /// <summary>
@ -34,4 +34,3 @@ namespace MaksIT.Core.Extensions {
return JsonSerializer.Serialize(obj, options); return JsonSerializer.Serialize(obj, options);
} }
} }
}

View File

@ -6,7 +6,7 @@ using System.Text.Json.Serialization;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MaksIT.Core.Extensions { namespace MaksIT.Core.Extensions;
public static class StringExtensions { public static class StringExtensions {
/// <summary> /// <summary>
/// Converts JSON string to object /// Converts JSON string to object
@ -37,4 +37,3 @@ namespace MaksIT.Core.Extensions {
: default; : default;
} }
} }
}

View File

@ -1,6 +1,6 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace MaksIT.Core { namespace MaksIT.Core;
public static class OperatingSystem { public static class OperatingSystem {
public static bool IsWindows() => public static bool IsWindows() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows); RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
@ -11,4 +11,3 @@ namespace MaksIT.Core {
public static bool IsLinux() => public static bool IsLinux() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Linux); RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
} }
}

View File

@ -2,7 +2,7 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace MaksIT.LetsEncrypt.Entities.Jws { namespace MaksIT.LetsEncrypt.Entities.Jws;
public class Jwk { public class Jwk {
/// <summary> /// <summary>
/// "kty" (Key Type) Parameter /// "kty" (Key Type) Parameter
@ -102,4 +102,3 @@ namespace MaksIT.LetsEncrypt.Entities.Jws {
[JsonPropertyName("alg")] [JsonPropertyName("alg")]
public string? Algorithm { get; set; } public string? Algorithm { get; set; }
} }
}

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace MaksIT.LetsEncrypt.Entities.Jws namespace MaksIT.LetsEncrypt.Entities.Jws;
{
public class JwsMessage { public class JwsMessage {
@ -34,7 +34,3 @@ namespace MaksIT.LetsEncrypt.Entities.Jws
[JsonPropertyName("Host")] [JsonPropertyName("Host")]
public string? Host { get; set; } public string? Host { get; set; }
} }
}

View File

@ -1,6 +1,6 @@
using System; using System;
namespace MaksIT.LetsEncrypt.Entities { namespace MaksIT.LetsEncrypt.Entities;
public class AuthorizationChallenge { public class AuthorizationChallenge {
public Uri? Url { get; set; } public Uri? Url { get; set; }
@ -10,4 +10,3 @@ namespace MaksIT.LetsEncrypt.Entities {
public string? Token { get; set; } public string? Token { get; set; }
} }
}

View File

@ -1,11 +1,8 @@
using System.Security.Cryptography; using System.Security.Cryptography;
namespace MaksIT.LetsEncrypt.Entities namespace MaksIT.LetsEncrypt.Entities;
{
public class CachedCertificateResult public class CachedCertificateResult {
{
public RSACryptoServiceProvider? PrivateKey { get; set; } public RSACryptoServiceProvider? PrivateKey { get; set; }
public string? Certificate { get; set; } public string? Certificate { get; set; }
} }
}

View File

@ -1,8 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Text;
using MaksIT.LetsEncrypt.Entities.Jws; using MaksIT.LetsEncrypt.Entities.Jws;
namespace MaksIT.LetsEncrypt.Entities { namespace MaksIT.LetsEncrypt.Entities;
public class CertificateCache { public class CertificateCache {
public string? Cert { get; set; } public string? Cert { get; set; }
public byte[]? Private { get; set; } public byte[]? Private { get; set; }
@ -14,5 +17,46 @@ namespace MaksIT.LetsEncrypt.Entities {
public string? Id { get; set; } public string? Id { get; set; }
public Jwk? Key { get; set; } public Jwk? Key { get; set; }
public Uri? Location { get; set; } public Uri? Location { get; set; }
/// <summary>
///
/// </summary>
/// <param name="subject"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool TryGetCachedCertificate(string subject, out CachedCertificateResult? value) {
value = null;
if (CachedCerts == null)
return false;
if (!CachedCerts.TryGetValue(subject, out var cache)) {
return false;
}
var cert = new X509Certificate2(Encoding.ASCII.GetBytes(cache.Cert));
// if it is about to expire, we need to refresh
if ((cert.NotAfter - DateTime.UtcNow).TotalDays < 30)
return false;
var rsa = new RSACryptoServiceProvider(4096);
rsa.ImportCspBlob(cache.Private);
value = new CachedCertificateResult {
Certificate = cache.Cert,
PrivateKey = rsa
};
return true;
}
/// <summary>
///
/// </summary>
/// <param name="hostsToRemove"></param>
public void ResetCachedCertificate(IEnumerable<string> hostsToRemove) {
if (CachedCerts != null)
foreach (var host in hostsToRemove)
CachedCerts.Remove(host);
} }
} }

View File

@ -1,7 +1,5 @@
using System; 
using System.Net.Http; namespace MaksIT.LetsEncrypt.Exceptions;
namespace MaksIT.LetsEncrypt.Exceptions {
public class LetsEncrytException : Exception { public class LetsEncrytException : Exception {
public LetsEncrytException(Problem problem, HttpResponseMessage response) public LetsEncrytException(Problem problem, HttpResponseMessage response)
: base($"{problem.Type}: {problem.Detail}") { : base($"{problem.Type}: {problem.Detail}") {
@ -22,4 +20,4 @@ namespace MaksIT.LetsEncrypt.Exceptions {
public string RawJson { get; set; } public string RawJson { get; set; }
} }
}

View File

@ -2,11 +2,10 @@
using MaksIT.LetsEncrypt.Services; using MaksIT.LetsEncrypt.Services;
namespace MaksIT.LetsEncrypt.Extensions { namespace MaksIT.LetsEncrypt.Extensions;
public static class ServiceCollectionExtensions { public static class ServiceCollectionExtensions {
public static void RegisterLetsEncrypt(this IServiceCollection services) { public static void RegisterLetsEncrypt(this IServiceCollection services) {
services.AddHttpClient<ILetsEncryptService, LetsEncryptService>(); services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
} }
} }
}

View File

@ -1,5 +1,4 @@
namespace MaksIT.LetsEncrypt.Models.Interfaces { namespace MaksIT.LetsEncrypt.Models.Interfaces;
public interface IHasLocation { public interface IHasLocation {
Uri? Location { get; set; } Uri? Location { get; set; }
} }
}

View File

@ -1,7 +1,5 @@
namespace MaksIT.LetsEncrypt.Models.Requests namespace MaksIT.LetsEncrypt.Models.Requests;
{
public class FinalizeRequest public class FinalizeRequest {
{
public string? Csr { get; set; } public string? Csr { get; set; }
} }
}

View File

@ -5,8 +5,8 @@ using MaksIT.LetsEncrypt.Models.Interfaces;
* https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.3 * https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.3
*/ */
namespace MaksIT.LetsEncrypt.Models.Responses namespace MaksIT.LetsEncrypt.Models.Responses;
{
public class Account : IHasLocation { public class Account : IHasLocation {
public bool TermsOfServiceAgreed { get; set; } public bool TermsOfServiceAgreed { get; set; }
@ -35,4 +35,3 @@ namespace MaksIT.LetsEncrypt.Models.Responses
public Uri? Location { get; set; } public Uri? Location { get; set; }
} }
}

View File

@ -1,11 +1,9 @@
using System; using System;
namespace MaksIT.LetsEncrypt.Models.Responses namespace MaksIT.LetsEncrypt.Models.Responses;
{
public class AcmeDirectory
{
public Uri NewNonce { get; set; }
public class AcmeDirectory {
public Uri NewNonce { get; set; }
public Uri NewAccount { get; set; } public Uri NewAccount { get; set; }
@ -22,8 +20,6 @@ namespace MaksIT.LetsEncrypt.Models.Responses
public AcmeDirectoryMeta Meta { get; set; } public AcmeDirectoryMeta Meta { get; set; }
} }
public class AcmeDirectoryMeta public class AcmeDirectoryMeta {
{
public string TermsOfService { get; set; } public string TermsOfService { get; set; }
} }
}

View File

@ -1,7 +1,8 @@
 
using MaksIT.LetsEncrypt.Entities; using MaksIT.LetsEncrypt.Entities;
namespace MaksIT.LetsEncrypt.Models.Responses { namespace MaksIT.LetsEncrypt.Models.Responses;
public class AuthorizationChallengeResponse { public class AuthorizationChallengeResponse {
public OrderIdentifier? Identifier { get; set; } public OrderIdentifier? Identifier { get; set; }
@ -17,4 +18,3 @@ namespace MaksIT.LetsEncrypt.Models.Responses {
public class AuthorizeChallenge { public class AuthorizeChallenge {
public string? KeyAuthorization { get; set; } public string? KeyAuthorization { get; set; }
} }
}

View File

@ -1,7 +1,7 @@
using MaksIT.LetsEncrypt.Exceptions; using MaksIT.LetsEncrypt.Exceptions;
using MaksIT.LetsEncrypt.Models.Interfaces; using MaksIT.LetsEncrypt.Models.Interfaces;
namespace MaksIT.LetsEncrypt.Models.Responses { namespace MaksIT.LetsEncrypt.Models.Responses;
public class OrderIdentifier { public class OrderIdentifier {
public string? Type { get; set; } public string? Type { get; set; }
@ -31,4 +31,3 @@ namespace MaksIT.LetsEncrypt.Models.Responses {
public Uri? Certificate { get; set; } public Uri? Certificate { get; set; }
} }
}

View File

@ -11,7 +11,8 @@ using MaksIT.LetsEncrypt.Entities.Jws;
using MaksIT.Core.Extensions; using MaksIT.Core.Extensions;
namespace MaksIT.LetsEncrypt.Services { namespace MaksIT.LetsEncrypt.Services;
public interface IJwsService { public interface IJwsService {
void SetKeyId(string location); void SetKeyId(string location);
@ -108,5 +109,4 @@ namespace MaksIT.LetsEncrypt.Services {
}
} }

View File

@ -18,10 +18,8 @@ using MaksIT.LetsEncrypt.Models.Responses;
using MaksIT.LetsEncrypt.Models.Interfaces; using MaksIT.LetsEncrypt.Models.Interfaces;
using MaksIT.LetsEncrypt.Models.Requests; using MaksIT.LetsEncrypt.Models.Requests;
using MaksIT.LetsEncrypt.Entities.Jws; using MaksIT.LetsEncrypt.Entities.Jws;
using System.Xml;
using System.Diagnostics;
namespace MaksIT.LetsEncrypt.Services { namespace MaksIT.LetsEncrypt.Services;
public interface ILetsEncryptService { public interface ILetsEncryptService {
@ -474,4 +472,3 @@ namespace MaksIT.LetsEncrypt.Services {
return result.Headers.GetValues("Replay-Nonce").First(); return result.Headers.GetValues("Replay-Nonce").First();
} }
} }
}

View File

@ -1,7 +1,3 @@
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -10,11 +6,10 @@ using MaksIT.Core.Extensions;
using MaksIT.LetsEncrypt.Services; using MaksIT.LetsEncrypt.Services;
using MaksIT.LetsEncrypt.Entities; using MaksIT.LetsEncrypt.Entities;
using MaksIT.LetsEncryptConsole.Services; using MaksIT.LetsEncryptConsole.Services;
using SSHProvider;
using Mono.Unix.Native;
using Serilog.Core;
namespace MaksIT.LetsEncryptConsole { using MaksIT.SSHProvider;
namespace MaksIT.LetsEncryptConsole;
public interface IApp { public interface IApp {
@ -107,7 +102,7 @@ namespace MaksIT.LetsEncryptConsole {
// if valid check if cert and key exists otherwise recreate // if valid check if cert and key exists otherwise recreate
// else continue with new certificate request // else continue with new certificate request
var certRes = new CachedCertificateResult(); var certRes = new CachedCertificateResult();
if (TryGetCachedCertificate(registrationCache, site.Name, out certRes)) { if (registrationCache.TryGetCachedCertificate(site.Name, out certRes)) {
string cert = Path.Combine(sslPath, $"{site.Name}.crt"); string cert = Path.Combine(sslPath, $"{site.Name}.crt");
//if(!File.Exists(cert)) //if(!File.Exists(cert))
File.WriteAllText(cert, certRes.Certificate); File.WriteAllText(cert, certRes.Certificate);
@ -156,10 +151,6 @@ namespace MaksIT.LetsEncryptConsole {
} }
} }
break; break;
} }
@ -182,9 +173,10 @@ namespace MaksIT.LetsEncryptConsole {
await Task.Delay(1000); await Task.Delay(1000);
// Download new certificate #region Download new certificate
_logger.LogInformation("4. Download certificate..."); _logger.LogInformation("4. Download certificate...");
var (cert, key) = await _letsEncryptService.GetCertificate(site.Name); var (cert, key) = await _letsEncryptService.GetCertificate(site.Name);
#endregion
#region Persist cache #region Persist cache
registrationCache = _letsEncryptService.GetRegistrationCache(); registrationCache = _letsEncryptService.GetRegistrationCache();
@ -194,7 +186,7 @@ namespace MaksIT.LetsEncryptConsole {
#region Save cert and key to filesystem #region Save cert and key to filesystem
certRes = new CachedCertificateResult(); certRes = new CachedCertificateResult();
if (TryGetCachedCertificate(registrationCache, site.Name, out certRes)) { if (registrationCache.TryGetCachedCertificate(site.Name, out certRes)) {
File.WriteAllText(Path.Combine(sslPath, site.Name + ".crt"), certRes.Certificate); File.WriteAllText(Path.Combine(sslPath, site.Name + ".crt"), certRes.Certificate);
@ -252,50 +244,9 @@ namespace MaksIT.LetsEncryptConsole {
} }
} }
/// <summary>
///
/// </summary>
/// <param name="subject"></param>
/// <param name="value"></param>
/// <returns></returns>
private bool TryGetCachedCertificate(RegistrationCache? registrationCache, string subject, out CachedCertificateResult? value) {
value = null;
if (registrationCache?.CachedCerts == null)
return false;
if (!registrationCache.CachedCerts.TryGetValue(subject, out var cache)) {
return false;
}
var cert = new X509Certificate2(Encoding.ASCII.GetBytes(cache.Cert));
// if it is about to expire, we need to refresh
if ((cert.NotAfter - DateTime.UtcNow).TotalDays < 30)
return false;
var rsa = new RSACryptoServiceProvider(4096);
rsa.ImportCspBlob(cache.Private);
value = new CachedCertificateResult {
Certificate = cache.Cert,
PrivateKey = rsa
};
return true;
}
/// <summary>
///
/// </summary>
/// <param name="hostsToRemove"></param>
public RegistrationCache? ResetCachedCertificate(RegistrationCache? registrationCache, IEnumerable<string> hostsToRemove) {
if (registrationCache?.CachedCerts != null)
foreach (var host in hostsToRemove)
registrationCache.CachedCerts.Remove(host);
return registrationCache;
}
private void UploadFiles( private void UploadFiles(
ILogger logger, ILogger logger,
SSHClientSettings sshSettings, SSHClientSettings sshSettings,
@ -320,4 +271,3 @@ namespace MaksIT.LetsEncryptConsole {
sshService.RunSudoCommand(sshSettings.Password, $"chmod {changeMode} {workDir} -R"); sshService.RunSudoCommand(sshSettings.Password, $"chmod {changeMode} {workDir} -R");
} }
} }
}

View File

@ -1,6 +1,6 @@
using System.Runtime.InteropServices;
namespace MaksIT.LetsEncryptConsole { namespace MaksIT.LetsEncryptConsole;
public class Configuration { public class Configuration {
public LetsEncryptEnvironment[]? Environments { get; set; } public LetsEncryptEnvironment[]? Environments { get; set; }
public Customer[]? Customers { get; set; } public Customer[]? Customers { get; set; }
@ -69,4 +69,3 @@ namespace MaksIT.LetsEncryptConsole {
public string[]? Hosts { get; set; } public string[]? Hosts { get; set; }
public string? Challenge { get; set; } public string? Challenge { get; set; }
} }
}

View File

@ -6,7 +6,8 @@ using Serilog;
using MaksIT.LetsEncryptConsole.Services; using MaksIT.LetsEncryptConsole.Services;
using MaksIT.LetsEncrypt.Extensions; using MaksIT.LetsEncrypt.Extensions;
namespace MaksIT.LetsEncryptConsole { namespace MaksIT.LetsEncryptConsole;
class Program { class Program {
private static readonly IConfiguration _configuration = InitConfig(); private static readonly IConfiguration _configuration = InitConfig();
@ -67,4 +68,4 @@ namespace MaksIT.LetsEncryptConsole {
return configuration.Build(); return configuration.Build();
} }
} }
}

View File

@ -1,6 +1,6 @@
using System.Security.Cryptography; using System.Security.Cryptography;
namespace MaksIT.LetsEncryptConsole.Services { namespace MaksIT.LetsEncryptConsole.Services;
public interface IKeyService { public interface IKeyService {
void ExportPublicKey(RSACryptoServiceProvider csp, TextWriter outputStream); void ExportPublicKey(RSACryptoServiceProvider csp, TextWriter outputStream);
@ -148,4 +148,3 @@ namespace MaksIT.LetsEncryptConsole.Services {
} }
} }
} }
}

View File

@ -1,6 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
namespace MaksIT.LetsEncryptConsole.Services { namespace MaksIT.LetsEncryptConsole.Services;
public interface ITerminalService { public interface ITerminalService {
void Exec(string cmd); void Exec(string cmd);
@ -26,5 +26,3 @@ namespace MaksIT.LetsEncryptConsole.Services {
pc.WaitForExit(); pc.WaitForExit();
} }
} }
}

View File

@ -1,10 +1,5 @@
using System; 
using System.Collections.Generic; namespace MaksIT.SSHProvider;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SSHProvider {
public class Configuration { public class Configuration {
} }
}

View File

@ -5,7 +5,7 @@ using Renci.SshNet;
using Renci.SshNet.Common; using Renci.SshNet.Common;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace SSHProvider { namespace MaksIT.SSHProvider {
public interface ISSHService : IDisposable { public interface ISSHService : IDisposable {
IDomainResult Upload(string workingdirectory, string fileName, byte[] bytes); IDomainResult Upload(string workingdirectory, string fileName, byte[] bytes);
@ -77,8 +77,8 @@ namespace SSHProvider {
_logger.LogInformation($"Listing directory:"); _logger.LogInformation($"Listing directory:");
foreach (var fi in listDirectory) { foreach (var file in listDirectory) {
_logger.LogInformation($" - " + fi.Name); _logger.LogInformation($" - " + file.Name);
} }
return IDomainResult.Success(); return IDomainResult.Success();

View File

@ -7,7 +7,7 @@ using Xunit;
//using PecMgr.VaultProvider; //using PecMgr.VaultProvider;
//using PecMgr.Core.Abstractions; //using PecMgr.Core.Abstractions;
namespace MaksIT.Tests.SSHProviderTests.Abstractions { namespace MaksIT.Tests.SSHProviderTests.Abstractions;
//[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] //[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)]
public abstract class ConfigurationBase { public abstract class ConfigurationBase {
@ -60,4 +60,3 @@ namespace MaksIT.Tests.SSHProviderTests.Abstractions {
return configurationBuilder.Build(); return configurationBuilder.Build();
} }
} }
}

View File

@ -4,9 +4,9 @@ using Serilog;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using SSHProvider; using MaksIT.SSHProvider;
namespace MaksIT.Tests.SSHProviderTests.Abstractions { namespace MaksIT.Tests.SSHProviderTests.Abstractions;
public abstract class ServicesBase : ConfigurationBase { public abstract class ServicesBase : ConfigurationBase {
public ServicesBase() : base() { } public ServicesBase() : base() { }
@ -27,4 +27,3 @@ namespace MaksIT.Tests.SSHProviderTests.Abstractions {
} }
} }
}

View File

@ -3,11 +3,11 @@ using System.Security.Cryptography;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SSHProvider; using MaksIT.SSHProvider;
using MaksIT.Tests.SSHProviderTests.Abstractions; using MaksIT.Tests.SSHProviderTests.Abstractions;
namespace SSHSerivceTests { namespace MaksIT.SSHSerivceTests;
public class UnitTest1 : ServicesBase { public class UnitTest1 : ServicesBase {
public readonly string _appPath = AppDomain.CurrentDomain.BaseDirectory; public readonly string _appPath = AppDomain.CurrentDomain.BaseDirectory;
@ -55,4 +55,3 @@ namespace SSHSerivceTests {
} }
} }
} }
}