mirror of
https://github.com/MAKS-IT-COM/maksit-certs-ui.git
synced 2025-12-31 04:00:03 +01:00
(feature): first release
This commit is contained in:
parent
6d10e3af53
commit
b30d7903a5
200
README.md
200
README.md
@ -7,82 +7,36 @@ Simple client to obtain Let's Encrypt HTTPS certificates developed with .net cor
|
||||
* 29 Jun, 2019 - V1.0
|
||||
* 01 Nov, 2019 - V2.0 (Dependency Injection pattern impelemtation)
|
||||
* 31 May, 2024 - V3.0 (Webapi and containerization)
|
||||
* 11 Aug, 2024 - V3.1 (Release)
|
||||
|
||||
## Haproxy configuration
|
||||
|
||||
```bash
|
||||
# Create the user with a normal shell
|
||||
sudo useradd -m -s /bin/bash acme
|
||||
|
||||
# Set the user's password
|
||||
sudo passwd acme
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo passwd acme
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo mkdir /etc/haproxy/certs
|
||||
chown acme:root /etc/haproxy/certs
|
||||
```
|
||||
|
||||
```bash
|
||||
#---------------------------------------------------------------------
|
||||
# Example configuration for a possible web application. See the
|
||||
# full configuration options online.
|
||||
#
|
||||
# https://www.haproxy.org/download/1.8/doc/configuration.txt
|
||||
#
|
||||
#---------------------------------------------------------------------
|
||||
sudo nano /etc/haproxy/haproxy.cfg
|
||||
```
|
||||
|
||||
```ini
|
||||
#---------------------------------------------------------------------
|
||||
# Global settings
|
||||
#---------------------------------------------------------------------
|
||||
global
|
||||
# to have these messages end up in /var/log/haproxy.log you will
|
||||
# need to:
|
||||
#
|
||||
# 1) configure syslog to accept network log events. This is done
|
||||
# by adding the '-r' option to the SYSLOGD_OPTIONS in
|
||||
# /etc/sysconfig/syslog
|
||||
#
|
||||
# 2) configure local2 events to go to the /var/log/haproxy.log
|
||||
# file. A line like the following can be added to
|
||||
# /etc/sysconfig/syslog
|
||||
#
|
||||
# local2.* /var/log/haproxy.log
|
||||
#
|
||||
log 127.0.0.1 local2
|
||||
|
||||
chroot /var/lib/haproxy
|
||||
pidfile /var/run/haproxy.pid
|
||||
maxconn 4000
|
||||
user haproxy
|
||||
group haproxy
|
||||
daemon
|
||||
|
||||
# Adjust the maxconn value based on your server\'s capacity
|
||||
maxconn 2048
|
||||
|
||||
# SSL certificates directory
|
||||
# ca-base /etc/ssl/certs
|
||||
#crt-base /etc/ssl/private
|
||||
|
||||
# Default SSL certificate (used if no SNI match)
|
||||
#ssl-default-bind-crt /etc/haproxy/certs/default.pem
|
||||
|
||||
# turn on stats unix socket
|
||||
# stats socket /var/lib/haproxy/stats level admin mode 660
|
||||
#stats socket /var/run/haproxy/admin.sock level admin mode 660 user haproxy group haproxy
|
||||
|
||||
# utilize system-wide crypto-policies
|
||||
stats socket /var/lib/haproxy/stats
|
||||
ssl-default-bind-ciphers PROFILE=SYSTEM
|
||||
ssl-default-server-ciphers PROFILE=SYSTEM
|
||||
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# common defaults that all the \'listen\' and \'backend\' sections will
|
||||
# common defaults that all the 'listen' and 'backend' sections will
|
||||
# use if not designated in their block
|
||||
#---------------------------------------------------------------------
|
||||
defaults
|
||||
@ -103,83 +57,111 @@ defaults
|
||||
timeout check 10s
|
||||
maxconn 3000
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Frontend for HTTP traffic on port 80
|
||||
#---------------------------------------------------------------------
|
||||
frontend http_frontend
|
||||
bind *:80
|
||||
acl acme_path path_beg /.well-known/acme-challenge/
|
||||
|
||||
# Redirect all HTTP traffic to HTTPS except ACME challenge requests
|
||||
redirect scheme https if !acme_path
|
||||
|
||||
# Use the appropriate backend based on hostname if it's an ACME challenge request
|
||||
use_backend acme_backend if acme_path
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Frontend configuration for handling multiple domains with SNI
|
||||
# Backend to handle ACME challenge requests
|
||||
#---------------------------------------------------------------------
|
||||
frontend web
|
||||
bind :80
|
||||
bind :443 ssl crt /etc/haproxy/certs/ strict-sni
|
||||
|
||||
# Handling for ACME challenge paths
|
||||
acl acme_challenge path_beg /.well-known/acme-challenge/
|
||||
use_backend acme_challenge_backend if acme_challenge
|
||||
|
||||
|
||||
backend acme_backend
|
||||
server local_acme 127.0.0.1:8080
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Backend configuration for ACME challenge
|
||||
# Frontend for HTTPS traffic (port 443) with SNI and strict-sni
|
||||
#---------------------------------------------------------------------
|
||||
backend acme_challenge_backend
|
||||
server acme_challenge 127.0.0.1:8080
|
||||
frontend https_frontend
|
||||
bind *:443 ssl crt /etc/haproxy/certs strict-sni
|
||||
|
||||
http-request capture req.hdr(host) len 64
|
||||
|
||||
# Define ACLs for routing based on hostname
|
||||
acl host_git hdr(host) -i git.maks-it.com
|
||||
acl host_cr hdr(host) -i cr.maks-it.com
|
||||
|
||||
# Use appropriate backend based on SNI hostname
|
||||
use_backend git_backend if host_git
|
||||
use_backend cr_backend if host_cr
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Backend for git.maks-it.com
|
||||
#---------------------------------------------------------------------
|
||||
backend git_backend
|
||||
http-request set-header X-Forwarded-Proto https
|
||||
http-request set-header X-Forwarded-Host %[hdr(host)]
|
||||
server git_server gitsrv0002.corp.maks-it.com:3000
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# Backend for cr.maks-it.com
|
||||
#---------------------------------------------------------------------
|
||||
backend cr_backend
|
||||
http-request set-header X-Forwarded-Proto https
|
||||
http-request set-header X-Forwarded-Host %[hdr(host)]
|
||||
server cr_server hcrsrv0001.corp.maks-it.com:80
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# letsencrypt load balancer
|
||||
#---------------------------------------------------------------------
|
||||
frontend letsencrypt
|
||||
bind *:8080
|
||||
mode http
|
||||
acl path_well_known_acme path_beg /.well-known/acme-challenge/
|
||||
acl path_swagger path_beg /swagger/
|
||||
acl path_api path_beg /api/
|
||||
|
||||
use_backend letsencrypt_server if path_well_known_acme
|
||||
use_backend letsencrypt_server if path_swagger
|
||||
use_backend letsencrypt_server if path_api
|
||||
default_backend letsencrypt_app
|
||||
|
||||
backend letsencrypt_server
|
||||
mode http
|
||||
server server1 127.0.0.1:9000 check
|
||||
|
||||
backend letsencrypt_app
|
||||
mode http
|
||||
server app1 127.0.0.1:3000 check
|
||||
|
||||
```
|
||||
|
||||
## MaksIT agent installation
|
||||
|
||||
|
||||
|
||||
## MaksIT agent
|
||||
From your home directory
|
||||
|
||||
```bash
|
||||
openssl rand -base64 32
|
||||
git clone https://github.com/MAKS-IT-COM/certs-ui.git
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
||||
sudo dnf install -y dotnet-sdk-8.0
|
||||
```
|
||||
|
||||
|
||||
Copy sources to
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/maks-it-agent
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
dotnet build --configuration Release
|
||||
dotnet publish -c Release -o /opt/maks-it-agent
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
sudo nano /etc/systemd/system/maks-it-agent.service
|
||||
cd certs-ui/src/Agent
|
||||
```
|
||||
|
||||
```bash
|
||||
[Unit]
|
||||
Description=Maks-IT Agent
|
||||
After=network.target
|
||||
sudo sh ./build_and_deploy.sh
|
||||
```
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/opt/maks-it-agent
|
||||
ExecStart=/usr/bin/dotnet /opt/maks-it-agent/Agent.dll --urls "http://*:5000"
|
||||
Restart=always
|
||||
# Restart service after 10 seconds if the dotnet service crashes:
|
||||
RestartSec=10
|
||||
KillSignal=SIGINT
|
||||
SyslogIdentifier=dotnet-servicereloader
|
||||
User=root
|
||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
## Maks IT LetsEncrypt server installation
|
||||
|
||||
From your home directory
|
||||
|
||||
```bash
|
||||
git clone https://github.com/MAKS-IT-COM/certs-ui.git
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now maks-it-agent.service
|
||||
sudo systemctl status maks-it-agent.service
|
||||
cd certs-ui/src
|
||||
```
|
||||
|
||||
```bash
|
||||
podman-compose -f docker-compose.final.yml up
|
||||
```
|
||||
|
||||
34
pipeline.json
Normal file
34
pipeline.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"name": "CI/CD Pipeline",
|
||||
"jobs": {
|
||||
"build-and-push": {
|
||||
"steps": [
|
||||
{
|
||||
"agent": "kaniko",
|
||||
|
||||
"context": "src",
|
||||
"dockerfile-path": "LetsEncryptServer/Dockerfile",
|
||||
|
||||
"image-name": "${{ env.REGISTRY_URL }}/${{ env.USERNAME }}/certs-ui-server:latest",
|
||||
"username": "${{ env.USERNAME }}",
|
||||
"password": "${{ env.PASSWORD }}"
|
||||
},
|
||||
|
||||
{
|
||||
"agent": "kaniko",
|
||||
|
||||
"context": "src",
|
||||
"dockerfile-path": "ClientApp/Dockerfile",
|
||||
|
||||
"image-name": "${{ env.REGISTRY_URL }}/${{ env.USERNAME }}/certs-ui-clientapp:latest",
|
||||
"username": "${{ env.USERNAME }}",
|
||||
"password": "${{ env.PASSWORD }}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"deploy": {
|
||||
"steps": []
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -19,5 +21,4 @@
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
37
src/Agent/Agent.generated.sln
Normal file
37
src/Agent/Agent.generated.sln
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent - Backup (1)", "Agent - Backup (1).csproj", "{392E9E34-E17C-4118-9C83-52AF52A56E54}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent - Backup", "Agent - Backup.csproj", "{18049E33-180E-41F1-8343-5BCD4755B2A8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent", "Agent.csproj", "{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {281E7450-1EDC-4E77-B04F-C14F65273D90}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@ -1,6 +1,29 @@
|
||||
namespace MaksIT.Agent {
|
||||
public class Configuration {
|
||||
public required string ApiKey { get; set; }
|
||||
public required string CertsPath { get; set; }
|
||||
|
||||
private string? _apiKey;
|
||||
public string ApiKey {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_API_KEY");
|
||||
return env ?? _apiKey ?? string.Empty;
|
||||
}
|
||||
|
||||
set {
|
||||
_apiKey = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string? _certsPath;
|
||||
public string CertsPath {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_CERTS_PATH");
|
||||
return env ?? _certsPath ?? string.Empty;
|
||||
}
|
||||
|
||||
set {
|
||||
_certsPath = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,15 +12,20 @@ namespace MaksIT.Agent.Controllers;
|
||||
public class CertsController : ControllerBase {
|
||||
|
||||
private readonly Configuration _appSettings;
|
||||
private readonly ILogger<CertsController> _logger;
|
||||
|
||||
public CertsController(
|
||||
IOptions<Configuration> appSettings
|
||||
IOptions<Configuration> appSettings,
|
||||
ILogger<CertsController> logger
|
||||
) {
|
||||
_logger = logger;
|
||||
_appSettings = appSettings.Value;
|
||||
}
|
||||
|
||||
[HttpPost("[action]")]
|
||||
public IActionResult Upload([FromBody] CertsUploadRequest requestData) {
|
||||
_logger.LogInformation("Uploading certificates");
|
||||
|
||||
foreach (var (fileName, fileContent) in requestData.Certs) {
|
||||
System.IO.File.WriteAllText(Path.Combine(_appSettings.CertsPath, fileName), fileContent);
|
||||
}
|
||||
|
||||
@ -1,23 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:7748",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5000"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
@ -26,6 +17,24 @@
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Container (Dockerfile)": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_HTTP_PORTS": "5000"
|
||||
},
|
||||
"publishAllPorts": true
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:7748",
|
||||
"sslPort": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ APPSETTINGS_FILE="appsettings.json"
|
||||
NO_NEW_KEY_FLAG="--no-new-key"
|
||||
|
||||
# Update package index and install the Microsoft package repository
|
||||
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
||||
# sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
||||
sudo dnf install -y dotnet-sdk-8.0
|
||||
|
||||
# Check if the service exists and stop it if it does
|
||||
@ -33,12 +33,9 @@ if [[ "$1" != "$NO_NEW_KEY_FLAG" ]]; then
|
||||
jq --arg newApiKey "$NEW_API_KEY" '.Configuration.ApiKey = $newApiKey' $APPSETTINGS_FILE > tmp.$$.json && mv tmp.$$.json $APPSETTINGS_FILE
|
||||
fi
|
||||
|
||||
cd
|
||||
|
||||
# Build and publish the .NET application
|
||||
cd "$(dirname "$(realpath "$0")")/Agent"
|
||||
sudo dotnet build --configuration Release
|
||||
sudo dotnet publish -c Release -o $INSTALL_DIR
|
||||
sudo dotnet build Agent.csproj --configuration Release
|
||||
sudo dotnet publish Agent.csproj -c Release -o $INSTALL_DIR
|
||||
|
||||
# Create the systemd service unit file
|
||||
sudo bash -c "cat > $SERVICE_FILE <<EOL
|
||||
@ -25,7 +25,9 @@ const GetApiRoute = (route: ApiRoutes, ...args: string[]): string => {
|
||||
args.forEach((arg) => {
|
||||
result = result.replace(/{.*?}/, arg)
|
||||
})
|
||||
// TODO: need env var
|
||||
return `http://localhost:8080/${result}`
|
||||
//return `http://websrv0001.corp.maks-it.com:8080/${result}`
|
||||
}
|
||||
|
||||
export { GetApiRoute, ApiRoutes }
|
||||
|
||||
@ -1,11 +1,19 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using MaksIT.LetsEncrypt.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace MaksIT.LetsEncrypt.Extensions;
|
||||
public static class ServiceCollectionExtensions {
|
||||
public static void RegisterLetsEncrypt(this IServiceCollection services) {
|
||||
public static void RegisterLetsEncrypt(this IServiceCollection services, ILetsEncryptConfiguration appSettings) {
|
||||
|
||||
|
||||
var config = new LetsEncryptConfiguration {
|
||||
Staging = appSettings.Staging,
|
||||
Production = appSettings.Production
|
||||
};
|
||||
|
||||
services.AddSingleton(config);
|
||||
services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
||||
}
|
||||
}
|
||||
|
||||
22
src/LetsEncrypt/LetsEncryptConfiguration.cs
Normal file
22
src/LetsEncrypt/LetsEncryptConfiguration.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.LetsEncrypt {
|
||||
|
||||
|
||||
public interface ILetsEncryptConfiguration {
|
||||
string Production { get; set; }
|
||||
string Staging { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class LetsEncryptConfiguration : ILetsEncryptConfiguration {
|
||||
public required string Production { get; set; }
|
||||
public required string Staging { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -22,6 +22,7 @@ using MaksIT.LetsEncrypt.Models.Interfaces;
|
||||
using MaksIT.LetsEncrypt.Models.Requests;
|
||||
using MaksIT.LetsEncrypt.Entities.Jws;
|
||||
using MaksIT.LetsEncrypt.Entities.LetsEncrypt;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace MaksIT.LetsEncrypt.Services;
|
||||
|
||||
@ -39,14 +40,18 @@ public interface ILetsEncryptService {
|
||||
|
||||
public class LetsEncryptService : ILetsEncryptService {
|
||||
private readonly ILogger<LetsEncryptService> _logger;
|
||||
private readonly LetsEncryptConfiguration _appSettings;
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
|
||||
public LetsEncryptService(
|
||||
ILogger<LetsEncryptService> logger,
|
||||
LetsEncryptConfiguration appSettings,
|
||||
HttpClient httpClient,
|
||||
IMemoryCache cache) {
|
||||
IMemoryCache cache
|
||||
) {
|
||||
_logger = logger;
|
||||
_appSettings = appSettings;
|
||||
_httpClient = httpClient;
|
||||
_memoryCache = cache;
|
||||
}
|
||||
@ -66,9 +71,7 @@ public class LetsEncryptService : ILetsEncryptService {
|
||||
|
||||
state.IsStaging = isStaging;
|
||||
// TODO: need to propagate from Configuration
|
||||
_httpClient.BaseAddress ??= new Uri(isStaging
|
||||
? "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
: "https://acme-v02.api.letsencrypt.org/directory");
|
||||
_httpClient.BaseAddress ??= new Uri(isStaging ? _appSettings.Staging : _appSettings.Production);
|
||||
|
||||
if (state.Directory == null) {
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("directory", UriKind.Relative));
|
||||
|
||||
@ -1,16 +1,85 @@
|
||||
namespace MaksIT.LetsEncryptServer {
|
||||
using MaksIT.LetsEncrypt;
|
||||
|
||||
namespace MaksIT.LetsEncryptServer {
|
||||
|
||||
public class Agent {
|
||||
public required string AgentHostname { get; set; }
|
||||
public required int AgentPort { get; set; }
|
||||
public required string AgentKey { get; set; }
|
||||
|
||||
public required string ServiceToReload { get; set; }
|
||||
private string? _agentHostname;
|
||||
public string AgentHostname {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_HOSTNAME");
|
||||
return env ?? _agentHostname ?? string.Empty;
|
||||
}
|
||||
set {
|
||||
_agentHostname = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int? _agentPort;
|
||||
public int AgentPort {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_PORT");
|
||||
return env != null ? int.Parse(env) : _agentPort ?? 0;
|
||||
}
|
||||
set {
|
||||
_agentPort = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string? _agentKey;
|
||||
public string AgentKey {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_KEY");
|
||||
return env ?? _agentKey ?? string.Empty;
|
||||
}
|
||||
set {
|
||||
_agentKey = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string? _serviceToReload;
|
||||
public string ServiceToReload {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_SERVICE");
|
||||
return env ?? _serviceToReload ?? string.Empty;
|
||||
}
|
||||
set {
|
||||
_serviceToReload = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class Configuration : ILetsEncryptConfiguration {
|
||||
|
||||
private string? _production;
|
||||
public string Production {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("LETSENCRYPT_SERVER_PRODUCTION");
|
||||
return env ?? _production ?? string.Empty;
|
||||
}
|
||||
set {
|
||||
_production = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private string? _staging;
|
||||
public string Staging {
|
||||
get {
|
||||
var env = Environment.GetEnvironmentVariable("LETSENCRYPT_SERVER_STAGING");
|
||||
return env ?? _staging ?? string.Empty;
|
||||
}
|
||||
set {
|
||||
_staging = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class Configuration {
|
||||
public required string Production { get; set; }
|
||||
public required string Staging { get; set; }
|
||||
public required Agent Agent { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||
USER app
|
||||
WORKDIR /app
|
||||
EXPOSE 8080
|
||||
EXPOSE 5000
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
|
||||
@ -3,6 +3,7 @@ using MaksIT.LetsEncrypt.Services;
|
||||
using MaksIT.LetsEncryptServer.Services;
|
||||
using MaksIT.LetsEncryptServer.BackgroundServices;
|
||||
using MaksIT.LetsEncryptServer.Middlewares;
|
||||
using MaksIT.LetsEncrypt.Extensions;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -28,7 +29,8 @@ builder.Services.AddCors();
|
||||
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
builder.Services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
||||
builder.Services.RegisterLetsEncrypt(appSettings);
|
||||
|
||||
builder.Services.AddSingleton<ICacheService, CacheService>();
|
||||
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
||||
builder.Services.AddSingleton<IAccountService, AccountService>();
|
||||
|
||||
@ -12,8 +12,8 @@
|
||||
"Staging": "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||
|
||||
"Agent": {
|
||||
"AgentHostname": "http://lblsrv0001.corp.maks-it.com",
|
||||
"AgentPort": 5000,
|
||||
"AgentHostname": "http://websrv0001.corp.maks-it.com",
|
||||
"AgentPort": 9000,
|
||||
"AgentKey": "UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=",
|
||||
|
||||
"ServiceToReload": "haproxy"
|
||||
|
||||
@ -5,39 +5,39 @@
|
||||
"Match": {
|
||||
"Path": "/.well-known/acme-challenge/{**catch-all}"
|
||||
},
|
||||
"ClusterId": "letsencryptserver"
|
||||
"ClusterId": "letsencrypt-server"
|
||||
},
|
||||
"swagger-route": {
|
||||
"Match": {
|
||||
"Path": "/swagger/{**catch-all}"
|
||||
},
|
||||
"ClusterId": "letsencryptserver"
|
||||
"ClusterId": "letsencrypt-server"
|
||||
},
|
||||
"api-route": {
|
||||
"Match": {
|
||||
"Path": "/api/{**catch-all}"
|
||||
},
|
||||
"ClusterId": "letsencryptserver"
|
||||
"ClusterId": "letsencrypt-server"
|
||||
},
|
||||
"default-route": {
|
||||
"Match": {
|
||||
"Path": "{**catch-all}"
|
||||
},
|
||||
"ClusterId": "letsencryptapp"
|
||||
"ClusterId": "letsencrypt-app"
|
||||
}
|
||||
},
|
||||
"Clusters": {
|
||||
"letsencryptserver": {
|
||||
"letsencrypt-server": {
|
||||
"Destinations": {
|
||||
"destination1": {
|
||||
"Address": "http://letsencryptserver:5000/"
|
||||
"Address": "http://letsencrypt-server:5000/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"letsencryptapp": {
|
||||
"letsencrypt-app": {
|
||||
"Destinations": {
|
||||
"destination1": {
|
||||
"Address": "http://letsencryptapp:3000/"
|
||||
"Address": "http://letsencrypt-app:3000/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
src/docker-compose.final.yml
Normal file
46
src/docker-compose.final.yml
Normal file
@ -0,0 +1,46 @@
|
||||
services:
|
||||
letsencrypt-app:
|
||||
image: ${DOCKER_REGISTRY-}letsencrypt-app
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ClientApp/Dockerfile
|
||||
container_name: letsencrypt-app
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Production
|
||||
- LETSENCRYPT_SERVER=http://websrv0001.corp.maks-it.com
|
||||
ports:
|
||||
- "3000:3000"
|
||||
network_mode: "host"
|
||||
|
||||
|
||||
letsencrypt-server:
|
||||
image: ${DOCKER_REGISTRY-}letsencrypt-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: LetsEncryptServer/Dockerfile
|
||||
container_name: letsencrypt-server
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Production
|
||||
- ASPNETCORE_HTTP_PORTS=9000
|
||||
- LETSENCRYPT_SERVER_PRODUCTION=https://acme-v02.api.letsencrypt.org/directory
|
||||
- LETSENCRYPT_SERVER_STAGING=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
- MAKS_IT_AGENT_HOSTNAME=http://websrv0001.corp.maks-it.com
|
||||
- MAKS-IT_AGENT_PORT=5000
|
||||
- MAKS-IT_AGENT_KEY=UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=
|
||||
- MAKS-IT_AGENT_SERVICE=haproxy
|
||||
volumes:
|
||||
- ./docker-compose/LetsEncryptServer/acme:/app/acme
|
||||
- ./docker-compose/LetsEncryptServer/cache:/app/cache
|
||||
ports:
|
||||
- "9000:9000"
|
||||
network_mode: "host"
|
||||
|
||||
|
||||
curl-test:
|
||||
image: curlimages/curl:latest
|
||||
container_name: curl-test
|
||||
command: >
|
||||
curl --location http://websrv0001.corp.maks-it.com:5000/HelloWorld
|
||||
--header "x-api-key: UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I="
|
||||
restart: "no"
|
||||
network_mode: "host"
|
||||
@ -1,24 +1,43 @@
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
reverseProxy:
|
||||
reverse-proxy:
|
||||
container_name: reverse-proxy
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
- letsencryptapp
|
||||
- letsencryptserver
|
||||
- letsencrypt-app
|
||||
- letsencrypt-server
|
||||
networks:
|
||||
- maks-it
|
||||
|
||||
# letsencryptapp:
|
||||
letsencrypt-app:
|
||||
container_name: letsencrypt-app
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- LETSENCRYPT_SERVER=http://localhost:8080
|
||||
# ports:
|
||||
# - "3000:3000"
|
||||
networks:
|
||||
- maks-it
|
||||
|
||||
letsencryptserver:
|
||||
letsencrypt-server:
|
||||
container_name: letsencrypt-server
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ASPNETCORE_HTTP_PORTS=5000
|
||||
- LETSENCRYPT_SERVER_PRODUCTION=https://acme-v02.api.letsencrypt.org/directory
|
||||
- LETSENCRYPT_SERVER_STAGING=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
- MAKS_IT_AGENT_HOSTNAME=http://websrv0001.corp.maks-it.com
|
||||
- MAKS-IT_AGENT_PORT=5000
|
||||
- MAKS-IT_AGENT_KEY=UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=
|
||||
- MAKS-IT_AGENT_SERVICE=haproxy
|
||||
volumes:
|
||||
- ./docker-compose/LetsEncryptServer/acme:/app/bin/Debug/net8.0/acme
|
||||
- ./docker-compose/LetsEncryptServer/cache:/app/bin/Debug/net8.0/cache
|
||||
ports:
|
||||
- "5000:5000"
|
||||
networks:
|
||||
- maks-it
|
||||
|
||||
networks:
|
||||
maks-it:
|
||||
driver: bridge
|
||||
@ -1,20 +1,18 @@
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
letsencryptapp:
|
||||
image: ${DOCKER_REGISTRY-}letsencryptapp
|
||||
letsencrypt-app:
|
||||
image: ${DOCKER_REGISTRY-}letsencrypt-app
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ClientApp/Dockerfile
|
||||
|
||||
reverseProxy:
|
||||
image: ${DOCKER_REGISTRY-}reverseproxy
|
||||
reverse-proxy:
|
||||
image: ${DOCKER_REGISTRY-}reverse-proxy
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ReverseProxy/Dockerfile
|
||||
|
||||
letsencryptserver:
|
||||
image: ${DOCKER_REGISTRY-}letsencryptserver
|
||||
letsencrypt-server:
|
||||
image: ${DOCKER_REGISTRY-}letsencrypt-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: LetsEncryptServer/Dockerfile
|
||||
|
||||
Loading…
Reference in New Issue
Block a user