Skip to content

Commit 1d6433c

Browse files
author
Bob Pokorny
committed
#137 Updated PS Scripts to check for existing bindings and resolve binding IIS certificates for machine with or without WebAdministrator module.
1 parent 7768870 commit 1d6433c

File tree

6 files changed

+642
-73
lines changed

6 files changed

+642
-73
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* fix a naming typo in the 2.5 migration SQL script
44
* update integration-manifest.json
55
* Updated the Alias in IIS to also include Site-Name. NOTE: Inventory will need to be performed prior to any management job to include new Alias format.
6+
* Added Bindings check when attempting to add bindings that already exist. NOTE: If you wish to add multiple bindings with the same IP:Port, Hostname must be included and SNI flag must be set to a minimum of '1'.
67

78
2.6.0
89
* Added the ability to run the extension in a Linux environment. To utilize this change, for each Cert Store Types (WinCert/WinIIS/WinSQL), add ssh to the Custom Field <b>WinRM Protocol</b>. When using ssh as a protocol, make sure to enter the appropriate ssh port number under WinRM Port.

IISU/ClientPSCertStoreReEnrollment.cs

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
using System.Linq;
3131
using Keyfactor.Extensions.Orchestrator.WindowsCertStore.IISU;
3232
using Keyfactor.Extensions.Orchestrator.WindowsCertStore.WinSql;
33+
using System.Numerics;
3334

3435
namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore
3536
{
@@ -127,10 +128,68 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
127128
switch (bindingType)
128129
{
129130
case CertStoreBindingTypeENUM.WinIIS:
131+
OrchestratorJobStatusJobResult psResult = OrchestratorJobStatusJobResult.Unknown;
132+
string failureMessage = "";
133+
130134
// Bind Certificate to IIS Site
131135
IISBindingInfo bindingInfo = new IISBindingInfo(config.JobProperties);
132-
WinIISBinding.BindCertificate(_psHelper, bindingInfo, thumbprint, "", storePath);
136+
var results = WinIISBinding.BindCertificate(_psHelper, bindingInfo, thumbprint, "", storePath);
137+
if (results != null && results.Count > 0)
138+
{
139+
if (results[0] != null && results[0].Properties["Status"] != null)
140+
{
141+
string status = results[0].Properties["Status"]?.Value as string ?? string.Empty;
142+
int code = results[0].Properties["Code"]?.Value is int iCode ? iCode : -1;
143+
string step = results[0].Properties["Step"]?.Value as string ?? string.Empty;
144+
string message = results[0].Properties["Message"]?.Value as string ?? string.Empty;
145+
string errorMessage = results[0].Properties["ErrorMessage"]?.Value as string ?? string.Empty;
146+
147+
switch (status)
148+
{
149+
case "Success":
150+
psResult = OrchestratorJobStatusJobResult.Success;
151+
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned successfully with Code: {code}, on Step: {step}");
152+
break;
153+
case "Skipped":
154+
psResult = OrchestratorJobStatusJobResult.Failure;
155+
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} - message:\n {errorMessage}");
156+
_logger.LogDebug(failureMessage);
157+
break;
158+
case "Warning":
159+
psResult = OrchestratorJobStatusJobResult.Warning;
160+
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned with a Warning on step: {step} with code: {code} - message: {message}");
161+
break;
162+
case "Error":
163+
psResult = OrchestratorJobStatusJobResult.Failure;
164+
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} with code: {code} - message: {errorMessage}");
165+
_logger.LogDebug(failureMessage);
166+
break;
167+
default:
168+
psResult = OrchestratorJobStatusJobResult.Unknown;
169+
_logger.LogWarning("Unknown status returned from New-KFIISSiteBinding: " + status);
170+
break;
171+
}
172+
}
173+
else
174+
{
175+
_logger.LogWarning("Unexpected object returned from PowerShell.");
176+
psResult = OrchestratorJobStatusJobResult.Unknown;
177+
}
178+
}
179+
else
180+
{
181+
_logger.LogWarning("PowerShell script returned with no results.");
182+
psResult = OrchestratorJobStatusJobResult.Unknown;
183+
}
184+
185+
jobResult = new JobResult
186+
{
187+
Result = psResult,
188+
JobHistoryId = config.JobHistoryId,
189+
FailureMessage = failureMessage
190+
};
133191
break;
192+
134193
case CertStoreBindingTypeENUM.WinSQL:
135194
// Bind Certificate to SQL Instance
136195
string sqlInstanceNames = "MSSQLSERVER";
@@ -139,18 +198,26 @@ public JobResult PerformReEnrollment(ReenrollmentJobConfiguration config, Submit
139198
sqlInstanceNames = config.JobProperties["InstanceName"]?.ToString() ?? "MSSQLSERVER";
140199
}
141200
WinSqlBinding.BindSQLCertificate(_psHelper, sqlInstanceNames, thumbprint, "", storePath, false);
201+
202+
jobResult = new JobResult
203+
{
204+
Result = OrchestratorJobStatusJobResult.Success,
205+
JobHistoryId = config.JobHistoryId,
206+
FailureMessage = ""
207+
};
208+
142209
break;
143210
}
144-
145211
}
146-
147-
jobResult = new JobResult
212+
else
148213
{
149-
Result = OrchestratorJobStatusJobResult.Success,
150-
JobHistoryId = config.JobHistoryId,
151-
FailureMessage = ""
152-
};
153-
214+
jobResult = new JobResult
215+
{
216+
Result = OrchestratorJobStatusJobResult.Failure,
217+
JobHistoryId = config.JobHistoryId,
218+
FailureMessage = "There was no thumbprint to bind."
219+
};
220+
}
154221
}
155222
else
156223
{

IISU/ImplementedStoreTypes/WinIIS/Management.cs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616
using System.Collections.Generic;
1717
using System.Collections.ObjectModel;
1818
using System.Management.Automation;
19+
using Keyfactor.Extensions.Orchestrator.WindowsCertStore.Models;
1920
using Keyfactor.Logging;
2021
using Keyfactor.Orchestrators.Common.Enums;
2122
using Keyfactor.Orchestrators.Extensions;
2223
using Keyfactor.Orchestrators.Extensions.Interfaces;
24+
using Microsoft.CodeAnalysis.CSharp.Syntax;
2325
using Microsoft.Extensions.Logging;
26+
using Microsoft.PowerShell.Commands;
2427
using Newtonsoft.Json;
2528

2629
namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore.IISU
@@ -101,6 +104,9 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
101104
// Add Certificate to Cert Store
102105
try
103106
{
107+
OrchestratorJobStatusJobResult psResult = OrchestratorJobStatusJobResult.Unknown;
108+
string failureMessage = "";
109+
104110
string newThumbprint = AddCertificate(certificateContents, privateKeyPassword, cryptoProvider);
105111
_logger.LogTrace($"Completed adding the certificate to the store");
106112
_logger.LogTrace($"New thumbprint: {newThumbprint}");
@@ -109,15 +115,61 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
109115
if (newThumbprint != null)
110116
{
111117
IISBindingInfo bindingInfo = new IISBindingInfo(config.JobProperties);
112-
WinIISBinding.BindCertificate(_psHelper, bindingInfo, newThumbprint, "", _storePath);
113-
114118
_logger.LogTrace("Returned after binding certificate to store");
119+
var results = WinIISBinding.BindCertificate(_psHelper, bindingInfo, newThumbprint, "", _storePath);
120+
if (results != null && results.Count > 0)
121+
{
122+
if (results[0] != null && results[0].Properties["Status"] != null)
123+
{
124+
string status = results[0].Properties["Status"]?.Value as string ?? string.Empty;
125+
int code = results[0].Properties["Code"]?.Value is int iCode ? iCode : -1;
126+
string step = results[0].Properties["Step"]?.Value as string ?? string.Empty;
127+
string message = results[0].Properties["Message"]?.Value as string ?? string.Empty;
128+
string errorMessage = results[0].Properties["ErrorMessage"]?.Value as string ?? string.Empty;
129+
130+
switch (status)
131+
{
132+
case "Success":
133+
psResult = OrchestratorJobStatusJobResult.Success;
134+
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned successfully with Code: {code}, on Step: {step}");
135+
break;
136+
case "Skipped":
137+
psResult = OrchestratorJobStatusJobResult.Failure;
138+
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} - message:\n {errorMessage}");
139+
_logger.LogDebug(failureMessage);
140+
break;
141+
case "Warning":
142+
psResult = OrchestratorJobStatusJobResult.Warning;
143+
_logger.LogDebug($"PowerShell function New-KFIISSiteBinding returned with a Warning on step: {step} with code: {code} - message: {message}");
144+
break;
145+
case "Error":
146+
psResult = OrchestratorJobStatusJobResult.Failure;
147+
failureMessage = ($"PowerShell function New-KFIISSiteBinding failed on step: {step} with code: {code} - message: {errorMessage}");
148+
_logger.LogDebug(failureMessage);
149+
break;
150+
default:
151+
psResult = OrchestratorJobStatusJobResult.Unknown;
152+
_logger.LogWarning("Unknown status returned from New-KFIISSiteBinding: " + status);
153+
break;
154+
}
155+
}
156+
else
157+
{
158+
_logger.LogWarning("Unexpected object returned from PowerShell.");
159+
psResult = OrchestratorJobStatusJobResult.Unknown;
160+
}
161+
}
162+
else
163+
{
164+
_logger.LogWarning("PowerShell script returned with no results.");
165+
psResult = OrchestratorJobStatusJobResult.Unknown;
166+
}
115167

116168
complete = new JobResult
117169
{
118-
Result = OrchestratorJobStatusJobResult.Success,
170+
Result = psResult,
119171
JobHistoryId = _jobHistoryID,
120-
FailureMessage = ""
172+
FailureMessage = failureMessage
121173
};
122174
}
123175
}

IISU/ImplementedStoreTypes/WinIIS/WinIISBinding.cs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class WinIISBinding
2929
private static Collection<PSObject>? _results = null;
3030
private static PSHelper _helper;
3131

32-
public static void BindCertificate(PSHelper psHelper, IISBindingInfo bindingInfo, string thumbprint, string renewalThumbprint, string storePath)
32+
public static Collection<PSObject> BindCertificate(PSHelper psHelper, IISBindingInfo bindingInfo, string thumbprint, string renewalThumbprint, string storePath)
3333
{
3434
_logger = LogHandler.GetClassLogger(typeof(WinIISBinding));
3535
_logger.LogTrace("Attempting to bind and execute PS function (New-KFIISSiteBinding)");
@@ -51,32 +51,7 @@ public static void BindCertificate(PSHelper psHelper, IISBindingInfo bindingInfo
5151

5252
try
5353
{
54-
_results = psHelper.ExecutePowerShell("New-KFIISSiteBinding", parameters); // returns true if successful
55-
_logger.LogTrace("Returned from executing PS function (New-KFIISSiteBinding)");
56-
57-
if (_results != null && _results.Count > 0)
58-
{
59-
var baseObject = _results[0]?.BaseObject;
60-
if (baseObject is bool value)
61-
{
62-
if (value)
63-
{
64-
_logger.LogTrace($"Bound certificate with the thumbprint: '{thumbprint}' to site: '{bindingInfo.SiteName}' successfully.");
65-
}
66-
else
67-
{
68-
_logger.LogTrace("Something happened and the binding failed.");
69-
}
70-
}
71-
else
72-
{
73-
_logger.LogWarning("Unexpected result type returned from script: " + baseObject?.GetType().Name);
74-
}
75-
}
76-
else
77-
{
78-
_logger.LogWarning("PowerShell script returned no results.");
79-
}
54+
return psHelper.ExecutePowerShell("New-KFIISSiteBinding", parameters); // returns true if successful
8055
}
8156
catch (Exception ex)
8257
{

IISU/Models/ResultObject.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Keyfactor.Extensions.Orchestrator.WindowsCertStore.Models
8+
{
9+
public class ResultObject
10+
{
11+
public string Status { get; set; }
12+
public int Code { get; set; }
13+
public string Step { get; set; }
14+
public string Message { get; set; }
15+
public string ErrorMessage { get; set; }
16+
public Dictionary<string, object> Details { get; set; }
17+
}
18+
}

0 commit comments

Comments
 (0)