Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/keyfactor-bootstrap-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ on:

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/[email protected]
uses: keyfactor/actions/.github/workflows/starter.yml@v4
with:
command_token_url: ${{ vars.COMMAND_TOKEN_URL }} # Only required for doctool generated screenshots
command_hostname: ${{ vars.COMMAND_HOSTNAME }} # Only required for doctool generated screenshots
command_base_api_path: ${{ vars.COMMAND_API_PATH }} # Only required for doctool generated screenshots
secrets:
token: ${{ secrets.V2BUILDTOKEN}}
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
scan_token: ${{ secrets.SAST_TOKEN }}
token: ${{ secrets.V2BUILDTOKEN}} # REQUIRED
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} # Only required for golang builds
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} # Only required for golang builds
scan_token: ${{ secrets.SAST_TOKEN }} # REQUIRED
entra_username: ${{ secrets.DOCTOOL_ENTRA_USERNAME }} # Only required for doctool generated screenshots
entra_password: ${{ secrets.DOCTOOL_ENTRA_PASSWD }} # Only required for doctool generated screenshots
command_client_id: ${{ secrets.COMMAND_CLIENT_ID }} # Only required for doctool generated screenshots
command_client_secret: ${{ secrets.COMMAND_CLIENT_SECRET }} # Only required for doctool generated screenshots
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v2.0.0
- Modify ODKG (Reenrollment) functionality to make use of the Keyfactor Command/UO 25.3 functionality to support SANs, Alias, and Overwrite indicator. Entry parameters SANs, Alias, and Overwrite will no longer be supported.

v1.2.0
- Documentation updated to use doctool and dual build for .net6/8.

Expand Down
8 changes: 6 additions & 2 deletions F5BigIQ/F5BigIQ.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@

<ItemGroup>
<PackageReference Include="Keyfactor.Logging" Version="1.1.1" />
<PackageReference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions" Version="0.7.0" />
<PackageReference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions" Version="1.0.0" />
<PackageReference Include="Keyfactor.PKI" Version="5.5.0" />
<PackageReference Include="RestSharp" Version="110.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="SSH.NET" Version="2024.0.0" />
<Reference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions">
<HintPath>External References\Keyfactor.Orchestrators.IOrchestratorJobExtensions.dll</HintPath>
</Reference>

Comment on lines +17 to 20
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package reference Keyfactor.Orchestrators.IOrchestratorJobExtensions is duplicated - it appears both as a PackageReference on line 12 and as a Reference with HintPath on lines 17-19. Remove the duplicate Reference to avoid potential conflicts.

Suggested change
<Reference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions">
<HintPath>External References\Keyfactor.Orchestrators.IOrchestratorJobExtensions.dll</HintPath>
</Reference>

Copilot uses AI. Check for mistakes.
<None Update="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
39 changes: 27 additions & 12 deletions F5BigIQ/Reenrollment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports should be removed. The imports System.Net.NetworkInformation, Microsoft.Win32.SafeHandles, and static Org.BouncyCastle.Math.EC.ECCurve are not used anywhere in this file.

Copilot uses AI. Check for mistakes.
using System.Security.Cryptography.X509Certificates;

using Keyfactor.Logging;
Expand All @@ -19,6 +20,8 @@
using Newtonsoft.Json;
using Org.BouncyCastle.X509;
using System.Text;
using Microsoft.Win32.SafeHandles;
using static Org.BouncyCastle.Math.EC.ECCurve;

Comment on lines +23 to 25
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused imports should be removed. The imports Microsoft.Win32.SafeHandles and static Org.BouncyCastle.Math.EC.ECCurve are not used anywhere in this file.

Suggested change
using Microsoft.Win32.SafeHandles;
using static Org.BouncyCastle.Math.EC.ECCurve;

Copilot uses AI. Check for mistakes.
namespace Keyfactor.Extensions.Orchestrator.F5BigIQ
{
Expand All @@ -40,7 +43,7 @@ public JobResult ProcessJob(ReenrollmentJobConfiguration config, SubmitReenrollm
{
logger.LogDebug($" {keyValue.Key}: {keyValue.Value}");
}

dynamic properties = JsonConvert.DeserializeObject(config.CertificateStoreDetails.Properties);

SetPAMSecrets(config.ServerUsername, config.ServerPassword, logger);
Expand All @@ -53,27 +56,39 @@ public JobResult ProcessJob(ReenrollmentJobConfiguration config, SubmitReenrollm
string keyType = !config.JobProperties.ContainsKey("keyType") || config.JobProperties["keyType"] == null || string.IsNullOrEmpty(config.JobProperties["keyType"].ToString()) ? string.Empty : config.JobProperties["keyType"].ToString();
int? keySize = !config.JobProperties.ContainsKey("keySize") || config.JobProperties["keySize"] == null || string.IsNullOrEmpty(config.JobProperties["keySize"].ToString()) ? null : Convert.ToInt32(config.JobProperties["keySize"]);
string subjectText = !config.JobProperties.ContainsKey("subjectText") || config.JobProperties["subjectText"] == null || config.JobProperties["subjectText"] == null || string.IsNullOrEmpty(config.JobProperties["subjectText"].ToString()) ? string.Empty : config.JobProperties["subjectText"].ToString();
string sans = !config.JobProperties.ContainsKey("SANs") || config.JobProperties["SANs"] == null || string.IsNullOrEmpty(config.JobProperties["SANs"].ToString()) ? string.Empty : config.JobProperties["SANs"].ToString();
if (!config.JobProperties.ContainsKey("Alias") || config.JobProperties["Alias"] == null || config.JobProperties["Alias"] == null || string.IsNullOrEmpty(config.JobProperties["Alias"].ToString()))
if (string.IsNullOrEmpty(config.Alias))
{
string errorMessage = "Error performing reenrollment. Alias blank or does not exist.";
string errorMessage = "Error performing reenrollment. Alias is required.";
logger.LogError(errorMessage);
return new JobResult() { Result = OrchestratorJobStatusJobResult.Failure, JobHistoryId = config.JobHistoryId, FailureMessage = $"Site {config.CertificateStoreDetails.StorePath} on server {config.CertificateStoreDetails.ClientMachine}: {errorMessage}"};
}
string alias = config.JobProperties["Alias"].ToString();
bool overwrite = !config.JobProperties.ContainsKey("Overwrite") || config.JobProperties["Overwrite"] == null || string.IsNullOrEmpty(config.JobProperties["Overwrite"].ToString()) ? false : Convert.ToBoolean(config.JobProperties["Overwrite"]);

try
{
F5BigIQClient f5Client = new F5BigIQClient(config.CertificateStoreDetails.ClientMachine, config.CertificateStoreDetails.StorePath, ServerUserName, ServerPassword, loginProviderName, useTokenAuthentication, ignoreSSLWarning);

int totalKeys = f5Client.GetKeyByName(alias).TotalItems;
if (!overwrite && totalKeys > 0)
int totalKeys = f5Client.GetKeyByName(config.Alias).TotalItems;
if (!config.Overwrite && totalKeys > 0)
{
throw new Exception($"Alias {config.Alias} already exists, but Overwrite is set to False. Overwrite must be set to True if you wish to perform reenrollment on an existing alias.");
}

string sans = string.Empty;
if (config.SANs.Count > 0)
{
throw new Exception($"Alias {alias} already exists, but Overwrite is set to False. Overwrite must be set to True if you wish to perform reenrollment on an existing alias.");
foreach(KeyValuePair<string, string[]> keyValue in config.SANs)
{
string key = keyValue.Key.Replace("ip4", "ip", StringComparison.OrdinalIgnoreCase).Replace("ip6", "ip", StringComparison.OrdinalIgnoreCase).Replace("upn", "uri", StringComparison.OrdinalIgnoreCase);
foreach (string value in keyValue.Value)
{
sans += (key + ":" + value + ",");
}
Comment on lines +84 to +85
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String concatenation in a loop is inefficient. Consider using StringBuilder for better performance when building the sans string, especially since SANs can potentially have multiple entries.

Copilot uses AI. Check for mistakes.
}
if (sans.Length > 0)
sans = sans.Substring(0, sans.Length - 1);
}

string csr = f5Client.GenerateCSR(alias, totalKeys > 0, subjectText, keyType, keySize, sans);
string csr = f5Client.GenerateCSR(config.Alias, totalKeys > 0, subjectText, keyType, keySize, sans);

X509Certificate2 cert = submitReenrollment.Invoke(csr);
if (cert == null)
Expand All @@ -87,8 +102,8 @@ public JobResult ProcessJob(ReenrollmentJobConfiguration config, SubmitReenrollm

try
{
f5Client.AddReplaceBindCertificate(alias, Convert.ToBase64String(pemBytes),
string.Empty, overwrite, deployCertificateOnRenewal, F5BigIQClient.CERT_FILE_TYPE_TO_ADD.CERT);
f5Client.AddReplaceBindCertificate(config.Alias, Convert.ToBase64String(pemBytes),
string.Empty, config.Overwrite, deployCertificateOnRenewal, F5BigIQClient.CERT_FILE_TYPE_TO_ADD.CERT);
}
catch (F5BigIQException ex)
{
Expand Down
Loading
Loading