Skip to content

Commit

Permalink
Ab#52646 (#2)
Browse files Browse the repository at this point in the history
* Initial public release
  • Loading branch information
leefine02 authored Jun 17, 2024
1 parent 1dd54c7 commit 4afcc62
Show file tree
Hide file tree
Showing 24 changed files with 1,053 additions and 872 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
v1.0.0
- Initial Version
15 changes: 14 additions & 1 deletion F5WafOrchestrator.Tests/F5WafCa.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
using System.Security.Cryptography.X509Certificates;
// Copyright 2024 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.CA;
using Keyfactor.Logging;
using Keyfactor.Orchestrators.Common.Enums;
Expand Down
18 changes: 14 additions & 4 deletions F5WafOrchestrator.Tests/F5WafTls.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
using System.Security.Cryptography.X509Certificates;
using Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.Client;
// Copyright 2024 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.TLS;
using Keyfactor.Logging;
using Keyfactor.Orchestrators.Common.Enums;
using Keyfactor.Orchestrators.Extensions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using NLog.Extensions.Logging;
using Org.BouncyCastle.Pkcs;

namespace F5WafOrchestrator.Tests;

Expand Down
78 changes: 39 additions & 39 deletions F5WafOrchestrator/CA/Discovery.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright 2024 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.Client;
using Keyfactor.Logging;
using Keyfactor.Orchestrators.Common.Enums;
Expand All @@ -6,47 +20,33 @@

namespace Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.CA;

[Job("Discovery")]
public class Discovery : Job<Discovery>, IDiscoveryJobExtension
public class Discovery : Job, IDiscoveryJobExtension
{
ILogger _logger = LogHandler.GetClassLogger<Discovery>();

public JobResult ProcessJob(DiscoveryJobConfiguration config, SubmitDiscoveryUpdate cb)

public JobResult ProcessJob(DiscoveryJobConfiguration config, SubmitDiscoveryUpdate cb)
{
_logger.LogDebug($"Begin {config.Capability} for job id {config.JobId}...");
_logger.LogDebug($"Server: {config.ClientMachine}");

List<string> namespaces;

try
{
_logger.LogDebug("Beginning F5 Distributed Cloud Discovery Job");

var result = new JobResult
{
Result = OrchestratorJobStatusJobResult.Failure,
JobHistoryId = config.JobHistoryId
};

try
{
F5Client = new F5WafClient(config.ClientMachine, config.ServerPassword);
} catch (Exception ex)
{
_logger.LogError(ex, $"Could not connect to F5 Client" + ex.Message);
return result;
}

List<string> namespaces;

try
{
namespaces = F5Client.DiscoverNamespacesforCaStoreType();
_logger.LogDebug($"Found {namespaces.Count()} namespaces in {config.ClientMachine}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error getting F5 namespaces from {config.ClientMachine}:\n" + ex.Message);
result.FailureMessage = $"Error getting F5 namespaces from {config.ClientMachine}:\n" + ex.Message;
return result;
}

cb.Invoke(namespaces);

result.Result = OrchestratorJobStatusJobResult.Success;
return result;
F5Client = new F5WafClient(config.ClientMachine, config.ServerPassword);

namespaces = F5Client.DiscoverNamespacesforStoreType("ca-");
_logger.LogDebug($"Found {namespaces.Count()} namespaces in {config.ClientMachine}");
}
catch (Exception ex)
{
_logger.LogError($"Exception for {config.Capability}: {F5WAFException.FlattenExceptionMessages(ex, string.Empty)} for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = F5WAFException.FlattenExceptionMessages(ex, $"Server {config.ClientMachine}:") };
}

cb.Invoke(namespaces);

_logger.LogDebug($"...End {config.Capability} job for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Success, JobHistoryId = config.JobHistoryId };
}
}
54 changes: 25 additions & 29 deletions F5WafOrchestrator/CA/Inventory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Keyfactor
// Copyright 2024 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,37 +20,26 @@

namespace Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.CA;

[Job("Inventory")]
public class Inventory : Job<Inventory>, IInventoryJobExtension
public class Inventory : Job, IInventoryJobExtension
{
private readonly ILogger _logger = LogHandler.GetClassLogger<Inventory>();

public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpdate cb)
{
_logger.LogDebug("Beginning F5 Distributed Cloud Inventory Job");

var result = new JobResult
{
Result = OrchestratorJobStatusJobResult.Failure,
JobHistoryId = config.JobHistoryId
};

_logger.LogDebug($"Begin {config.Capability} for job id {config.JobId}...");
_logger.LogDebug($"Server: {config.CertificateStoreDetails.ClientMachine}");
_logger.LogDebug($"Store Path: {config.CertificateStoreDetails.StorePath}");

List<CurrentInventoryItem> inventoryItems;

try
{
F5Client = new F5WafClient(config.CertificateStoreDetails.ClientMachine, config.ServerPassword);
} catch (Exception ex)
{
_logger.LogError(ex, $"Could not connect to F5 Client" + ex.Message);
return result;
}


List<CurrentInventoryItem> inventoryItems;
string storePath = config.CertificateStoreDetails.StorePath;
string storePath = config.CertificateStoreDetails.StorePath;

try
{
// check if the string starts with "ca-" and remove it if present
// check if the string starts with "ca-" and remove it if present. This may occur
// if store was created in Command via a Discovery job
if (config.CertificateStoreDetails.StorePath.StartsWith("ca-"))
{
storePath = config.CertificateStoreDetails.StorePath.Substring(3); // Skip the first 3 characters ("ca-")
Expand All @@ -68,14 +57,21 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error getting F5 Certificate from namespace {storePath}:\n" + ex.Message);
result.FailureMessage = $"Error getting F5 Certificates from namespace {storePath}:\n" + ex.Message;
return result;
_logger.LogError($"Exception for {config.Capability}: {F5WAFException.FlattenExceptionMessages(ex, string.Empty)} for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = F5WAFException.FlattenExceptionMessages(ex, $"Site {config.CertificateStoreDetails.StorePath} on server {config.CertificateStoreDetails.ClientMachine}:") };
}

cb.Invoke(inventoryItems);

result.Result = OrchestratorJobStatusJobResult.Success;
return result;
try
{
cb.Invoke(inventoryItems);
_logger.LogDebug($"...End {config.Capability} job for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Success, JobHistoryId = config.JobHistoryId };
}
catch (Exception ex)
{
string errorMessage = F5WAFException.FlattenExceptionMessages(ex, string.Empty);
_logger.LogError($"Exception returning certificates for {config.Capability}: {errorMessage} for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = F5WAFException.FlattenExceptionMessages(ex, $"Site {config.CertificateStoreDetails.StorePath} on server {config.CertificateStoreDetails.ClientMachine}:") };
}
}
}
149 changes: 62 additions & 87 deletions F5WafOrchestrator/CA/Management.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2023 Keyfactor
// Copyright 2024 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -20,105 +20,80 @@

namespace Keyfactor.Extensions.Orchestrator.F5WafOrchestrator.CA;

[Job("Management")]
public class Management : Job<Management>, IManagementJobExtension
public class Management : Job, IManagementJobExtension
{
ILogger _logger = LogHandler.GetClassLogger<Management>();

public JobResult ProcessJob(ManagementJobConfiguration config)
public JobResult ProcessJob(ManagementJobConfiguration config)
{
_logger.LogDebug($"Begin {config.Capability} for job id {config.JobId}...");
_logger.LogDebug($"Server: {config.CertificateStoreDetails.ClientMachine}");
_logger.LogDebug($"Store Path: {config.CertificateStoreDetails.StorePath}");

try
{
_logger.LogDebug("Beginning F5 Cloud Management Job");
F5Client = new F5WafClient(config.CertificateStoreDetails.ClientMachine, config.ServerPassword);

JobResult result = new JobResult
{
Result = OrchestratorJobStatusJobResult.Failure,
JobHistoryId = config.JobHistoryId
};

try
// check if the string starts with "ca-" and remove it if present. This may occur
// if store was created in Command via a Discovery job
if (config.CertificateStoreDetails.StorePath.StartsWith("ca-"))
{
F5Client = new F5WafClient(config.CertificateStoreDetails.ClientMachine, config.ServerPassword);
} catch (Exception ex)
config.CertificateStoreDetails.StorePath = config.CertificateStoreDetails.StorePath.Substring(3);
}

switch (config.OperationType)
{
_logger.LogError(ex, $"Could not connect to F5 Client" + ex.Message);
return result;
case CertStoreOperationType.Add:
_logger.LogDebug($"BEGIN Add Operation for {config.CertificateStoreDetails.StorePath} on {config.CertificateStoreDetails.ClientMachine}.");
PerformCaCertAddition(config);
_logger.LogDebug($"END Add Operation for {config.CertificateStoreDetails.StorePath} on {config.CertificateStoreDetails.ClientMachine}.");
break;
case CertStoreOperationType.Remove:
_logger.LogDebug($"BEGIN Delete Operation for {config.CertificateStoreDetails.StorePath} on {config.CertificateStoreDetails.ClientMachine}.");
F5Client.RemoveCaOrTlsCertificate(config.CertificateStoreDetails.StorePath, config.JobCertificate.Alias, false);
_logger.LogDebug($"END Delete Operation for {config.CertificateStoreDetails.StorePath} on {config.CertificateStoreDetails.ClientMachine}.");
break;
default:
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = $"Site {config.CertificateStoreDetails.StorePath} on server {config.CertificateStoreDetails.ClientMachine}: Unsupported operation: {config.OperationType.ToString()}" };
}
}
catch (Exception ex)
{
_logger.LogError($"Exception for {config.Capability}: {F5WAFException.FlattenExceptionMessages(ex, string.Empty)} for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = F5WAFException.FlattenExceptionMessages(ex, $"Site {config.CertificateStoreDetails.StorePath} on server {config.CertificateStoreDetails.ClientMachine}:") };
}

try
{
// check if the string starts with "ca-" and remove it if present
if (config.CertificateStoreDetails.StorePath.StartsWith("ca-"))
{
config.CertificateStoreDetails.StorePath = config.CertificateStoreDetails.StorePath.Substring(3);
}

switch (config.OperationType)
{
case CertStoreOperationType.Add:
_logger.LogDebug("Adding certificate to F5 Cloud");

PerformCaCertAddition(config, result);
_logger.LogDebug($"...End {config.Capability} job for job id {config.JobId}");
return new JobResult() { Result = OrchestratorJobStatusJobResult.Success, JobHistoryId = config.JobHistoryId };
}

_logger.LogDebug("Add operation complete.");

result.Result = OrchestratorJobStatusJobResult.Success;
break;
case CertStoreOperationType.Remove:
_logger.LogDebug("Removing certificate from F5 Cloud");

F5Client.RemoveCaCertificate(config.CertificateStoreDetails.StorePath, config.JobCertificate.Alias);
private void PerformCaCertAddition(ManagementJobConfiguration config)
{
_logger.MethodEntry(LogLevel.Debug);

_logger.LogDebug("Remove operation complete.");

result.Result = OrchestratorJobStatusJobResult.Success;
break;
default:
_logger.LogDebug("Invalid management operation type: {0}", config.OperationType);
throw new ArgumentOutOfRangeException();
}
} catch (Exception ex)
{
_logger.LogError(ex, "Error processing job:\n {0}", ex.Message);
result.FailureMessage = ex.Message;
return result;
}
bool certificateExists = F5Client.CertificateExistsInF5(config.CertificateStoreDetails.StorePath, config.JobCertificate.Alias, false);

return result;
}

private void PerformCaCertAddition(ManagementJobConfiguration config, JobResult result)
if (certificateExists && !config.Overwrite)
{
// ensure that an alias is provided
if (string.IsNullOrWhiteSpace(config.JobCertificate.Alias))
{
throw new Exception("Certificate alias is required.");
}
// ensure that an alias is provided
if (!string.IsNullOrWhiteSpace(config.JobCertificate.PrivateKeyPassword))
{
throw new Exception("Certificate passed is not a CA.");
}

if (F5Client.CertificateExistsInF5(config.CertificateStoreDetails.StorePath, config.JobCertificate.Alias) && !config.Overwrite)
{
string message =
$"Certificate with alias \"{config.JobCertificate.Alias}\" already exists in F5, and job was not configured to overwrite.";
_logger.LogDebug(message);
throw new Exception(message);
}
string message =
$"Certificate with alias \"{config.JobCertificate.Alias}\" already exists in F5, and job was not configured to overwrite.";
_logger.LogDebug(message);
throw new Exception(message);
}

F5WafClient.CaPostRoot reqBody = F5Client.FormatCaCertificateRequest(config.JobCertificate);
if (F5Client.CertificateExistsInF5(config.CertificateStoreDetails.StorePath, config.JobCertificate.Alias) &&
config.Overwrite)
{
_logger.LogDebug("Overwrite is enabled, replacing certificate in F5 called \"{0}\"",
config.JobCertificate.Alias);
F5Client.ReplaceCaCertificateInF5(config.CertificateStoreDetails.StorePath, reqBody);
}
else
{
_logger.LogDebug("Adding certificate to F5 Cloud");
F5Client.AddCaCertificate(config.CertificateStoreDetails.StorePath, reqBody);
}
F5WafClient.CaPostRoot reqBody = F5Client.FormatCaCertificateRequest(config.JobCertificate);
if (certificateExists && config.Overwrite)
{
_logger.LogDebug("Overwrite is enabled, replacing certificate in F5 called \"{0}\"",
config.JobCertificate.Alias);
F5Client.ReplaceCaOrTlsCertificate(config.CertificateStoreDetails.StorePath, null, reqBody, false);
}
else
{
_logger.LogDebug("Adding certificate to F5 Cloud");
F5Client.AddCaOrTlsCertificate(config.CertificateStoreDetails.StorePath, null, reqBody, false);
}

_logger.MethodExit(LogLevel.Debug);
}
}
Loading

0 comments on commit 4afcc62

Please sign in to comment.