Skip to content

Commit

Permalink
Merge pull request #25 from Keyfactor/release-2.1
Browse files Browse the repository at this point in the history
Merge Release 2.1 to main
  • Loading branch information
fiddlermikey authored Feb 5, 2024
2 parents d7f866d + 9b235b8 commit 1f8e677
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2.1.0
* Added new Custom Field, Link To Issuer, to identify if Managment-Add jobs should attempt to link an added certificate to its issuing certificate if it resides in Netscaler.

2.0.1
* Fixed Issue with Inventory when VServer Cannot be retreived by Citrix API

Expand Down
28 changes: 28 additions & 0 deletions CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Xml.Linq;
Expand Down Expand Up @@ -548,6 +550,27 @@ public void UpdateBindings(string keyPairName, string virtualServerName, string
}
}

public void LinkToIssuer(string cert, string privateKeyPassword, string keyPairName)
{
sslcertificatechain chain = sslcertificatechain.get(_nss, keyPairName);
if (chain.chaincomplete == 1)
{
Logger.LogDebug($"Certificate {keyPairName} already linked to {chain.chainlinked}");
return;
}

if (chain.chainpossiblelinks == null || string.IsNullOrEmpty(chain.chainpossiblelinks[0]) || chain.chainpossiblelinks.Length == 0)
{
string msg = $"Certificate added, but link not performed. No Issuing CA Certificate exists for {keyPairName}.";
Logger.LogWarning(msg);
throw new LinkException(msg);
}

sslcertkey certKey = sslcertkey.get(_nss, keyPairName);
certKey.linkcertkeyname = chain.chainpossiblelinks[0];
sslcertkey.link(_nss, certKey);
}

private (byte[], byte[]) GetPemFromPfx(byte[] pfxBytes, char[] pfxPassword)
{
try
Expand Down Expand Up @@ -859,4 +882,9 @@ public void SaveConfiguration()
}
}
}

public class LinkException : Exception
{
public LinkException(string message) : base(message) { }
}
}
4 changes: 2 additions & 2 deletions CitrixAdcOrchestratorJobExtension/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
_logger.LogDebug("Getting file list...");
var files = store.ListFiles();

Dictionary<string, string> existing = jobConfiguration.LastInventory.ToDictionary(i => i.Alias, i => i.Thumbprints.First());
///////Dictionary<string, string> existing = jobConfiguration.LastInventory.ToDictionary(i => i.Alias, i => i.Thumbprints.First());
// ReSharper disable once CollectionNeverQueried.Local
HashSet<string> processedAliases = new HashSet<string>();

//union the remote keys + last Inventory
List<String> contentsToCheck = files?.Select(x => x.filename).Union(existing.Keys).ToList() ?? new List<string>();
List<String> contentsToCheck = files?.Select(x => x.filename).ToList() ?? new List<string>();

_logger.LogDebug("Getting KeyPair list...");
var keyPairList = store.ListKeyPairs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="Keyfactor.Logging" Version="1.1.1" />
<PackageReference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions" Version="0.7.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.10" />
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.0" />
<PackageReference Include="System.Text.Encodings.Web" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
52 changes: 42 additions & 10 deletions CitrixAdcOrchestratorJobExtension/Management.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.IO;
using static Org.BouncyCastle.Math.EC.ECCurve;
using com.citrix.netscaler.nitro.resource.config.pq;

namespace Keyfactor.Extensions.Orchestrator.CitricAdc
{
Expand Down Expand Up @@ -81,15 +83,15 @@ public JobResult ProcessJob(ManagementJobConfiguration jobConfiguration)
}

private void PerformAdd(CitrixAdcStore store, ManagementJobCertificate cert, string keyPairName,
string virtualServerName, bool overwrite,string sniCert)
string virtualServerName, bool overwrite, string sniCert, bool linkToIssuer)
{
_logger.LogTrace("Enter performAdd");
var alias = cert.Alias;
AddBindCert(store, cert, keyPairName, virtualServerName, overwrite, alias,sniCert);
AddBindCert(store, cert, keyPairName, virtualServerName, overwrite, alias, sniCert, linkToIssuer);
}

private void AddBindCert(CitrixAdcStore store, ManagementJobCertificate cert, string keyPairName,
string virtualServerName, bool overwrite, string alias,string sniCert)
string virtualServerName, bool overwrite, string alias, string sniCert, bool linkToIssuer)
{
var (pemFile, privateKeyFile) =
store.UploadCertificate(cert.Contents, cert.PrivateKeyPassword, alias, overwrite);
Expand All @@ -100,14 +102,19 @@ private void AddBindCert(CitrixAdcStore store, ManagementJobCertificate cert, st

_logger.LogDebug("Updating cert bindings");
//update cert bindings
store.UpdateBindings(keyPairName, virtualServerName,sniCert);
store.UpdateBindings(keyPairName, virtualServerName, sniCert);

if (linkToIssuer)
{
store.LinkToIssuer(cert.Contents, cert.PrivateKeyPassword, keyPairName);
}
}

private void PerformDelete(CitrixAdcStore store, ManagementJobCertificate cert)
{
_logger.LogTrace("Enter PerformDelete");
var sslKeyFile = store.GetKeyPairByName(cert.Alias);

//1. Delete the Keypair
store.DeleteKeyPair(sslKeyFile);

Expand Down Expand Up @@ -137,6 +144,9 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo
var virtualServerName = (string)jobConfiguration.JobProperties["virtualServerName"];
var sniCert = (string)jobConfiguration.JobProperties["sniCert"];

dynamic properties = JsonConvert.DeserializeObject(jobConfiguration.CertificateStoreDetails.Properties.ToString());
var linkToIssuer = properties.linkToIssuer == null || string.IsNullOrEmpty(properties.linkToIssuer.Value) ? false : Convert.ToBoolean(properties.linkToIssuer.Value);

//Check if Keypair name exists, if so, we need to append something to it so we don't get downtime
var keyPairName = jobConfiguration.JobCertificate.Alias;

Expand All @@ -152,7 +162,7 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo
{
_logger.LogDebug($"Begin Add/Enrollment... overwrite: {jobConfiguration.Overwrite}");
PerformAdd(store, jobConfiguration.JobCertificate, keyPairName, virtualServerName,
jobConfiguration.Overwrite, sniCert);
jobConfiguration.Overwrite, sniCert, linkToIssuer);
_logger.LogDebug("End Add/Enrollment...");
}
else
Expand All @@ -178,14 +188,26 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo
if (x?.Thumbprint == _thumbprint)
{
_logger.LogTrace($"Thumbprint Match: {_thumbprint}");
foreach (var sBinding in binding.sslcertkey_sslvserver_binding)
if (binding.sslcertkey_sslvserver_binding == null)
{
_logger.LogTrace(
$"Starting PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}");
$"Starting PerformAdd Binding kp.certkey: {kp.certkey}");
PerformAdd(store, jobConfiguration.JobCertificate, kp.certkey,
sBinding.servername, true,sniCert);
virtualServerName, true, sniCert, linkToIssuer);
_logger.LogTrace(
$"Finished PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}");
$"Finished PerformAdd kp.certkey: {kp.certkey}");
}
else
{
foreach (var sBinding in binding.sslcertkey_sslvserver_binding)
{
_logger.LogTrace(
$"Starting PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}");
PerformAdd(store, jobConfiguration.JobCertificate, kp.certkey,
sBinding.servername, true, sniCert, linkToIssuer);
_logger.LogTrace(
$"Finished PerformAdd Binding Name: {sBinding.servername} kp.certkey: {kp.certkey}");
}
}
}
}
Expand Down Expand Up @@ -223,6 +245,16 @@ private JobResult ProcessJob(CitrixAdcStore store, ManagementJobConfiguration jo
};
}
}
catch (LinkException ex)
{
//Status: 2=Success, 3=Warning, 4=Error
return new JobResult
{
Result = OrchestratorJobStatusJobResult.Warning,
JobHistoryId = jobConfiguration.JobHistoryId,
FailureMessage = ex.Message
};
}
catch (Exception ex)
{
//Status: 2=Success, 3=Warning, 4=Error
Expand Down
Binary file modified Images/CertStore.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/CertStoreTypeSettings.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

# Citrix Netscaler Universal Orchestrator

Orchestrator to manage certificates and keys on one to many VServers in Netscaler. The integration supports Enrollment, Renewal, Inventory and Remove from Store.

#### Integration status: Production - Ready for use in production environments.


## About the Keyfactor Universal Orchestrator Extension

This repository contains a Universal Orchestrator Extension which is a plugin to the Keyfactor Universal Orchestrator. Within the Keyfactor Platform, Orchestrators are used to manage “certificate stores” &mdash; collections of certificates and roots of trust that are found within and used by various applications.
Expand All @@ -13,23 +13,22 @@ The Universal Orchestrator is part of the Keyfactor software distribution and is

The Universal Orchestrator is the successor to the Windows Orchestrator. This Orchestrator Extension plugin only works with the Universal Orchestrator and does not work with the Windows Orchestrator.


## Support for Citrix Netscaler Universal Orchestrator

Citrix Netscaler Universal Orchestrator is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com

###### To report a problem or suggest a new feature, use the **[Issues](../../issues)** tab. If you want to contribute actual bug fixes or proposed enhancements, use the **[Pull requests](../../pulls)** tab.


---


---



## Keyfactor Version Supported

The minimum version of the Keyfactor Universal Orchestrator Framework needed to run this version of the extension is 10.1

## Platform Specific Notes

The Keyfactor Universal Orchestrator may be installed on either Windows or Linux based platforms. The certificate operations supported by a capability may vary based what platform the capability is installed on. The table below indicates what capabilities are supported based on which platform the encompassing Universal Orchestrator is running.
Expand Down Expand Up @@ -155,6 +154,9 @@ Allow
* When performing management operations to either of services, Users may enter the specific VServer name to complete the operation.

**NOTE:** If multiple VServers share the same Alias, all VServers that share that alias will be updated.

* Supports optional linking of added certificates to issuing CA certificate if issuing CA is already installed in the managed Netscaler instance.

<details>
<summary>Cert Store Type Settings</summary>
<br />
Expand Down Expand Up @@ -191,6 +193,7 @@ Name|Display Name|Type|Default Value|Required|Description
ServerUsername|Server Username|Secret||No|The username to log into the Server
ServerPassword|Server Password|Secret||No|The password that matches the username to log into the Server
ServerUseSsl|Use SSL|Bool|True|Yes|Determine whether the server uses SSL or not
linkToIssuer|Link To Issuer|Bool|False|False|Determines whether attempt will be made to link certificate added via a Management-Add job to its issuing CA certificate

**Entry Parameters**

Expand Down
8 changes: 8 additions & 0 deletions integration-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@
"DependsOn": null,
"DefaultValue": "true",
"Required": true
},
{
"Name": "linkToIssuer",
"DisplayName": "Link To Issuer",
"Type": "Bool",
"DependsOn": null,
"DefaultValue": "false",
"Required": false
}
],
"EntryParameters": [
Expand Down
4 changes: 4 additions & 0 deletions readme_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ Allow
* When performing management operations to either of services, Users may enter the specific VServer name to complete the operation.

**NOTE:** If multiple VServers share the same Alias, all VServers that share that alias will be updated.

* Supports optional linking of added certificates to issuing CA certificate if issuing CA is already installed in the managed Netscaler instance.

<details>
<summary>Cert Store Type Settings</summary>
<br />
Expand Down Expand Up @@ -90,6 +93,7 @@ Name|Display Name|Type|Default Value|Required|Description
ServerUsername|Server Username|Secret||No|The username to log into the Server
ServerPassword|Server Password|Secret||No|The password that matches the username to log into the Server
ServerUseSsl|Use SSL|Bool|True|Yes|Determine whether the server uses SSL or not
linkToIssuer|Link To Issuer|Bool|False|False|Determines whether attempt will be made to link certificate added via a Management-Add job to its issuing CA certificate

**Entry Parameters**

Expand Down

0 comments on commit 1f8e677

Please sign in to comment.