Skip to content
Merged

Gsma #75

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6a2cc25
Win cert changes (#49) (#50)
fiddlermikey Apr 12, 2023
5a9c6d4
update workflow (#63)
fiddlermikey Apr 12, 2023
9df6dfa
Fixed missing parameter error when writing out settings to log file.
Apr 26, 2023
a210aa2
Update generated README
Apr 26, 2023
6e42e82
Readme to fixdictionary (#66)
RexWheeler Apr 26, 2023
740021c
Update CHANGELOG.md
RexWheeler Apr 26, 2023
5896aab
Update CHANGELOG.md
rcpokorny Apr 27, 2023
ad8fe78
Added GMSA functionality
bhillkeyfactor May 5, 2023
56f7690
Update generated README
May 5, 2023
2ccafe5
Hook Up Testing Program
bhillkeyfactor May 8, 2023
18132fa
When localhost, no remote connection will be established. Only local…
May 8, 2023
1e7a4e4
Merge branch 'release-2.1.1' into 44692-Add_local_PS_support
May 8, 2023
3091a84
Release 2.1 (#72)
RexWheeler May 8, 2023
55ef6f6
checkpoint
bhillkeyfactor May 10, 2023
6ca058d
Checkpoint
bhillkeyfactor May 10, 2023
0e77d38
Checkpoint
bhillkeyfactor May 10, 2023
f3357cf
Code Cleanup
bhillkeyfactor May 10, 2023
ae7a525
Final Test Cases
bhillkeyfactor May 10, 2023
feb2685
Merged localhost Changes
bhillkeyfactor May 11, 2023
bf15edf
merge localhost and GSMA
bhillkeyfactor May 11, 2023
a1c2f38
Update CHANGELOG.md
bhillkeyfactor May 11, 2023
e167a0e
Update readme_source.md
bhillkeyfactor May 11, 2023
255e437
Update generated README
May 11, 2023
0491502
merge localhost and GSMA
bhillkeyfactor May 11, 2023
9ef433a
Merge branch 'gsma' of https://github.com/Keyfactor/iis-orchestrator …
bhillkeyfactor May 11, 2023
7c4f634
Updated the ChangeLog and ReadMe to relect GMSA and localhost changes.
May 11, 2023
c7cd91f
Update generated README
May 11, 2023
867210d
Simplified ChangeLog message
May 11, 2023
4dfa5fc
Merge branch 'gsma' of https://github.com/Keyfactor/iis-orchestrator …
May 11, 2023
a2eaab0
Update name in manifest, clarify localhost and empty account use in r…
RexWheeler May 11, 2023
032b1c1
Update generated README
May 11, 2023
97c2e77
spelling in changelog
RexWheeler May 11, 2023
840c2c3
Tested 'localhost' connections so not to use WinRM.
May 18, 2023
6c6e391
Merge branch 'gsma' of https://github.com/Keyfactor/iis-orchestrator …
May 18, 2023
0fc9920
Testing issues creating local runspace
May 22, 2023
93b7a0a
Use out of process PowerShell when running locally
RexWheeler May 24, 2023
952fc07
release_dir updated to reflect new build paths for net6.0
May 24, 2023
dcc432c
Update CHANGELOG.md
rcpokorny May 30, 2023
0dfe496
Update CHANGELOG.md
rcpokorny May 30, 2023
bf709cd
Rex wheeler patch 1 (#74)
RexWheeler Jun 1, 2023
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 @@ -24,7 +24,7 @@ jobs:
with:
release_version: ${{ needs.call-create-github-release-workflow.outputs.release_version }}
release_url: ${{ needs.call-create-github-release-workflow.outputs.release_url }}
release_dir: IISU/bin/Release/netcoreapp3.1
release_dir: IISU/bin/Release/net6.0
secrets:
token: ${{ secrets.PRIVATE_PACKAGE_ACCESS }}

Expand Down
17 changes: 15 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
2.2.0
* Added Support for GMSA Account by using no value for ServerUsernanme and ServerPassword. KF Command version 10.2 or later is required to specify empty credentials.
* Added local PowerShell support, triggered when specifying 'localhost' as the client machine while using the IISU or WinCert Orchestrator. This change was tested using KF Command 10.3
* Moved to .NET 6

2.1.1
* Fixed the missing site name error when issuing a WinCert job when writing trace log settings to the log file.
* Several display names changed in the documented certificate store type definitions. There are no changes to the internal type or parameter names, so no migration is necessary for currently configured stores.
* Display name for IISU changed to "IIS Bound Certificate".
* Display name for WinCert changed to "Windows Certificate".
* Display names for several Store and Entry parameters changed to be more descriptive and UI friendly.
* Significant readme cleanup

2.1.0
* Fixed issue that was occuring during renewal when there were bindings outside of http and https like net.tcp
* Fixed issue that was occurring during renewal when there were bindings outside of http and https like net.tcp
* Added PAM registration/initialization documentation in README.md
* Resolved Null HostName error
* Added WinCert Cert Store Type
Expand All @@ -8,7 +21,7 @@

2.0.0
* Add support for reenrollment jobs (On Device Key Generation) with the ability to specify a cryptographic provider. Specification of cryptographic provider allows HSM (Hardware Security Module) use.
* Local PAM Support added (requires Univesal Orchestrator Framework version 10.1)
* Local PAM Support added (requires Universal Orchestrator Framework version 10.1)
* Certificate store type changed from IISBin to IISU. See readme for migration notes.


Expand Down
90 changes: 48 additions & 42 deletions IISU/ClientPSCertStoreReEnrollment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
using System.Management.Automation.Remoting;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.Extensions.Logging;
using Keyfactor.Orchestrators.Extensions.Interfaces;
using System.Linq;
using System.IO;

using Microsoft.PowerShell;

namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore
{
internal class ClientPSCertStoreReEnrollment
Expand All @@ -52,37 +54,28 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
var serverUserName = PAMUtilities.ResolvePAMField(_resolver, _logger, "Server UserName", config.ServerUsername);
var serverPassword = PAMUtilities.ResolvePAMField(_resolver, _logger, "Server Password", config.ServerPassword);



// Extract values necessary to create remote PS connection
JobProperties properties = JsonConvert.DeserializeObject<JobProperties>(config.CertificateStoreDetails.Properties,
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Populate });

WSManConnectionInfo connectionInfo = new WSManConnectionInfo(new Uri($"{properties?.WinRmProtocol}://{config.CertificateStoreDetails.ClientMachine}:{properties?.WinRmPort}/wsman"))
{
IncludePortInSPN = properties.SpnPortFlag
};
var pw = new NetworkCredential(serverUserName, serverPassword).SecurePassword;
_logger.LogTrace($"Credentials: UserName:{serverUserName}");

connectionInfo.Credential = new PSCredential(serverUserName, pw);
_logger.LogTrace($"PSCredential Created {pw}");

// Establish new remote ps session
_logger.LogTrace("Creating remote PS Workspace");
using var runSpace = RunspaceFactory.CreateRunspace(connectionInfo);
_logger.LogTrace("Workspace created");
JobProperties jobProperties = JsonConvert.DeserializeObject<JobProperties>(config.CertificateStoreDetails.Properties,
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Populate });

string protocol = jobProperties.WinRmProtocol;
string port = jobProperties.WinRmPort;
bool IncludePortInSPN = jobProperties.SpnPortFlag;
string clientMachineName = config.CertificateStoreDetails.ClientMachine;
string storePath = config.CertificateStoreDetails.StorePath;

_logger.LogTrace($"Establishing runspace on client machine: {clientMachineName}");
using var runSpace = PsHelper.GetClientPsRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);

_logger.LogTrace("Runspace created");
runSpace.Open();
_logger.LogTrace("Workspace opened");
_logger.LogTrace("Runspace opened");

// NEW
var ps = PowerShell.Create();
PowerShell ps = PowerShell.Create();
ps.Runspace = runSpace;

string CSR = string.Empty;

string storePath = config.CertificateStoreDetails.StorePath;

var subjectText = config.JobProperties["subjectText"];
var providerName = config.JobProperties["ProviderName"];
var keyType = config.JobProperties["keyType"];
Expand All @@ -100,23 +93,23 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit

ps.AddScript("if (Test-Path $csrFilename) { Remove-Item $csrFilename }");

ps.AddScript($"Set-Content $infFilename [NewRequest]");
ps.AddScript($"Add-Content $infFilename 'Subject = \"{subjectText}\"'");
ps.AddScript($"Add-Content $infFilename 'ProviderName = \"{providerName}\"'");
ps.AddScript($"Add-Content $infFilename 'MachineKeySet = True'");
ps.AddScript($"Add-Content $infFilename 'HashAlgorithm = SHA256'");
ps.AddScript($"Add-Content $infFilename 'KeyAlgorithm = {keyType}'");
ps.AddScript($"Add-Content $infFilename 'KeyLength={keySize}'");
ps.AddScript($"Add-Content $infFilename 'KeySpec = 0'");
ps.AddScript($"Set-Content $infFilename -Value [NewRequest]");
ps.AddScript($"Add-Content $infFilename -Value 'Subject = \"{subjectText}\"'");
ps.AddScript($"Add-Content $infFilename -Value 'ProviderName = \"{providerName}\"'");
ps.AddScript($"Add-Content $infFilename -Value 'MachineKeySet = True'");
ps.AddScript($"Add-Content $infFilename -Value 'HashAlgorithm = SHA256'");
ps.AddScript($"Add-Content $infFilename -Value 'KeyAlgorithm = {keyType}'");
ps.AddScript($"Add-Content $infFilename -Value 'KeyLength={keySize}'");
ps.AddScript($"Add-Content $infFilename -Value 'KeySpec = 0'");

if (SAN != null)
{
ps.AddScript($"Add-Content $infFilename '[Extensions]'");
ps.AddScript(@"Add-Content $infFilename '2.5.29.17 = ""{text}""'");
ps.AddScript($"Add-Content $infFilename -Value '[Extensions]'");
ps.AddScript(@"Add-Content $infFilename -Value '2.5.29.17 = ""{text}""'");

foreach (string s in SAN.ToString().Split("&"))
{
ps.AddScript($"Add-Content $infFilename '_continue_ = \"{s + "&"}\"'");
ps.AddScript($"Add-Content $infFilename -Value '_continue_ = \"{s + "&"}\"'");
}
}

Expand Down Expand Up @@ -153,7 +146,7 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit

try
{
ps.AddScript($"$CSR = Get-Content $csrFilename");
ps.AddScript($"$CSR = Get-Content $csrFilename -Raw");
_logger.LogTrace("Attempting to get the contents of the CSR file.");
results = ps.Invoke();
_logger.LogTrace("Finished getting the CSR Contents.");
Expand All @@ -177,14 +170,14 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
results = ps.Invoke();

if (hasError) runSpace.Close();
}

// Get the byte array
var CSRContent = ps.Runspace.SessionStateProxy.GetVariable("CSR").ToString();
}

// Get the byte array
var RawContent = runSpace.SessionStateProxy.GetVariable("CSR");

// Sign CSR in Keyfactor
_logger.LogTrace("Get the signed CSR from KF.");
X509Certificate2 myCert = submitReenrollment.Invoke(CSRContent);
X509Certificate2 myCert = submitReenrollment.Invoke(RawContent.ToString());

if (myCert != null)
{
Expand Down Expand Up @@ -257,6 +250,19 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
};
}

}
catch (PSRemotingTransportException psEx)
{
var failureMessage = $"ReEnrollment job failed for Site '{config.CertificateStoreDetails.StorePath}' on server '{config.CertificateStoreDetails.ClientMachine}' with a PowerShell Transport Exception: {psEx.Message}";
_logger.LogError(failureMessage + LogHandler.FlattenException(psEx));

return new JobResult
{
Result = OrchestratorJobStatusJobResult.Failure,
JobHistoryId = config.JobHistoryId,
FailureMessage = failureMessage
};

}
catch (Exception ex)
{
Expand Down
4 changes: 2 additions & 2 deletions IISU/ClientPSIIManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public ClientPSIIManager(ReenrollmentJobConfiguration config, string serverUsern
bool includePortInSPN = jobProperties.SpnPortFlag;

_logger.LogTrace($"Establishing runspace on client machine: {ClientMachineName}");
_runSpace = PSHelper.GetClientPSRunspace(winRmProtocol, ClientMachineName, winRmPort, includePortInSPN, serverUsername, serverPassword);
_runSpace = PsHelper.GetClientPsRunspace(winRmProtocol, ClientMachineName, winRmPort, includePortInSPN, serverUsername, serverPassword);
}
catch (Exception e)
{
Expand Down Expand Up @@ -144,7 +144,7 @@ public ClientPSIIManager(ManagementJobConfiguration config, string serverUsernam
bool includePortInSPN = jobProperties.SpnPortFlag;

_logger.LogTrace($"Establishing runspace on client machine: {ClientMachineName}");
_runSpace = PSHelper.GetClientPSRunspace(winRmProtocol, ClientMachineName, winRmPort, includePortInSPN, serverUsername, serverPassword);
_runSpace = PsHelper.GetClientPsRunspace(winRmProtocol, ClientMachineName, winRmPort, includePortInSPN, serverUsername, serverPassword);
}
catch (Exception e)
{
Expand Down
2 changes: 1 addition & 1 deletion IISU/ImplementedStoreTypes/Win/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private JobResult PerformInventory(InventoryJobConfiguration config, SubmitInven
if (storePath != null)
{
_logger.LogTrace($"Establishing runspace on client machine: {clientMachineName}");
using var myRunspace = PSHelper.GetClientPSRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
using var myRunspace = PsHelper.GetClientPsRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
myRunspace.Open();

_logger.LogTrace("Runspace is now open");
Expand Down
2 changes: 1 addition & 1 deletion IISU/ImplementedStoreTypes/Win/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
long JobHistoryID = config.JobHistoryId;

_logger.LogTrace($"Establishing runspace on client machine: {clientMachineName}");
myRunspace = PSHelper.GetClientPSRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
myRunspace = PsHelper.GetClientPsRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);

var complete = new JobResult
{
Expand Down
13 changes: 5 additions & 8 deletions IISU/ImplementedStoreTypes/WinIIS/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Net;
using Keyfactor.Logging;
using Keyfactor.Orchestrators.Common.Enums;
using Keyfactor.Orchestrators.Extensions;
using Keyfactor.Orchestrators.Extensions.Interfaces;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;

namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore.IISU
{
Expand All @@ -43,6 +39,7 @@ public JobResult ProcessJob(InventoryJobConfiguration jobConfiguration, SubmitIn
_logger = LogHandler.GetClassLogger<Inventory>();
_logger.MethodEntry();


return PerformInventory(jobConfiguration, submitInventoryUpdate);
}

Expand Down Expand Up @@ -70,14 +67,14 @@ private JobResult PerformInventory(InventoryJobConfiguration config, SubmitInven
if (storePath != null)
{
_logger.LogTrace($"Establishing runspace on client machine: {clientMachineName}");
using var myRunspace = PSHelper.GetClientPSRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
using var myRunspace = PsHelper.GetClientPsRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
myRunspace.Open();

_logger.LogTrace("Runspace is now open");
_logger.LogTrace($"Attempting to read bound IIS certificates from cert store: {storePath}");
WinIISInventory IISInventory = new WinIISInventory(_logger);
inventoryItems = IISInventory.GetInventoryItems(myRunspace, storePath);

_logger.LogTrace($"A total of {inventoryItems.Count} were found");
_logger.LogTrace("Closing runspace...");
myRunspace.Close();
Expand Down
2 changes: 1 addition & 1 deletion IISU/ImplementedStoreTypes/WinIIS/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
long JobHistoryID = config.JobHistoryId;

_logger.LogTrace($"Establishing runspace on client machine: {clientMachineName}");
myRunspace = PSHelper.GetClientPSRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);
myRunspace = PsHelper.GetClientPsRunspace(protocol, clientMachineName, port, IncludePortInSPN, serverUserName, serverPassword);

var complete = new JobResult
{
Expand Down
28 changes: 19 additions & 9 deletions IISU/ImplementedStoreTypes/WinIIS/WinIISInventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Keyfactor.Orchestrators.Common.Enums;
using Keyfactor.Orchestrators.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.PowerShell;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -38,21 +39,30 @@ public List<CurrentInventoryItem> GetInventoryItems(Runspace runSpace, string st
// Contains the inventory items to be sent back to KF
List<CurrentInventoryItem> myBoundCerts = new List<CurrentInventoryItem>();

using (var ps = PowerShell.Create())
using (PowerShell ps2 = PowerShell.Create())
{
ps.Runspace = runSpace;
ps2.Runspace = runSpace;

ps.AddCommand("Import-Module")
.AddParameter("Name", "WebAdministration")
.AddStatement();
if (runSpace.RunspaceIsRemote)
{
ps2.AddCommand("Import-Module")
.AddParameter("Name", "WebAdministration")
.AddStatement();
}
else
{
ps2.AddScript("Set-ExecutionPolicy RemoteSigned");
ps2.AddScript("Import-Module WebAdministration");
//var result = ps.Invoke();
}

var searchScript = "Foreach($Site in get-website) { Foreach ($Bind in $Site.bindings.collection) {[pscustomobject]@{name=$Site.name;Protocol=$Bind.Protocol;Bindings=$Bind.BindingInformation;thumbprint=$Bind.certificateHash;sniFlg=$Bind.sslFlags}}}";
ps.AddScript(searchScript).AddStatement();
var iisBindings = ps.Invoke(); // Responsible for getting all bound certificates for each website
ps2.AddScript(searchScript);
var iisBindings = ps2.Invoke(); // Responsible for getting all bound certificates for each website

if (ps.HadErrors)
if (ps2.HadErrors)
{
var psError = ps.Streams.Error.ReadAll().Aggregate(String.Empty, (current, error) => current + error.ErrorDetails.Message);
var psError = ps2.Streams.Error.ReadAll().Aggregate(String.Empty, (current, error) => current + error.ErrorDetails.Message);
}

if (iisBindings.Count == 0)
Expand Down
Loading