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

Combine chain certs #19

Merged
merged 54 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
7c84f59
updated to support 2 store types. HCVKV and HCV.
joevanwanzeeleKF Feb 17, 2023
8bd698e
Updated to distinguish between multiple supported store types.
joevanwanzeeleKF Mar 20, 2023
b5ca9f1
Fixed store path and mount point mapping
joevanwanzeeleKF Mar 20, 2023
ef57edd
updated doc to reflect multiple store type configs.
joevanwanzeeleKF Mar 28, 2023
3cffae8
Merge branch 'release-2.0' into changes-before-public
joevanwanzeeleKF Mar 28, 2023
35d86ce
Updated to new workflow
Mar 28, 2023
3fd7d6e
Merge pull request #10 from Keyfactor/update-workflow
fiddlermikey Mar 28, 2023
65506fd
Update generated README
Mar 28, 2023
9d92127
add apache license header
Mar 28, 2023
3151ede
Merge branch 'changes-before-public' of https://github.com/Keyfactor/…
Mar 28, 2023
ce9d231
Only trimming leading slashes from the store path now.
joevanwanzeeleKF Apr 13, 2023
8b84ad9
updated documentation to store Vault token as a secret instead of pla…
joevanwanzeeleKF Apr 13, 2023
a57c2db
Update generated README
Apr 13, 2023
4ef2e3e
removed sensitive info from tracelog.
joevanwanzeeleKF Apr 17, 2023
8e8c7d6
Merge branch 'kv-sub-path-support' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF Apr 17, 2023
3970213
Update generated README
Apr 17, 2023
e803643
Fixed issue with path not being resolved before attempting to write c…
joevanwanzeeleKF Apr 19, 2023
098bdc9
Merge branch 'kv-sub-path-support' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF Apr 19, 2023
1b58671
Update generated README
Apr 19, 2023
d1b34c4
Removed KEY_SECRET from PutCertificate Task
afolsom-kf Apr 21, 2023
ef9e7b4
Modified PutCertificate to include ---BEGIN ----END banners (for key+…
afolsom-kf Apr 21, 2023
edeb7a6
Merge pull request #13 from afolsom-kf/KV-HCVault-Saving
joevanwanzeeleKF Apr 21, 2023
cc81f01
Allows for Recursive subfolder inventory
afolsom-kf May 1, 2023
a2eb304
Merge pull request #14 from afolsom-kf/Subfolder-Inventory
joevanwanzeeleKF May 2, 2023
87a1d11
Update generated README
May 2, 2023
af822db
Updated readme_source with documentation changes.
joevanwanzeeleKF May 2, 2023
28291c0
updated screenshots
joevanwanzeeleKF May 2, 2023
4f574db
Merge branch 'kv-sub-path-support' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF May 2, 2023
ac54067
Update generated README
May 2, 2023
27cd1dc
Update readme to call out cert store limits
RexWheeler May 2, 2023
a0962e2
Update generated README
May 2, 2023
8e8d248
Adding InputValidation for KeyValue secrets
afolsom-kf May 8, 2023
e0c863c
Merge pull request #16 from afolsom-kf/bugfix-HCKF-InputValidationSec…
joevanwanzeeleKF May 15, 2023
b474f6d
Update generated README
May 15, 2023
535a302
updated screenshot to reflect token as a secret.
joevanwanzeeleKF May 18, 2023
40e4105
Merge branch 'kv-sub-path-support' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF May 18, 2023
df4fd98
including certificate chain when enrolling via platform.
joevanwanzeeleKF May 31, 2023
c2122a8
Update generated README
May 31, 2023
3a7015e
added flag on store type to indicate whether to include cert chain
joevanwanzeeleKF May 31, 2023
43b0d51
Merge branch 'include-pem-chain' of https://github.com/Keyfactor/hash…
joevanwanzeeleKF May 31, 2023
348ec25
Update generated README
May 31, 2023
ce47d0d
fixed issue when checking for revocation time for inventory.
joevanwanzeeleKF Jun 14, 2023
b763f1c
Merge branch 'include-pem-chain' of https://github.com/Keyfactor/hash…
joevanwanzeeleKF Jun 14, 2023
9cc3aed
Updated property names. now including full chain in ca_chain field.
joevanwanzeeleKF Jun 14, 2023
4bc043e
Update generated README
Jun 14, 2023
5f59202
updated CHANGELOG
joevanwanzeeleKF Jun 14, 2023
22f4286
Merge branch 'combine_chain_certs' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF Jun 14, 2023
9409f53
fixed issue with revocation time check.
joevanwanzeeleKF Jun 16, 2023
8811685
updated fields. the full chain is now stored in certificate if selec…
joevanwanzeeleKF Jun 19, 2023
e7a14f6
Update generated README
Jun 19, 2023
d5e6f25
Fixed issue where improperly formatted secrets would cause inventory …
joevanwanzeeleKF Jun 20, 2023
2440362
Merge branch 'combine_chain_certs' of https://github.com/Keyfactor/ha…
joevanwanzeeleKF Jun 20, 2023
6f56a64
Merge branch '43934-dev-2.0.0' into combine_chain_certs
joevanwanzeeleKF Jun 21, 2023
0df56bb
Update generated README
Jun 21, 2023
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/hashicorp-vault-orchestrator/hashicorp-vault-orchestrator.csproj.user
.vs
*.licenseheader
README.md
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
2.0.1

* Added support for storing certs in sub-paths
* Updated documentation to specify storing the token as a secret.

* **Breaking Change**: the properties have been renamed from:
* `PUBLIC_KEY` to `certificate`
* `PRIVATE_KEY` to `private_key`
* `PUBLIC_KEY_<n>` has been removed. Now the chain is stored in `certificate` if the option is selected.

* **Breaking Change**: Added a flag on the Keyfactor Certificate store definition to indicate whether to store the full CA chain along with the certificate

2.0

* Added inventory job support for the Hashicorp PKI secrets engine
* Added inventory job support for the Keyfactor secrets engine

* **Breaking Change**: the cert store types are now:
* **HCVPKI** for the PKI and Keyfactor secrets engine
* **HCVKV** for the Key-Value secrets engine
* **HCVKV** for the Key-Value secrets engine
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,10 @@ This integration was built on the .NET Core 3.1 target framework and are compati

1. For the Key-Value secrets engine, the certificates are stored as an entry with these fields.

- `PUBLIC_KEY` - The certificate public key
- `PUBLIC_KEY_<n>` - The nth certificate in the chain
- `PRIVATE_KEY` - The certificate private key
- `certificate` - The PEM formatted certificate and intermediate CA chain (if selected)
- `private_key` - The certificate private key

**Note**: Key/Value secrets that do not include these keys (PUBLIC_KEY, and PRIVATE_KEY), will be ignored during inventory scans.
**Note**: Key/Value secrets that do not include the keys `certificate` and `private_key` will be ignored during inventory scans.

## Extension Configuration

Expand Down
85 changes: 45 additions & 40 deletions hashicorp-vault-orchestrator/HcvKeyValueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)
Secret<SecretData> res;
var fullPath = _storePath + key;
var relativePath = fullPath.Substring(_storePath.Length);

try
{
try
Expand All @@ -102,7 +103,8 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)
}
catch (Exception ex)
{
logger.LogWarning($"Error getting certificate (deleted?) {fullPath}", ex);
logger.LogError($"Error getting certificate {fullPath}", ex);

return null;
}

Expand All @@ -116,42 +118,49 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)

try
{
string publicKey;
bool hasPrivateKey;
string certificate = null;

//Validates if the "PUBLIC_KEY" and "PRIVATE_KEY" keys exist in certData
if (certData.TryGetValue("PUBLIC_KEY", out object publicKeyObj))
//Validates if the "certificate" and "private_key" keys exist in certData
if (certData.TryGetValue("certificate", out object publicKeyObj))
{
publicKey = publicKeyObj?.ToString();
certificate = publicKeyObj as string;
}
else
{
publicKey = null;

var certs = new List<string>() { certificate };

certData.TryGetValue("private_key", out object privateKeyObj);

// if either field is missing, don't include it in inventory

if (publicKeyObj == null || privateKeyObj == null) return null;

//split the chain entries (if chain is included)

var certFooter = "\n-----END CERTIFICATE-----";

certs = certificate.Split(new string[] { certFooter }, StringSplitOptions.RemoveEmptyEntries).ToList();

for (int i = 0; i<certs.Count(); i++) {
certs[i] = certs[i] + certFooter;
}

if (certData.TryGetValue("PRIVATE_KEY", out object privateKeyObj))
// if the certs have not been revoked, include them

if (certs.Count() > 0)
{
hasPrivateKey = true;
return new CurrentInventoryItem()
{
Alias = key,
PrivateKeyEntry = privateKeyObj != null,
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
UseChainLevel = certs.Count() > 1,
Certificates = certs
};
}
else
{
hasPrivateKey = false;
return null;
}

var certs = new List<string>() { publicKey };

var keys = certData.Keys.Where(k => k.StartsWith("PUBLIC_KEY_")).ToList();

keys.ForEach(k => certs.Add(certData[k].ToString()));

return new CurrentInventoryItem()
{
Alias = relativePath,
PrivateKeyEntry = hasPrivateKey,
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
UseChainLevel = true,
Certificates = certs.ToArray()
};
}
catch (Exception ex)
{
Expand Down Expand Up @@ -190,7 +199,7 @@ public async Task PutCertificate(string certName, string contents, string pfxPas
{
VaultClient.V1.Auth.ResetVaultToken();

var certDict = new Dictionary<string, string>();
var certDict = new Dictionary<string, object>();

var pfxBytes = Convert.FromBase64String(contents);
Pkcs12Store p;
Expand Down Expand Up @@ -225,7 +234,7 @@ public async Task PutCertificate(string certName, string contents, string pfxPas
streamWriter.Flush();
privateKeyString = Encoding.ASCII.GetString(memoryStream.GetBuffer()).Trim()
.Replace("\r", "").Replace("\0", "");
// logger.LogTrace($"Got Private Key String {privateKeyString}");

logger.LogTrace($"Got Private Key String");
memoryStream.Close();
streamWriter.Close();
Expand All @@ -250,21 +259,17 @@ public async Task PutCertificate(string certName, string contents, string pfxPas

try
{
certDict.Add("PRIVATE_KEY", privateKeyString);
certDict.Add("PUBLIC_KEY", pubCertPem);
certDict.Add("private_key", privateKeyString);

// certDict.Add("revocation_time", 0);

if (includeChain)
{
var i = 1;
pemChain.ForEach(pc =>
{
if (pc != pubCertPem)
{
certDict.Add($"PUBLIC_KEY_{i}", pc);
i++;
}
});

certDict.Add("certificate", String.Join("\n", pemChain));
}
else {
certDict.Add("certificate", pubCertPem);
}
}
catch (Exception ex)
Expand Down
38 changes: 22 additions & 16 deletions hashicorp-vault-orchestrator/HcvKeyfactorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,42 +55,48 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)
req.Method = WebRequestMethods.Http.Get;
var res = await req.GetResponseAsync();
CertResponse content = JsonConvert.DeserializeObject<CertResponse>(new StreamReader(res.GetResponseStream()).ReadToEnd());
string cert;
content.data.TryGetValue("certificate", out cert);

content.data.TryGetValue("certificate", out object cert);
content.data.TryGetValue("ca_chain", out object caChain);
content.data.TryGetValue("private_key", out object privateKey);
content.data.TryGetValue("revocation_time", out object revokeTime);

string issuingCA;
content.data.TryGetValue("issuing_ca", out issuingCA);
List<string> certList = new List<string>() { cert as string };

string privateKey;
content.data.TryGetValue("private_key", out privateKey);
// if the chain is available, include all certs

string revokeTime;
content.data.TryGetValue("revocation_time", out revokeTime);

if (!string.IsNullOrEmpty(caChain as string))
{
string fullChain = caChain.ToString();
certList = fullChain.Split(new string[] { "\n\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
}

// don't include them in inventory unless they haven't been revoked

if (revokeTime.Equals("0"))
if (revokeTime == null || Equals(revokeTime.ToString(), "0"))
{
var inventoryItem = new CurrentInventoryItem()
{
Alias = key,
Certificates = new string[] { cert },
Certificates = certList,
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
PrivateKeyEntry = !string.IsNullOrEmpty(privateKey),
UseChainLevel = !string.IsNullOrEmpty(issuingCA),
PrivateKeyEntry = !string.IsNullOrEmpty(privateKey as string),
UseChainLevel = !string.IsNullOrEmpty(caChain as string),
};
return inventoryItem;
}
return null;
}
catch (Exception ex)
{
logger.LogWarning("Error getting certificate (deleted?)", ex);
logger.LogWarning($"Error getting certificate \"{fullPath}\" from Vault", ex);

return null;
}
}
catch (Exception ex)
{
logger.LogError("Error getting certificate from Vault", ex);
logger.LogError($"Error getting certificate \"{fullPath}\" from Vault", ex);
throw;
}
}
Expand Down Expand Up @@ -153,7 +159,7 @@ public class HashiResponse

public class CertResponse : HashiResponse
{
public Dictionary<string, string> data { get; set; }
public Dictionary<string, object> data { get; set; }
}

public class ListResponse : HashiResponse
Expand Down
Binary file modified images/vault_cli_read.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions readme_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ This integration was built on the .NET Core 3.1 target framework and are compati

1. For the Key-Value secrets engine, the certificates are stored as an entry with these fields.

- `PUBLIC_KEY` - The certificate public key
- `PUBLIC_KEY_<n>` - The nth certificate in the chain
- `PRIVATE_KEY` - The certificate private key
- `certificate` - The PEM formatted certificate and intermediate CA chain (if selected)
- `private_key` - The certificate private key

**Note**: Key/Value secrets that do not include these keys (PUBLIC_KEY, and PRIVATE_KEY), will be ignored during inventory scans.
**Note**: Key/Value secrets that do not include the keys `certificate` and `private_key` will be ignored during inventory scans.

## Extension Configuration

Expand Down
Loading