Skip to content

Commit

Permalink
Updated property names. now including full chain in ca_chain field.
Browse files Browse the repository at this point in the history
  • Loading branch information
joevanwanzeeleKF committed Jun 14, 2023
1 parent b763f1c commit 9cc3aed
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 60 deletions.
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
75 changes: 35 additions & 40 deletions hashicorp-vault-orchestrator/HcvKeyValueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)
Dictionary<string, object> certData;
Secret<SecretData> res;
var fullPath = _storePath + key;
var relativePath = fullPath.Substring(_storePath.Length);
//var relativePath = fullPath.Substring(_storePath.Length);
try
{
try
Expand All @@ -102,7 +102,7 @@ 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 +116,45 @@ public async Task<CurrentInventoryItem> GetCertificate(string key)

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

//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();
}
else
{
publicKey = null;
certificate = publicKeyObj as string;
}

if (certData.TryGetValue("PRIVATE_KEY", out object privateKeyObj))
{
hasPrivateKey = true;
}
else
var certs = new List<string>() { certificate };

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

if (certData.TryGetValue("ca_chain", out object caChainObj))
{
hasPrivateKey = false;
caChain = caChainObj?.ToString();
}

var certs = new List<string>() { publicKey };
certData.TryGetValue("revocation_time", out object revocationTime);

var keys = certData.Keys.Where(k => k.StartsWith("PUBLIC_KEY_")).ToList();
certs = !string.IsNullOrEmpty(caChain) ? caChain.Split(new string[] { "\n\n" }, StringSplitOptions.RemoveEmptyEntries).ToList() : certs;

keys.ForEach(k => certs.Add(certData[k].ToString()));
// if the certs have not been revoked, include them

return new CurrentInventoryItem()
if (!string.IsNullOrEmpty(certificate) && (revocationTime == null || revocationTime.Equals(0)))
{
Alias = relativePath,
PrivateKeyEntry = hasPrivateKey,
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
UseChainLevel = true,
Certificates = certs.ToArray()
};
return new CurrentInventoryItem()
{
Alias = key,
PrivateKeyEntry = privateKeyObj != null,
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
UseChainLevel = true,
Certificates = certs
};
}
else
{
return null;
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -190,7 +193,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 @@ -250,21 +253,13 @@ 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("certificate", pubCertPem);
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("ca_chain", String.Join("\n\n", pemChain));
}
}
catch (Exception ex)
Expand Down
37 changes: 21 additions & 16 deletions hashicorp-vault-orchestrator/HcvKeyfactorClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,42 +55,47 @@ 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 || revokeTime.Equals(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 +158,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.
9 changes: 5 additions & 4 deletions readme_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ 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
- `ca_chain` - The full certificate authority chain, including the certificate
- `private_key` - The certificate private key
- `revocation_time` - a value other than "0" indicates the time that a certificate was revoked.

**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

0 comments on commit 9cc3aed

Please sign in to comment.