Skip to content

Commit a78ff1f

Browse files
authored
Merge cab6c20 into 4a53b63
2 parents 4a53b63 + cab6c20 commit a78ff1f

File tree

10 files changed

+156
-89
lines changed

10 files changed

+156
-89
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
v1.9.0
2+
- Added new SSLProfiles READ ONLY entry parameter that will contain a comma delimited list of SSL Profiles a certificate is bound to on the F5 device.
3+
4+
v1.8.1
5+
- Documentation changes including highlighting lack of HA support as well as a correction to the proper StorePath value for F5-CA-REST stores.
6+
17
v1.8.0
28
- Add new custom field - Remove Chain on Add - to allow the removal of the certificate chain before adding/replacing a certificate on the F5 device. Default = false.
39
- Apply store password when replacing a certificate as well as adding (extension to change made in v1.6.0)

F5Client.cs

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
using System.Collections.Concurrent;
2525
using System.Drawing.Printing;
2626
using System.Diagnostics.CodeAnalysis;
27+
using static Keyfactor.Orchestrators.Common.OrchestratorConstants;
28+
using static Org.BouncyCastle.Math.EC.ECCurve;
2729

2830
namespace Keyfactor.Extensions.Orchestrator.F5Orchestrator
2931
{
@@ -91,7 +93,9 @@ public void AddEntry(string partition, string name, string b64Certificate, strin
9193
{
9294
LogHandlerCommon.MethodEntry(logger, CertificateStore, "AddEntry");
9395
LogHandlerCommon.Trace(logger, CertificateStore, $"Processing certificate for partition '{partition}' and name '{name}'");
96+
LogHandlerCommon.Trace(logger, CertificateStore, $"*** CERT CONTENTS: *** {b64Certificate}");
9497
byte[] entryContents = Convert.FromBase64String(b64Certificate);
98+
LogHandlerCommon.Trace(logger, CertificateStore, $"*** AFTER CERT CONTENTS: ***");
9599
string password = PFXPassword;
96100
CertificateConverter converter = CertificateConverterFactory.FromDER(entryContents, password);
97101
X509Certificate2 certificate = converter.ToX509Certificate2(password);
@@ -350,6 +354,35 @@ private X509Certificate2Collection GetCertificateEntry(string path)
350354
return c.ToX509Certificate2Collection();
351355
}
352356

357+
public List<F5SSLProfile> GetSSLProfiles(int pageSize)
358+
{
359+
LogHandlerCommon.MethodEntry(logger, CertificateStore, "GetSSLProfiles");
360+
string partition = CertificateStore.StorePath;
361+
string query = $"/mgmt/tm/ltm/profile/client-ssl?$top={pageSize}&$skip=0";
362+
F5PagedSSLProfiles pagedProfiles = REST.Get<F5PagedSSLProfiles>(query);
363+
List<F5SSLProfile> profiles = new List<F5SSLProfile>();
364+
365+
if (pagedProfiles.totalItems == 0 || pagedProfiles.items?.Length == 0)
366+
{
367+
return profiles;
368+
}
369+
370+
for (int i = pagedProfiles.pageIndex; i <= pagedProfiles.totalPages; i++)
371+
{
372+
profiles.AddRange(pagedProfiles.items);
373+
374+
// The current paged profile will contain a link to the next set, unless the end has been reached
375+
if (string.IsNullOrEmpty(pagedProfiles.nextLink)) { break; }
376+
377+
// Get the next page of profiles
378+
query = pagedProfiles.nextLink.Replace("https://localhost", "");
379+
pagedProfiles = REST.Get<F5PagedSSLProfiles>(query);
380+
}
381+
382+
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetCertificateEntries");
383+
return profiles;
384+
}
385+
353386
private void SetItemStatus(CurrentInventoryItem agentInventoryItem)
354387
{
355388
LogHandlerCommon.MethodEntry(logger, CertificateStore, "SetItemStatus");
@@ -609,67 +642,79 @@ private List<X509Certificate2> ReorderPEMLIst(List<X509Certificate2> certList)
609642
// WebServer
610643
#endregion
611644

612-
#region SSL Profiles
645+
#region SSL Certificates
613646

614-
public List<CurrentInventoryItem> GetSSLProfiles(int pageSize)
647+
public List<CurrentInventoryItem> GetCertificateEntries(int pageSize)
615648
{
616-
LogHandlerCommon.MethodEntry(logger, CertificateStore, "GetSSLProfiles");
649+
LogHandlerCommon.MethodEntry(logger, CertificateStore, "GetCertificateEntries");
617650
string partition = CertificateStore.StorePath;
618651
string query = $"/mgmt/tm/sys/file/ssl-cert?$filter=partition+eq+{partition}&$select=name,keyType,isBundle&$top={pageSize}&$skip=0";
619-
F5PagedSSLProfiles pagedProfiles = REST.Get<F5PagedSSLProfiles>(query);
620-
List<F5SSLProfile> profiles = new List<F5SSLProfile>();
652+
F5PagedSSLCertificates pagedCertificates = REST.Get<F5PagedSSLCertificates>(query);
653+
List<F5SSLCertificate> certificates = new List<F5SSLCertificate>();
621654
List<CurrentInventoryItem> inventory = new List<CurrentInventoryItem>();
622655

623-
if (pagedProfiles.totalItems == 0 || pagedProfiles.items?.Length == 0)
656+
LogHandlerCommon.Debug(logger, CertificateStore, $"Getting SSL Profiles from '{CertificateStore.StorePath}'");
657+
List<F5SSLProfile> sslProfiles = GetSSLProfiles(pageSize);
658+
659+
if (pagedCertificates.totalItems == 0 || pagedCertificates.items?.Length == 0)
624660
{
625-
LogHandlerCommon.Trace(logger, CertificateStore, $"No SSL profiles found in partition '{partition}'");
626-
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetSSLProfiles");
661+
LogHandlerCommon.Trace(logger, CertificateStore, $"No SSL certificates found in partition '{partition}'");
662+
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetCertificateEntries");
627663
return inventory;
628664
}
629665
else
630666
{
631-
LogHandlerCommon.Trace(logger, CertificateStore, $"Compiling {pagedProfiles.totalPages} pages containing {pagedProfiles.totalItems} total inventory entries");
667+
LogHandlerCommon.Trace(logger, CertificateStore, $"Compiling {pagedCertificates.totalPages} pages containing {pagedCertificates.totalItems} total inventory entries");
632668
}
633669

634-
// Collected all of the profile entry names
635-
for (int i = pagedProfiles.pageIndex; i <= pagedProfiles.totalPages; i++)
670+
// Collected all of the certificate entry names
671+
for (int i = pagedCertificates.pageIndex; i <= pagedCertificates.totalPages; i++)
636672
{
637-
profiles.AddRange(pagedProfiles.items);
673+
certificates.AddRange(pagedCertificates.items);
638674

639-
// The current paged profile will contain a link to the next set, unless the end has been reached
640-
if (string.IsNullOrEmpty(pagedProfiles.nextLink)) { break; }
675+
// The current paged certificate list will contain a link to the next set, unless the end has been reached
676+
if (string.IsNullOrEmpty(pagedCertificates.nextLink)) { break; }
641677

642-
// Get the next page of profiles
643-
query = pagedProfiles.nextLink.Replace("https://localhost", "");
644-
pagedProfiles = REST.Get<F5PagedSSLProfiles>(query);
678+
// Get the next page of certificates
679+
query = pagedCertificates.nextLink.Replace("https://localhost", "");
680+
pagedCertificates = REST.Get<F5PagedSSLCertificates>(query);
645681
}
646682

647683
// Compile the entries into inventory items
648-
for (int i = 0; i < profiles.Count; i++)
684+
for (int i = 0; i < certificates.Count; i++)
649685
{
650686
try
651687
{
652-
LogHandlerCommon.Trace(logger, CertificateStore, $"Processing alias {profiles[i].name}");
688+
LogHandlerCommon.Trace(logger, CertificateStore, $"Processing alias {certificates[i].name}");
653689
// Exclude 'ca-bundle.crt' as that can only be managed by F5
654-
if (profiles[i].name.Equals("ca-bundle.crt", StringComparison.OrdinalIgnoreCase)
655-
|| profiles[i].name.Equals("f5-ca-bundle.crt", StringComparison.OrdinalIgnoreCase))
690+
if (certificates[i].name.Equals("ca-bundle.crt", StringComparison.OrdinalIgnoreCase)
691+
|| certificates[i].name.Equals("f5-ca-bundle.crt", StringComparison.OrdinalIgnoreCase))
656692
{
657-
LogHandlerCommon.Trace(logger, CertificateStore, $"Skipping '{profiles[i].name}' because it is managed by F5");
693+
LogHandlerCommon.Trace(logger, CertificateStore, $"Skipping '{certificates[i].name}' because it is managed by F5");
658694
continue;
659695
}
660-
inventory.Add(GetInventoryItem(partition, profiles[i].name, true));
696+
CurrentInventoryItem inventoryItem = GetInventoryItem(partition, certificates[i].name, true);
697+
Dictionary<string, object> parameters = new Dictionary<string, object>();
698+
699+
string certName = $"/{partition}/{inventoryItem.Alias}";
700+
string sslProfileNames = string.Join(",", sslProfiles.Where(p => p.cert == certName).Select(p => p.name));
701+
if (!string.IsNullOrEmpty(sslProfileNames))
702+
parameters.Add("SSLProfiles", sslProfileNames);
703+
inventoryItem.Parameters = parameters;
704+
705+
inventory.Add(inventoryItem);
661706
}
662707
catch (Exception ex)
663708
{
664-
LogHandlerCommon.Error(logger, CertificateStore, ExceptionHandler.FlattenExceptionMessages(ex, $"Unable to process inventory item {profiles[i].name}."));
709+
LogHandlerCommon.Error(logger, CertificateStore, ExceptionHandler.FlattenExceptionMessages(ex, $"Unable to process inventory item {certificates[i].name}."));
665710
}
666711
}
667712

668-
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetSSLProfiles");
713+
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetCertificateEntries");
669714
return inventory;
670715
}
671716

672-
// SSL Profiles
717+
// SSL Certificates
673718
#endregion
674719

675720
#region Auth & Version

F5DataModels.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ internal class F5CABundle
6262
public string[] includeBundle { get; set; }
6363
}
6464

65+
internal class F5PagedSSLCertificates : F5PagedResult
66+
{
67+
public F5SSLCertificate[] items { get; set; }
68+
}
69+
70+
internal class F5SSLCertificate
71+
{
72+
public string name { get; set; }
73+
public bool isBundle { get; set; }
74+
public string keyType { get; set; }
75+
}
76+
6577
internal class F5PagedSSLProfiles : F5PagedResult
6678
{
6779
public F5SSLProfile[] items { get; set; }
@@ -70,8 +82,7 @@ internal class F5PagedSSLProfiles : F5PagedResult
7082
internal class F5SSLProfile
7183
{
7284
public string name { get; set; }
73-
public bool isBundle { get; set; }
74-
public string keyType { get; set; }
85+
public string cert { get; set; }
7586
}
7687

7788
internal class F5Key

0 commit comments

Comments
 (0)