Skip to content

Commit 20a84ef

Browse files
authored
Release 3.0 (#23)
Reconcile 3.0.0 to main * Added additional store types, pfx discovery and inventory complete. * jks stores discovery and inventory complete * PKCS12 store discovery and inventory completed. * added add, remove, and create functionality to JKS store. Added store type classes. * Completed add/remove/create for PFX and PKCS12 * Added capability to PEM cert stores for creating an empty store location. * Update integration-manifest.json removing storepathtype and storepathvalue to prevent errors in KFUtil when creating store types.
1 parent a82ff1d commit 20a84ef

25 files changed

+2165
-248
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 3.0.0
2+
3+
* Added support for JKS, PKCS12 and PFX file stores in the Hashicorp Vault Key-Value secrets engine.
4+
* Added PAM support for server credentials.
5+
6+
* **Breaking Changes**
7+
* The server url and Vault Token have been moved to the server username and server password fields of server credentials, respectively.
8+
* The HCVKV store type for PEM files has been renamed to HCVKVPEM
9+
10+
111
## 2.0.0
212

313
* Added support for storing certs in sub-paths

README.md

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,13 @@ The Universal Orchestrator is part of the Keyfactor software distribution and is
1414
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.
1515

1616

17-
18-
1917
## Support for Orchestrator Extension for Hashicorp Vault
2018

2119
Orchestrator Extension for Hashicorp Vault is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative.
2220

2321
###### 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.
2422

2523

26-
2724
---
2825

2926

@@ -62,17 +59,39 @@ This integration supports 3 Hashicorp Secrets Engines; PKI, Key-Value store, and
6259

6360
### The Key-Value secrets engine
6461

65-
The Following operations are supported by this integration **only** for the Key-Value secrets engine.
62+
For the Key-Value secrets engine, we have 4 store types that can be used.
6663

67-
1. Discovery - Discover all sub-paths containing certificate.
68-
1. Inventory - Return all certificates stored in a path.
64+
- *HCVKVJKS* - For JKS certificate files, treats each file as it's own store.
65+
- *HCVKVPFX* - For PFX certificate files, treats each file as it's own store.
66+
- *HCVKVP12* - For PKCS12 certificate files, treats each file as it's own store.
67+
- *HCVKVPEM* - For PEM encoded certificates, treats each _path_ as it's own store. Each certificate exists in a sub-path from the store path.
68+
69+
The following operations are supported by this integration for all of the Key-Value secrets engine types:
70+
71+
1. Discovery - Discovery all file repositories for the type
72+
1. Inventory - Inventory all certificates in the path
6973
1. Management (Add) - Add a certificate to a defined certificate store.
7074
1. Management (Remove) - Remove a certificate from a defined certificate store.
75+
1. Create - Create a new, empty certificate store at the path defined in Store Path.
76+
77+
78+
Excluding *HCVKVPEM*, the discovery process requires that:
79+
1. The entry for the certificate contain the base64 encoded certificate file.
80+
1. The name (key) for the entry ends with the suffix corresponding to the certificate store type:
81+
1. *HCVKVJKS* - `*_jks`
82+
1. *HCVKVPFX* - `*_pfx`
83+
1. *HCVKVP12* - `*_p12`
84+
1. *HCVKVPEM* - `certificate`
85+
1. For all except *HCVKVPEM*, there be an entry named `passphrase` that contains the password for the store.
86+
1. For *HCVKVPEM*, there be an entry named `private_key` containing the private key portion of the key-pair.
87+
88+
**Note**: Key/Value secrets that do not include the expected keys will be ignored during inventory scans.
7189

7290
### The Hashicorp PKI and Keyfactor Plugin secrets engines
7391

74-
Both the Hashicorp PKI and Keyfactor plugin are designed to allow managing certifications directly on the Hashicorp Vault instance.
75-
This integration does support the following in order to view your certificates from the platform:
92+
Both the Hashicorp PKI and Keyfactor Secrets Engine plugins are designed to allow managing certifications directly on the Hashicorp Vault instance.
93+
The store type for the PKI and/or the Keyfactor secrets engine is the same; `HCVPKI`.
94+
This integration supports the following in order to view your certificates from the platform:
7695

7796
1. Inventory - Return all certificates stored in a path.
7897

@@ -90,13 +109,6 @@ This integration was built on the .NET Core 3.1 target framework and are compati
90109

91110
1. It is not necessary to use the Vault root token when creating a Certificate Store for HashicorpVault. We recommend creating a token with policies that reflect the minimum permissions necessary to perform the intended operations.
92111

93-
1. For the Key-Value secrets engine, the certificates are stored as an entry with these fields.
94-
95-
- `certificate` - The PEM formatted certificate and intermediate CA chain (if selected)
96-
- `private_key` - The certificate private key
97-
98-
**Note**: Key/Value secrets that do not include the keys `certificate` and `private_key` will be ignored during inventory scans.
99-
100112
## Extension Configuration
101113

102114
### On the Orchestrator Agent Machine
@@ -111,7 +123,7 @@ This integration was built on the .NET Core 3.1 target framework and are compati
111123

112124
### In the Keyfactor Platform
113125

114-
#### Add a new Certificate Store Type - **Key-Value Secrets Engine**
126+
#### Add a new Certificate Store Type - **Hashicorp Vault Key-Value PEM**
115127

116128
- Log into Keyfactor as Administrator or a user with permissions to add certificate store types.
117129
- Click on the gear icon in the top right and then navigate to the "Certificate Store Types"
@@ -120,9 +132,11 @@ This integration was built on the .NET Core 3.1 target framework and are compati
120132
![](images/store_type_add.png)
121133

122134
- Set the following values in the "Basic" tab:
123-
- **Name:** "Hashicorp Vault Key-Value" (or another preferred name)
124-
- **Short Name:** "HCVKV"
135+
- **Name:** "Hashicorp Vault Key-Value PEM" (or another preferred name)
136+
- **Short Name:** "HCVKVPEM"
125137
- **Supported Job Types** - "Inventory", "Add", "Remove", "Discovery"
138+
- **NOTE** If you are setting up "`HCVKVJKS`, `HCVKVPFX`, or `HCVKVP12` the supported job types will be "Inventory, Discovery".
139+
- **Needs Server** - should be checked (true).
126140

127141
![](images/store-type-kv.PNG)
128142

@@ -134,13 +148,14 @@ This integration was built on the .NET Core 3.1 target framework and are compati
134148

135149
- Click the "Custom Fields" tab to add the following custom fields:
136150
- **MountPoint** - type: *string*
137-
- **VaultServerUrl** - type: *string*, *required*
138-
- **VaultToken** - type: *secret*, *required*
139151
- **SubfolderInventory** - type: *bool* (By default, this is set to false. Not a required field)
140152
- **IncludeCertChain** - type: *bool* (If true, the available intermediate certificates will also be written to Vault during enrollment)
141153

142154
![](images/store_type_fields.png)
143155

156+
**Note**
157+
The 3 highlighted fields above will be added automatically by the platform, you will not need to include them when creating the certificate store type.
158+
144159
- Click **Save** to save the new Store Type.
145160

146161
#### Add the Hashicorp Vault Certificate Store - **Key-Value Secrets Engine**
@@ -154,16 +169,19 @@ In Keyfactor Command create a new Certificate Store that resembles the one below
154169

155170
![](images/cert_store_fields.png)
156171

157-
- **Client Machine** - Enter the URL for the Vault host machine
172+
- **Client Machine** - Enter an identifier for the client machine. This could be the Orchestrator host name, or anything else useful. This value is not used by the extension.
158173
- **Store Path** - This is the path after mount point where the certs will be stored.
159174
- example: `kv-v2\kf-secrets\certname` would use the path "\kf-secrets"
160175
- **Mount Point** - This is the mount point name for the instance of the Key Value secrets engine.
161176
- If left blank, will default to "kv-v2".
162177
- If your organization utilizes Vault enterprise namespaces, you should include the namespace here.
163-
- **Vault Token** - This is the access token that will be used by the orchestrator for requests to Vault.
164-
- **Vault Server Url** - the full url and port of the Vault server instance
165178
- **Subfolder Inventory** - Set to 'True' if it is a requirement to inventory secrets at the subfolder/component level. The default, 'False' will inventory secrets stored at the root of the "Store Path", but will not look at secrets in subfolders. **Note** that there is a limit on the number of certificates that can be in a certificate store. In certain environments enabling Subfolder Inventory may exceed this limit and cause inventory job failure. Inventory job results are currently submitted to the Command platform as a single HTTP POST. There is not a specific limit on the number of certificates in a store, rather the limit is based on the size of the actual certificates and the HTTP POST size limit configured on the Command web server.
166179

180+
#### Set the server name and password
181+
182+
- The server name should be the full URL to the instance of Vault that will be accessible by the orchestrator. (example: `http://127.0.0.1:8200`)
183+
- The server password should be the Vault token that will be used for authenticating.
184+
167185
### For the Keyfactor and PKI plugins
168186

169187
- Add a new Certificate Store Type

hashicorp-vault-orchestrator.sln

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1414
readme_source.md = readme_source.md
1515
EndProjectSection
1616
EndProject
17+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "readme-src", "readme-src", "{3266961F-0B1D-4DB6-9A58-C0DA958EB832}"
18+
ProjectSection(SolutionItems) = preProject
19+
readme-pam-support.md = readme-pam-support.md
20+
EndProjectSection
21+
EndProject
1722
Global
1823
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1924
Debug|Any CPU = Debug|Any CPU
@@ -28,6 +33,9 @@ Global
2833
GlobalSection(SolutionProperties) = preSolution
2934
HideSolutionNode = FALSE
3035
EndGlobalSection
36+
GlobalSection(NestedProjects) = preSolution
37+
{3266961F-0B1D-4DB6-9A58-C0DA958EB832} = {83623EBF-AC4C-4158-922D-959AEFC75453}
38+
EndGlobalSection
3139
GlobalSection(ExtensibilityGlobals) = postSolution
3240
SolutionGuid = {F1706189-FE1B-4EE6-9AE1-EF4A777B2F06}
3341
EndGlobalSection
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2023 Keyfactor
2+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4+
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
5+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
6+
// and limitations under the License.
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.IO;
11+
using System.Linq;
12+
using System.Security.Cryptography;
13+
using System.Text;
14+
using Keyfactor.Logging;
15+
using Keyfactor.Orchestrators.Extensions;
16+
using Microsoft.Extensions.Logging;
17+
using Org.BouncyCastle.OpenSsl;
18+
using Org.BouncyCastle.Pkcs;
19+
20+
namespace Keyfactor.Extensions.Orchestrator.HashicorpVault
21+
{
22+
public static class CertUtility
23+
{
24+
public static List<CurrentInventoryItem> CurrentInventoryFromPkcs12(Pkcs12Store store)
25+
{
26+
var logger = LogHandler.GetClassLogger<HcvKeyValueClient>();
27+
28+
logger.MethodEntry();
29+
var certs = new List<CurrentInventoryItem>();
30+
31+
try
32+
{
33+
using (var memoryStream = new MemoryStream())
34+
{
35+
using (TextWriter streamWriter = new StreamWriter(memoryStream))
36+
{
37+
logger.LogTrace("Extracting Private Key...");
38+
var pemWriter = new PemWriter(streamWriter);
39+
logger.LogTrace("Created pemWriter...");
40+
var aliases = store.Aliases.Cast<string>().Where(a => store.IsKeyEntry(a));
41+
//logger.LogTrace($"Alias = {alias}");
42+
foreach (var alias in aliases)
43+
{
44+
var certInventoryItem = new CurrentInventoryItem { Alias = alias };
45+
46+
var entryCerts = new List<string>();
47+
logger.LogTrace("extracting public key");
48+
var publicKey = store.GetCertificate(alias).Certificate.GetPublicKey();
49+
var privateKeyEntry = store.GetKey(alias);
50+
if (privateKeyEntry != null) certInventoryItem.PrivateKeyEntry = true;
51+
pemWriter.WriteObject(publicKey);
52+
streamWriter.Flush();
53+
var publicKeyString = Encoding.ASCII.GetString(memoryStream.GetBuffer()).Trim()
54+
.Replace("\r", "").Replace("\0", "");
55+
entryCerts.Add(publicKeyString);
56+
57+
var pemChain = new List<string>();
58+
59+
logger.LogTrace("getting chain certs");
60+
61+
var chain = store.GetCertificateChain(alias).ToList();
62+
63+
chain.ForEach(c =>
64+
{
65+
var cert = c.Certificate.GetEncoded();
66+
var encoded = Pemify(Convert.ToBase64String(cert));
67+
pemChain.Add(encoded);
68+
});
69+
70+
if (chain.Count() > 0)
71+
{
72+
certInventoryItem.UseChainLevel = true;
73+
entryCerts.AddRange(pemChain);
74+
}
75+
certInventoryItem.Certificates = pemChain;
76+
certs.Add(certInventoryItem);
77+
}
78+
memoryStream.Close();
79+
streamWriter.Close();
80+
}
81+
logger.MethodExit();
82+
return certs;
83+
}
84+
}
85+
catch (Exception ex)
86+
{
87+
logger.LogError("error extracting certs from pkcs12", ex);
88+
throw;
89+
}
90+
}
91+
92+
public static Func<string, string> Pemify = base64Cert =>
93+
{
94+
string FormatBase64(string ss) =>
95+
ss.Length <= 64 ? ss : ss.Substring(0, 64) + "\n" + FormatBase64(ss.Substring(64));
96+
97+
string header = "-----BEGIN CERTIFICATE-----\n";
98+
string footer = "\n-----END CERTIFICATE-----";
99+
100+
return header + FormatBase64(base64Cert) + footer;
101+
};
102+
103+
public static string GenerateRandomString(int length)
104+
{
105+
using (Aes crypto = Aes.Create())
106+
{
107+
crypto.GenerateKey();
108+
return Convert.ToBase64String(crypto.Key).Substring(0, length);
109+
}
110+
}
111+
}
112+
}

hashicorp-vault-orchestrator/Constants.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2022 Keyfactor
1+
// Copyright 2023 Keyfactor
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
33
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
44
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,12 +13,28 @@ static class AzureKeyVaultConstants
1313
public const string PKI_STORE_TYPE = "HCV"; //same for Keyfactor plugin store type
1414
}
1515

16-
static class JobTypes
16+
static class JobType
1717
{
1818
public const string CREATE = "Create";
1919
public const string DISCOVERY = "Discovery";
2020
public const string INVENTORY = "Inventory";
2121
public const string MANAGEMENT = "Management";
2222
public const string REENROLLMENT = "Enrollment";
2323
}
24+
25+
static class StoreType
26+
{
27+
public const string HCVKVPEM = "HCVKVPEM";
28+
public const string KCVKVJKS = "HCVKVJKS";
29+
public const string HCVKVPKCS12 = "HCVKVP12";
30+
public const string HCVKVPFX = "HCVKVPFX";
31+
public const string HCVPKI = "HCVPKI";
32+
}
33+
34+
static class StoreFileExtensions {
35+
public const string HCVKVJKS = "_jks";
36+
public const string HCVKVPKCS12 = "_p12";
37+
public const string HCVKVPFX = "_pfx";
38+
public const string HCVKVPEM = "certificate";
39+
}
2440
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2023 Keyfactor
2+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
3+
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4+
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
5+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
6+
// and limitations under the License.
7+
8+
using System.Collections.Generic;
9+
using Keyfactor.Orchestrators.Extensions;
10+
11+
namespace Keyfactor.Extensions.Orchestrator.HashicorpVault
12+
{
13+
public interface IFileStore
14+
{
15+
string AddCertificate(string alias, string pfxPassword, string entryContents, bool includeChain, string certContent, string passphrase);
16+
string RemoveCertificate(string alias, string passphrase, string storeFileContent);
17+
byte[] CreateFileStore(string passphrase);
18+
IEnumerable<CurrentInventoryItem> GetInventory(Dictionary<string, object> certFields);
19+
}
20+
}

0 commit comments

Comments
 (0)