Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Keyandbindingfixes (#13)" #15

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 0 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
2.0.1
* Fixed Issue with Inventory when VServer Cannot be retreived by Citrix API

2.0.0
* Added AutoSave Configuration (default set to false)
* Added PAM Support
Expand Down
20 changes: 6 additions & 14 deletions CitrixAdcOrchestratorJobExtension/CitrixAdcStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ private string UpdateKeyPair(string keyPairName, string certPath, string keyPath
catch (nitro_exception ne)
{
Logger.LogError($"Exception occured while trying to add or update {keyPairName}");
if ((((uint)ne.HResult).Equals(0x80138500) || ((uint)ne.HResult).Equals(0x80131500)) &&
if ((((uint) ne.HResult).Equals(0x80138500) || ((uint) ne.HResult).Equals(0x80131500)) &&
ne.Message.Contains("Resource already exists"))
{
if (ne.Message.Contains("certkeyName Contents,"))
Expand Down Expand Up @@ -663,13 +663,6 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey)
return null;
}

//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
Expand Down Expand Up @@ -702,8 +695,7 @@ public X509Certificate2 GetX509Certificate(string fileLocation, out bool hasKey)
// check .key file
try
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileLocation);
var keyFile = GetSystemFile(fileNameWithoutExtension + ".key");
var keyFile = GetSystemFile(fileLocation + ".key");
keyString = Encoding.UTF8.GetString(Convert.FromBase64String(keyFile.filecontent));
}
catch (Exception e)
Expand Down Expand Up @@ -755,7 +747,7 @@ private systemfile GetSystemFile(string fileName)

//option.set_args($"filelocation:{urlPath},filename:{fileName}");
option.filelocation = StorePath;
var f = new systemfile { filelocation = StorePath, filename = fileName };
var f = new systemfile {filelocation = StorePath, filename = fileName};
var result = systemfile.get(_nss, f);
Logger.LogDebug("Exiting GetSystemFile(string fileName)");
return result;
Expand Down Expand Up @@ -828,10 +820,10 @@ private bool EvaluatePrivateKey(X509Certificate2 cert, string keyString)
if (string.IsNullOrEmpty(keyString)) return false;
try
{
var keypair = (AsymmetricCipherKeyPair)new PemReader(new StringReader(keyString)).ReadObject();
var privateKey = (RsaPrivateCrtKeyParameters)keypair.Private;
var keypair = (AsymmetricCipherKeyPair) new PemReader(new StringReader(keyString)).ReadObject();
var privateKey = (RsaPrivateCrtKeyParameters) keypair.Private;

var publicKey = (RsaKeyParameters)DotNetUtilities.FromX509Certificate(cert).GetPublicKey();
var publicKey = (RsaKeyParameters) DotNetUtilities.FromX509Certificate(cert).GetPublicKey();
Logger.LogDebug("Exiting EvaluatePrivateKey(X509Certificate2 cert, string keyString)");

return privateKey.Modulus.Equals(publicKey.Modulus) &&
Expand Down
36 changes: 14 additions & 22 deletions CitrixAdcOrchestratorJobExtension/Inventory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public JobResult ProcessJob(InventoryJobConfiguration jobConfiguration, SubmitIn


_logger.LogDebug("Entering ProcessJob");
CitrixAdcStore store = new CitrixAdcStore(jobConfiguration, ServerUserName, ServerPassword);
CitrixAdcStore store = new CitrixAdcStore(jobConfiguration,ServerUserName,ServerPassword);

_logger.LogDebug("Logging into Citrix...");
store.Login();
Expand All @@ -76,8 +76,8 @@ private string ResolvePamField(string name, string value)

private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration jobConfiguration, SubmitInventoryUpdate submitInventoryUpdate)
{
_logger.LogDebug("Begin New Bindings Fix Inventory...");

_logger.LogDebug("Begin Inventory...");
List<CurrentInventoryItem> inventory = new List<CurrentInventoryItem>();

try
Expand Down Expand Up @@ -109,7 +109,7 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job

processedAliases.Add(s);

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

var containsKeyWithPath = keyPairMap.ContainsKey(store.StorePath + "/" + s);
var containsKey = keyPairMap.ContainsKey(s);
Expand All @@ -126,25 +126,17 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
var vserverBindings = binding?.sslcertkey_sslvserver_binding;
if (vserverBindings != null)
{
try
{
var virtualServerName = String.Join(",", vserverBindings.Select(p => p.servername));
_logger.LogDebug($"Found virtualServerName(s): {virtualServerName}");
parameters.Add("virtualServerName", virtualServerName);
string bindingsCsv = string.Empty;
foreach (string server in virtualServerName.Split(','))
{
var bindings = store.GetBindingByVServer(server);
var first = bindings.FirstOrDefault(b => b.certkeyname == keyPairName);
if (first != null) bindingsCsv += first.snicert + ",";
}
parameters.Add("sniCert", bindingsCsv.TrimEnd(','));
}
catch (Exception e)
var virtualServerName = String.Join(",", vserverBindings.Select(p => p.servername));
_logger.LogDebug($"Found virtualServerName(s): {virtualServerName}");
parameters.Add("virtualServerName", virtualServerName);
string bindingsCsv = string.Empty;
foreach (string server in virtualServerName.Split(','))
{
_logger.LogError($"Error handling SNI or VServerBindings {LogHandler.FlattenException(e)}");
var bindings = store.GetBindingByVServer(server);
var first = bindings.FirstOrDefault(b => b.certkeyname == keyPairName);
if (first != null) bindingsCsv += first.snicert + ",";
}

parameters.Add("sniCert", bindingsCsv.TrimEnd(','));
}
}

Expand Down Expand Up @@ -206,4 +198,4 @@ private JobResult ProcessJob(CitrixAdcStore store, InventoryJobConfiguration job
}
}
}
}
}
152 changes: 75 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,55 +102,6 @@ This text would be entered in as the value for the __Server Password__, instead
---


# Citrix ADC Orchestrator Configuration
## Overview

The Citrix ADC Orchestrator remotely manages certificates on the NetScaler device. Since the ADC supports services including:
Load Balancing, Authentication/Authorization/Auditing (AAA), and Gateways, this orchestrator can bind to any of these virtual servers when using unique virtual server names for each service.

### Permissions

The NetScaler user needs permission to perform the following API calls:

API Endpoint|Methods
---|---
/nitro/v1/config/login|post
/nitro/v1/config/lbvserver| get
/nitro/v1/config/sslcertkey| get, update, add, delete
/nitro/v1/config/sslcertkey_service_binding| get, update, add, delete
/nitro/v1/config/systemfile| get, add, delete

### Upgrade Procedures

* Upgrade From v1.0.2 to v2.0.0
* In the Keyfactor Command Database, run the following SQL Script to update the store types and store information [Upgrade Script](https://github.com/Keyfactor/citrix-adc-orchestrator/blob/snipamupdates/UpgradeScript.sql)

### Below are specific notes and limitations

* Direct PFX Binding Inventory
* In NetScaler you can directly Bind a Pfx file to a Virtual Server. Keyfactor cannot inventory these because it does not have access to the password. The recommended way to Import PFX Files in NetScaler is descibed in this [NetScaler Documentation](https://docs.netscaler.com/en-us/citrix-adc/12-1/ssl/ssl-certificates/export-existing-certs-keys.html#convert-ssl-certificates-for-import-or-export)

* Specifiy Multiple VServers and Sni Flags
* When Binding to Multiple VServers and using Multiple SniFlags, you must use a comma separated list of values as described in Test Case 13 in the Test Cases Section. This will change in future version, so each binding is a store in Keyfactor.

* Down Time When Replacing Certs
* The orchestrator uses [NetScaler recommended methods](https://docs.netscaler.com/en-us/citrix-adc/12-1/ssl/ssl-certificates/add-group-certs.html) to replace bound certs which creates a sub second blip of downtime. There is currently no way around this if you want readable keypair names.

* Removing Certs from Store
* As defined in Test Cases 5 and 13 below, certificates that are bound to a server will not be removed. This was done to limit the possibility of bringing production servers down. Users are currently required to manually unbind the certificate from the server and then remove the cert using Command. This requirement may change in a future version.

* Renewals
* The renewal process will find the thumbprint of the cert on all VServers and renew them in all places. See test cases #6 and #10 in the Test Cases section.

* AutoSave Config
* A new config.json file in the extension folder contains the 'AutoSaveConfig' flag with a default value of 'N'. When this flag is set to 'Y', successful configuration changes made by a management job will be automatically saved to disk; no interaction with the Citrix ADC UI is necessary.

**NOTE:** Any changes in-process through the Citrix ADC UI will also be persisted to disk when a management job is performed and the AutoSaveConfig flag is set to 'Y'.

* Support for Virtual Authentication Servers & Gateways
* 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.
<details>
<summary>Cert Store Type Settings</summary>
<br />
Expand All @@ -159,49 +110,46 @@ API Endpoint|Methods

**Basic Settings**

CONFIG ELEMENT | VALUE | DESCRIPTION
CONFIG ELEMENT | DESCRIPTION
------------------|------------------
Name |Citrix ADC |A descriptive name for the extension. Example: CitrixAdc
Short Name|CitrixADC|The short name that identifies the registered functionality of the orchestrator. Must be CitrixAdc.
Custom Capability|Unchecked|Store type name orchestrator will register with.
Supported Job Types|Inventory, Add, Remove |Job types this extension supports
Needs Server | Checked | Determines if a target server name is required when creating store
Blueprint Allowed | Unchecked | Determines if store type may be included in an Orchestrator blueprint
Uses PowerShell | Unchecked | Determines if underlying implementation is PowerShell
Requires Store Password|Unchecked |Determines if a store password is required when configuring an individual store.
Supports Entry Password|Unchecked |Determined if an individual entry within a store can have a password.
Name |A descriptive name for the extension. Example: CitrixAdc
Short Name |The short name that identifies the registered functionality of the orchestrator. Must be CitrixAdc.
Custom Capability|Store type name orchestrator will register with. Uncheck This
Job Types |Inventory (Checked), check the additional checkboxes: Add, Remove
General Settings|Needs Server - Checked<br>Blueprint Allowed - Unchecked<br>Uses PowerShell - Unchecked
Requires Store Password |Determines if a store password is required when configuring an individual store. This must be unchecked.
Supports Entry Password |Determined if an individual entry within a store can have a password. This must be unchecked.

**Advanced Settings**

CONFIG ELEMENT | VALUE | DESCRIPTION
CONFIG ELEMENT | DESCRIPTION
------------------|------------------
Store Path Type |Freeform |Determines what restrictions are applied to the store path field when configuring a new store.
Supports Custom Alias |Required |Determines if an individual entry within a store can have a custom Alias.
Private Keys |Required |This determines if Keyfactor can send the private key associated with a certificate to the store. This is required since Citrix ADC will need the private key material to establish TLS connections.
PFX Password Style |Default or Custom |This determines how the platform generate passwords to protect a PFX enrollment job that is delivered to the store.
Store Path Type |Determines what restrictions are applied to the store path field when configuring a new store. Select Freeform
Supports Custom Alias |Determines if an individual entry within a store can have a custom Alias. This must be Required.
Private Keys |This determines if Keyfactor can send the private key associated with a certificate to the store. This is required since Citrix ADC will need the private key material to establish TLS connections.
PFX Password Style |This determines how the platform generate passwords to protect a PFX enrollment job that is delivered to the store. This can be either Default (system generated) or Custom (user determined).

**Custom Fields**

Name|Display Name|Type|Default Value|Required|Description
Parameter Name|Display Name|Parameter 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

**Entry Parameters**
**Custom Fields**

Name|Display Name|Type|Default Value|Required|Description
---|---|---|---|---|---
virtualServerName|Virtual Server Name|String| |Leave All Unchecked|Contains the name of the VServer the operation should be performed upon
sniCert|SNI Cert|String|false
Parameter Name|Display Name|Parameter Type|Default Value|Required When
---|---|---|---|---
virtualServerName|Virtual Server Name|String| |Leave All Unchecked
sniCert|SNI Cert|String|false|Adding Entry


#### STORE TYPE ENTRY PARAMS
CONFIG ELEMENT | DESCRIPTION
------------------|------------------
Alias | When Enrolling, this is the name of the Certificate that will be installed on NetScaler.
Virtual Server | When Enrolling, this can be a single or comma separated list of VServers in NetScaler to replace. <br/>**NOTE:** When adding multiple VServers, each certificate will contain the same alias name.
SNI Cert| When multiple VServers are used, a comma separated value must be accompanied with each VServer name.
Virtual Server | When Enrolling, this can be a single or comma separated list of VServers in Netscaler to replace.
Key Pair| When Enrolling, this is the name of the Certificate that will be installed on Netscaler

</details>

Expand All @@ -214,15 +162,65 @@ SNI Cert| When multiple VServers are used, a comma separated value must be accom
#### STORE CONFIG
CONFIG ELEMENT | DESCRIPTION
------------------|------------------
Client Machine | This is the IP Address of the NetScaler Appliance.
Store Path| This is the path of the NetScaler Appliance. /nsconfig/ssl/.
User| This is the user that will be authenticated against the NetScaler Appliance
Password| This is the password that will be authenticated against the NetScaler Appliance
Client Machine | This is the IP Address of the Netscaler Appliance.
Store Path| This is the path of the Netscaler Appliance. /nsconfig/ssl/.
User| This is the user that will be authenticated against the Netscaler Appliance
Password| This is the password that will be authenticated against the Netscaler Appliance
Use SSL| This should be set to True in Production when there is a valid certificate.
Inventory Schedule| Set this for the appropriate inventory interval needed.

</details>

<details>
<summary>Permissions</summary>
<br />

The Netscaler user needs permission to perform the following API calls:

API Endpoint|Methods
---|---
/nitro/v1/config/login|post
/nitro/v1/config/lbvserver| get
/nitro/v1/config/sslcertkey| get, update, add, delete
/nitro/v1/config/sslcertkey_service_binding| get, update, add, delete
/nitro/v1/config/systemfile| get, add, delete

</details>

<details>
<summary>Integration Notes and Limitations</summary>
<br />


* Direct PFX Binding Inventory
* In Netscaler you can directly Bind a Pfx file to a Virtual Server. Keyfactor cannot inventory these because it does not have access to the password. The recommended way to Import PFX Files in Netscaler is descibed in this [Netscaler Documentation](https://docs.netscaler.com/en-us/citrix-adc/12-1/ssl/ssl-certificates/export-existing-certs-keys.html#convert-ssl-certificates-for-import-or-export)

* Sepcifiy Multiple VServers and Sni Flags
* When Binding to Multiple VServers and using Multiple SniFlags, you have to use a comma separated list of values as descibed in Test Case 13 in the Test Cases Section. This will change in future version so each binding is a store in Keyfactor.

* Down Time When Replacing Certs
* The orchestrator uses [Netscaler recommended methods](https://docs.netscaler.com/en-us/citrix-adc/12-1/ssl/ssl-certificates/add-group-certs.html) to replace bound certs which creates a sub second blip of downtime. There is currently no way around this if you want readable keypair names.

* Renewals
* The renewal process will find the thumprint of the cert on all VServers and renew them in all places. See test cases #6 and #10 in the Test Cases section.

* AutoSave Config
* A new config.json file in the extension folder contains the 'AutoSaveConfig' flag with a default value of 'N'. When this flag is set to 'Y', successful configuration changes made by a management job will be automatically saved to disk; no interaction with the Citrix ADC UI is necessary.

**NOTE:** Any changes in-process through the Citrix ADC UI will also be persisted to disk when a management job is performed and the AutoSaveConfig flag is set to 'Y'.

</details>

<details>
<summary>Upgrade Procedures</summary>
<br />


* Upgrade From v1.0.2 to v2.0.0
* In the Keyfactor Command Database, run the following SQL Script to update the store types and store information [Upgrade Script](https://github.com/Keyfactor/citrix-adc-orchestrator/blob/snipamupdates/UpgradeScript.sql)


</details>


<details>
Expand Down
Loading