Skip to content

Commit 5928438

Browse files
updated read/write operations on kv-v1 to reflect that the secrets are _always_ stored as JSON in v1.
1 parent 16692ca commit 5928438

File tree

3 files changed

+54
-12
lines changed

3 files changed

+54
-12
lines changed

hashicorp-vault-orchestrator/FileStores/PfxFileStore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ public string AddCertificate(string alias, string pfxPassword, string entryConte
4545
var newCertBytes = Convert.FromBase64String(entryContents);
4646

4747
logger.LogTrace("adding the new certificate, and getting the new PFX store bytes.");
48-
var newJksBytes = AddOrRemoveCert(alias, pfxPassword, newCertBytes, pfxBytes, passphrase);
48+
var newPFXbytes = AddOrRemoveCert(alias, pfxPassword, newCertBytes, pfxBytes, passphrase);
4949

50-
return Convert.ToBase64String(newJksBytes);
50+
return Convert.ToBase64String(newPFXbytes);
5151
}
5252
public string RemoveCertificate(string alias, string passphrase, string storeFileContent)
5353
{

hashicorp-vault-orchestrator/HcvKeyValueClient.cs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ private async Task CreateFileStore()
9999

100100
var certSecretIsJSON = !string.IsNullOrEmpty(_certPropName);
101101
if (certSecretIsJSON) logger.LogTrace($"the certificate data will be stored as a JSON object with the base64 encoded cert stored in the property '{_certPropName}'");
102-
102+
else logger.LogTrace($"the certificate data will be stored as the entire secret content at '{certParentPath}/{certSecretName}' and contain the base64 encoded cert.");
103103
var passphraseSecretIsJSON = !string.IsNullOrEmpty(_passphrasePropName);
104104
if (passphraseSecretIsJSON) logger.LogTrace($"the passphrase secret will be stored as a JSON object with the passphrase in the property '{_passphrasePropName}'");
105-
105+
else logger.LogTrace($"the passphrase string will be stored as the entire secret content at '{passphraseParentPath}/{passphraseSecretName}'");
106106
switch (_storeType)
107107
{
108108
case StoreType.HCVKVPFX:
@@ -131,6 +131,13 @@ private async Task CreateFileStore()
131131

132132
try
133133
{
134+
var kvVersion = await GetKVVersionAsync();
135+
if (!certSecretIsJSON && kvVersion == 1)
136+
{
137+
_certPropName = "value"; // kv v1 secrets are _always_ stored as JSON; setting generic "value" property
138+
certSecretIsJSON = true;
139+
}
140+
134141
// create the cert secret
135142
Dictionary<string, object> certSecretContent;
136143
var pathToWriteCert = string.Empty;
@@ -141,7 +148,7 @@ private async Task CreateFileStore()
141148
{
142149
// this means the cert should be stored as a JSON object with property _certPropName, as opposed to a raw base64 string.
143150
certSecretContent = new Dictionary<string, object> { { _certPropName, Convert.ToBase64String(newStoreBytes) } }; // the content includes the property name
144-
pathToWriteCert = certParentPath + certSecretName; // we write to the secret
151+
pathToWriteCert = $"{certParentPath}/{certSecretName}"; // we write to the secret
145152
}
146153
else
147154
{
@@ -161,13 +168,19 @@ private async Task CreateFileStore()
161168

162169
// create the passphrase secret
163170

171+
if (!passphraseSecretIsJSON && kvVersion == 1)
172+
{
173+
_passphrasePropName = "value"; // kv v1 secrets are _always_ stored as JSON; setting generic "value" property
174+
passphraseSecretIsJSON = true;
175+
}
176+
164177
Dictionary<string, object> passphraseSecretContent;
165178
var pathToWritePassphrase = string.Empty;
166179

167180
if (passphraseSecretIsJSON)
168181
{
169182
passphraseSecretContent = new Dictionary<string, object> { { _passphrasePropName, passphrase } };
170-
pathToWritePassphrase = passphraseParentPath + passphraseSecretName;
183+
pathToWritePassphrase = $"{passphraseParentPath}/{passphraseSecretName}";
171184
}
172185
else
173186
{
@@ -394,7 +407,6 @@ public async Task<CurrentInventoryItem> GetCertificateFromPemStore(string key)
394407
return (vaultPaths, warnings);
395408
}
396409

397-
398410
public async Task PutCertificate(string certName, string contents, string pfxPassword, string certPath, string certPropName, string keyPath, string keyPropName, bool includeChain)
399411
{
400412
logger.MethodEntry();
@@ -943,8 +955,10 @@ private async Task<List<string>> GetSubPaths(string storagePath)
943955

944956
private async Task<(string, string)> GetCertificateAndPassphrase()
945957
{
958+
946959
(var certParentPath, var certSecretName, var passphraseParentPath, var passphraseSecretName) = ParsedSecretPaths();
947960
var certSecretIsJSON = !string.IsNullOrEmpty(_certPropName);
961+
948962
var passphraseSecretIsJSON = !string.IsNullOrEmpty(_passphrasePropName);
949963

950964
string certContent = string.Empty;
@@ -954,6 +968,22 @@ private async Task<List<string>> GetSubPaths(string storagePath)
954968
// first get cert contents
955969
try
956970
{
971+
var kvVersion = await GetKVVersionAsync();
972+
973+
if (kvVersion == 1) // in the key-value secrets engine v1; all secrets are stored as JSON
974+
{
975+
if (!certSecretIsJSON)
976+
{
977+
_certPropName = "value";
978+
certSecretIsJSON = true;
979+
}
980+
if (!passphraseSecretIsJSON)
981+
{
982+
_passphrasePropName = "value";
983+
passphraseSecretIsJSON = true;
984+
}
985+
}
986+
957987
logger.LogTrace($"cert secret name {certSecretName}");
958988
logger.LogTrace($"retreiving the certificate store secret at {certParentPath + "/" + certSecretName} from the Key-Value secrets engine mounted at {_mountPoint}..");
959989
logger.LogTrace($"the cert is {(certSecretIsJSON ? "" : "not")} a JSON property.");
@@ -1123,12 +1153,12 @@ public async Task<Dictionary<string, object>> ReadSecretAutoAsync(
11231153
}
11241154
else // v1
11251155
{
1126-
Secret<Dictionary<string, object>> secret = null;
1156+
logger.LogTrace($"making request to read secret at {mountPoint}{path}..");
11271157

11281158
var secretv1 = await _vaultClient.V1.Secrets.KeyValue.V1.ReadSecretAsync(
11291159
path,
11301160
mountPoint: mountPoint);
1131-
1161+
logger.LogTrace($"response: {JsonConvert.SerializeObject(secretv1)}");
11321162
return secretv1.Data;
11331163
}
11341164
}
@@ -1234,17 +1264,25 @@ await _vaultClient.V1.Secrets.KeyValue.V2.PatchSecretAsync(
12341264
}
12351265
else // v1
12361266
{
1267+
Dictionary<string, object> existing = null;
12371268
// KV v1 requires read-modify-write
1238-
var existing = await ReadSecretAutoAsync(path, mountPoint);
1239-
1269+
try
1270+
{
1271+
existing = await ReadSecretAutoAsync(path, mountPoint);
1272+
}
1273+
catch (VaultApiException ex) {
1274+
if (ex.StatusCode != 404) throw;
1275+
// if it's not found, that's ok. we'll create a new secret
1276+
}
1277+
if (existing == null) existing = new Dictionary<string, object>();
12401278
// Merge with new data
12411279
foreach (var kvp in keysToUpdate)
12421280
{
12431281
existing[kvp.Key] = kvp.Value;
12441282
}
12451283

12461284
// Write back the merged data
1247-
await WriteSecretAutoAsync(path, existing as Dictionary<string, object>, mountPoint);
1285+
await WriteSecretAutoAsync(path, existing, mountPoint);
12481286
}
12491287
}
12501288
catch (VaultApiException ex)

hashicorp-vault-orchestrator/Jobs/JobBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ public void Initialize(DiscoveryJobConfiguration config)
117117
logger.LogTrace($"Directories to search (mount point): {JobParameters.MountPoint}");
118118
logger.LogTrace($"Enterprise Namespace: {JobParameters.Namespace}");
119119
logger.LogTrace($"Directories to ignore (subpath to search): {subPath}");
120+
120121
InitProps(config.JobProperties, config.Capability);
122+
123+
LogInitValues();
121124
}
122125
public void Initialize(ManagementJobConfiguration config)
123126
{
@@ -130,6 +133,7 @@ public void Initialize(ManagementJobConfiguration config)
130133
JobParameters.StorePath = config.CertificateStoreDetails.StorePath;
131134
dynamic props = JsonConvert.DeserializeObject(config.CertificateStoreDetails.Properties.ToString());
132135
InitProps(props, config.Capability);
136+
LogInitValues();
133137
}
134138

135139
private async void InitProps(dynamic props, string capability)

0 commit comments

Comments
 (0)