-
Notifications
You must be signed in to change notification settings - Fork 0
Retreive role name (product ID) from metadata if available #7
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
Changes from all commits
50ad68e
cb9b021
3d4276f
8e1dcd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| ## 1.0.1 | ||
| * added retrieval of roles associated with enrolled certificates via metadata for Vault Enterprise users | ||
|
|
||
| ## 1.0.0 | ||
| * initial release |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright 2025 Keyfactor | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
| // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions | ||
| // and limitations under the License. | ||
|
|
||
| using System; | ||
| using System.Text.Json.Serialization; | ||
|
|
||
| namespace Keyfactor.Extensions.CAPlugin.HashicorpVault.APIProxy | ||
| { | ||
| public class MetadataResponse | ||
| { | ||
| [JsonPropertyName("issuer_id")] | ||
| public string IssuerId { get; set; } | ||
|
|
||
| [JsonPropertyName("expiration")] | ||
| public DateTime? Expiration { get; set; } | ||
|
|
||
| [JsonPropertyName("cert_metadata")] | ||
| public string CertMetadata { get; set; } | ||
|
|
||
| [JsonPropertyName("role")] | ||
| public string Role { get; set; } | ||
|
|
||
| [JsonPropertyName("serial_number")] | ||
| public string SerialNumber { get; set; } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| // Copyright 2024 Keyfactor | ||
| // Copyright 2025 Keyfactor | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
| // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, | ||
|
|
@@ -246,6 +246,41 @@ public async Task<List<string>> GetRoleNamesAsync() | |
| finally { logger.MethodExit(); } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Retreives the metadata for the certificate | ||
| /// </summary> | ||
| /// <param name="certSerial"></param> | ||
| /// <returns></returns> | ||
| public async Task<MetadataResponse> GetCertMetadata(string certSerial) | ||
| { | ||
| logger.MethodEntry(); | ||
|
|
||
| try | ||
| { | ||
| var res = await _vaultHttp.GetAsync<WrappedResponse<MetadataResponse>>($"cert-metadata/{certSerial}"); | ||
| var md = res?.Data; | ||
| if (md != null) | ||
| { | ||
| logger.LogTrace($"got response from cert-metadata"); | ||
| logger.LogTrace($"serial number: {md.SerialNumber}"); | ||
| logger.LogTrace($"issuer id: {md.IssuerId}"); | ||
| logger.LogTrace($"expiration: {md.Expiration}"); | ||
| logger.LogTrace($"metadata: {md.CertMetadata}"); | ||
| logger.LogTrace($"role: {md.Role}"); | ||
| } | ||
| else { | ||
| logger.LogTrace($"no metadata associated with cert {certSerial} could be found."); | ||
| } | ||
| return md; | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| logger.LogError($"an error occurred when attempting to retreive the certificate metadata: {ex.Message}"); | ||
|
||
| throw; | ||
| } | ||
| finally { logger.MethodExit(); } | ||
| } | ||
|
|
||
| private void SetClientValuesFromConfigs(HashicorpVaultCAConfig caConfig, HashicorpVaultCATemplateConfig templateConfig) | ||
| { | ||
| logger.MethodEntry(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| // Copyright 2024 Keyfactor | ||
| // Copyright 2025 Keyfactor | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
| // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, | ||
|
|
@@ -26,7 +26,7 @@ | |
| private readonly ILogger logger; | ||
| private HashicorpVaultCAConfig _caConfig { get; set; } | ||
| private HashicorpVaultClient _client { get; set; } | ||
| private ICertificateDataReader _certificateDataReader; | ||
|
Check warning on line 29 in hashicorp-vault-cagateway/HashicorpVaultCAConnector.cs
|
||
| private JsonSerializerOptions _serializerOptions; | ||
|
|
||
| public HashicorpVaultCAConnector() | ||
|
|
@@ -263,7 +263,7 @@ | |
| } | ||
| logger.LogTrace($"converting {certSerial} to database trackingId"); | ||
|
|
||
| var trackingId = certSerial.Replace(":", "-"); // we store with '-'; hashi stores with ':' | ||
| var trackingId = certSerial.Replace(":", "-"); // we store with '-'; hashi stores with ':' | ||
|
|
||
| // then, check for an existing local entry | ||
| try | ||
|
|
@@ -280,14 +280,33 @@ | |
| { | ||
| logger.LogTrace($"adding cert with serial {trackingId} to the database. fullsync is {fullSync}, and the certificate {(dbStatus == -1 ? "does not yet exist" : "already exists")} in the database."); | ||
|
|
||
| logger.LogTrace("attempting to retreive the role name (productId) from the certificate metadata, if available"); | ||
joevanwanzeeleKF marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| var metaData = new MetadataResponse(); | ||
|
|
||
| try | ||
| { | ||
| metaData = await _client.GetCertMetadata(certSerial); | ||
| } | ||
| catch (Exception) | ||
| { | ||
| logger.LogTrace("an error occurred when attempting to retreive the metadata, continuing.."); | ||
|
||
| } | ||
|
|
||
| var newCert = new AnyCAPluginCertificate | ||
| { | ||
| CARequestID = trackingId, | ||
| Certificate = certFromVault.Certificate, | ||
| Status = certFromVault.RevocationTime != null ? (int)EndEntityStatus.REVOKED : (int)EndEntityStatus.GENERATED, | ||
| RevocationDate = certFromVault.RevocationTime, | ||
| RevocationDate = certFromVault.RevocationTime, | ||
| }; | ||
|
|
||
| // if we were able to get the role name from metadata, we include it | ||
| if (!string.IsNullOrEmpty(metaData?.Role)) | ||
| { | ||
| newCert.ProductID = metaData.Role; | ||
| } | ||
|
|
||
| try | ||
| { | ||
| logger.LogTrace($"writing the result."); | ||
|
|
@@ -327,8 +346,9 @@ | |
| /// </summary> | ||
| /// <param name="connectionInfo">The information used to connect to the CA.</param> | ||
| public async Task ValidateCAConnectionInfo(Dictionary<string, object> connectionInfo) | ||
| { | ||
| { | ||
| logger.MethodEntry(); | ||
| logger.LogTrace(message: $"Validating CA connection info: {JsonSerializer.Serialize(connectionInfo)}"); | ||
|
|
||
| // first, we check to see if the CA Gateway is enabled in the configuration | ||
| if (!(bool)connectionInfo[Constants.CAConfig.ENABLED]) | ||
|
|
@@ -352,7 +372,10 @@ | |
|
|
||
| // make sure an authentication mechanism is defined (either certificate or token) | ||
| var token = connectionInfo[Constants.CAConfig.TOKEN] as string; | ||
| var cert = connectionInfo[Constants.CAConfig.CLIENTCERT] as string; | ||
|
|
||
| //var cert = connectionInfo[Constants.CAConfig.CLIENTCERT] as string; | ||
|
|
||
| var cert = string.Empty; // temporary until client cert auth into vault is implemented | ||
|
|
||
| if (string.IsNullOrEmpty(token) && string.IsNullOrEmpty(cert)) | ||
| { | ||
|
|
@@ -422,14 +445,17 @@ | |
| public Task ValidateProductInfo(EnrollmentProductInfo productInfo, Dictionary<string, object> connectionInfo) | ||
| { | ||
| logger.MethodEntry(); | ||
|
|
||
| logger.LogTrace($"validating product info: {JsonSerializer.Serialize(productInfo)}"); | ||
|
|
||
| List<string> errors = new List<string>(); | ||
|
|
||
| HashicorpVaultCATemplateConfig templateConfig = null; | ||
| HashicorpVaultCAConfig caConfig = null; | ||
| // deserialize the values | ||
| try | ||
| { | ||
| templateConfig = JsonSerializer.Deserialize<HashicorpVaultCATemplateConfig>(JsonSerializer.Serialize(productInfo)); | ||
| templateConfig = JsonSerializer.Deserialize<HashicorpVaultCATemplateConfig>(JsonSerializer.Serialize(productInfo.ProductParameters)); | ||
| caConfig = JsonSerializer.Deserialize<HashicorpVaultCAConfig>(JsonSerializer.Serialize(connectionInfo)); | ||
| logger.LogTrace("successfully deserialized the product and CA config values."); | ||
| } | ||
|
|
@@ -439,12 +465,7 @@ | |
| logger.LogError(LogHandler.FlattenException(ex)); | ||
| throw; | ||
| } | ||
| // make sure Role Name is present in the template config | ||
| if (string.IsNullOrEmpty(productInfo.ProductParameters[Constants.TemplateConfig.ROLENAME] as string)) | ||
| { | ||
| errors.Add($"The '{Constants.TemplateConfig.ROLENAME}' is required."); | ||
| } | ||
|
|
||
|
|
||
| // if any errors, throw | ||
| if (errors.Any()) | ||
| { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.