Skip to content

Commit

Permalink
ab#61881
Browse files Browse the repository at this point in the history
  • Loading branch information
leefine02 authored and leefine02 committed Aug 19, 2024
1 parent fe29494 commit aa11837
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 121 deletions.
98 changes: 15 additions & 83 deletions CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -759,120 +759,52 @@ public X509Certificate2 GetX509Certificate(sslcertkey certificate)
{
Logger.MethodEntry(LogLevel.Debug);

systemfile f;
string[] privateKeyDelims = new string[3] { "-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN PRIVATE KEY-----", "-----BEGIN ENCRYPTED PRIVATE KEY-----" };

string certString = null;
string keyString = null;
X509Certificate2 x509Cert = null;

try
{
Logger.LogTrace($"Trying GetSystemFile(fileLocation): {fileLocation}");
f = GetSystemFile(fileLocation);
Logger.LogTrace($"Finished GetSystemFile(fileLocation): {fileLocation}");
}
catch
{
Logger.LogError("Error Occurred in GetSystemFile(fileLocation)");
hasKey = false;
return null;
}
Logger.LogTrace($"Trying GetSystemFile(fileLocation): {certificate.cert}");
systemfile f = GetSystemFile(certificate.cert);
Logger.LogTrace($"Finished GetSystemFile(fileLocation): {certificate.cert}");

//Ignore Directories
if (f.filemode != null && f.filemode[0].ToUpper() == "DIRECTORY")
{
hasKey = false;
return null;
}

// Determine if it's a cert
X509Certificate2 x = null;
try
{
var b = Convert.FromBase64String(f.filecontent);
var fileString = Encoding.Default.GetString(b);

// Check if private key is included with certificate
var privateKeyIdx = -1;
foreach(string privateKeyDelim in privateKeyDelims)
{
if (fileString.IndexOf(privateKeyDelim, StringComparison.Ordinal) >= 0)
privateKeyIdx = Array.IndexOf(privateKeyDelims, privateKeyDelim);
}

var containsCert = fileString.IndexOf("-----BEGIN CERTIFICATE-----", StringComparison.Ordinal) >= 0;
string endDelim = "-----END CERTIFICATE-----";
int startIdx = fileString.IndexOf("-----BEGIN CERTIFICATE-----", StringComparison.Ordinal);
int endIdx = fileString.IndexOf(endDelim, StringComparison.Ordinal);

Logger.LogTrace($"containsKey: {privateKeyIdx > -1} containsCert: {containsCert}");

if (containsCert && privateKeyIdx > -1)
{
Logger.LogTrace($"File contains certificate and key: {fileLocation}");

var keyStart = fileString.IndexOf(privateKeyDelims[privateKeyIdx], StringComparison.Ordinal);
var keyEnd = fileString.IndexOf(privateKeyDelims[privateKeyIdx].Replace("BEGIN","END"), StringComparison.Ordinal) +
privateKeyDelims[privateKeyIdx].Replace("BEGIN", "END").Length;

// check if need to remove new line
keyString = fileString.Substring(keyStart, keyEnd - keyStart);
certString = fileString.Remove(keyStart, keyEnd - keyStart);
}
else if (containsCert)
if (startIdx == -1 || endIdx == -1)
{
Logger.LogTrace("containsCert");
certString = fileString;
// check .key file
try
{
var fileNameWithoutExtension = fileLocation;
if (fileLocation.EndsWith(".crt",StringComparison.CurrentCultureIgnoreCase) ||
fileLocation.EndsWith(".cer", StringComparison.CurrentCultureIgnoreCase) ||
fileLocation.EndsWith(".pem", StringComparison.CurrentCultureIgnoreCase) ||
fileLocation.EndsWith(".pfx", StringComparison.CurrentCultureIgnoreCase) ||
fileLocation.EndsWith(".cert", StringComparison.CurrentCultureIgnoreCase) ||
fileLocation.EndsWith(".der", StringComparison.CurrentCultureIgnoreCase))
{
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileLocation);
}
var keyFile = GetSystemFile(fileNameWithoutExtension + ".key");
keyString = Encoding.UTF8.GetString(Convert.FromBase64String(keyFile.filecontent));
}
catch (Exception e)
{
Logger.LogError("Unable to evaluate private key - " + LogHandler.FlattenException(e));
}
Logger.LogWarning($"Certificate {certificate.certkey} does not contain a valid PEM formatted certificate");
}

certString = fileString.Substring(startIdx, endIdx - startIdx + endDelim.Length);

if (certString == null)
{
hasKey = false;
return null;
}

try
{
x = ReadX509Certificate(certString);
x509Cert = ReadX509Certificate(certString);
}
catch (Exception e)
{
// Not a certificate file
Logger.LogError($"Error reading x509Certificate at {fileLocation}");
Logger.LogError(LogHandler.FlattenException(e));
hasKey = false;
Logger.LogError($"Error reading converting {certificate.certkey} to X509 certificate format: {LogHandler.FlattenException(e)}");
return null;
}

hasKey = !string.IsNullOrEmpty(keyString);
}
catch (Exception e)
{
// Not a certificate file
Logger.LogError($"{fileLocation} is not a certificate");
Logger.LogError(LogHandler.FlattenException(e));
hasKey = false;
Logger.LogError($"Error reading/processing certificate {certificate.certkey}: {LogHandler.FlattenException(e)}");
}

Logger.MethodExit(LogLevel.Debug);
return x;
return x509Cert;
}

private systemfile GetSystemFile(string fileName)
Expand Down
43 changes: 9 additions & 34 deletions CitrixAdcOrchestratorJobExtension/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,39 +94,17 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
foreach (sslcertkey certificate in certificates)
{
_logger.LogDebug($"Retrieving certificate file: {certificate.cert} for alias {certificate.certkey}");
X509Certificate2 x = store.GetX509Certificate(s, out bool privateKeyEntry);
X509Certificate2 x = store.GetX509Certificate(certificate);

if (x == null) continue;

_logger.LogTrace($"##### privateKeyEntry: {privateKeyEntry.ToString()}");
if (!privateKeyEntry)
{
var certKey = keyPairList.FirstOrDefault(p => p.cert == s);
_logger.LogTrace($"##### certKey: {certKey}");
privateKeyEntry = certKey != null && !string.IsNullOrEmpty(certKey.key);
}
_logger.LogTrace($"##### privateKeyEntry: {privateKeyEntry.ToString()}");

processedAliases.Add(s);

Dictionary<string, object> parameters = new Dictionary<string, object>();

string tempStorePath = store.StorePath.Substring(store.StorePath.Length-1,1) == "/" ? store.StorePath : store.StorePath + "/";
var containsKeyWithPath = keyPairMap.ContainsKey(tempStorePath + s);
var containsKey = keyPairMap.ContainsKey(s);

_logger.LogTrace($"##### containsKeyWithPath: {containsKeyWithPath.ToString()}");
_logger.LogTrace($"##### containsKey: {containsKey.ToString()}");


if (containsKey || containsKeyWithPath)
if (certificate.key != null)
{
var keyPairName = containsKeyWithPath ? keyPairMap[tempStorePath + s] : keyPairMap[s];

_logger.LogDebug($"Found keyPairName: {keyPairName}");
parameters.Add("keyPairName", keyPairName);
parameters.Add("keyPairName", certificate.certkey);

var binding = store.GetBinding(keyPairName);
var binding = store.GetBinding(certificate.certkey);

var vserverBindings = binding?.sslcertkey_sslvserver_binding;
if (vserverBindings != null)
Expand All @@ -140,7 +118,7 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
foreach (string server in virtualServerName.Split(','))
{
var bindings = store.GetBindingByVServer(server);
var first = bindings.FirstOrDefault(b => b.certkeyname == keyPairName);
var first = bindings.FirstOrDefault(b => b.certkeyname == certificate.certkey);
if (first != null) bindingsCsv += first.snicert + ",";
}
parameters.Add("sniCert", bindingsCsv.TrimEnd(','));
Expand All @@ -155,18 +133,16 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job

inventory.Add(new CurrentInventoryItem()
{
Alias = s,
Alias = certificate.certkey,
Certificates = new[] { Convert.ToBase64String(x.GetRawCertData()) },
//ItemStatus = itemStatus,
PrivateKeyEntry = privateKeyEntry,
PrivateKeyEntry = certificate.key != null,
UseChainLevel = false,
Parameters = parameters
});
}
_logger.LogDebug($"Found {inventory.Count} certificates at {jobConfiguration.CertificateStoreDetails.StorePath}");


}

catch (Exception ex)
{
_logger.LogError("Error performing certificate Inventory: " + ex.Message);
Expand All @@ -177,14 +153,13 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
{
Result = Orchestrators.Common.Enums.OrchestratorJobStatusJobResult.Failure,
JobHistoryId = jobConfiguration.JobHistoryId,
FailureMessage = "Error while performing certificate Inventory"
FailureMessage = "Error while performing certificate Inventory" + ex.Message
};
}

try
{
_logger.LogDebug("Sending results back to command");
//Sends inventoried certificates back to KF Command
submitInventoryUpdate.Invoke(inventory);

_logger.LogDebug("Successfully Completed Job");
Expand Down
6 changes: 2 additions & 4 deletions CitrixAdcOrchestratorJobExtension/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,15 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo
{
//PerformRenewal
//1. Get All Keys /config/sslcertkey store.ListKeyPairs()
var keyPairList = store.ListKeyPairs();
var keyPairList = store.GetCertificates();

_logger.LogTrace($"KeyPairList: {JsonConvert.SerializeObject(keyPairList)}");

//2. For Each check the binding /config/sslcertkey_binding store.GetBinding(strKey)
foreach (var kp in keyPairList)
{
//4. Open the file and check the thumbprint
var x = store.GetX509Certificate(
kp.cert.Substring(kp.cert.LastIndexOf("/", StringComparison.Ordinal) + 1),
out _);
var x = store.GetX509Certificate(kp);

//5. If the Thumbprint matches the cert renewed from KF then PerformAdd With Overwrite
if (x?.Thumbprint == _thumbprint)
Expand Down

0 comments on commit aa11837

Please sign in to comment.