Skip to content
Open
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4c4f900
Initial JEA for WinCert
Apr 24, 2026
c45ef24
Update generated docs
Apr 24, 2026
585fd7f
Helper updates
Apr 24, 2026
aa2e660
Merge branch '81018-Adding_JEA_Support' of https://github.com/Keyfact…
Apr 24, 2026
3d8180a
Updated spelling of PowerShell script and fixed Information Messages …
Apr 27, 2026
59d239f
Added JEA support for IIS
Apr 28, 2026
d3a92d4
Fixed and updated IIS Components
Apr 28, 2026
355c3ac
Completed SQL Module and updated test projects
Apr 30, 2026
c38621d
Testing
May 1, 2026
0643435
Removed WinCertScripts from extension.
May 6, 2026
a9cd833
changed way LocalHost and JEA are configured.
May 6, 2026
0c432a9
Fixed ODKG missing file error
May 6, 2026
eca4c19
Updated KF Import of Signed Certificates PowerShell Script
May 7, 2026
f9bd02b
Fixed missing PowerShell script not being found.
May 11, 2026
df9ddcf
Fix missing path
May 11, 2026
8ad923c
Updated documentation to include JEA information.
May 11, 2026
4094f15
Update generated docs
May 11, 2026
9e102ea
chore(ci): Update build workflow to v5
spbsoluble May 12, 2026
2158f3c
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 12, 2026
f85f910
Update generated docs
spbsoluble May 12, 2026
fb4031a
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 12, 2026
d9fbee8
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 12, 2026
89f92f0
Adding dotnet 10 support
May 13, 2026
0413000
modified: IISU/PowerShell/Build/KeyfactorWinCert.pssc
May 13, 2026
51dca80
Merge branch '81018-Adding_JEA_Support' of https://github.com/Keyfact…
May 13, 2026
6395a23
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 13, 2026
aa8d504
Updated packages to support dotnet 10
May 13, 2026
cdcc1d2
Merge branch '81018-Adding_JEA_Support' of https://github.com/Keyfact…
May 13, 2026
43035b7
Updating Unit Tests
May 13, 2026
9197a2c
Fixed timeout issue when migrating to dotnet 10
May 13, 2026
a85707d
modified: IISU/PSHelper.cs
May 13, 2026
fb7444c
Remove .net6 libraries and support
May 13, 2026
6b3a95a
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 13, 2026
467ed39
#86137 Cleaned up messages returned to Command
May 15, 2026
5fba9a8
Merge branch '81018-Adding_JEA_Support' of https://github.com/Keyfact…
May 15, 2026
9418667
Updated language for WinSQL binding concerns
May 15, 2026
7f1cac9
docs: auto-generate README and documentation [skip ci]
github-actions[bot] May 15, 2026
cd9a401
Updated JEA Documentation
Jun 18, 2026
8397532
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jun 18, 2026
8720d89
Added diagnostic cmdlet
Jun 25, 2026
970a9a8
Updated the JEA documentation. Added the get-keyfactordiagnostics cm…
Jun 26, 2026
5479921
Merge branch '81018-Adding_JEA_Support' of github.com:Keyfactor/iis-o…
Jun 26, 2026
3fe25ef
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jun 26, 2026
e0da7d4
Potential fix for pull request finding
rcpokorny Jun 26, 2026
bc07ae8
Updated error reporting when bad CSP
Jul 1, 2026
e38da14
Updated PS scripts to get CSPs from registry not certutil.
Jul 6, 2026
7250263
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 6, 2026
db4b068
Fixed formatting issue in CHANGELOG
Jul 6, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@v4
uses: keyfactor/actions/.github/workflows/starter.yml@v5
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
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# Local test credentials (never commit)
local.runsettings

# User-specific files
*.rsuser
*.suo
Expand Down
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "PowerShell: Launch Script",
"type": "PowerShell",
"request": "launch",
"script": "${file}",
"args": []
}
]
}
112 changes: 78 additions & 34 deletions CHANGELOG.md

Large diffs are not rendered by default.

29 changes: 14 additions & 15 deletions IISU/ClientPSCertStoreReEnrollment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,11 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
string protocol = jobProperties.WinRmProtocol;
string port = jobProperties.WinRmPort;
bool includePortInSPN = jobProperties.SpnPortFlag;
string jeaEndpoint = jobProperties?.JEAEndpointName ?? "";
string clientMachineName = config.CertificateStoreDetails.ClientMachine;
string storePath = config.CertificateStoreDetails.StorePath;

//_psHelper = new(protocol, port, includePortInSPN, clientMachineName, serverUserName, serverPassword);

_psHelper = new(protocol, port, includePortInSPN, clientMachineName, serverUserName, serverPassword);
_psHelper = new(protocol, port, includePortInSPN, clientMachineName, serverUserName, serverPassword, jeaEndpoint: jeaEndpoint);
_psHelper.Initialize();

using (_psHelper)
Expand Down Expand Up @@ -160,25 +159,25 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
{
case "Success":
psResult = OrchestratorJobStatusJobResult.Success;
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned successfully with Code: {code}, on Step: {step}");
_logger.LogDebug($"PowerShell function New-KeyfactorIISSiteBinding returned successfully with Code: {code}, on Step: {step}");
break;
case "Skipped":
psResult = OrchestratorJobStatusJobResult.Failure;
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} - message:\n {errorMessage}");
failureMessage = ($"PowerShell function New-KeyfactorIISSiteBinding failed on step: {step} - message:\n {errorMessage}");
_logger.LogDebug(failureMessage);
break;
Comment on lines 164 to 168
case "Warning":
psResult = OrchestratorJobStatusJobResult.Warning;
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned with a Warning on step: {step} with code: {code} - message: {message}");
_logger.LogDebug($"PowerShell function New-KeyfactorIISSiteBinding returned with a Warning on step: {step} with code: {code} - message: {message}");
break;
case "Error":
psResult = OrchestratorJobStatusJobResult.Failure;
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} with code: {code} - message: {errorMessage}");
failureMessage = ($"PowerShell function New-KeyfactorIISSiteBinding failed on step: {step} with code: {code} - message: {errorMessage}");
_logger.LogDebug(failureMessage);
break;
default:
psResult = OrchestratorJobStatusJobResult.Unknown;
_logger.LogWarning("Unknown status returned from New-KFIISSiteBinding: " + status);
_logger.LogWarning("Unknown status returned from New-KeyfactorIISSiteBinding: " + status);
break;
}
}
Expand Down Expand Up @@ -294,9 +293,9 @@ private string CreateCSR(string subjectText, string providerName, string keyType
{ "keyLength", keySize },
{ "SAN", SAN }
};
_logger.LogInformation("Attempting to execute PS function (New-CsrEnrollment)");
_results = _psHelper.ExecutePowerShell("New-CsrEnrollment", parameters);
_logger.LogInformation("Returned from executing PS function (New-CsrEnrollment)");
_logger.LogInformation("Attempting to execute PS function (New-KeyfactorODKGEnrollment)");
_results = _psHelper.ExecutePowerShell("New-KeyfactorODKGEnrollment", parameters);
_logger.LogInformation("Returned from executing PS function (New-KeyfactorODKGEnrollment)");

// This should return the CSR that was generated
if (_results == null || _results.Count == 0)
Expand Down Expand Up @@ -356,9 +355,9 @@ private string ImportCertificate(byte[] certificateRawData, string storeName)
{ "storeName", storeName }
};

_logger.LogTrace("Attempting to execute PS function (Import-SignedCertificate)");
_results = _psHelper.ExecutePowerShell("Import-SignedCertificate", parameters);
_logger.LogTrace("Returned from executing PS function (Import-SignedCertificate)");
_logger.LogTrace("Attempting to execute PS function (Import-KeyfactorSignedCertificate)");
_results = _psHelper.ExecutePowerShell("Import-KeyfactorSignedCertificate", parameters);
_logger.LogTrace("Returned from executing PS function (Import-KeyfactorSignedCertificate)");

// This should return the CSR that was generated
if (_results != null && _results.Count > 0)
Expand Down Expand Up @@ -399,7 +398,7 @@ public string ResolveSANString(ReenrollmentJobConfiguration config)
}
else if (config.JobProperties != null &&
config.JobProperties.TryGetValue("SAN", out object legacySanValue) &&
!string.IsNullOrWhiteSpace(legacySanValue.ToString()))
(legacySanValue is not null && !string.IsNullOrWhiteSpace(legacySanValue.ToString())))
{
sanValue = legacySanValue.ToString().Trim();
sourceUsed = "config.JobProperties[\"SAN\"] (legacy)";
Expand Down
10 changes: 5 additions & 5 deletions IISU/ImplementedStoreTypes/Win/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public JobResult ProcessJob(InventoryJobConfiguration jobConfiguration, SubmitIn
settings.IncludePortInSPN = jobProperties.SpnPortFlag;
settings.ServerUserName = serverUserName;
settings.ServerPassword = serverPassword;
settings.JEAEndpointName = jobProperties.JEAEndpointName;

_logger.LogTrace($"Querying Window certificate in store: {storePath}");
inventoryItems = QueryWinCertCertificates(settings, storePath);
Expand Down Expand Up @@ -109,7 +110,7 @@ public JobResult ProcessJob(InventoryJobConfiguration jobConfiguration, SubmitIn
{
_logger.LogTrace(LogHandler.FlattenException(ex));

var failureMessage = $"Inventory job failed for Site '{jobConfiguration.CertificateStoreDetails.StorePath}' on server '{jobConfiguration.CertificateStoreDetails.ClientMachine}' with error: '{LogHandler.FlattenException(ex)}'";
var failureMessage = $"Inventory job failed for Site '{jobConfiguration.CertificateStoreDetails.StorePath}' on server '{jobConfiguration.CertificateStoreDetails.ClientMachine}' with error: '{ex.Message}'";
_logger.LogWarning(failureMessage);

return new JobResult
Expand All @@ -126,7 +127,7 @@ public List<CurrentInventoryItem> QueryWinCertCertificates(RemoteSettings settin
{
List<CurrentInventoryItem> Inventory = new();

using (PSHelper ps = new(settings.Protocol, settings.Port, settings.IncludePortInSPN, settings.ClientMachineName, settings.ServerUserName, settings.ServerPassword))
using (PSHelper ps = new(settings.Protocol, settings.Port, settings.IncludePortInSPN, settings.ClientMachineName, settings.ServerUserName, settings.ServerPassword, jeaEndpoint: settings.JEAEndpointName))
{
ps.Initialize();

Expand All @@ -135,7 +136,7 @@ public List<CurrentInventoryItem> QueryWinCertCertificates(RemoteSettings settin
{ "StoreName", StoreName }
};

results = ps.ExecutePowerShell("Get-KFCertificates", parameters);
results = ps.ExecutePowerShell("Get-KeyfactorCertificates", parameters);

// If there are certificates, deserialize the results and send them back to command
if (results != null && results.Count > 0)
Expand All @@ -147,8 +148,7 @@ public List<CurrentInventoryItem> QueryWinCertCertificates(RemoteSettings settin
{
var siteSettingsDict = new Dictionary<string, object>
{
{ "ProviderName", cert.ProviderName},
{ "SAN", cert.SAN }
{ "ProviderName", cert.ProviderName}
};

Inventory.Add(
Expand Down
48 changes: 32 additions & 16 deletions IISU/ImplementedStoreTypes/Win/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using Keyfactor.Logging;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Keyfactor.Extensions.Orchestrator.WindowsCertStore.Models;

namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore.WinCert
{
Expand Down Expand Up @@ -88,8 +89,9 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
string protocol = jobProperties?.WinRmProtocol;
string port = jobProperties?.WinRmPort;
bool includePortInSPN = (bool)jobProperties?.SpnPortFlag;
string jeaEndpoint = jobProperties?.JEAEndpointName ?? "";

_psHelper = new(protocol, port, includePortInSPN, _clientMachineName, serverUserName, serverPassword);
_psHelper = new(protocol, port, includePortInSPN, _clientMachineName, serverUserName, serverPassword, jeaEndpoint: jeaEndpoint);

switch (_operationType)
{
Expand Down Expand Up @@ -125,7 +127,7 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
{
_logger.LogTrace(LogHandler.FlattenException(ex));

var failureMessage = $"Management job {_operationType} failed on Store '{_storePath}' on server '{_clientMachineName}' with error: '{LogHandler.FlattenException(ex)}'";
var failureMessage = $"Management job {_operationType} failed on Store '{_storePath}' on server '{_clientMachineName}' with error: '{ex.Message}'";
_logger.LogWarning(failureMessage);

return new JobResult
Expand All @@ -145,7 +147,7 @@ public JobResult AddCertificate(string certificateContents, string privateKeyPas
{
_psHelper.Initialize();

_logger.LogTrace("Attempting to execute PS function (Add-KFCertificateToStore)");
_logger.LogTrace("Attempting to execute PS function (Add-KeyfactorCertificate)");

// Mandatory parameters
var parameters = new Dictionary<string, object>
Expand All @@ -158,20 +160,34 @@ public JobResult AddCertificate(string certificateContents, string privateKeyPas
if (!string.IsNullOrEmpty(privateKeyPassword)) { parameters.Add("PrivateKeyPassword", privateKeyPassword); }
if (!string.IsNullOrEmpty(cryptoProvider)) { parameters.Add("CryptoServiceProvider", cryptoProvider); }

_results = _psHelper.ExecutePowerShell("Add-KFCertificateToStore", parameters);
_logger.LogTrace("Returned from executing PS function (Add-KFCertificateToStore)");
_results = _psHelper.ExecutePowerShell("Add-KeyfactorCertificate", parameters);
_logger.LogTrace("Returned from executing PS function (Add-KeyfactorCertificate)");

// This should return the thumbprint of the certificate
if (_results != null && _results.Count > 0)
{
var thumbprint = _results[0].ToString();
_logger.LogTrace($"Added certificate to store {_storePath}, returned with the thumbprint {thumbprint}");
}
else
ResultObject addResult = ResultObject.FromPSResults(_results);
_logger.LogTrace($"Add-KeyfactorCertificate returned Status={addResult.Status}, Code={addResult.Code}, Step={addResult.Step}, Thumbprint='{addResult.Thumbprint}'");

_psHelper.Terminate();

if (!addResult.IsSuccess)
{
_logger.LogTrace("No results were returned. There could have been an error while adding the certificate. Look in the trace logs for PowerShell information.");
string detail = !string.IsNullOrEmpty(addResult.ErrorMessage)
? addResult.ErrorMessage
: addResult.Message;

string failureMessage =
$"Add certificate to store '{_storePath}' failed at step '{addResult.Step}' (code {addResult.Code}): {detail}";

_logger.LogWarning(failureMessage);

return new JobResult
{
Result = OrchestratorJobStatusJobResult.Failure,
JobHistoryId = _jobHistoryID,
FailureMessage = failureMessage
};
}
_psHelper.Terminate();

_logger.LogTrace($"Added certificate to store {_storePath}, thumbprint {addResult.Thumbprint}");
}

return new JobResult
Expand Down Expand Up @@ -212,8 +228,8 @@ public JobResult RemoveCertificate(string thumbprint)
{ "StorePath", _storePath }
};

_psHelper.ExecutePowerShell("Remove-KFCertificateFromStore", parameters);
_logger.LogTrace("Returned from executing PS function (Remove-KFCertificateFromStore)");
_psHelper.ExecutePowerShell("Remove-KeyfactorCertificate", parameters);
_logger.LogTrace("Returned from executing PS function (Remove-KeyfactorCertificate)");

_psHelper.Terminate();
}
Expand Down
1 change: 0 additions & 1 deletion IISU/ImplementedStoreTypes/Win/WinCertCertificateInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class WinCertCertificateInfo
public string Issuer { get; set; }
public string Thumbprint { get; set; }
public bool HasPrivateKey { get; set; }
public string SAN { get; set; }
public string ProviderName { get; set; }
public string Base64Data { get; set; }
}
Expand Down
1 change: 1 addition & 0 deletions IISU/ImplementedStoreTypes/Win/WinInventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore.WinCert
{
[Obsolete("This class is no longer used and will be removed in a future release.")]
internal class WinInventory : ClientPSCertStoreInventory
{
private ILogger _logger;
Expand Down
3 changes: 1 addition & 2 deletions IISU/ImplementedStoreTypes/WinADFS/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@ public List<CurrentInventoryItem> QueryWinADFSCertificates(RemoteSettings settin
{
var siteSettingsDict = new Dictionary<string, object>
{
{ "ProviderName", cert.ProviderName},
{ "SAN", cert.SAN }
{ "ProviderName", cert.ProviderName}
};

Inventory.Add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ public static void UpdateFarmCertificateSettings(string thumbprint, PSHelper psH
}
}
}
catch (Exception ex)
catch (Exception)
{
throw;
}
Expand Down
2 changes: 1 addition & 1 deletion IISU/ImplementedStoreTypes/WinAdfs/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
{
_logger.LogTrace(LogHandler.FlattenException(ex));

var failureMessage = $"Management job {_operationType} failed on Store '{_storePath}' on server '{_clientMachineName}' with error: '{LogHandler.FlattenException(ex)}'";
var failureMessage = $"Management job {_operationType} failed on Store '{_storePath}' on server '{_clientMachineName}' with error: '{ex.Message}'";
_logger.LogWarning(failureMessage);

return new JobResult
Expand Down
5 changes: 3 additions & 2 deletions IISU/ImplementedStoreTypes/WinIIS/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public JobResult ProcessJob(InventoryJobConfiguration jobConfiguration, SubmitIn
settings.IncludePortInSPN = jobProperties.SpnPortFlag;
settings.ServerUserName = serverUserName;
settings.ServerPassword = serverPassword;
settings.JEAEndpointName = jobProperties.JEAEndpointName;

_logger.LogTrace("Querying IIS Inventory..");
inventoryItems = QueryIISCertificates(settings);
Expand Down Expand Up @@ -127,7 +128,7 @@ public List<CurrentInventoryItem> QueryIISCertificates(RemoteSettings settings)
{
List<CurrentInventoryItem> Inventory = new();

using (PSHelper ps = new(settings.Protocol, settings.Port, settings.IncludePortInSPN, settings.ClientMachineName, settings.ServerUserName, settings.ServerPassword))
using (PSHelper ps = new(settings.Protocol, settings.Port, settings.IncludePortInSPN, settings.ClientMachineName, settings.ServerUserName, settings.ServerPassword, jeaEndpoint: settings.JEAEndpointName))
{
ps.Initialize();

Expand All @@ -142,7 +143,7 @@ public List<CurrentInventoryItem> QueryIISCertificates(RemoteSettings settings)
// results = ps.InvokeFunction("Get-KFIISBoundCertificates");
//}

results = ps.ExecutePowerShell("Get-KFIISBoundCertificates");
results = ps.ExecutePowerShell("Get-KeyfactorIISBoundCertificates");

// If there are certificates, deserialize the results and send them back to command
if (results != null && results.Count > 0)
Expand Down
Loading