Skip to content

Commit 193720d

Browse files
authored
Merge d4c4637 into 4a53b63
2 parents 4a53b63 + d4c4637 commit 193720d

13 files changed

+166
-90
lines changed

.github/workflows/keyfactor-starter-workflow.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,19 @@ on:
1111

1212
jobs:
1313
call-starter-workflow:
14-
uses: keyfactor/actions/.github/workflows/starter.yml@3.1.2
14+
uses: keyfactor/actions/.github/workflows/starter.yml@screenshots
15+
with:
16+
command_token_url: ${{ vars.DOCTOOL_COMMAND_TOKEN_URL }}
17+
command_hostname: ${{ vars.DOCTOOL_COMMAND_HOSTNAME }}
18+
command_base_api_path: ${{ vars.DOCTOOL_COMMAND_BASE_API_PATH }}
1519
secrets:
1620
token: ${{ secrets.V2BUILDTOKEN}}
1721
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
1822
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
1923
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
2024
scan_token: ${{ secrets.SAST_TOKEN }}
25+
entra_username: ${{ secrets.DOCTOOL_ENTRA_USERNAME }}
26+
entra_password: ${{ secrets.DOCTOOL_ENTRA_PASSWD }}
27+
command_client_id: ${{ secrets.DOCTOOL_COMMAND_CLIENT_ID }}
28+
command_client_secret: ${{ secrets.DOCTOOL_COMMAND_CLIENT_SECRET }}
29+

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: 69 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
{
@@ -350,6 +352,35 @@ private X509Certificate2Collection GetCertificateEntry(string path)
350352
return c.ToX509Certificate2Collection();
351353
}
352354

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

612-
#region SSL Profiles
643+
#region SSL Certificates
613644

614-
public List<CurrentInventoryItem> GetSSLProfiles(int pageSize)
645+
public List<CurrentInventoryItem> GetCertificateEntries(int pageSize)
615646
{
616-
LogHandlerCommon.MethodEntry(logger, CertificateStore, "GetSSLProfiles");
647+
LogHandlerCommon.MethodEntry(logger, CertificateStore, "GetCertificateEntries");
617648
string partition = CertificateStore.StorePath;
618649
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>();
650+
F5PagedSSLCertificates pagedCertificates = REST.Get<F5PagedSSLCertificates>(query);
651+
List<F5SSLCertificate> certificates = new List<F5SSLCertificate>();
621652
List<CurrentInventoryItem> inventory = new List<CurrentInventoryItem>();
622653

623-
if (pagedProfiles.totalItems == 0 || pagedProfiles.items?.Length == 0)
654+
LogHandlerCommon.Debug(logger, CertificateStore, $"Getting SSL Profiles from '{CertificateStore.StorePath}'");
655+
List<F5SSLProfile> sslProfiles = GetSSLProfiles(pageSize);
656+
657+
if (pagedCertificates.totalItems == 0 || pagedCertificates.items?.Length == 0)
624658
{
625-
LogHandlerCommon.Trace(logger, CertificateStore, $"No SSL profiles found in partition '{partition}'");
626-
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetSSLProfiles");
659+
LogHandlerCommon.Trace(logger, CertificateStore, $"No SSL certificates found in partition '{partition}'");
660+
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetCertificateEntries");
627661
return inventory;
628662
}
629663
else
630664
{
631-
LogHandlerCommon.Trace(logger, CertificateStore, $"Compiling {pagedProfiles.totalPages} pages containing {pagedProfiles.totalItems} total inventory entries");
665+
LogHandlerCommon.Trace(logger, CertificateStore, $"Compiling {pagedCertificates.totalPages} pages containing {pagedCertificates.totalItems} total inventory entries");
632666
}
633667

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

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; }
673+
// The current paged certificate list will contain a link to the next set, unless the end has been reached
674+
if (string.IsNullOrEmpty(pagedCertificates.nextLink)) { break; }
641675

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

647681
// Compile the entries into inventory items
648-
for (int i = 0; i < profiles.Count; i++)
682+
for (int i = 0; i < certificates.Count; i++)
649683
{
650684
try
651685
{
652-
LogHandlerCommon.Trace(logger, CertificateStore, $"Processing alias {profiles[i].name}");
686+
LogHandlerCommon.Trace(logger, CertificateStore, $"Processing alias {certificates[i].name}");
653687
// 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))
688+
if (certificates[i].name.Equals("ca-bundle.crt", StringComparison.OrdinalIgnoreCase)
689+
|| certificates[i].name.Equals("f5-ca-bundle.crt", StringComparison.OrdinalIgnoreCase))
656690
{
657-
LogHandlerCommon.Trace(logger, CertificateStore, $"Skipping '{profiles[i].name}' because it is managed by F5");
691+
LogHandlerCommon.Trace(logger, CertificateStore, $"Skipping '{certificates[i].name}' because it is managed by F5");
658692
continue;
659693
}
660-
inventory.Add(GetInventoryItem(partition, profiles[i].name, true));
694+
CurrentInventoryItem inventoryItem = GetInventoryItem(partition, certificates[i].name, true);
695+
Dictionary<string, object> parameters = new Dictionary<string, object>();
696+
697+
string certName = $"/{partition}/{inventoryItem.Alias}";
698+
string sslProfileNames = string.Join(",", sslProfiles.Where(p => p.cert == certName).Select(p => p.name));
699+
if (!string.IsNullOrEmpty(sslProfileNames))
700+
parameters.Add("SSLProfiles", sslProfileNames);
701+
inventoryItem.Parameters = parameters;
702+
703+
inventory.Add(inventoryItem);
661704
}
662705
catch (Exception ex)
663706
{
664-
LogHandlerCommon.Error(logger, CertificateStore, ExceptionHandler.FlattenExceptionMessages(ex, $"Unable to process inventory item {profiles[i].name}."));
707+
LogHandlerCommon.Error(logger, CertificateStore, ExceptionHandler.FlattenExceptionMessages(ex, $"Unable to process inventory item {certificates[i].name}."));
665708
}
666709
}
667710

668-
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetSSLProfiles");
711+
LogHandlerCommon.MethodExit(logger, CertificateStore, "GetCertificateEntries");
669712
return inventory;
670713
}
671714

672-
// SSL Profiles
715+
// SSL Certificates
673716
#endregion
674717

675718
#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)