From b9707fd809d4e2470dcc0dada88c60dbb1c6a899 Mon Sep 17 00:00:00 2001 From: JoeKF Date: Thu, 19 Oct 2023 15:50:31 -0400 Subject: [PATCH] reverted to .netstandard 2.0 from 2.1 to fix serialization error. Add certificate functionality for JKS. --- .../FileStores/JksFileStore.cs | 79 +++++++++++-------- .../FileStores/PfxFileStore.cs | 9 ++- .../FileStores/Pkcs12FileStore.cs | 5 ++ .../HcvKeyValueClient.cs | 65 ++++++++++----- .../Jobs/Discovery.cs | 2 +- hashicorp-vault-orchestrator/Jobs/JobBase.cs | 30 +++---- .../Jobs/Management.cs | 5 +- .../hashicorp-vault-orchestrator.csproj | 8 +- hashicorp-vault-orchestrator/manifest.json | 18 ++++- integration-manifest.json | 6 +- 10 files changed, 147 insertions(+), 80 deletions(-) diff --git a/hashicorp-vault-orchestrator/FileStores/JksFileStore.cs b/hashicorp-vault-orchestrator/FileStores/JksFileStore.cs index 7632719..5767181 100644 --- a/hashicorp-vault-orchestrator/FileStores/JksFileStore.cs +++ b/hashicorp-vault-orchestrator/FileStores/JksFileStore.cs @@ -17,6 +17,10 @@ public class JksFileStore : IFileStore { internal protected ILogger logger { get; set; } + public JksFileStore() + { + logger = LogHandler.GetClassLogger(); + } public string AddCertificate(string alias, string pfxPassword, string entryContents, bool includeChain, string storeFileContent, string passphrase) { @@ -26,7 +30,7 @@ public string AddCertificate(string alias, string pfxPassword, string entryConte var jksBytes = Convert.FromBase64String(storeFileContent); logger.LogTrace("converting JKS to PKCS12 store for manipulation"); - + var newCertBytes = Convert.FromBase64String(entryContents); logger.LogTrace("adding the new certificate, and getting the new JKS store bytes."); @@ -40,11 +44,13 @@ public byte[] CreateFileStore(string name, string password) // Create new Pkcs12Store from newPkcs12Bytes var newStore = new JksStore(); - using var outstream = new MemoryStream(); - logger.LogDebug("Created new JKS store, saving it to outStream"); + using (var outstream = new MemoryStream()) + { + logger.LogDebug("Created new JKS store, saving it to outStream"); - newStore.Save(outstream, password.ToCharArray()); - return outstream.ToArray(); + newStore.Save(outstream, password.ToCharArray()); + return outstream.ToArray(); + } } public IEnumerable GetInventory(Dictionary certFields) @@ -120,17 +126,18 @@ private byte[] AddOrRemoveCert(string alias, string newCertPassword, byte[] newC if (existingStore != null) { logger.LogDebug("Loading existing JKS store"); - using var ms = new MemoryStream(existingStore); - - try + using (var ms = new MemoryStream(existingStore)) { - existingJksStore.Load(ms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); - } - catch (Exception ex) - { - logger.LogError(ex, $"Error loading existing JKS store: {ex.Message}"); - } + try + { + existingJksStore.Load(ms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); + } + catch (Exception ex) + { + logger.LogError(ex, $"Error loading existing JKS store: {ex.Message}"); + } + } if (existingJksStore.ContainsAlias(alias)) { // If alias exists, delete it from existingJksStore @@ -140,19 +147,23 @@ private byte[] AddOrRemoveCert(string alias, string newCertPassword, byte[] newC { // If remove is true, save existingJksStore and return logger.LogDebug("This is a removal operation, saving existing JKS store"); - using var mms = new MemoryStream(); - existingJksStore.Save(mms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); - logger.LogDebug("Returning existing JKS store"); - return mms.ToArray(); + using (var mms = new MemoryStream()) + { + existingJksStore.Save(mms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); + logger.LogDebug("Returning existing JKS store"); + return mms.ToArray(); + } } } else if (remove) { // If alias does not exist and remove is true, return existingStore logger.LogDebug("Alias '{Alias}' does not exist in existing JKS store and this is a removal operation, returning existing JKS store as-is", alias); - using var mms = new MemoryStream(); - existingJksStore.Save(mms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); - return mms.ToArray(); + using (var mms = new MemoryStream()) + { + existingJksStore.Save(mms, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); + return mms.ToArray(); + } } } else @@ -168,8 +179,10 @@ private byte[] AddOrRemoveCert(string alias, string newCertPassword, byte[] newC try { logger.LogDebug("Loading new Pkcs12Store from newPkcs12Bytes"); - using var pkcs12Ms = new MemoryStream(newCertBytes); - newCert.Load(pkcs12Ms, string.IsNullOrEmpty(newCertPassword) ? Array.Empty() : newCertPassword.ToCharArray()); + using (var pkcs12Ms = new MemoryStream(newCertBytes)) + { + newCert.Load(pkcs12Ms, string.IsNullOrEmpty(newCertPassword) ? Array.Empty() : newCertPassword.ToCharArray()); + } } catch (Exception) { @@ -237,15 +250,19 @@ private byte[] AddOrRemoveCert(string alias, string newCertPassword, byte[] newC } } - using var outStream = new MemoryStream(); - - logger.LogDebug("Saving existing JKS store to outStream"); - existingJksStore.Save(outStream, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); - - // Return existingJksStore as byte[] - logger.LogDebug("Returning JKS store as byte[]"); - return outStream.ToArray(); + using (var outStream = new MemoryStream()) + { + + logger.LogDebug("Saving existing JKS store to outStream"); + existingJksStore.Save(outStream, string.IsNullOrEmpty(existingStorePassword) ? Array.Empty() : existingStorePassword.ToCharArray()); + // Return existingJksStore as byte[] + logger.LogDebug("Returning JKS store as byte[]"); + var bytes = outStream.ToArray(); + outStream.Flush(); + outStream.Dispose(); + return bytes; + } } private Pkcs12Store JksToPkcs12Store(byte[] storeContents, string storePassword) diff --git a/hashicorp-vault-orchestrator/FileStores/PfxFileStore.cs b/hashicorp-vault-orchestrator/FileStores/PfxFileStore.cs index 5f9731a..2e059e2 100644 --- a/hashicorp-vault-orchestrator/FileStores/PfxFileStore.cs +++ b/hashicorp-vault-orchestrator/FileStores/PfxFileStore.cs @@ -13,6 +13,11 @@ public class PfxFileStore : IFileStore { internal protected ILogger logger { get; set; } + public PfxFileStore() + { + logger = LogHandler.GetClassLogger(); + } + public string AddCertificate(string alias, string pfxPassword, string entryContents, bool includeChain, string storeFileContent, string passphrase) { throw new NotImplementedException(); @@ -27,7 +32,7 @@ public IEnumerable GetInventory(Dictionary { logger = LogHandler.GetClassLogger(); logger.MethodEntry(); - // certFields should contain two entries. The certificate with the "pfx-contents" suffix, and "password" + // certFields should contain two entries. The certificate with the "_pfx" suffix, and "passphrase" string password; string base64encodedCert; var certs = new List(); @@ -44,7 +49,7 @@ public IEnumerable GetInventory(Dictionary base64encodedCert = certFields[certKey].ToString(); } - if (certFields.TryGetValue("password", out object filePasswordObj)) + if (certFields.TryGetValue("passphrase", out object filePasswordObj)) { password = filePasswordObj.ToString(); } diff --git a/hashicorp-vault-orchestrator/FileStores/Pkcs12FileStore.cs b/hashicorp-vault-orchestrator/FileStores/Pkcs12FileStore.cs index 5e144d4..f804197 100644 --- a/hashicorp-vault-orchestrator/FileStores/Pkcs12FileStore.cs +++ b/hashicorp-vault-orchestrator/FileStores/Pkcs12FileStore.cs @@ -13,6 +13,11 @@ public class Pkcs12FileStore : IFileStore { internal protected ILogger logger { get; set; } + public Pkcs12FileStore() + { + logger = LogHandler.GetClassLogger(); + } + public string AddCertificate(string alias, string pfxPassword, string entryContents, bool includeChain, string storeFileContent, string passphrase) { throw new NotImplementedException(); diff --git a/hashicorp-vault-orchestrator/HcvKeyValueClient.cs b/hashicorp-vault-orchestrator/HcvKeyValueClient.cs index 40bbca1..e4ad390 100644 --- a/hashicorp-vault-orchestrator/HcvKeyValueClient.cs +++ b/hashicorp-vault-orchestrator/HcvKeyValueClient.cs @@ -9,7 +9,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using Keyfactor.Extensions.Orchestrator.HashicorpVault.FileStores; using Keyfactor.Logging; @@ -23,6 +25,7 @@ using VaultSharp.V1.AuthMethods; using VaultSharp.V1.AuthMethods.Token; using VaultSharp.V1.Commons; +using VaultSharp.V1.SecretsEngines.KeyValue.V2; namespace Keyfactor.Extensions.Orchestrator.HashicorpVault { @@ -49,7 +52,7 @@ public HcvKeyValueClient(string vaultToken, string serverUrl, string mountPoint, // Initialize settings. You can also set proxies, custom delegates etc. here. var clientSettings = new VaultClientSettings(serverUrl, authMethod); _mountPoint = mountPoint; - _storePath = !string.IsNullOrEmpty(storePath) ? "/" + storePath.Trim() : storePath?.Trim(); + _storePath = (!string.IsNullOrEmpty(storePath) && !storePath.StartsWith("/")) ? "/" + storePath.Trim() : storePath?.Trim(); _vaultClient = new VaultClient(clientSettings); _subfolderInventory = SubfolderInventory; _storeType = storeType?.Split('.')[1]; @@ -221,7 +224,8 @@ public async Task> GetVaults(string storePath) keys = res.Data.Subkeys; } // does it have an entry with the suffix we are looking for? - if (keys.Any(k => k.Key.Contains(suffix))) + var key = keys.FirstOrDefault(k => k.Key.EndsWith(suffix)); + if (key.Key != null) { if (_storeType == StoreType.HCVKVPEM) { @@ -230,7 +234,7 @@ public async Task> GetVaults(string storePath) } else { - vaultPaths.Add(storePath + path); + vaultPaths.Add(storePath + path + "/" + key.Key); } } } @@ -255,16 +259,22 @@ public async Task> GetVaults(string storePath) public async Task PutCertificate(string certName, string contents, string pfxPassword, bool includeChain) { logger.MethodEntry(); + try + { + if (_storeType != StoreType.HCVKVPEM) + { + await PutCertificateIntoFileStore(certName, contents, pfxPassword, includeChain); + return; + } + // for PEM stores, the store path is the container name, not entry name as with file stores - if (_storeType != StoreType.HCVKVPEM) + await PutCertificateIntoPemStore(certName, contents, pfxPassword, includeChain); + } + catch (Exception ex) { - await PutCertificateIntoFileStore(certName, contents, pfxPassword, includeChain); - return; + logger.LogError(ex, "Error when adding the new certificate."); + throw; } - // for PEM stores, the store path is the container name, not entry name as with file stores - - await PutCertificateIntoPemStore(certName, contents, pfxPassword, includeChain); - logger.MethodExit(); } public async Task PutCertificateIntoPemStore(string certName, string contents, string pfxPassword, bool includeChain) @@ -407,7 +417,7 @@ private async Task PutCertificateIntoFileStore(string certName, string contents, try { // first get entry contents and passphrase - + logger.LogTrace("getting all secrets in the parent container for the store."); if (string.IsNullOrEmpty(_mountPoint)) { @@ -418,6 +428,7 @@ private async Task PutCertificateIntoFileStore(string certName, string contents, res = await VaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(parentPath, mountPoint: _mountPoint); } certData = (Dictionary)res.Data.Data; + logger.LogTrace("got secret data.", certData); string certificate = null; string passphrase = null; @@ -425,36 +436,48 @@ private async Task PutCertificateIntoFileStore(string certName, string contents, //Validates if the "certificate" and "private_key" keys exist in certData var key = _storePath.Substring(_storePath.LastIndexOf("/")); + key = key.TrimStart('/'); + + logger.LogTrace($"getting the contents of {key}"); if (!certData.TryGetValue(key, out object certFileObj)) { throw new DirectoryNotFoundException($"entry named {key} not found at {parentPath}"); } certificate = certFileObj.ToString(); - + if (!certData.TryGetValue("passphrase", out object passphraseObj)) { throw new DirectoryNotFoundException($"no passphrase entry found at {parentPath}"); } passphrase = passphraseObj.ToString(); + logger.LogTrace("got passphrase and certificate store secrets from vault."); + + logger.LogTrace("calling method to add certificate to store file."); // get new store entry var newEntry = fileStore.AddCertificate(certName, pfxPassword, contents, includeChain, certificate, passphrase); - + logger.LogTrace("got new store file."); // write new store entry - try { logger.LogTrace("writing file store with new certificate to vault."); - VaultClient.V1.Auth.ResetVaultToken(); + VaultClient.V1.Auth.ResetVaultToken(); + + var newData = new Dictionary { { key, newEntry } }; + var patchReq = new PatchSecretDataRequest() { Data = newData }; + + // temporary debugging code + var stringContent = new StringContent(JsonSerializer.Serialize(newData), Encoding.UTF8); + // - if (_mountPoint == null) + if (string.IsNullOrEmpty(_mountPoint)) { - await VaultClient.V1.Secrets.KeyValue.V2.WriteSecretAsync(_storePath, newEntry); + await VaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(parentPath, patchReq); } else { - await VaultClient.V1.Secrets.KeyValue.V2.WriteSecretAsync(_storePath, newEntry, mountPoint: _mountPoint); + await VaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(parentPath, patchReq, _mountPoint); } } catch (Exception ex) @@ -570,7 +593,7 @@ public async Task> GetCertificatesFromFileStor //file stores for JKS, PKCS12 and PFX will have a "passphrase" entry on the same level by convention. We'll need this in order to extract the certificates for inventory. var pos = _storePath.LastIndexOf("/"); - var parentPath = _storePath.Substring(pos); + var parentPath = _storePath.Substring(0, pos); try { @@ -607,7 +630,7 @@ public async Task> GetCertificatesFromFileStor break; default: - throw new InvalidOperationException($"unrecognized store type vaule {_storeType}"); + throw new InvalidOperationException($"unrecognized store type value {_storeType}"); } try @@ -624,7 +647,7 @@ public async Task> GetCertificatesFromFileStor //private List GetCertsFromJKS(Dictionary certFields) //{ // logger.MethodEntry(); - // // certFields should contain two entries. The certificate with the "jks-contents" suffix, and "password" + // // certFields should contain two entries. The certificate with the "_jks" suffix, and "passphrase" // string password; // string base64encodedCert; diff --git a/hashicorp-vault-orchestrator/Jobs/Discovery.cs b/hashicorp-vault-orchestrator/Jobs/Discovery.cs index 8b969f8..ecff776 100644 --- a/hashicorp-vault-orchestrator/Jobs/Discovery.cs +++ b/hashicorp-vault-orchestrator/Jobs/Discovery.cs @@ -41,7 +41,7 @@ public JobResult ProcessJob(DiscoveryJobConfiguration config, SubmitDiscoveryUpd { logger.LogError("Attempt to perform discovery on unsupported Secrets Engine backend."); - result.FailureMessage = $"{StoreType} does not support Discovery jobs."; + result.FailureMessage = $"{_storeType} does not support Discovery jobs."; } else { diff --git a/hashicorp-vault-orchestrator/Jobs/JobBase.cs b/hashicorp-vault-orchestrator/Jobs/JobBase.cs index 8ec083c..2af5476 100644 --- a/hashicorp-vault-orchestrator/Jobs/JobBase.cs +++ b/hashicorp-vault-orchestrator/Jobs/JobBase.cs @@ -33,7 +33,7 @@ public abstract class JobBase public string MountPoint { get; set; } // the mount point of the KV secrets engine. defaults to KV by Vault if not provided. internal protected IHashiClient VaultClient { get; set; } - internal protected string StoreType { get; set; } + internal protected string _storeType { get; set; } internal protected ILogger logger { get; set; } internal protected IPAMSecretResolver PamSecretResolver { get; set; } @@ -80,32 +80,34 @@ public void InitializeStore(ManagementJobConfiguration config) StorePath = config.CertificateStoreDetails.StorePath; ClientMachine = config.CertificateStoreDetails.ClientMachine; - - var props = (Dictionary)JsonConvert.DeserializeObject(config.CertificateStoreDetails.Properties); + dynamic props = JsonConvert.DeserializeObject(config.CertificateStoreDetails.Properties.ToString()); InitProps(props, config.Capability); } - private void InitProps(IDictionary props, string capability) - { + private void InitProps(dynamic props, string capability) + { + _storeType = capability; + if (props == null) throw new Exception("Properties is null"); - if (props.TryGetValue("StorePath", out var p)) { - StorePath = p.ToString(); + if (props.ContainsKey("StorePath")) { + StorePath = props["StorePath"].ToString(); StorePath = StorePath.TrimStart('/'); StorePath = StorePath.TrimEnd('/'); - StorePath += "/"; //ensure single trailing slash for path + if (_storeType.Contains(StoreType.HCVKVPEM) || _storeType.Contains(StoreType.HCVPKI)) { + StorePath += "/"; //ensure single trailing slash for path for PKI or PEM stores. Others use the entry value instead of the container. + } } MountPoint = props.ContainsKey("MountPoint") ? props["MountPoint"].ToString() : null; - SubfolderInventory = props.ContainsKey("SubfolderInventory") ? Boolean.Parse(props["SubfolderInventory"].ToString()) : false; - IncludeCertChain = props.ContainsKey("IncludeCertChain") ? Boolean.Parse(props["IncludeCertChain"].ToString()) : false; - StoreType = capability; - - var isPki = StoreType.Contains("HCVPKI"); + SubfolderInventory = props.ContainsKey("SubfolderInventory") ? bool.Parse(props["SubfolderInventory"].ToString()) : false; + IncludeCertChain = props.ContainsKey("IncludeCertChain") ? bool.Parse(props["IncludeCertChain"].ToString()) : false; + + var isPki = _storeType.Contains("HCVPKI"); if (!isPki) { - VaultClient = new HcvKeyValueClient(VaultToken, VaultServerUrl, MountPoint, StorePath, StoreType, SubfolderInventory); + VaultClient = new HcvKeyValueClient(VaultToken, VaultServerUrl, MountPoint, StorePath, _storeType, SubfolderInventory); } else { diff --git a/hashicorp-vault-orchestrator/Jobs/Management.cs b/hashicorp-vault-orchestrator/Jobs/Management.cs index af549a4..869e185 100644 --- a/hashicorp-vault-orchestrator/Jobs/Management.cs +++ b/hashicorp-vault-orchestrator/Jobs/Management.cs @@ -59,6 +59,7 @@ protected virtual JobResult PerformAddition(string alias, string pfxPassword, st try { var cert = VaultClient.PutCertificate(alias, entryContents, pfxPassword, IncludeCertChain); + cert.Wait(); complete.Result = OrchestratorJobStatusJobResult.Success; } catch (Exception ex) @@ -66,7 +67,7 @@ protected virtual JobResult PerformAddition(string alias, string pfxPassword, st if (ex.GetType() == typeof(NotSupportedException)) { logger.LogError("Attempt to Add Certificate on unsupported Secrets Engine backend."); - complete.FailureMessage = $"{StoreType} does not support adding certificates via the Orchestrator."; + complete.FailureMessage = $"{_storeType} does not support adding certificates via the Orchestrator."; } else { @@ -115,7 +116,7 @@ protected virtual JobResult PerformRemoval(string alias, long jobHistoryId) if (ex.GetType() == typeof(NotSupportedException)) { logger.LogError("Attempt to Delete Certificate on unsupported Secrets Engine backend."); - complete.FailureMessage = $"{StoreType} does not support removing certificates via the Orchestrator."; + complete.FailureMessage = $"{_storeType} does not support removing certificates via the Orchestrator."; } else { diff --git a/hashicorp-vault-orchestrator/hashicorp-vault-orchestrator.csproj b/hashicorp-vault-orchestrator/hashicorp-vault-orchestrator.csproj index 96c5545..a7c518b 100644 --- a/hashicorp-vault-orchestrator/hashicorp-vault-orchestrator.csproj +++ b/hashicorp-vault-orchestrator/hashicorp-vault-orchestrator.csproj @@ -1,7 +1,7 @@  - netstandard2.1 + netstandard2.0 Keyfactor.Extensions.Orchestrator.HashicorpVault Keyfactor.Extensions.Orchestrator.HCV true @@ -25,7 +25,7 @@ - DEBUG;TRACE + Auto false false @@ -45,14 +45,12 @@ all - - all - all + all diff --git a/hashicorp-vault-orchestrator/manifest.json b/hashicorp-vault-orchestrator/manifest.json index 393b023..12610d0 100644 --- a/hashicorp-vault-orchestrator/manifest.json +++ b/hashicorp-vault-orchestrator/manifest.json @@ -1,7 +1,7 @@ { "extensions": { "Keyfactor.Orchestrators.Extensions.IOrchestratorJobExtension": { - + "CertStores.HCVKVPEM.Inventory": { "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Inventory" @@ -14,6 +14,7 @@ "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Management" }, + "CertStores.HCVKVJKS.Inventory": { "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Inventory" @@ -22,6 +23,11 @@ "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Discovery" }, + "CertStores.HCVKVJKS.Management": { + "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", + "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Management" + }, + "CertStores.HCVKVP12.Inventory": { "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Inventory" @@ -30,6 +36,11 @@ "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Discovery" }, + "CertStores.HCVKVP12.Management": { + "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", + "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Management" + }, + "CertStores.HCVKVPFX.Inventory": { "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Inventory" @@ -38,6 +49,11 @@ "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Discovery" }, + "CertStores.HCVKVPFX.Management": { + "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", + "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Management" + }, + "CertStores.HCVPKI.Inventory": { "assemblypath": "Keyfactor.Extensions.Orchestrator.HCV.dll", "TypeFullName": "Keyfactor.Extensions.Orchestrator.HashicorpVault.Jobs.Inventory" diff --git a/integration-manifest.json b/integration-manifest.json index b2fe7b8..283c9c6 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -166,11 +166,11 @@ "Capability": "HCVKVJKS", "LocalStore": false, "SupportedOperations": { - "Add": false, - "Create": false, + "Add": true, + "Create": true, "Discovery": true, "Enrollment": false, - "Remove": false + "Remove": true }, "Properties": [ {