diff --git a/README.md b/README.md
index ae7d6c7..030102b 100644
--- a/README.md
+++ b/README.md
@@ -122,4 +122,64 @@ frontend web
#---------------------------------------------------------------------
backend acme_challenge_backend
server acme_challenge 127.0.0.1:8080
-```
\ No newline at end of file
+```
+
+
+
+
+## MaksIT agent
+
+```bash
+openssl rand -base64 32
+```
+
+```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
+```
+
+```bash
+[Unit]
+Description=Maks-IT Agent
+After=network.target
+
+[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
+```
+
+```bash
+sudo systemctl daemon-reload
+sudo systemctl enable --now maks-it-agent.service
+sudo systemctl status maks-it-agent.service
+```
diff --git a/src/Agent/Agent.csproj b/src/Agent/Agent.csproj
new file mode 100644
index 0000000..6726b4e
--- /dev/null
+++ b/src/Agent/Agent.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+ Never
+
+
+
+
diff --git a/src/Agent/Configuration.cs b/src/Agent/Configuration.cs
new file mode 100644
index 0000000..b90bc89
--- /dev/null
+++ b/src/Agent/Configuration.cs
@@ -0,0 +1,6 @@
+namespace MaksIT.Agent {
+ public class Configuration {
+ public required string ApiKey { get; set; }
+ public required string CertsPath { get; set; }
+ }
+}
diff --git a/src/Agent/Controllers/CertsController.cs b/src/Agent/Controllers/CertsController.cs
new file mode 100644
index 0000000..5578991
--- /dev/null
+++ b/src/Agent/Controllers/CertsController.cs
@@ -0,0 +1,41 @@
+
+using System.Diagnostics;
+
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+
+using MaksIT.Models.Agent.Requests;
+
+namespace MaksIT.Agent.Controllers;
+
+[ApiController]
+[Route("[controller]")]
+public class CertsController : ControllerBase {
+
+ private readonly Configuration _appSettings;
+
+ public CertsController(
+ IOptions appSettings
+ ) {
+ _appSettings = appSettings.Value;
+ }
+
+ [HttpPost("[action]")]
+ public IActionResult Upload([FromBody] CertsUploadRequest requestData) {
+ if (!Request.Headers.TryGetValue("X-API-KEY", out var extractedApiKey)) {
+ return Unauthorized("API Key is missing");
+ }
+
+ if (!_appSettings.ApiKey.Equals(extractedApiKey)) {
+ return Unauthorized("Unauthorized client");
+ }
+
+ foreach (var (fileName, fileContent) in requestData.Certs) {
+ System.IO.File.WriteAllText(Path.Combine(_appSettings.CertsPath, fileName), fileContent);
+ }
+
+ return Ok("Certificates uploaded successfully");
+ }
+
+}
+
diff --git a/src/Agent/Controllers/HelloWorldController.cs b/src/Agent/Controllers/HelloWorldController.cs
new file mode 100644
index 0000000..d3d3dc0
--- /dev/null
+++ b/src/Agent/Controllers/HelloWorldController.cs
@@ -0,0 +1,14 @@
+using Microsoft.AspNetCore.Mvc;
+
+namespace Agent.Controllers {
+
+ [ApiController]
+ [Route("[controller]")]
+ public class HelloWorldController : ControllerBase {
+
+ [HttpGet]
+ public IActionResult Get() {
+ return Ok("Hello, World!");
+ }
+ }
+}
diff --git a/src/Agent/Controllers/ServiceController.cs b/src/Agent/Controllers/ServiceController.cs
new file mode 100644
index 0000000..d849b6a
--- /dev/null
+++ b/src/Agent/Controllers/ServiceController.cs
@@ -0,0 +1,61 @@
+using System.Diagnostics;
+using MaksIT.Models.Agent.Requests;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+
+namespace MaksIT.Agent.Controllers;
+
+[ApiController]
+[Route("[controller]")]
+public class ServiceController : ControllerBase {
+
+ private readonly Configuration _appSettings;
+
+ public ServiceController(
+ IOptions appSettings
+ ) {
+ _appSettings = appSettings.Value;
+ }
+
+ [HttpPost("[action]")]
+ public IActionResult Reload([FromBody] ServiceReloadRequest requestData) {
+ var serviceName = requestData.ServiceName;
+
+ if (!Request.Headers.TryGetValue("X-API-KEY", out var extractedApiKey)) {
+ return Unauthorized("API Key is missing");
+ }
+
+ if (!_appSettings.ApiKey.Equals(extractedApiKey)) {
+ return Unauthorized("Unauthorized client");
+ }
+
+ try {
+ var processStartInfo = new ProcessStartInfo {
+ FileName = "/bin/systemctl",
+ Arguments = $"reload {serviceName}",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using (var process = new Process { StartInfo = processStartInfo }) {
+ process.Start();
+ process.WaitForExit();
+
+ var output = process.StandardOutput.ReadToEnd();
+ var error = process.StandardError.ReadToEnd();
+
+ if (process.ExitCode != 0) {
+ return StatusCode(500, $"Error reloading service: {error}");
+ }
+
+ return Ok($"Service {serviceName} reloaded successfully: {output}");
+ }
+ }
+ catch (Exception ex) {
+ return StatusCode(500, $"Exception: {ex.Message}");
+ }
+ }
+}
+
diff --git a/src/Agent/Program.cs b/src/Agent/Program.cs
new file mode 100644
index 0000000..af450c9
--- /dev/null
+++ b/src/Agent/Program.cs
@@ -0,0 +1,34 @@
+using MaksIT.Agent;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Extract configuration
+var configuration = builder.Configuration;
+
+// Configure strongly typed settings objects
+var configurationSection = configuration.GetSection("Configuration");
+var appSettings = configurationSection.Get() ?? throw new ArgumentNullException();
+
+// Allow configurations to be available through IOptions
+builder.Services.Configure(configurationSection);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment()) {
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/src/Agent/Properties/launchSettings.json b/src/Agent/Properties/launchSettings.json
new file mode 100644
index 0000000..8747336
--- /dev/null
+++ b/src/Agent/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+{
+ "$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"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/Agent/ServiceReloader.http b/src/Agent/ServiceReloader.http
new file mode 100644
index 0000000..3f65e8d
--- /dev/null
+++ b/src/Agent/ServiceReloader.http
@@ -0,0 +1,6 @@
+@ServiceReloader_HostAddress = http://localhost:5186
+
+GET {{ServiceReloader_HostAddress}}/weatherforecast/
+Accept: application/json
+
+###
diff --git a/src/Agent/appsettings.Development.json b/src/Agent/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/src/Agent/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/Agent/appsettings.json b/src/Agent/appsettings.json
new file mode 100644
index 0000000..c2941ed
--- /dev/null
+++ b/src/Agent/appsettings.json
@@ -0,0 +1,14 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+
+ "Configuration": {
+ "ApiKey": "UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=",
+ "CertsPath": "/etc/haproxy/certs"
+ }
+}
\ No newline at end of file
diff --git a/src/Agent/build_and_deploy.sh b/src/Agent/build_and_deploy.sh
new file mode 100644
index 0000000..39d9d4e
--- /dev/null
+++ b/src/Agent/build_and_deploy.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+# Variables
+SERVICE_NAME="maks-it-agent"
+SERVICE_PORT="5000"
+SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
+INSTALL_DIR="/opt/$SERVICE_NAME"
+DOTNET_EXEC="/usr/bin/dotnet"
+EXEC_CMD="$DOTNET_EXEC $INSTALL_DIR/Agent.dll --urls \"http://*:$SERVICE_PORT\""
+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 dnf install -y dotnet-sdk-8.0
+
+# Check if the service exists and stop it if it does
+if systemctl list-units --full -all | grep -Fq "$SERVICE_NAME.service"; then
+ sudo systemctl stop $SERVICE_NAME.service
+ sudo systemctl disable $SERVICE_NAME.service
+ sudo rm -f $SERVICE_FILE
+fi
+
+# Clean up the old files if they exist
+sudo rm -rf $INSTALL_DIR
+
+# Create the application directory
+sudo mkdir -p $INSTALL_DIR
+
+# Update appsettings.json if --no-new-key flag is not provided
+if [[ "$1" != "$NO_NEW_KEY_FLAG" ]]; then
+ NEW_API_KEY=$(openssl rand -base64 32)
+ jq --arg newApiKey "$NEW_API_KEY" '.Configuration.ApiKey = $newApiKey' $APPSETTINGS_FILE > tmp.$$.json && mv tmp.$$.json $APPSETTINGS_FILE
+fi
+
+# Build and publish the .NET application
+sudo dotnet build --configuration Release
+sudo dotnet publish -c Release -o $INSTALL_DIR
+
+# Create the systemd service unit file
+sudo bash -c "cat > $SERVICE_FILE <
+
+ Maks-IT Agent
+
+' > /etc/firewalld/services/maks-it-agent.xml
+
+sleep 10
+
+# Add the services to the firewall
+firewall-cmd --permanent --add-service=maks-it-agent
+
+# Reload the firewall
+firewall-cmd --reload
diff --git a/src/LetsEncrypt.sln b/src/LetsEncrypt.sln
index 62d0dbf..42180a2 100644
--- a/src/LetsEncrypt.sln
+++ b/src/LetsEncrypt.sln
@@ -15,10 +15,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3374FDB1
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SSHProviderTests", "Tests\SSHSerivceTests\SSHProviderTests.csproj", "{3937760A-FFB3-4A8C-ABD1-CDDCE1D977C4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LetsEncryptServer", "LetsEncryptServer\LetsEncryptServer.csproj", "{B5F39E04-C2E3-49BF-82C2-9DEBAA949E3D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LetsEncryptServer", "LetsEncryptServer\LetsEncryptServer.csproj", "{B5F39E04-C2E3-49BF-82C2-9DEBAA949E3D}"
EndProject
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{0233E43F-435D-4309-B20C-ECD4BFBD2E63}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent", "Agent\Agent.csproj", "{871BDED3-C6AE-437D-9B45-3AA3F184D002}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{6814169B-D4D0-40B2-9FA9-89997DD44C30}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -53,6 +57,14 @@ Global
{0233E43F-435D-4309-B20C-ECD4BFBD2E63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0233E43F-435D-4309-B20C-ECD4BFBD2E63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0233E43F-435D-4309-B20C-ECD4BFBD2E63}.Release|Any CPU.Build.0 = Release|Any CPU
+ {871BDED3-C6AE-437D-9B45-3AA3F184D002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {871BDED3-C6AE-437D-9B45-3AA3F184D002}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {871BDED3-C6AE-437D-9B45-3AA3F184D002}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {871BDED3-C6AE-437D-9B45-3AA3F184D002}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6814169B-D4D0-40B2-9FA9-89997DD44C30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6814169B-D4D0-40B2-9FA9-89997DD44C30}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6814169B-D4D0-40B2-9FA9-89997DD44C30}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6814169B-D4D0-40B2-9FA9-89997DD44C30}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/LetsEncryptServer/Configuration.cs b/src/LetsEncryptServer/Configuration.cs
index 445b624..ced1dd4 100644
--- a/src/LetsEncryptServer/Configuration.cs
+++ b/src/LetsEncryptServer/Configuration.cs
@@ -1,20 +1,17 @@
namespace MaksIT.LetsEncryptServer {
- public class Server {
- public required string Ip { get; set; }
- public required int SocketPort { get; set; }
- public required int SSHPort { get; set; }
- public required string Path { get; set; }
+ public class Agent {
+ public required string AgentHostname { get; set; }
+ public required int AgentPort { get; set; }
+ public required string AgentKey { get; set; }
- public required string Username { get; set; }
- public string? Password { get; set; }
- public string[]? PrivateKeys { get; set; }
+ public required string ServiceToReload { get; set; }
}
public class Configuration {
public required string Production { get; set; }
public required string Staging { get; set; }
public required bool DevMode { get; set; }
- public required Server Server { get; set; }
+ public required Agent Agent { get; set; }
}
}
diff --git a/src/LetsEncryptServer/Controllers/CertsFlowController.cs b/src/LetsEncryptServer/Controllers/CertsFlowController.cs
index 222bda6..d6efd49 100644
--- a/src/LetsEncryptServer/Controllers/CertsFlowController.cs
+++ b/src/LetsEncryptServer/Controllers/CertsFlowController.cs
@@ -3,8 +3,8 @@ using Microsoft.Extensions.Options;
using DomainResults.Mvc;
-using MaksIT.LetsEncryptServer.Models.Requests;
using MaksIT.LetsEncryptServer.Services;
+using MaksIT.Models.LetsEncryptServer.Requests;
namespace MaksIT.LetsEncryptServer.Controllers;
@@ -107,8 +107,8 @@ public class CertsFlowController : ControllerBase {
///
///
[HttpPost("[action]/{sessionId}")]
- public IActionResult ApplyCertificates(Guid sessionId, [FromBody] GetCertificatesRequest requestData) {
- var result = _certsFlowService.ApplyCertificates(sessionId, requestData);
+ public async Task ApplyCertificates(Guid sessionId, [FromBody] GetCertificatesRequest requestData) {
+ var result = await _certsFlowService.ApplyCertificates(sessionId, requestData);
return result.ToActionResult();
}
}
diff --git a/src/LetsEncryptServer/LetsEncryptServer.csproj b/src/LetsEncryptServer/LetsEncryptServer.csproj
index 2c55ec6..5b4d566 100644
--- a/src/LetsEncryptServer/LetsEncryptServer.csproj
+++ b/src/LetsEncryptServer/LetsEncryptServer.csproj
@@ -17,11 +17,7 @@
-
-
-
-
-
+
diff --git a/src/LetsEncryptServer/Program.cs b/src/LetsEncryptServer/Program.cs
index 756ac93..0bb7cf3 100644
--- a/src/LetsEncryptServer/Program.cs
+++ b/src/LetsEncryptServer/Program.cs
@@ -28,6 +28,7 @@ builder.Services.AddMemoryCache();
builder.Services.AddHttpClient();
builder.Services.AddScoped();
builder.Services.AddSingleton();
+builder.Services.AddHttpClient();
var app = builder.Build();
diff --git a/src/LetsEncryptServer/Services/AgentService.cs b/src/LetsEncryptServer/Services/AgentService.cs
new file mode 100644
index 0000000..8d98f34
--- /dev/null
+++ b/src/LetsEncryptServer/Services/AgentService.cs
@@ -0,0 +1,72 @@
+using DomainResults.Common;
+using MaksIT.Models.Agent.Requests;
+using Microsoft.Extensions.Options;
+using System.Text;
+using System.Text.Json;
+
+namespace MaksIT.LetsEncryptServer.Services {
+
+ public interface IAgentService {
+ Task GetHelloWorld();
+ Task UploadCerts(Dictionary certs);
+ Task ReloadService(string serviceName);
+ }
+
+ public class AgentService : IAgentService {
+
+ private readonly Configuration _appSettings;
+ private readonly ILogger _logger;
+ private readonly HttpClient _httpClient;
+
+ public AgentService(
+ IOptions appSettings,
+ ILogger logger,
+ HttpClient httpClient
+ ) {
+ _appSettings = appSettings.Value;
+ _logger = logger;
+ _httpClient = httpClient;
+ }
+
+ public Task GetHelloWorld() {
+ throw new NotImplementedException();
+ }
+
+ public async Task ReloadService(string serviceName) {
+ var requestBody = new ServiceReloadRequest { ServiceName = serviceName };
+ var endpoint = $"/Service/Reload";
+ return await SendHttpRequest(requestBody, endpoint);
+ }
+
+ public async Task UploadCerts(Dictionary certs) {
+ var requestBody = new CertsUploadRequest { Certs = certs };
+ var endpoint = $"/Certs/Upload";
+ return await SendHttpRequest(requestBody, endpoint);
+ }
+
+ private async Task SendHttpRequest(T requestBody, string endpoint) {
+ try {
+ var request = new HttpRequestMessage(HttpMethod.Post, $"{_appSettings.Agent.AgentHostname}:{_appSettings.Agent.AgentPort}{endpoint}") {
+ Content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json")
+ };
+
+ request.Headers.Add("x-api-key", _appSettings.Agent.AgentKey);
+ request.Headers.Add("accept", "application/json");
+
+ var response = await _httpClient.SendAsync(request);
+
+ if (response.IsSuccessStatusCode) {
+ return IDomainResult.Success();
+ }
+ else {
+ _logger.LogError($"Request to {endpoint} failed with status code: {response.StatusCode}");
+ return IDomainResult.Failed($"Request to {endpoint} failed with status code: {response.StatusCode}");
+ }
+ }
+ catch (Exception ex) {
+ _logger.LogError(ex, "Something went wrong");
+ return IDomainResult.Failed("Something went wrong");
+ }
+ }
+ }
+}
diff --git a/src/LetsEncryptServer/Services/CertsFlowService.cs b/src/LetsEncryptServer/Services/CertsFlowService.cs
index 26185db..ddb3be9 100644
--- a/src/LetsEncryptServer/Services/CertsFlowService.cs
+++ b/src/LetsEncryptServer/Services/CertsFlowService.cs
@@ -6,8 +6,7 @@ using DomainResults.Common;
using MaksIT.LetsEncrypt.Entities;
using MaksIT.LetsEncrypt.Services;
-using MaksIT.LetsEncryptServer.Models.Requests;
-using MaksIT.SSHProvider;
+using MaksIT.Models.LetsEncryptServer.Requests;
namespace MaksIT.LetsEncryptServer.Services;
@@ -24,7 +23,7 @@ public interface ICertsFlowService : ICertsFlowServiceBase {
Task CompleteChallengesAsync(Guid sessionId);
Task GetOrderAsync(Guid sessionId, GetOrderRequest requestData);
Task GetCertificatesAsync(Guid sessionId, GetCertificatesRequest requestData);
- (Dictionary?, IDomainResult) ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData);
+ Task<(Dictionary?, IDomainResult)> ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData);
}
public class CertsFlowService : ICertsFlowService {
@@ -33,6 +32,7 @@ public class CertsFlowService : ICertsFlowService {
private readonly ILogger _logger;
private readonly ILetsEncryptService _letsEncryptService;
private readonly ICacheService _cacheService;
+ private readonly IAgentService _agentService;
private readonly string _acmePath;
@@ -40,12 +40,14 @@ public class CertsFlowService : ICertsFlowService {
IOptions appSettings,
ILogger logger,
ILetsEncryptService letsEncryptService,
- ICacheService cashService
+ ICacheService cashService,
+ IAgentService agentService
) {
_appSettings = appSettings.Value;
_logger = logger;
_letsEncryptService = letsEncryptService;
_cacheService = cashService;
+ _agentService = agentService;
_acmePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "acme");
if (!Directory.Exists(_acmePath))
@@ -138,7 +140,7 @@ public class CertsFlowService : ICertsFlowService {
return IDomainResult.Success();
}
- public (Dictionary?, IDomainResult) ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData) {
+ public async Task<(Dictionary?, IDomainResult)> ApplyCertificates(Guid sessionId, GetCertificatesRequest requestData) {
var results = new Dictionary();
foreach (var subject in requestData.Hostnames) {
@@ -150,16 +152,13 @@ public class CertsFlowService : ICertsFlowService {
results.Add(subject, content);
}
- var uploadResult = UploadToServer(results);
- if (!uploadResult.IsSuccess)
+ // TODO: send the certificates to the server
+ var uploadResult = await _agentService.UploadCerts(results);
+ if(!uploadResult.IsSuccess)
return (null, uploadResult);
- //var notifyResult = NotifyHaproxy(results);
- //if (!notifyResult.IsSuccess)
- // return (null, notifyResult);
-
- var reloadResult = ReloadServer();
- if (!reloadResult.IsSuccess)
+ var reloadResult = await _agentService.ReloadService(_appSettings.Agent.ServiceToReload);
+ if(!reloadResult.IsSuccess)
return (null, reloadResult);
return IDomainResult.Success(results);
@@ -175,129 +174,6 @@ public class CertsFlowService : ICertsFlowService {
return IDomainResult.Success(fileContent);
}
- private IDomainResult UploadToServer(Dictionary results) {
- var server = _appSettings.Server;
-
- try {
- using (SSHService sshClient = (server.PrivateKeys != null && server.PrivateKeys.Any(x => !string.IsNullOrWhiteSpace(x)))
- ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.PrivateKeys)
- : !string.IsNullOrWhiteSpace(server.Password)
- ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.Password)
- : throw new ArgumentNullException("Neither private keys nor password was provided")) {
-
- var sshConnectResult = sshClient.Connect();
- if (!sshConnectResult.IsSuccess)
- return sshConnectResult;
-
- foreach (var result in results) {
- var uploadResult = sshClient.Upload(server.Path, result.Key, Encoding.UTF8.GetBytes(result.Value));
- if (!uploadResult.IsSuccess)
- return uploadResult;
- }
- }
- }
- catch (Exception ex) {
- var message = "Unable to upload files to remote server";
- _logger.LogError(ex, message);
-
- return IDomainResult.CriticalDependencyError(message);
- }
-
- return IDomainResult.Success();
- }
- private IDomainResult ReloadServer() {
- var server = _appSettings.Server;
-
- try {
- using (SSHService sshClient = (server.PrivateKeys != null && server.PrivateKeys.Any(x => !string.IsNullOrWhiteSpace(x)))
- ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.PrivateKeys)
- : !string.IsNullOrWhiteSpace(server.Password)
- ? new SSHService(_logger, server.Ip, server.SSHPort, server.Username, server.Password)
- : throw new ArgumentNullException("Neither private keys nor password was provided")) {
-
- var sshConnectResult = sshClient.Connect();
- if (!sshConnectResult.IsSuccess)
- return sshConnectResult;
-
- // TODO: Prefer to create the native linux service which can receive the signal to reload the services
- return sshClient.RunSudoCommand("", "systemctl reload haproxy");
- }
- }
- catch (Exception ex) {
- var message = "Unable to upload files to remote server";
- _logger.LogError(ex, message);
-
- return IDomainResult.CriticalDependencyError(message);
- }
-
- return IDomainResult.Success();
- }
-
- ///
- /// Currently not working
- ///
- ///
- ///
- private IDomainResult NotifyHaproxy(Dictionary results) {
- var server = _appSettings.Server;
-
- try {
- using (var client = new TcpClient(server.Ip, server.SocketPort))
- using (var networkStream = client.GetStream())
- using (var writer = new StreamWriter(networkStream, Encoding.ASCII))
- using (var reader = new StreamReader(networkStream, Encoding.ASCII)) {
- writer.AutoFlush = true;
-
- foreach (var result in results) {
- var certFile = result.Key;
-
- // Prepare the certificate
- string prepareCommand = $"new ssl cert {server.Path}/{certFile}";
- writer.WriteLine(prepareCommand);
- writer.Flush();
- string prepareResponse = reader.ReadLine();
- //if (prepareResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) {
- // _logger.LogError($"Error while preparing certificate {certFile}: {prepareResponse}");
- // return IDomainResult.CriticalDependencyError($"Error while preparing certificate {certFile}");
- //}
-
- // Set the certificate
- string setCommand = $"set ssl cert {server.Path}/{certFile} <<\n{result.Value}\n";
- writer.WriteLine(setCommand);
- writer.Flush();
- string setResponse = reader.ReadLine();
- //if (setResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) {
- // _logger.LogError($"Error while setting certificate {certFile}: {setResponse}");
- // return IDomainResult.CriticalDependencyError($"Error while setting certificate {certFile}");
- //}
-
- // Commit the certificate
- string commitCommand = $"commit ssl cert {server.Path}/{certFile}";
- writer.WriteLine(commitCommand);
- writer.Flush();
- string commitResponse = reader.ReadLine();
- //if (commitResponse.Contains("error", StringComparison.OrdinalIgnoreCase)) {
- // _logger.LogError($"Error while committing certificate {certFile}: {commitResponse}");
- // return IDomainResult.CriticalDependencyError($"Error while committing certificate {certFile}");
- //}
- }
-
- _logger.LogInformation("Certificates committed successfully.");
- }
- }
- catch (Exception ex) {
- var message = "An error occurred while committing certificates";
- _logger.LogError(ex, message);
-
- return IDomainResult.CriticalDependencyError(message);
- }
-
- return IDomainResult.Success();
- }
-
-
-
-
private void DeleteExporedChallenges() {
var currentDate = DateTime.Now;
diff --git a/src/LetsEncryptServer/appsettings.json b/src/LetsEncryptServer/appsettings.json
index a9fcddf..cff203a 100644
--- a/src/LetsEncryptServer/appsettings.json
+++ b/src/LetsEncryptServer/appsettings.json
@@ -13,14 +13,12 @@
"DevMode": true,
- "Server": {
- "Ip": "192.168.1.4",
- "SocketPort": 9999,
- "SSHPort": 22,
- "Path": "/etc/haproxy/certs",
- "Username": "acme",
- "PrivateKeys": [],
- "Password": "acme"
+ "Agent": {
+ "AgentHostname": "http://lblsrv0001.corp.maks-it.com",
+ "AgentPort": 5000,
+ "AgentKey": "UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=",
+
+ "ServiceToReload": "haproxy"
}
}
}
diff --git a/src/Models/Agent/Requests/CertsUploadRequest.cs b/src/Models/Agent/Requests/CertsUploadRequest.cs
new file mode 100644
index 0000000..d2dbb7c
--- /dev/null
+++ b/src/Models/Agent/Requests/CertsUploadRequest.cs
@@ -0,0 +1,7 @@
+namespace MaksIT.Models.Agent.Requests {
+ public class CertsUploadRequest {
+
+ public Dictionary Certs { get; set; }
+
+ }
+}
diff --git a/src/Models/Agent/Requests/ServiceReloadRequest.cs b/src/Models/Agent/Requests/ServiceReloadRequest.cs
new file mode 100644
index 0000000..9921ba9
--- /dev/null
+++ b/src/Models/Agent/Requests/ServiceReloadRequest.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MaksIT.Models.Agent.Requests {
+ public class ServiceReloadRequest {
+ public string ServiceName { get; set; }
+ }
+}
diff --git a/src/LetsEncryptServer/Models/Requests/GetCerificatesRequest.cs b/src/Models/LetsEncryptServer/Requests/GetCerificatesRequest.cs
similarity index 61%
rename from src/LetsEncryptServer/Models/Requests/GetCerificatesRequest.cs
rename to src/Models/LetsEncryptServer/Requests/GetCerificatesRequest.cs
index a93b758..cddb599 100644
--- a/src/LetsEncryptServer/Models/Requests/GetCerificatesRequest.cs
+++ b/src/Models/LetsEncryptServer/Requests/GetCerificatesRequest.cs
@@ -1,4 +1,4 @@
-namespace MaksIT.LetsEncryptServer.Models.Requests {
+namespace MaksIT.Models.LetsEncryptServer.Requests {
public class GetCertificatesRequest {
public string[] Hostnames { get; set; }
}
diff --git a/src/LetsEncryptServer/Models/Requests/GetOrderRequest.cs b/src/Models/LetsEncryptServer/Requests/GetOrderRequest.cs
similarity index 59%
rename from src/LetsEncryptServer/Models/Requests/GetOrderRequest.cs
rename to src/Models/LetsEncryptServer/Requests/GetOrderRequest.cs
index e4f76fc..8cde81e 100644
--- a/src/LetsEncryptServer/Models/Requests/GetOrderRequest.cs
+++ b/src/Models/LetsEncryptServer/Requests/GetOrderRequest.cs
@@ -1,4 +1,4 @@
-namespace MaksIT.LetsEncryptServer.Models.Requests {
+namespace MaksIT.Models.LetsEncryptServer.Requests {
public class GetOrderRequest {
public string[] Hostnames { get; set; }
}
diff --git a/src/LetsEncryptServer/Models/Requests/InitRequest.cs b/src/Models/LetsEncryptServer/Requests/InitRequest.cs
similarity index 78%
rename from src/LetsEncryptServer/Models/Requests/InitRequest.cs
rename to src/Models/LetsEncryptServer/Requests/InitRequest.cs
index 459bf25..0ae1e9e 100644
--- a/src/LetsEncryptServer/Models/Requests/InitRequest.cs
+++ b/src/Models/LetsEncryptServer/Requests/InitRequest.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace MaksIT.LetsEncryptServer.Models.Requests {
+namespace MaksIT.Models.LetsEncryptServer.Requests {
public class InitRequest {
public string[] Contacts { get; set; }
}
diff --git a/src/LetsEncryptServer/Models/Requests/NewOrderRequest.cs b/src/Models/LetsEncryptServer/Requests/NewOrderRequest.cs
similarity index 70%
rename from src/LetsEncryptServer/Models/Requests/NewOrderRequest.cs
rename to src/Models/LetsEncryptServer/Requests/NewOrderRequest.cs
index 71d2899..f1f8820 100644
--- a/src/LetsEncryptServer/Models/Requests/NewOrderRequest.cs
+++ b/src/Models/LetsEncryptServer/Requests/NewOrderRequest.cs
@@ -1,4 +1,4 @@
-namespace MaksIT.LetsEncryptServer.Models.Requests {
+namespace MaksIT.Models.LetsEncryptServer.Requests {
public class NewOrderRequest {
public string[] Hostnames { get; set; }
diff --git a/src/Models/Models.csproj b/src/Models/Models.csproj
new file mode 100644
index 0000000..a5e4d8f
--- /dev/null
+++ b/src/Models/Models.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/src/Postman/LetsEncrypt Production.postman_collection.json b/src/Postman/LetsEncrypt Production.postman_collection.json
new file mode 100644
index 0000000..609661c
--- /dev/null
+++ b/src/Postman/LetsEncrypt Production.postman_collection.json
@@ -0,0 +1,479 @@
+{
+ "info": {
+ "_postman_id": "728f64b6-893b-43fa-802e-ee836d1dc372",
+ "name": "LetsEncrypt Production",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "33635244"
+ },
+ "item": [
+ {
+ "name": "letsencrypt production",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "https://acme-v02.api.letsencrypt.org/directory",
+ "protocol": "https",
+ "host": [
+ "acme-v02",
+ "api",
+ "letsencrypt",
+ "org"
+ ],
+ "path": [
+ "directory"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "configure client",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "// Ensure the response status code is 200 (OK)\r",
+ "if (pm.response.code === 200) {\r",
+ " // Get the plain text response\r",
+ " let responseBody = pm.response.text();\r",
+ " \r",
+ " // Remove the surrounding quotes if present\r",
+ " responseBody = responseBody.replace(/^\"|\"$/g, '');\r",
+ " \r",
+ " // Check if the response body is a valid GUID\r",
+ " if (/^[0-9a-fA-F-]{36}$/.test(responseBody)) {\r",
+ " // Set the environment variable sessionId with the response\r",
+ " pm.environment.set(\"sessionId\", responseBody);\r",
+ " console.log(`sessionId set to: ${responseBody}`);\r",
+ " } else {\r",
+ " console.log(\"Response body is not a valid GUID\");\r",
+ " }\r",
+ "} else {\r",
+ " console.log(`Request failed with status code: ${pm.response.code}`);\r",
+ "}\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/ConfigureClient",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "ConfigureClient"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "terms of service",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/TermsOfService/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "TermsOfService",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "init",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "// Ensure the response status code is 200 (OK)\r",
+ "if (pm.response.code === 200) {\r",
+ " // Get the plain text response\r",
+ " let responseBody = pm.response.text();\r",
+ " \r",
+ " // Remove the surrounding quotes if present\r",
+ " responseBody = responseBody.replace(/^\"|\"$/g, '');\r",
+ " \r",
+ " // Check if the response body is a valid GUID\r",
+ " if (/^[0-9a-fA-F-]{36}$/.test(responseBody)) {\r",
+ " // Set the environment variable accountId with the response\r",
+ " pm.environment.set(\"accountId\", responseBody);\r",
+ " console.log(`accountId set to: ${responseBody}`);\r",
+ " } else {\r",
+ " console.log(\"Response body is not a valid GUID\");\r",
+ " }\r",
+ "} else {\r",
+ " console.log(`Request failed with status code: ${pm.response.code}`);\r",
+ "}\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ },
+ {
+ "listen": "prerequest",
+ "script": {
+ "exec": [
+ "// Retrieve sessionId and accountId from environment variables or global variables\r",
+ "var sessionId = pm.environment.get(\"sessionId\") || pm.globals.get(\"sessionId\");\r",
+ "var accountId = pm.environment.get(\"accountId\") || pm.globals.get(\"accountId\");\r",
+ "\r",
+ "// Base URL without the optional accountId parameter\r",
+ "var baseUrl = `http://localhost:8080/CertsFlow/Init/${sessionId}`;\r",
+ "\r",
+ "// Append the accountId if it is provided\r",
+ "if (accountId) {\r",
+ " pm.request.url = `${baseUrl}/${accountId}`;\r",
+ "} else {\r",
+ " pm.request.url = baseUrl;\r",
+ "}"
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"contacts\": [\r\n \"maksym.sadovnychyy@gmail.com\"\r\n ]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/Init/{{sessionId}}/{{accountId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "Init",
+ "{{sessionId}}",
+ "{{accountId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "new order",
+ "event": [
+ {
+ "listen": "test",
+ "script": {
+ "exec": [
+ "// Ensure the response status code is 200 (OK)\r",
+ "if (pm.response.code === 200) {\r",
+ " // Parse the JSON response\r",
+ " let responseBody;\r",
+ " try {\r",
+ " responseBody = pm.response.json();\r",
+ " } catch (e) {\r",
+ " console.error(\"Failed to parse JSON response:\", e);\r",
+ " return;\r",
+ " }\r",
+ "\r",
+ " // Check if the response is an array and has at least one element\r",
+ " if (Array.isArray(responseBody) && responseBody.length > 0) {\r",
+ " // Get the first element of the array\r",
+ " const firstElement = responseBody[0];\r",
+ " \r",
+ " // Set the environment variable challenge with the first element\r",
+ " pm.environment.set(\"challenge\", firstElement);\r",
+ " console.log(`challenge set to: ${firstElement}`);\r",
+ " } else {\r",
+ " console.log(\"Response body is not an array or is empty\");\r",
+ " }\r",
+ "} else {\r",
+ " console.log(`Request failed with status code: ${pm.response.code}`);\r",
+ "}\r",
+ ""
+ ],
+ "type": "text/javascript",
+ "packages": {}
+ }
+ }
+ ],
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"hostnames\": [\r\n \"maks-it.com\",\r\n \"auth.maks-it.com\"\r\n ],\r\n \"challengeType\": \"http-01\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/NewOrder/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "NewOrder",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "acme-challenge local",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://localhost:8080/.well-known/acme-challenge/{{challenge}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ ".well-known",
+ "acme-challenge",
+ "{{challenge}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "acme-challenge",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://maks-it.com/.well-known/acme-challenge/{{challenge}}",
+ "protocol": "http",
+ "host": [
+ "maks-it",
+ "com"
+ ],
+ "path": [
+ ".well-known",
+ "acme-challenge",
+ "{{challenge}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "complete challenges",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/CompleteChallenges/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "CompleteChallenges",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "get order",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"hostnames\": [\r\n \"maks-it.com\",\r\n \"auth.maks-it.com\"\r\n ]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/GetOrder/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "GetOrder",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "get certificates",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"hostnames\": [\r\n \"maks-it.com\",\r\n \"auth.maks-it.com\"\r\n ]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/GetCertificates/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "GetCertificates",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "apply certificates",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"hostnames\": [\r\n \"maks-it.com\",\r\n \"auth.maks-it.com\"\r\n ]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/CertsFlow/ApplyCertificates/{{sessionId}}",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "CertsFlow",
+ "ApplyCertificates",
+ "{{sessionId}}"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/LetsEncrypt.postman_collection.json b/src/Postman/LetsEncrypt Staging.postman_collection.json
similarity index 96%
rename from LetsEncrypt.postman_collection.json
rename to src/Postman/LetsEncrypt Staging.postman_collection.json
index ae8aaab..51962ce 100644
--- a/LetsEncrypt.postman_collection.json
+++ b/src/Postman/LetsEncrypt Staging.postman_collection.json
@@ -1,7 +1,7 @@
{
"info": {
- "_postman_id": "728f64b6-893b-43fa-802e-ee836d1dc372",
- "name": "LetsEncrypt",
+ "_postman_id": "95186b61-1197-4a6e-a90f-d97223528d90",
+ "name": "LetsEncrypt Staging",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "33635244"
},
@@ -28,27 +28,6 @@
},
"response": []
},
- {
- "name": "letsencrypt production",
- "request": {
- "method": "GET",
- "header": [],
- "url": {
- "raw": "https://acme-v02.api.letsencrypt.org/directory",
- "protocol": "https",
- "host": [
- "acme-v02",
- "api",
- "letsencrypt",
- "org"
- ],
- "path": [
- "directory"
- ]
- }
- },
- "response": []
- },
{
"name": "configure client",
"event": [
diff --git a/src/Postman/Maks-IT Agent.postman_collection.json b/src/Postman/Maks-IT Agent.postman_collection.json
new file mode 100644
index 0000000..9624c74
--- /dev/null
+++ b/src/Postman/Maks-IT Agent.postman_collection.json
@@ -0,0 +1,77 @@
+{
+ "info": {
+ "_postman_id": "1e13f461-ccaa-436a-92e4-e14c05131b96",
+ "name": "Maks-IT Agent",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "33635244"
+ },
+ "item": [
+ {
+ "name": "reload service",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "x-api-key",
+ "value": "{{agentKey}}"
+ },
+ {
+ "key": "Accept",
+ "value": "application/json"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"serviceName\": {{serviceName}}\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://lblsrv0001.corp.maks-it.com:5000/Service/Reload",
+ "protocol": "http",
+ "host": [
+ "lblsrv0001",
+ "corp",
+ "maks-it",
+ "com"
+ ],
+ "port": "5000",
+ "path": [
+ "Service",
+ "Reload"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "hello world",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "http://lblsrv0001.corp.maks-it.com:5000/HelloWorld",
+ "protocol": "http",
+ "host": [
+ "lblsrv0001",
+ "corp",
+ "maks-it",
+ "com"
+ ],
+ "port": "5000",
+ "path": [
+ "HelloWorld"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+}
\ No newline at end of file