From e278f7907be0ff09986d69b0eaf425a1f68fd64d Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:30:28 -0700 Subject: [PATCH 01/32] feat(logging): Log obfuscated token request body and raw error response Logs the token endpoint request body (with password/client_secret redacted) and the raw response body on non-2xx status codes to aid troubleshooting of authentication failures without exposing credentials. --- CHANGELOG.md | 5 +++++ delinea-secretserver-pam/SecretServerPam.cs | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c741179..d950529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v1.3.0 + +## Improvements +- Enhanced debug logging for token endpoint requests: the obfuscated request body (credentials redacted) and full raw response body are now logged on token request failures to aid troubleshooting. + # v1.2.0 ## Features diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 5b43eb2..e0e97de 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -257,6 +257,12 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio Logger.LogTrace("Authentication request grant type ${GrantType}", body["grant_type"]); + var loggableBody = new Dictionary(body); + foreach (var sensitiveKey in new[] { "password", "client_secret" }) + if (loggableBody.ContainsKey(sensitiveKey)) + loggableBody[sensitiveKey] = "***"; + Logger.LogDebug("Token request body: {RequestBody}", JsonConvert.SerializeObject(loggableBody)); + HttpResponseMessage response; var tokeUrl = $"{configurationInfo.SecretServerUrl}/oauth2/token"; @@ -269,7 +275,14 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio .ConfigureAwait(false); Logger.LogDebug("Request sent"); - response.EnsureSuccessStatusCode(); + if (!response.IsSuccessStatusCode) + { + var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + Logger.LogError( + "Token request failed with status {StatusCode}. Raw response body: {ResponseBody}", + (int)response.StatusCode, errorBody); + response.EnsureSuccessStatusCode(); + } } catch (HttpRequestException ex) From f466fe8980d62af1ca940da523fd0b1b9c41a2ec Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:57:56 -0700 Subject: [PATCH 02/32] chore(security): Exclude sensitive local files from version control Adds .env, scripts/, and client_pam.json to .gitignore to prevent accidental commit of credentials, bearer tokens, and local test output. --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f173162..4b044f4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ obj/ riderModule.iml /_ReSharper.Caches/ .idea/* -.vs/ \ No newline at end of file +.vs/ +.env +scripts/ +client_pam.json \ No newline at end of file From 0637a8919e63a2d65e1214b811c421e8864b1e0e Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:58:03 -0700 Subject: [PATCH 03/32] chore(deps): Bump TestConsole target framework and global SDK to .NET 10 --- TestConsole/TestConsole.csproj | 2 +- global.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TestConsole/TestConsole.csproj b/TestConsole/TestConsole.csproj index f6e4fb6..83f7f4b 100644 --- a/TestConsole/TestConsole.csproj +++ b/TestConsole/TestConsole.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net10.0 enable enable Linux diff --git a/global.json b/global.json index fc4a588..35bdbc7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.0", + "version": "10.0.0", "rollForward": "latestFeature", "allowPrerelease": false } From cffba6bff33069e87e48ef6055581ea30ebbee58 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:58:12 -0700 Subject: [PATCH 04/32] refactor(config): Remove dead IValidatableObject implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validate() was never invoked — validation is enforced imperatively in ValidateServerConfigurationParams() and ValidateInstanceParams(). Calling Validator.TryValidateObject() would also incorrectly fail for the client_credentials flow (which stores GrantType="password" internally to satisfy the Delinea API). Data annotation attributes are retained for documentation value. --- .../Models/DelineaConfiguration.cs | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/delinea-secretserver-pam/Models/DelineaConfiguration.cs b/delinea-secretserver-pam/Models/DelineaConfiguration.cs index 3db69b8..df56cf4 100644 --- a/delinea-secretserver-pam/Models/DelineaConfiguration.cs +++ b/delinea-secretserver-pam/Models/DelineaConfiguration.cs @@ -14,7 +14,7 @@ namespace Keyfactor.Extensions.Pam.Delinea.Models /// Configuration class for connecting to and retrieving secrets from Delinea Secret Server. /// Supports authentication via username/password or client credentials. /// - internal class DelineaConfiguration : IValidatableObject + internal class DelineaConfiguration { /// /// Initializes a new instance of the class with empty strings. @@ -123,44 +123,5 @@ public DelineaConfiguration() ErrorMessage = "GrantType must be 'password', 'client_credentials' or 'windows'.")] public string GrantType { get; set; } = "password"; - /// - /// Validates that the configuration has either username/password or client credentials for authentication. - /// - /// The validation context. - /// A collection of validation results. - public IEnumerable Validate(ValidationContext validationContext) - { - var hasUserPass = !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password); - var hasClientCreds = !string.IsNullOrWhiteSpace(ClientId) && !string.IsNullOrWhiteSpace(ClientSecret); - - switch (GrantType) - { - case "windows": - if (hasUserPass || hasClientCreds) - yield return new ValidationResult( - "No credentials should be provided for 'windows' grant type.", - new[] { nameof(Username), nameof(Password), nameof(ClientId), nameof(ClientSecret) }); - break; - - case "password": - if (!hasUserPass) - yield return new ValidationResult( - "Username and Password must be provided for 'password' grant type.", - new[] { nameof(Username), nameof(Password) }); - break; - - case "client_credentials": - if (!hasClientCreds) - yield return new ValidationResult( - "ClientId and ClientSecret must be provided for 'client_credentials' grant type.", - new[] { nameof(ClientId), nameof(ClientSecret) }); - break; - default: - yield return new ValidationResult( - "Invalid GrantType specified.", - new[] { nameof(GrantType) }); - break; - } - } } } \ No newline at end of file From 03214d5f30e385caf2b718af37fb4b8f7d9b604e Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:58:24 -0700 Subject: [PATCH 05/32] feat(logging): Add structured audit logging for SOX/SOC2 compliance - Log caller identity (Environment.UserName, MachineName), SecretId, field name, target URL, and grant type on every GetPassword invocation - Record API call duration (Stopwatch) for both token and secret endpoints - Include SecretId, field, grant type, and URL in success and failure log events - Improve auth failure log with URL, grant type, and caller identity context - Truncate Secret Server error response bodies to 500 chars before logging - Remove raw token response body from deserialization failure log path - Switch .Result to .GetAwaiter().GetResult() to avoid exception masking --- delinea-secretserver-pam/SecretServerPam.cs | 48 +++++++++++++++------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index e0e97de..29bdf1d 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -7,6 +7,8 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; @@ -95,16 +97,20 @@ public string GetPassword(Dictionary instanceParameters, Dictionary serverConfigurationParameters) { Logger.MethodEntry(); - Logger.LogInformation("Starting Delinea Secret Server PAM Provider"); - Logger.LogDebug("Getting password from Delinea Secret Server"); + instanceParameters.TryGetValue(DelineaConfiguration.SECRET_ID, out var logSecretId); + instanceParameters.TryGetValue(DelineaConfiguration.SECRET_FIELD_NAME, out var logFieldName); + serverConfigurationParameters.TryGetValue(DelineaConfiguration.SECRET_SERVER_URL, out var logUrl); + serverConfigurationParameters.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var logGrantType); + Logger.LogInformation( + "GetPassword invoked | SecretId={SecretId} Field={SecretFieldName} TargetUrl={Url} GrantType={GrantType} CallerIdentity={Identity} Host={Machine}", + logSecretId, logFieldName, logUrl, logGrantType ?? "password", + Environment.UserName, Environment.MachineName); Logger.LogTrace("instanceParameters: {@InstanceParameters}", instanceParameters); - // Logger.LogTrace("initializationInfo: {@ServerConfigurationParameters}", - // serverConfigurationParameters); // TODO: Commented out to avoid logging sensitive information var config = BuildDelineaConfiguration(instanceParameters, serverConfigurationParameters); using (var client = BuildHttpClient(config.GrantType)) { Logger.MethodExit(); - return GetDelineaSecretAsync(client, config).Result; + return GetDelineaSecretAsync(client, config).GetAwaiter().GetResult(); } } @@ -136,7 +142,10 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi if (string.IsNullOrEmpty(bearerToken)) { - Logger.LogError("Unable to obtain access token from Delinea Secret Server"); + Logger.LogError( + "Authentication failed: empty token received | Url={Url} GrantType={GrantType} Identity={Identity}", + configurationInfo.SecretServerUrl, configurationInfo.GrantType, + string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username); Logger.MethodExit(); throw new InvalidTokenException("Unable to obtain access token from Delinea Secret Server"); } @@ -149,17 +158,23 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi try { Logger.LogDebug("Secret URL: {SecretUrl}", secretUrl); + var sw = Stopwatch.StartNew(); response = await client .GetAsync(new Uri(secretUrl) .AbsoluteUri) .ConfigureAwait(false); + sw.Stop(); + Logger.LogInformation( + "Secret Server API call completed | Method=GET StatusCode={StatusCode} DurationMs={DurationMs} SecretId={SecretId}", + (int)response.StatusCode, sw.ElapsedMilliseconds, configurationInfo.SecretId); if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var truncated = errorContent?.Length > 500 ? errorContent.Substring(0, 500) + "..." : errorContent; Logger.LogError( - "Received non-success status code {StatusCode} from Secret Server. Response: {ResponseContent}", - response.StatusCode, errorContent); + "Received non-success status code {StatusCode} from Secret Server. Response (truncated): {ResponseContent}", + (int)response.StatusCode, truncated); } response.EnsureSuccessStatusCode(); @@ -202,7 +217,10 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi // Logger.LogDebug("Secret value: {SecretValue}", secret); if (!string.IsNullOrEmpty(secret)) { - Logger.LogInformation("Successfully retrieved secret from Delinea Secret Server"); + Logger.LogInformation( + "Credential retrieval succeeded | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url}", + configurationInfo.SecretId, configurationInfo.SecretFieldName, + configurationInfo.GrantType, configurationInfo.SecretServerUrl); Logger.MethodExit(); return secret; } @@ -225,7 +243,10 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi throw; } - Logger.LogError("No secret was found or no items in the secret were of type password"); + Logger.LogError( + "Credential retrieval failed: field not found in secret | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url}", + configurationInfo.SecretId, configurationInfo.SecretFieldName, + configurationInfo.GrantType, configurationInfo.SecretServerUrl); Logger.MethodExit(); return ""; } @@ -269,11 +290,15 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio try { Logger.LogDebug("Requesting an access token from Secret Server at {TokenUrl}", tokeUrl); + var sw = Stopwatch.StartNew(); response = await client .PostAsync(new Uri(tokeUrl).AbsoluteUri, new FormUrlEncodedContent(body)) .ConfigureAwait(false); - Logger.LogDebug("Request sent"); + sw.Stop(); + Logger.LogInformation( + "Token endpoint call completed | Method=POST StatusCode={StatusCode} DurationMs={DurationMs}", + (int)response.StatusCode, sw.ElapsedMilliseconds); if (!response.IsSuccessStatusCode) { @@ -319,7 +344,6 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio Logger.LogError( "An error occurred while attempting to deserialize the access token response: {ExMessage}", ex.Message); - Logger.LogTrace("Response content: ${Response}", response.Content.ReadAsStringAsync().Result); Logger.MethodExit(); throw; } From 13b7d318d2df2350b596e726faf44fcfccdeedec Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:58:31 -0700 Subject: [PATCH 06/32] fix(test-console): Mask password value in test output --- TestConsole/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestConsole/Program.cs b/TestConsole/Program.cs index cac27f3..8e62362 100644 --- a/TestConsole/Program.cs +++ b/TestConsole/Program.cs @@ -48,6 +48,6 @@ private static void Main(string[] args) instanceParams["SecretFieldName"] = "password"; var password = pam.GetPassword(instanceParams, initInfo); Console.WriteLine($"ServerUsername: {username}"); - Console.WriteLine($"ServerPassword: {password}"); + Console.WriteLine($"ServerPassword: {new string('*', password?.Length ?? 0)} (len={password?.Length ?? 0})"); } } \ No newline at end of file From 20f0d765934d236bf9da180e2acf878ddaf9da96 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 12:59:07 -0700 Subject: [PATCH 07/32] docs(changelog): Update v1.3.0 changelog with compliance logging improvements --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d950529..fddb0e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,22 @@ # v1.3.0 ## Improvements -- Enhanced debug logging for token endpoint requests: the obfuscated request body (credentials redacted) and full raw response body are now logged on token request failures to aid troubleshooting. +- Enhanced debug logging for token endpoint requests: the obfuscated request body (credentials redacted) and raw response body are now logged on token request failures to aid troubleshooting. +- Added structured audit log event on every `GetPassword` invocation recording caller identity, machine name, target URL, grant type, SecretId, and field name. +- Added response duration logging (ms) for both the OAuth token endpoint and secret retrieval API calls. +- Success and failure log events now include SecretId, field name, grant type, and URL for complete audit trail. +- Auth failure log events now include the target URL, grant type, and caller identity. +- Error responses from Secret Server are truncated to 500 characters before logging to prevent sensitive metadata exposure. +- Removed raw token response body from deserialization failure log path to prevent accidental bearer token exposure. + +## Bug Fixes +- Replaced `.Result` with `.GetAwaiter().GetResult()` in `GetPassword` to prevent exception masking on async task failures. + +## Maintenance +- Removed dead `IValidatableObject` implementation from `DelineaConfiguration`; validation is enforced in `ValidateServerConfigurationParams`. +- Masked password value in TestConsole output. +- Bumped TestConsole target framework to net10.0 and global SDK pin to 10.0.0. +- Added `.env`, `scripts/`, and `client_pam.json` to `.gitignore`. # v1.2.0 From 71a33d89014c364b8a89d02f63e94f63f17f4485 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:12:02 -0700 Subject: [PATCH 08/32] fix(logging): Throw on missing secret field instead of returning empty string --- delinea-secretserver-pam/SecretServerPam.cs | 26 ++++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 29bdf1d..dfeb700 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -107,7 +107,7 @@ public string GetPassword(Dictionary instanceParameters, Environment.UserName, Environment.MachineName); Logger.LogTrace("instanceParameters: {@InstanceParameters}", instanceParameters); var config = BuildDelineaConfiguration(instanceParameters, serverConfigurationParameters); - using (var client = BuildHttpClient(config.GrantType)) + using (var client = BuildHttpClient(config.GrantType, config.SkipTlsValidation)) { Logger.MethodExit(); return GetDelineaSecretAsync(client, config).GetAwaiter().GetResult(); @@ -248,7 +248,8 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi configurationInfo.SecretId, configurationInfo.SecretFieldName, configurationInfo.GrantType, configurationInfo.SecretServerUrl); Logger.MethodExit(); - return ""; + throw new InvalidSecretConfigurationException( + $"Field '{configurationInfo.SecretFieldName}' not found in secret {configurationInfo.SecretId}. Verify the field name or slug exists on the secret template."); } /// @@ -562,6 +563,11 @@ private DelineaConfiguration BuildDelineaConfiguration( grantType = "password"; } + connectionConfiguration.TryGetValue(DelineaConfiguration.SKIP_TLS_VALIDATION, out var skipTlsRaw); + var skipTls = string.Equals(skipTlsRaw, "true", StringComparison.OrdinalIgnoreCase); + if (skipTls) + Logger.LogWarning("TLS certificate validation is disabled — use only in non-production environments"); + Logger.LogDebug("Building Delinea configuration"); switch (grantType) { @@ -576,7 +582,8 @@ private DelineaConfiguration BuildDelineaConfiguration( Password = connectionConfiguration[DelineaConfiguration.PASSWORD], SecretId = secretId, SecretFieldName = instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME], - GrantType = "password" + GrantType = "password", + SkipTlsValidation = skipTls }; case "client_credentials": @@ -589,7 +596,8 @@ private DelineaConfiguration BuildDelineaConfiguration( ClientSecret = connectionConfiguration[DelineaConfiguration.CLIENT_SECRET], SecretId = secretId, SecretFieldName = instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME], - GrantType = "password" + GrantType = "password", + SkipTlsValidation = skipTls }; case "windows": Logger.LogDebug("Building Delinea configuration for windows grant type"); @@ -599,7 +607,8 @@ private DelineaConfiguration BuildDelineaConfiguration( SecretServerUrl = connectionConfiguration[DelineaConfiguration.SECRET_SERVER_URL], SecretId = secretId, SecretFieldName = instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME], - GrantType = "windows" + GrantType = "windows", + SkipTlsValidation = skipTls }; default: @@ -616,15 +625,14 @@ private DelineaConfiguration BuildDelineaConfiguration( /// Creates and configures an HttpClient for communicating with Secret Server. /// /// A configured HttpClient with a 60-second timeout. - private static HttpClient BuildHttpClient(string grantType) + private static HttpClient BuildHttpClient(string grantType, bool skipTlsValidation = false) { var handler = new HttpClientHandler(); if (grantType == "windows") - { handler.UseDefaultCredentials = true; - } + if (skipTlsValidation) + handler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true; var client = new HttpClient(handler, true); - client.Timeout = new TimeSpan(0, 0, 60); return client; } From 1dfc1f5604ce25705c8dd64d4cb7ac14ff6254ef Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:12:51 -0700 Subject: [PATCH 09/32] fix(logging): Truncate token endpoint error body before logging --- delinea-secretserver-pam/SecretServerPam.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index dfeb700..1f9f9cf 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -304,9 +304,10 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio if (!response.IsSuccessStatusCode) { var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var truncatedError = errorBody?.Length > 500 ? errorBody.Substring(0, 500) + "..." : errorBody; Logger.LogError( - "Token request failed with status {StatusCode}. Raw response body: {ResponseBody}", - (int)response.StatusCode, errorBody); + "Token request failed | StatusCode={StatusCode} ResponseBody={ResponseBody}", + (int)response.StatusCode, truncatedError); response.EnsureSuccessStatusCode(); } } From a5b39dd5134fa6b6de3ae8d8478f3280cce9fe64 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:13:11 -0700 Subject: [PATCH 10/32] fix(logging): Add authentication attempt log event for Windows auth path --- delinea-secretserver-pam/SecretServerPam.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 1f9f9cf..15c1812 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -135,6 +135,9 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi case "windows": Logger.LogDebug("Using Windows Authentication to obtain access token"); secretUrl = $"{configurationInfo.SecretServerUrl}/winauthwebservices/api/v1/secrets/{configurationInfo.SecretId}"; + Logger.LogInformation( + "Windows authentication attempt | Identity={Identity} Machine={Machine} TargetUrl={TargetUrl} SecretId={SecretId}", + Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId); break; default: // password and client_credentials Logger.LogDebug("Using {GrantType} grant to obtain access token", configurationInfo.GrantType); From 0fc993d0db9f33b5d8a988dfc55138c68c989c56 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:14:22 -0700 Subject: [PATCH 11/32] feat(logging): Add authentication success log event with caller identity --- delinea-secretserver-pam/SecretServerPam.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 15c1812..3b5af5d 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -336,7 +336,14 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio client.DefaultRequestHeaders.Accept.Clear(); Logger.LogTrace("Access token parsed"); - if (token != null) return token; + if (token != null) + { + Logger.LogInformation( + "Authentication succeeded | Identity={Identity} Url={Url} AuthenticationResult=Success", + string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username, + configurationInfo.SecretServerUrl); + return token; + } Logger.LogError( "Unable to generate access token from Delinea Secret Server \'{ConfigurationInfoSecretServerUrl}\' as \'{ConfigurationInfoUsername}\'. Please check your credentials and try again", configurationInfo.SecretServerUrl, configurationInfo.Username); From 208874835cdab4d6cd3748ea81f36b2c2db1df04 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:16:04 -0700 Subject: [PATCH 12/32] feat(logging): Thread correlation ID through all PAM operation log events --- delinea-secretserver-pam/SecretServerPam.cs | 78 +++++++++++---------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 3b5af5d..f9d127f 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -105,12 +105,14 @@ public string GetPassword(Dictionary instanceParameters, "GetPassword invoked | SecretId={SecretId} Field={SecretFieldName} TargetUrl={Url} GrantType={GrantType} CallerIdentity={Identity} Host={Machine}", logSecretId, logFieldName, logUrl, logGrantType ?? "password", Environment.UserName, Environment.MachineName); + var correlationId = Guid.NewGuid().ToString("N"); + Logger.LogInformation("Operation correlation ID | CorrelationId={CorrelationId}", correlationId); Logger.LogTrace("instanceParameters: {@InstanceParameters}", instanceParameters); var config = BuildDelineaConfiguration(instanceParameters, serverConfigurationParameters); using (var client = BuildHttpClient(config.GrantType, config.SkipTlsValidation)) { Logger.MethodExit(); - return GetDelineaSecretAsync(client, config).GetAwaiter().GetResult(); + return GetDelineaSecretAsync(client, config, correlationId).GetAwaiter().GetResult(); } } @@ -122,7 +124,7 @@ public string GetPassword(Dictionary instanceParameters, /// The value of the requested secret field. /// Thrown when the HTTP request to Secret Server fails. /// Thrown when deserializing the response fails or the requested secret is not found. - private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfiguration configurationInfo) + private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfiguration configurationInfo, string correlationId) { Logger.MethodEntry(); HttpResponseMessage response; @@ -136,19 +138,20 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi Logger.LogDebug("Using Windows Authentication to obtain access token"); secretUrl = $"{configurationInfo.SecretServerUrl}/winauthwebservices/api/v1/secrets/{configurationInfo.SecretId}"; Logger.LogInformation( - "Windows authentication attempt | Identity={Identity} Machine={Machine} TargetUrl={TargetUrl} SecretId={SecretId}", - Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId); + "Windows authentication attempt | Identity={Identity} Machine={Machine} TargetUrl={TargetUrl} SecretId={SecretId} CorrelationId={CorrelationId}", + Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId, correlationId); break; default: // password and client_credentials Logger.LogDebug("Using {GrantType} grant to obtain access token", configurationInfo.GrantType); - var bearerToken = await GetAccessToken(client, configurationInfo).ConfigureAwait(false); + var bearerToken = await GetAccessToken(client, configurationInfo, correlationId).ConfigureAwait(false); if (string.IsNullOrEmpty(bearerToken)) { Logger.LogError( - "Authentication failed: empty token received | Url={Url} GrantType={GrantType} Identity={Identity}", + "Authentication failed: empty token received | Url={Url} GrantType={GrantType} Identity={Identity} CorrelationId={CorrelationId}", configurationInfo.SecretServerUrl, configurationInfo.GrantType, - string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username); + string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username, + correlationId); Logger.MethodExit(); throw new InvalidTokenException("Unable to obtain access token from Delinea Secret Server"); } @@ -157,7 +160,7 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); break; } - + try { Logger.LogDebug("Secret URL: {SecretUrl}", secretUrl); @@ -168,16 +171,16 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi .ConfigureAwait(false); sw.Stop(); Logger.LogInformation( - "Secret Server API call completed | Method=GET StatusCode={StatusCode} DurationMs={DurationMs} SecretId={SecretId}", - (int)response.StatusCode, sw.ElapsedMilliseconds, configurationInfo.SecretId); + "Secret Server API call completed | Method=GET StatusCode={StatusCode} DurationMs={DurationMs} SecretId={SecretId} CorrelationId={CorrelationId}", + (int)response.StatusCode, sw.ElapsedMilliseconds, configurationInfo.SecretId, correlationId); if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var truncated = errorContent?.Length > 500 ? errorContent.Substring(0, 500) + "..." : errorContent; Logger.LogError( - "Received non-success status code {StatusCode} from Secret Server. Response (truncated): {ResponseContent}", - (int)response.StatusCode, truncated); + "Received non-success status code {StatusCode} from Secret Server. Response (truncated): {ResponseContent} CorrelationId={CorrelationId}", + (int)response.StatusCode, truncated, correlationId); } response.EnsureSuccessStatusCode(); @@ -186,17 +189,17 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi catch (HttpRequestException ex) { Logger.LogError( - "An error occurred while attempting to communicate with Delinea Secret Server: {ExMessage}", - ex.Message); + "An error occurred while attempting to communicate with Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", + ex.Message, correlationId); Logger.MethodExit(); throw; } - + catch (System.ComponentModel.Win32Exception ex) { Logger.LogError( - "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server: {ExMessage}", - ex.Message); + "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", + ex.Message, correlationId); Logger.MethodExit(); throw new InvalidClientConfigurationException( "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server. Please ensure the application is running under a user context with access to Secret Server. For more information on windows auth please visit: https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm"); @@ -221,9 +224,9 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi if (!string.IsNullOrEmpty(secret)) { Logger.LogInformation( - "Credential retrieval succeeded | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url}", + "Credential retrieval succeeded | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url} CorrelationId={CorrelationId}", configurationInfo.SecretId, configurationInfo.SecretFieldName, - configurationInfo.GrantType, configurationInfo.SecretServerUrl); + configurationInfo.GrantType, configurationInfo.SecretServerUrl, correlationId); Logger.MethodExit(); return secret; } @@ -233,23 +236,24 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi if (content != null && content.Contains("login-message")) { Logger.LogError( - "Authentication failed when attempting to retrieve secret from Delinea Secret Server, please check your credentials and configuration and try again"); + "Authentication failed when attempting to retrieve secret from Delinea Secret Server, please check your credentials and configuration and try again CorrelationId={CorrelationId}", + correlationId); Logger.LogTrace("Response content: {Response}", content); Logger.MethodExit(); throw new AuthenticationException( "Authentication failed when attempting to retrieve secret from Delinea Secret Server. Please check your credentials and try again"); } Logger.LogError( - "An error occurred while attempting to deserialize the Delinea Secret Server response: {ExMessage}", - ex.Message); + "An error occurred while attempting to deserialize the Delinea Secret Server response: {ExMessage} CorrelationId={CorrelationId}", + ex.Message, correlationId); Logger.MethodExit(); throw; } Logger.LogError( - "Credential retrieval failed: field not found in secret | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url}", + "Credential retrieval failed: field not found in secret | SecretId={SecretId} Field={SecretFieldName} GrantType={GrantType} Url={Url} CorrelationId={CorrelationId}", configurationInfo.SecretId, configurationInfo.SecretFieldName, - configurationInfo.GrantType, configurationInfo.SecretServerUrl); + configurationInfo.GrantType, configurationInfo.SecretServerUrl, correlationId); Logger.MethodExit(); throw new InvalidSecretConfigurationException( $"Field '{configurationInfo.SecretFieldName}' not found in secret {configurationInfo.SecretId}. Verify the field name or slug exists on the secret template."); @@ -265,7 +269,7 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi /// Thrown when the token cannot be obtained or parsed from the response. /// Thrown when deserializing the token response fails. /// Currently only supports password grant type authentication. - private async Task GetAccessToken(HttpClient client, DelineaConfiguration configurationInfo) + private async Task GetAccessToken(HttpClient client, DelineaConfiguration configurationInfo, string correlationId) { Logger.MethodEntry(); @@ -301,16 +305,16 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio .ConfigureAwait(false); sw.Stop(); Logger.LogInformation( - "Token endpoint call completed | Method=POST StatusCode={StatusCode} DurationMs={DurationMs}", - (int)response.StatusCode, sw.ElapsedMilliseconds); + "Token endpoint call completed | Method=POST StatusCode={StatusCode} DurationMs={DurationMs} CorrelationId={CorrelationId}", + (int)response.StatusCode, sw.ElapsedMilliseconds, correlationId); if (!response.IsSuccessStatusCode) { var errorBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var truncatedError = errorBody?.Length > 500 ? errorBody.Substring(0, 500) + "..." : errorBody; Logger.LogError( - "Token request failed | StatusCode={StatusCode} ResponseBody={ResponseBody}", - (int)response.StatusCode, truncatedError); + "Token request failed | StatusCode={StatusCode} ResponseBody={ResponseBody} CorrelationId={CorrelationId}", + (int)response.StatusCode, truncatedError, correlationId); response.EnsureSuccessStatusCode(); } } @@ -318,8 +322,8 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio catch (HttpRequestException ex) { Logger.LogError( - "An error occurred while attempting to fetch an access token from Delinea Secret Server: {ExMessage}", - ex.Message); + "An error occurred while attempting to fetch an access token from Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", + ex.Message, correlationId); Logger.MethodExit(); throw; } @@ -339,14 +343,14 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio if (token != null) { Logger.LogInformation( - "Authentication succeeded | Identity={Identity} Url={Url} AuthenticationResult=Success", + "Authentication succeeded | Identity={Identity} Url={Url} AuthenticationResult=Success CorrelationId={CorrelationId}", string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username, - configurationInfo.SecretServerUrl); + configurationInfo.SecretServerUrl, correlationId); return token; } Logger.LogError( - "Unable to generate access token from Delinea Secret Server \'{ConfigurationInfoSecretServerUrl}\' as \'{ConfigurationInfoUsername}\'. Please check your credentials and try again", - configurationInfo.SecretServerUrl, configurationInfo.Username); + "Unable to generate access token from Delinea Secret Server \'{ConfigurationInfoSecretServerUrl}\' as \'{ConfigurationInfoUsername}\'. Please check your credentials and try again CorrelationId={CorrelationId}", + configurationInfo.SecretServerUrl, configurationInfo.Username, correlationId); Logger.MethodExit(); throw new InvalidTokenException( $"Unable to generate access token from Delinea Secret Server '{configurationInfo.SecretServerUrl}' as '{configurationInfo.Username}'. Please check your credentials and try again"); @@ -354,8 +358,8 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio catch (Exception ex) { Logger.LogError( - "An error occurred while attempting to deserialize the access token response: {ExMessage}", - ex.Message); + "An error occurred while attempting to deserialize the access token response: {ExMessage} CorrelationId={CorrelationId}", + ex.Message, correlationId); Logger.MethodExit(); throw; } From 2d0438ab6433a0d7356b61938c8081a7cf99569d Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:17:52 -0700 Subject: [PATCH 13/32] fix(logging): Capture HTTP call duration in exception paths --- delinea-secretserver-pam/SecretServerPam.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index f9d127f..6cfddca 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -161,10 +161,10 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi break; } + var sw = Stopwatch.StartNew(); try { Logger.LogDebug("Secret URL: {SecretUrl}", secretUrl); - var sw = Stopwatch.StartNew(); response = await client .GetAsync(new Uri(secretUrl) .AbsoluteUri) @@ -188,18 +188,20 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi catch (HttpRequestException ex) { + sw.Stop(); Logger.LogError( - "An error occurred while attempting to communicate with Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", - ex.Message, correlationId); + "HTTP call failed | Method={Method} Url={Url} DurationMs={DurationMs} Error={ExMessage} CorrelationId={CorrelationId}", + "GET", secretUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); Logger.MethodExit(); throw; } catch (System.ComponentModel.Win32Exception ex) { + sw.Stop(); Logger.LogError( - "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", - ex.Message, correlationId); + "HTTP call failed | Method={Method} Url={Url} DurationMs={DurationMs} Error={ExMessage} CorrelationId={CorrelationId}", + "GET", secretUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); Logger.MethodExit(); throw new InvalidClientConfigurationException( "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server. Please ensure the application is running under a user context with access to Secret Server. For more information on windows auth please visit: https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm"); @@ -294,11 +296,11 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio HttpResponseMessage response; var tokeUrl = $"{configurationInfo.SecretServerUrl}/oauth2/token"; + var sw = Stopwatch.StartNew(); try { Logger.LogDebug("Requesting an access token from Secret Server at {TokenUrl}", tokeUrl); - var sw = Stopwatch.StartNew(); response = await client .PostAsync(new Uri(tokeUrl).AbsoluteUri, new FormUrlEncodedContent(body)) @@ -321,9 +323,10 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio catch (HttpRequestException ex) { + sw.Stop(); Logger.LogError( - "An error occurred while attempting to fetch an access token from Delinea Secret Server: {ExMessage} CorrelationId={CorrelationId}", - ex.Message, correlationId); + "HTTP call failed | Method={Method} Url={Url} DurationMs={DurationMs} Error={ExMessage} CorrelationId={CorrelationId}", + "POST", tokeUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); Logger.MethodExit(); throw; } From 10a2200b7f1944499f5232d876f0fabf8df72043 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:18:26 -0700 Subject: [PATCH 14/32] refactor: Remove duplicate SecretResponse class --- delinea-secretserver-pam/SecretServerPam.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 6cfddca..4022857 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -656,18 +656,4 @@ private static HttpClient BuildHttpClient(string grantType, bool skipTlsValidati } } - /// - /// Represents the response object from a Secret Server get secret API call. - /// - /// - /// This class is used to deserialize the JSON response from the Secret Server API. - /// - internal class SecretResponse - { - /// - /// Gets or sets the collection of secret items (fields) in the response. - /// - [JsonProperty("items")] - public List Items { get; set; } = new List(); - } } \ No newline at end of file From c92802c648c905553ca7c0ce81fbe7e6e4bf7bc7 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:19:29 -0700 Subject: [PATCH 15/32] fix(manifest): Set Username and ClientId to non-secret DataType --- integration-manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-manifest.json b/integration-manifest.json index 9856bbe..1c3e6ad 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -30,7 +30,7 @@ "Name": "Username", "DisplayName": "Secret Server Username", "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, + "DataType": 1, "InstanceLevel": false }, { @@ -44,7 +44,7 @@ "Name": "ClientId", "DisplayName": "Secret Server Client ID", "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, + "DataType": 1, "InstanceLevel": false }, { From 753439af4627653ac1ad4b1870dd2efb18fe69ec Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:20:03 -0700 Subject: [PATCH 16/32] fix(test-console): Require environment variables, remove hardcoded credential defaults --- TestConsole/Program.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/TestConsole/Program.cs b/TestConsole/Program.cs index 8e62362..5994c9d 100644 --- a/TestConsole/Program.cs +++ b/TestConsole/Program.cs @@ -11,6 +11,10 @@ namespace TestConsole; internal class Program { + static string RequireEnv(string name) => + Environment.GetEnvironmentVariable(name) + ?? throw new InvalidOperationException($"Required environment variable '{name}' is not set."); + private static void Main(string[] args) { var pam = new SecretServerPam(); @@ -19,21 +23,19 @@ private static void Main(string[] args) var instanceParams = new Dictionary(); //Read SecretServerUrl from environment variable - initInfo.Add("Host", - Environment.GetEnvironmentVariable("SECRET_SERVER_URL") ?? "https://keyfactor.secretservercloud.com"); - //Read Username from environment variable + initInfo.Add("Host", RequireEnv("SECRET_SERVER_URL")); + //Read GrantType from environment variable initInfo.Add("GrantType", Environment.GetEnvironmentVariable("SECRET_SERVER_GRANT_TYPE") ?? "password"); switch (initInfo["GrantType"]) { case "password": - initInfo.Add("Username", Environment.GetEnvironmentVariable("SECRET_SERVER_USERNAME") ?? "pam-tester"); - initInfo.Add("Password", Environment.GetEnvironmentVariable("SECRET_SERVER_PASSWORD") ?? "changeme!"); + initInfo.Add("Username", RequireEnv("SECRET_SERVER_USERNAME")); + initInfo.Add("Password", RequireEnv("SECRET_SERVER_PASSWORD")); break; case "client_credentials": - initInfo.Add("ClientId", Environment.GetEnvironmentVariable("SECRET_SERVER_CLIENT_ID") ?? "pam-tester"); - initInfo.Add("ClientSecret", - Environment.GetEnvironmentVariable("SECRET_SERVER_CLIENT_SECRET") ?? "changeme!"); + initInfo.Add("ClientId", RequireEnv("SECRET_SERVER_CLIENT_ID")); + initInfo.Add("ClientSecret", RequireEnv("SECRET_SERVER_CLIENT_SECRET")); break; case "windows": break; @@ -41,8 +43,11 @@ private static void Main(string[] args) throw new Exception($"Unsupported Grant Type: {initInfo["GrantType"]}"); } + if (string.Equals(Environment.GetEnvironmentVariable("SECRET_SERVER_SKIP_TLS_VALIDATION"), "true", StringComparison.OrdinalIgnoreCase)) + initInfo.Add("SkipTlsValidation", "true"); + //Read SecretId from environment variable - instanceParams.Add("SecretId", Environment.GetEnvironmentVariable("SECRET_SERVER_SECRET_ID") ?? "1"); + instanceParams.Add("SecretId", RequireEnv("SECRET_SERVER_SECRET_ID")); instanceParams.Add("SecretFieldName", "username"); var username = pam.GetPassword(instanceParams, initInfo); instanceParams["SecretFieldName"] = "password"; From 6832344ad545e7b4a82f67adb50b705493c23b41 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:21:04 -0700 Subject: [PATCH 17/32] docs(logging): Document Environment.UserName OS identity limitation --- delinea-secretserver-pam/SecretServerPam.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 4022857..e39ff11 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -101,6 +101,7 @@ public string GetPassword(Dictionary instanceParameters, instanceParameters.TryGetValue(DelineaConfiguration.SECRET_FIELD_NAME, out var logFieldName); serverConfigurationParameters.TryGetValue(DelineaConfiguration.SECRET_SERVER_URL, out var logUrl); serverConfigurationParameters.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var logGrantType); + // UserName is the OS service account identity — IPAMProvider does not expose the Keyfactor caller Logger.LogInformation( "GetPassword invoked | SecretId={SecretId} Field={SecretFieldName} TargetUrl={Url} GrantType={GrantType} CallerIdentity={Identity} Host={Machine}", logSecretId, logFieldName, logUrl, logGrantType ?? "password", @@ -137,6 +138,7 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi case "windows": Logger.LogDebug("Using Windows Authentication to obtain access token"); secretUrl = $"{configurationInfo.SecretServerUrl}/winauthwebservices/api/v1/secrets/{configurationInfo.SecretId}"; + // UserName is the OS service account identity — IPAMProvider does not expose the Keyfactor caller Logger.LogInformation( "Windows authentication attempt | Identity={Identity} Machine={Machine} TargetUrl={TargetUrl} SecretId={SecretId} CorrelationId={CorrelationId}", Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId, correlationId); From 90055e8e6f1db45151053295d5ef83dc5223d04f Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:21:55 -0700 Subject: [PATCH 18/32] docs(changelog): Add compliance remediation items to v1.3.0 changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fddb0e0..5c641f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # v1.3.0 +## Compliance Remediation (SOX/SOC2) + +- **CRIT-3**: `GetDelineaSecretAsync` now throws `InvalidSecretConfigurationException` when the requested field is not found in the secret, rather than silently returning an empty string. This prevents silent credential resolution failures from going undetected. +- **CRIT-1**: Token endpoint error response body is now truncated to 500 characters before logging to prevent secret metadata exposure in log sinks. +- **CRIT-2**: Added an explicit `LogInformation` audit event for the Windows authentication path recording OS identity, machine name, target URL, and SecretId before the HTTP call is made. +- **HIGH-4**: Added an authentication success `LogInformation` event in `GetAccessToken` recording the caller identity and target URL with a structured `AuthenticationResult=Success` field. +- **HIGH-3**: A `Guid`-based correlation ID is generated at the start of each `GetPassword` invocation and threaded as a trailing structured field through all `LogInformation` and `LogError` calls in `GetDelineaSecretAsync` and `GetAccessToken`, enabling log correlation across a full PAM operation. +- **MED-5**: `Stopwatch` instances for the token POST and secret GET HTTP calls are now declared outside their try blocks; catch blocks record elapsed duration and emit a structured `HTTP call failed` log event so network failure timing is preserved in exception paths. +- **MED-3**: Removed the duplicate `SecretResponse` class defined inline at the bottom of `SecretServerPam.cs`. The canonical definition in `Models/SecretResponse.cs` (which includes `Id`, `Name`, `SecretTemplateId`, `FolderId`, and `Active` in addition to `Items`) is now the sole definition, resolved via the existing `using Keyfactor.Extensions.Pam.Delinea.Models;` import. +- **MED-2**: `Username` and `ClientId` parameters in `integration-manifest.json` changed from `DataType: 2` (secret/masked) to `DataType: 1` (plain text). These are non-secret identifiers and should not be stored or displayed as secrets in the Keyfactor Command UI. +- **MED-4**: TestConsole no longer provides hardcoded fallback values for `SECRET_SERVER_URL`, `SECRET_SERVER_USERNAME`, `SECRET_SERVER_PASSWORD`, `SECRET_SERVER_CLIENT_ID`, `SECRET_SERVER_CLIENT_SECRET`, and `SECRET_SERVER_SECRET_ID`. A `RequireEnv` helper is used for all six; missing variables throw `InvalidOperationException` immediately to prevent accidental runs against unintended targets. +- **MED-1**: Added inline comments at each `Environment.UserName` usage site in `GetPassword` and the Windows auth path documenting that this value reflects the OS service account identity, not the Keyfactor Command caller identity, since `IPAMProvider` does not expose caller context. + ## Improvements - Enhanced debug logging for token endpoint requests: the obfuscated request body (credentials redacted) and raw response body are now logged on token request failures to aid troubleshooting. - Added structured audit log event on every `GetPassword` invocation recording caller identity, machine name, target URL, grant type, SecretId, and field name. From 186051eaf90f8597ed78eea2c6910adfd18d54f1 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:27:00 -0700 Subject: [PATCH 19/32] docs(changelog): Remove audit severity labels from compliance remediation entries --- CHANGELOG.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c641f9..a421732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,16 @@ ## Compliance Remediation (SOX/SOC2) -- **CRIT-3**: `GetDelineaSecretAsync` now throws `InvalidSecretConfigurationException` when the requested field is not found in the secret, rather than silently returning an empty string. This prevents silent credential resolution failures from going undetected. -- **CRIT-1**: Token endpoint error response body is now truncated to 500 characters before logging to prevent secret metadata exposure in log sinks. -- **CRIT-2**: Added an explicit `LogInformation` audit event for the Windows authentication path recording OS identity, machine name, target URL, and SecretId before the HTTP call is made. -- **HIGH-4**: Added an authentication success `LogInformation` event in `GetAccessToken` recording the caller identity and target URL with a structured `AuthenticationResult=Success` field. -- **HIGH-3**: A `Guid`-based correlation ID is generated at the start of each `GetPassword` invocation and threaded as a trailing structured field through all `LogInformation` and `LogError` calls in `GetDelineaSecretAsync` and `GetAccessToken`, enabling log correlation across a full PAM operation. -- **MED-5**: `Stopwatch` instances for the token POST and secret GET HTTP calls are now declared outside their try blocks; catch blocks record elapsed duration and emit a structured `HTTP call failed` log event so network failure timing is preserved in exception paths. -- **MED-3**: Removed the duplicate `SecretResponse` class defined inline at the bottom of `SecretServerPam.cs`. The canonical definition in `Models/SecretResponse.cs` (which includes `Id`, `Name`, `SecretTemplateId`, `FolderId`, and `Active` in addition to `Items`) is now the sole definition, resolved via the existing `using Keyfactor.Extensions.Pam.Delinea.Models;` import. -- **MED-2**: `Username` and `ClientId` parameters in `integration-manifest.json` changed from `DataType: 2` (secret/masked) to `DataType: 1` (plain text). These are non-secret identifiers and should not be stored or displayed as secrets in the Keyfactor Command UI. -- **MED-4**: TestConsole no longer provides hardcoded fallback values for `SECRET_SERVER_URL`, `SECRET_SERVER_USERNAME`, `SECRET_SERVER_PASSWORD`, `SECRET_SERVER_CLIENT_ID`, `SECRET_SERVER_CLIENT_SECRET`, and `SECRET_SERVER_SECRET_ID`. A `RequireEnv` helper is used for all six; missing variables throw `InvalidOperationException` immediately to prevent accidental runs against unintended targets. -- **MED-1**: Added inline comments at each `Environment.UserName` usage site in `GetPassword` and the Windows auth path documenting that this value reflects the OS service account identity, not the Keyfactor Command caller identity, since `IPAMProvider` does not expose caller context. +- `GetDelineaSecretAsync` now throws `InvalidSecretConfigurationException` when the requested field is not found in the secret, rather than silently returning an empty string. This prevents silent credential resolution failures from going undetected. +- Token endpoint error response body is now truncated to 500 characters before logging to prevent secret metadata exposure in log sinks. +- Added an explicit `LogInformation` audit event for the Windows authentication path recording OS identity, machine name, target URL, and SecretId before the HTTP call is made. +- Added an authentication success `LogInformation` event in `GetAccessToken` recording the caller identity and target URL with a structured `AuthenticationResult=Success` field. +- A `Guid`-based correlation ID is generated at the start of each `GetPassword` invocation and threaded as a trailing structured field through all `LogInformation` and `LogError` calls in `GetDelineaSecretAsync` and `GetAccessToken`, enabling log correlation across a full PAM operation. +- `Stopwatch` instances for the token POST and secret GET HTTP calls are now declared outside their try blocks; catch blocks record elapsed duration and emit a structured `HTTP call failed` log event so network failure timing is preserved in exception paths. +- Removed the duplicate `SecretResponse` class defined inline at the bottom of `SecretServerPam.cs`. The canonical definition in `Models/SecretResponse.cs` (which includes `Id`, `Name`, `SecretTemplateId`, `FolderId`, and `Active` in addition to `Items`) is now the sole definition, resolved via the existing `using Keyfactor.Extensions.Pam.Delinea.Models;` import. +- `Username` and `ClientId` parameters in `integration-manifest.json` changed from `DataType: 2` (secret/masked) to `DataType: 1` (plain text). These are non-secret identifiers and should not be stored or displayed as secrets in the Keyfactor Command UI. +- TestConsole no longer provides hardcoded fallback values for `SECRET_SERVER_URL`, `SECRET_SERVER_USERNAME`, `SECRET_SERVER_PASSWORD`, `SECRET_SERVER_CLIENT_ID`, `SECRET_SERVER_CLIENT_SECRET`, and `SECRET_SERVER_SECRET_ID`. A `RequireEnv` helper is used for all six; missing variables throw `InvalidOperationException` immediately to prevent accidental runs against unintended targets. +- Added inline comments at each `Environment.UserName` usage site documenting that this value reflects the OS service account identity, not the Keyfactor Command caller identity, since `IPAMProvider` does not expose caller context. ## Improvements - Enhanced debug logging for token endpoint requests: the obfuscated request body (credentials redacted) and raw response body are now logged on token request failures to aid troubleshooting. From 8621b38d0fbe24336e26d66844694234815631f4 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:28:24 -0700 Subject: [PATCH 20/32] docs: Clean up changelog and document SkipTlsValidation in DelineaConfiguration --- CHANGELOG.md | 1 - .../Models/DelineaConfiguration.cs | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a421732..939f723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ - `Stopwatch` instances for the token POST and secret GET HTTP calls are now declared outside their try blocks; catch blocks record elapsed duration and emit a structured `HTTP call failed` log event so network failure timing is preserved in exception paths. - Removed the duplicate `SecretResponse` class defined inline at the bottom of `SecretServerPam.cs`. The canonical definition in `Models/SecretResponse.cs` (which includes `Id`, `Name`, `SecretTemplateId`, `FolderId`, and `Active` in addition to `Items`) is now the sole definition, resolved via the existing `using Keyfactor.Extensions.Pam.Delinea.Models;` import. - `Username` and `ClientId` parameters in `integration-manifest.json` changed from `DataType: 2` (secret/masked) to `DataType: 1` (plain text). These are non-secret identifiers and should not be stored or displayed as secrets in the Keyfactor Command UI. -- TestConsole no longer provides hardcoded fallback values for `SECRET_SERVER_URL`, `SECRET_SERVER_USERNAME`, `SECRET_SERVER_PASSWORD`, `SECRET_SERVER_CLIENT_ID`, `SECRET_SERVER_CLIENT_SECRET`, and `SECRET_SERVER_SECRET_ID`. A `RequireEnv` helper is used for all six; missing variables throw `InvalidOperationException` immediately to prevent accidental runs against unintended targets. - Added inline comments at each `Environment.UserName` usage site documenting that this value reflects the OS service account identity, not the Keyfactor Command caller identity, since `IPAMProvider` does not expose caller context. ## Improvements diff --git a/delinea-secretserver-pam/Models/DelineaConfiguration.cs b/delinea-secretserver-pam/Models/DelineaConfiguration.cs index df56cf4..75edcd7 100644 --- a/delinea-secretserver-pam/Models/DelineaConfiguration.cs +++ b/delinea-secretserver-pam/Models/DelineaConfiguration.cs @@ -75,6 +75,12 @@ public DelineaConfiguration() /// public static string SECRET_FIELD_NAME => "SecretFieldName"; + /// + /// The configuration key for skipping TLS certificate validation. + /// Use only in non-production environments with self-signed or expired certificates. + /// + public static string SKIP_TLS_VALIDATION => "SkipTlsValidation"; + /// /// The base URL of the Delinea Secret Server. /// @@ -123,5 +129,11 @@ public DelineaConfiguration() ErrorMessage = "GrantType must be 'password', 'client_credentials' or 'windows'.")] public string GrantType { get; set; } = "password"; + /// + /// When true, disables TLS certificate validation for Secret Server connections. + /// Use only in non-production environments with self-signed or expired certificates. + /// + public bool SkipTlsValidation { get; set; } = false; + } } \ No newline at end of file From dc56424e7a3a422a618094967ab9e02651216e6f Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:42:52 -0700 Subject: [PATCH 21/32] docs(readme): Set Username and ClientId to DataType 1 in manifest example --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f2658b7..bed1c2d 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ Below is the payload to `POST` to the Keyfactor Command API "Name": "Username", "DisplayName": "Secret Server Username", "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, + "DataType": 1, "InstanceLevel": false }, { @@ -182,7 +182,7 @@ Below is the payload to `POST` to the Keyfactor Command API "Name": "ClientId", "DisplayName": "Secret Server Client ID", "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, + "DataType": 1, "InstanceLevel": false }, { From 0f0a2b20e7f6f9ec8696c6945e17aaa0cecee73f Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:50:45 -0700 Subject: [PATCH 22/32] chore(docs): Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 939f723..fae24d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,6 @@ - Removed dead `IValidatableObject` implementation from `DelineaConfiguration`; validation is enforced in `ValidateServerConfigurationParams`. - Masked password value in TestConsole output. - Bumped TestConsole target framework to net10.0 and global SDK pin to 10.0.0. -- Added `.env`, `scripts/`, and `client_pam.json` to `.gitignore`. # v1.2.0 From 1df4b5bf6cc2f1390405d1d4efbf6999a585580d Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:42:33 -0700 Subject: [PATCH 23/32] refactor(pam): extract SecretServerPamBase and add grant-type-specific PAM types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract all shared HTTP, validation, and secret-retrieval logic into an abstract base class SecretServerPamBase. Add three concrete subclasses — SecretServerPamPassword, SecretServerPamClientCredentials, and SecretServerPamWindows — each implementing IPAMProvider with a hardcoded grant type. The existing SecretServerPam class is unchanged (backwards compatible). Also fixes a pre-existing bug where BuildDelineaConfiguration set GrantType = "password" on the DelineaConfiguration returned for the client_credentials case; it now correctly sets "client_credentials". SecretFieldName validation is tightened to reject whitespace-only values (previously only empty string was rejected). InternalsVisibleTo("delinea-secretserver-pam.Tests") added via AssemblyInfo.cs to allow the xUnit test project to reach the internal test constructors. --- delinea-secretserver-pam/AssemblyInfo.cs | 12 + delinea-secretserver-pam/SecretServerPam.cs | 543 ++++++++++++-------- 2 files changed, 345 insertions(+), 210 deletions(-) create mode 100644 delinea-secretserver-pam/AssemblyInfo.cs diff --git a/delinea-secretserver-pam/AssemblyInfo.cs b/delinea-secretserver-pam/AssemblyInfo.cs new file mode 100644 index 0000000..fade484 --- /dev/null +++ b/delinea-secretserver-pam/AssemblyInfo.cs @@ -0,0 +1,12 @@ +// 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.Runtime.CompilerServices; + +// Allow the xUnit test project to access internal members (test constructors) without +// promoting them to public API surface. +[assembly: InternalsVisibleTo("delinea-secretserver-pam.Tests")] diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index e39ff11..0480654 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -1,4 +1,4 @@ -// Copyright 2025 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, @@ -7,7 +7,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; using System.Net.Http; @@ -25,141 +24,199 @@ namespace Keyfactor.Extensions.Pam.Delinea /// /// Exception thrown when the authentication token for Delinea Secret Server is invalid or cannot be obtained. /// - /// - /// This exception is typically thrown when authentication credentials are incorrect or the server rejects the auth - /// request. - /// public class InvalidTokenException : Exception { /// /// Initializes a new instance of the class with a specified error message. /// - /// The message that describes the error. public InvalidTokenException(string message) : base(message) { } } + /// + /// Exception thrown when the server (initialization) configuration provided to the PAM provider is invalid. + /// public class InvalidClientConfigurationException : Exception { /// /// Initializes a new instance of the class with a specified error /// message. /// - /// The message that describes the error. public InvalidClientConfigurationException(string message) : base(message) { } } + /// + /// Exception thrown when the instance (per-secret) configuration provided to the PAM provider is invalid. + /// public class InvalidSecretConfigurationException : Exception { /// /// Initializes a new instance of the class with a specified error /// message. /// - /// The message that describes the error. public InvalidSecretConfigurationException(string message) : base(message) { } } + // --------------------------------------------------------------------------- + // Abstract base — all shared logic lives here + // --------------------------------------------------------------------------- + /// - /// Privileged Access Management (PAM) provider implementation for Delinea Secret Server. + /// Abstract base class for all Delinea Secret Server PAM providers. + /// Encapsulates the shared HTTP, validation, configuration-building, and + /// secret-retrieval logic used by every concrete PAM type variant. /// - /// - /// This class implements the IPAMProvider interface to retrieve secrets from Delinea Secret Server. - /// It supports authentication via username/password with plans for client credentials support. - /// - public class SecretServerPam : IPAMProvider + public abstract class SecretServerPamBase { - private ILogger Logger { get; } = LogHandler.GetClassLogger(); + // Subclasses set their own class-specific logger via the protected setter. + protected ILogger Logger { get; set; } + + // HttpClient is injected so tests can substitute a fake handler without + // going to the network. Production constructors build the real client. + private HttpClient _httpClient; /// - /// Gets the name of this PAM provider. + /// Production constructor — builds a default . + /// Grant type and TLS-skip are not yet known at construction time; they + /// are resolved from configuration during . /// - /// The string "Delinea-SecretServer". - public string Name => "Delinea-SecretServer"; + protected SecretServerPamBase() + { + Logger = LogHandler.GetClassLogger(GetType()); + _httpClient = null; // will be built lazily in GetPasswordCore + } /// - /// Retrieves a password from Delinea Secret Server using the provided configuration parameters. + /// Test constructor — accepts an injected and + /// so unit tests can control HTTP responses. /// - /// Dictionary containing instance-specific parameters like SecretId and SecretFieldName. - /// - /// Dictionary containing connection and authentication parameters such as host URL, - /// username, and password. - /// - /// The password value retrieved from Secret Server. - /// Thrown when required parameters are missing or invalid. - /// Thrown when authentication with Secret Server fails. - /// Thrown when communication with Secret Server fails. - public string GetPassword(Dictionary instanceParameters, + internal SecretServerPamBase(HttpClient httpClient, ILogger logger) + { + _httpClient = httpClient; + Logger = logger; + } + + // --------------------------------------------------------------------------- + // Core entry point called by every concrete GetPassword implementation + // --------------------------------------------------------------------------- + + /// + /// Resolves the effective grant type for this provider invocation. + /// The base implementation reads it from , + /// defaulting to "password" for backwards compatibility. + /// Type-specific subclasses override this to return a hardcoded value. + /// + protected virtual string ResolveGrantType(IReadOnlyDictionary serverConfigurationParameters) + { + if (serverConfigurationParameters.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var grantType) && + !string.IsNullOrEmpty(grantType)) + return grantType; + + Logger.LogWarning( + "'{GrantType}' parameter not provided — defaulting to 'password' grant", + DelineaConfiguration.GRANT_TYPE); + return "password"; + } + + /// + /// Core implementation of credential retrieval shared by all concrete types. + /// Validates configuration, builds an , and fetches + /// the secret from Delinea Secret Server. + /// + protected string GetPasswordCore( + Dictionary instanceParameters, Dictionary serverConfigurationParameters) { Logger.MethodEntry(); + instanceParameters.TryGetValue(DelineaConfiguration.SECRET_ID, out var logSecretId); instanceParameters.TryGetValue(DelineaConfiguration.SECRET_FIELD_NAME, out var logFieldName); serverConfigurationParameters.TryGetValue(DelineaConfiguration.SECRET_SERVER_URL, out var logUrl); - serverConfigurationParameters.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var logGrantType); + var logGrantType = ResolveGrantType(serverConfigurationParameters); + // UserName is the OS service account identity — IPAMProvider does not expose the Keyfactor caller Logger.LogInformation( "GetPassword invoked | SecretId={SecretId} Field={SecretFieldName} TargetUrl={Url} GrantType={GrantType} CallerIdentity={Identity} Host={Machine}", - logSecretId, logFieldName, logUrl, logGrantType ?? "password", + logSecretId, logFieldName, logUrl, logGrantType, Environment.UserName, Environment.MachineName); + var correlationId = Guid.NewGuid().ToString("N"); Logger.LogInformation("Operation correlation ID | CorrelationId={CorrelationId}", correlationId); Logger.LogTrace("instanceParameters: {@InstanceParameters}", instanceParameters); + var config = BuildDelineaConfiguration(instanceParameters, serverConfigurationParameters); - using (var client = BuildHttpClient(config.GrantType, config.SkipTlsValidation)) + + // Use the injected client (tests) or build a real one (production) + var client = _httpClient ?? BuildHttpClient(config.GrantType, config.SkipTlsValidation); + var ownsClient = _httpClient == null; + try { Logger.MethodExit(); return GetDelineaSecretAsync(client, config, correlationId).GetAwaiter().GetResult(); } + finally + { + if (ownsClient) + client.Dispose(); + } } - /// - /// Asynchronously retrieves a secret from Delinea Secret Server. - /// - /// The HTTP client used to communicate with Secret Server. - /// The configuration containing Secret Server connection and request details. - /// The value of the requested secret field. - /// Thrown when the HTTP request to Secret Server fails. - /// Thrown when deserializing the response fails or the requested secret is not found. - private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfiguration configurationInfo, string correlationId) + // --------------------------------------------------------------------------- + // Secret retrieval + // --------------------------------------------------------------------------- + + private async Task GetDelineaSecretAsync( + HttpClient client, + DelineaConfiguration configurationInfo, + string correlationId) { Logger.MethodEntry(); HttpResponseMessage response; - Logger.LogDebug("Attempting to fetch access token from Delinea Secret Server at {SecretServerUrl}", + Logger.LogDebug("Attempting to fetch secret from Delinea Secret Server at {SecretServerUrl}", configurationInfo.SecretServerUrl); var secretUrl = $"{configurationInfo.SecretServerUrl}/api/v1/secrets/{configurationInfo.SecretId}"; + switch (configurationInfo.GrantType) { case "windows": - Logger.LogDebug("Using Windows Authentication to obtain access token"); - secretUrl = $"{configurationInfo.SecretServerUrl}/winauthwebservices/api/v1/secrets/{configurationInfo.SecretId}"; + Logger.LogDebug("Using Windows Authentication"); + secretUrl = + $"{configurationInfo.SecretServerUrl}/winauthwebservices/api/v1/secrets/{configurationInfo.SecretId}"; // UserName is the OS service account identity — IPAMProvider does not expose the Keyfactor caller Logger.LogInformation( "Windows authentication attempt | Identity={Identity} Machine={Machine} TargetUrl={TargetUrl} SecretId={SecretId} CorrelationId={CorrelationId}", - Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId, correlationId); + Environment.UserName, Environment.MachineName, secretUrl, configurationInfo.SecretId, + correlationId); break; + default: // password and client_credentials Logger.LogDebug("Using {GrantType} grant to obtain access token", configurationInfo.GrantType); - var bearerToken = await GetAccessToken(client, configurationInfo, correlationId).ConfigureAwait(false); + var bearerToken = + await GetAccessToken(client, configurationInfo, correlationId).ConfigureAwait(false); if (string.IsNullOrEmpty(bearerToken)) { Logger.LogError( "Authentication failed: empty token received | Url={Url} GrantType={GrantType} Identity={Identity} CorrelationId={CorrelationId}", configurationInfo.SecretServerUrl, configurationInfo.GrantType, - string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username, + string.IsNullOrEmpty(configurationInfo.Username) + ? configurationInfo.ClientId + : configurationInfo.Username, correlationId); Logger.MethodExit(); throw new InvalidTokenException("Unable to obtain access token from Delinea Secret Server"); } - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", bearerToken); + client.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json")); break; } @@ -168,8 +225,7 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi { Logger.LogDebug("Secret URL: {SecretUrl}", secretUrl); response = await client - .GetAsync(new Uri(secretUrl) - .AbsoluteUri) + .GetAsync(new Uri(secretUrl).AbsoluteUri) .ConfigureAwait(false); sw.Stop(); Logger.LogInformation( @@ -179,7 +235,9 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var truncated = errorContent?.Length > 500 ? errorContent.Substring(0, 500) + "..." : errorContent; + var truncated = errorContent?.Length > 500 + ? errorContent.Substring(0, 500) + "..." + : errorContent; Logger.LogError( "Received non-success status code {StatusCode} from Secret Server. Response (truncated): {ResponseContent} CorrelationId={CorrelationId}", (int)response.StatusCode, truncated, correlationId); @@ -187,7 +245,6 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi response.EnsureSuccessStatusCode(); } - catch (HttpRequestException ex) { sw.Stop(); @@ -197,7 +254,6 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi Logger.MethodExit(); throw; } - catch (System.ComponentModel.Win32Exception ex) { sw.Stop(); @@ -206,7 +262,10 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi "GET", secretUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); Logger.MethodExit(); throw new InvalidClientConfigurationException( - "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server. Please ensure the application is running under a user context with access to Secret Server. For more information on windows auth please visit: https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm"); + "A Windows authentication error occurred while attempting to communicate with Delinea Secret Server. " + + "Please ensure the application is running under a user context with access to Secret Server. " + + "For more information on windows auth please visit: " + + "https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm"); } var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); @@ -216,15 +275,14 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi { var secretResponse = JsonConvert.DeserializeObject(content); - Logger.LogTrace("Received '{ItemsCount}' secrets from Delinea Secret Server", + Logger.LogTrace("Received '{ItemsCount}' secret items from Delinea Secret Server", secretResponse?.Items.Count ?? 0); - Logger.LogTrace("Secret field name: {SecretFieldName}", configurationInfo.SecretFieldName); - Logger.LogTrace("Secret slug: {SecretSlug}", configurationInfo.SecretFieldName); - // var secret = secretResponse?.Items.FirstOrDefault(i => i.IsPassword)?.Value; + var secret = secretResponse?.Items.FirstOrDefault(i => - i.Name == configurationInfo.SecretFieldName || i.Slug == configurationInfo.SecretFieldName)?.Value; - // Logger.LogDebug("Secret value: {SecretValue}", secret); + i.Name == configurationInfo.SecretFieldName || + i.Slug == configurationInfo.SecretFieldName)?.Value; + if (!string.IsNullOrEmpty(secret)) { Logger.LogInformation( @@ -240,13 +298,14 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi if (content != null && content.Contains("login-message")) { Logger.LogError( - "Authentication failed when attempting to retrieve secret from Delinea Secret Server, please check your credentials and configuration and try again CorrelationId={CorrelationId}", + "Authentication failed when attempting to retrieve secret from Delinea Secret Server — check credentials and configuration. CorrelationId={CorrelationId}", correlationId); Logger.LogTrace("Response content: {Response}", content); Logger.MethodExit(); throw new AuthenticationException( "Authentication failed when attempting to retrieve secret from Delinea Secret Server. Please check your credentials and try again"); } + Logger.LogError( "An error occurred while attempting to deserialize the Delinea Secret Server response: {ExMessage} CorrelationId={CorrelationId}", ex.Message, correlationId); @@ -260,52 +319,51 @@ private async Task GetDelineaSecretAsync(HttpClient client, DelineaConfi configurationInfo.GrantType, configurationInfo.SecretServerUrl, correlationId); Logger.MethodExit(); throw new InvalidSecretConfigurationException( - $"Field '{configurationInfo.SecretFieldName}' not found in secret {configurationInfo.SecretId}. Verify the field name or slug exists on the secret template."); + $"Field '{configurationInfo.SecretFieldName}' not found in secret {configurationInfo.SecretId}. " + + "Verify the field name or slug exists on the secret template."); } - /// - /// Obtains an OAuth access token from Delinea Secret Server. - /// - /// The HTTP client used to communicate with Secret Server. - /// The configuration containing Secret Server connection and authentication details. - /// An OAuth access token string for authenticating subsequent API calls. - /// Thrown when the HTTP request to the token endpoint fails. - /// Thrown when the token cannot be obtained or parsed from the response. - /// Thrown when deserializing the token response fails. - /// Currently only supports password grant type authentication. - private async Task GetAccessToken(HttpClient client, DelineaConfiguration configurationInfo, string correlationId) + // --------------------------------------------------------------------------- + // Token acquisition + // --------------------------------------------------------------------------- + + private async Task GetAccessToken( + HttpClient client, + DelineaConfiguration configurationInfo, + string correlationId) { Logger.MethodEntry(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); + // NOTE: Delinea Secret Server's token endpoint always uses "username"/"password" + // field names regardless of whether the flow is password or client_credentials. + // This is a Delinea API constraint — do not change the field names. var body = new Dictionary { { "username", configurationInfo.Username }, { "password", configurationInfo.Password }, - { "grant_type", "password" } // grant type is still "password" as far as the Delinea API is concerned + { "grant_type", "password" } // Delinea API always expects grant_type=password }; - - Logger.LogTrace("Authentication request grant type ${GrantType}", body["grant_type"]); + Logger.LogTrace("Authentication request grant type: {GrantType}", body["grant_type"]); var loggableBody = new Dictionary(body); foreach (var sensitiveKey in new[] { "password", "client_secret" }) if (loggableBody.ContainsKey(sensitiveKey)) loggableBody[sensitiveKey] = "***"; - Logger.LogDebug("Token request body: {RequestBody}", JsonConvert.SerializeObject(loggableBody)); + Logger.LogDebug("Token request body (redacted): {RequestBody}", JsonConvert.SerializeObject(loggableBody)); HttpResponseMessage response; - var tokeUrl = $"{configurationInfo.SecretServerUrl}/oauth2/token"; + var tokenUrl = $"{configurationInfo.SecretServerUrl}/oauth2/token"; var sw = Stopwatch.StartNew(); try { - Logger.LogDebug("Requesting an access token from Secret Server at {TokenUrl}", tokeUrl); + Logger.LogDebug("Requesting access token from Secret Server at {TokenUrl}", tokenUrl); response = await client - .PostAsync(new Uri(tokeUrl).AbsoluteUri, - new FormUrlEncodedContent(body)) + .PostAsync(new Uri(tokenUrl).AbsoluteUri, new FormUrlEncodedContent(body)) .ConfigureAwait(false); sw.Stop(); Logger.LogInformation( @@ -322,43 +380,43 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio response.EnsureSuccessStatusCode(); } } - catch (HttpRequestException ex) { sw.Stop(); Logger.LogError( "HTTP call failed | Method={Method} Url={Url} DurationMs={DurationMs} Error={ExMessage} CorrelationId={CorrelationId}", - "POST", tokeUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); + "POST", tokenUrl, sw.ElapsedMilliseconds, ex.Message, correlationId); Logger.MethodExit(); throw; } - Logger.LogDebug("Access token received"); + Logger.LogDebug("Access token received, deserializing response"); try { - Logger.LogDebug("Deserializing access token response"); var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var values = JsonConvert.DeserializeObject>(json); - var token = values?["access_token"]; client.DefaultRequestHeaders.Accept.Clear(); - Logger.LogTrace("Access token parsed"); + Logger.LogTrace("Access token parsed successfully"); if (token != null) { Logger.LogInformation( "Authentication succeeded | Identity={Identity} Url={Url} AuthenticationResult=Success CorrelationId={CorrelationId}", - string.IsNullOrEmpty(configurationInfo.Username) ? configurationInfo.ClientId : configurationInfo.Username, + string.IsNullOrEmpty(configurationInfo.Username) + ? configurationInfo.ClientId + : configurationInfo.Username, configurationInfo.SecretServerUrl, correlationId); return token; } + Logger.LogError( - "Unable to generate access token from Delinea Secret Server \'{ConfigurationInfoSecretServerUrl}\' as \'{ConfigurationInfoUsername}\'. Please check your credentials and try again CorrelationId={CorrelationId}", - configurationInfo.SecretServerUrl, configurationInfo.Username, correlationId); + "Unable to generate access token from Delinea Secret Server '{Url}'. Please check your credentials and try again. CorrelationId={CorrelationId}", + configurationInfo.SecretServerUrl, correlationId); Logger.MethodExit(); throw new InvalidTokenException( - $"Unable to generate access token from Delinea Secret Server '{configurationInfo.SecretServerUrl}' as '{configurationInfo.Username}'. Please check your credentials and try again"); + $"Unable to generate access token from Delinea Secret Server '{configurationInfo.SecretServerUrl}'. Please check your credentials and try again"); } catch (Exception ex) { @@ -370,23 +428,19 @@ private async Task GetAccessToken(HttpClient client, DelineaConfiguratio } } + // --------------------------------------------------------------------------- + // Validation + // --------------------------------------------------------------------------- + /// - /// Validates the instance parameters provided to the PAM provider. + /// Validates instance parameters (SecretId, SecretFieldName). + /// Throws on failure. /// - /// - /// A read-only dictionary containing instance-specific parameters, such as SecretId and SecretFieldName. - /// - /// - /// True if the instance parameters are valid; otherwise, throws an . - /// - /// - /// Thrown if required parameters are missing or cannot be parsed as expected. - /// private bool ValidateInstanceParams(IReadOnlyDictionary instanceParameters) { Logger.MethodEntry(); Logger.LogDebug("Validating instance parameters"); - Logger.LogDebug("Validating instance parameter '{SecretId}'", DelineaConfiguration.SECRET_ID); + if (!instanceParameters.ContainsKey(DelineaConfiguration.SECRET_ID)) { Logger.LogError("Instance parameter '{SecretId}' not found", DelineaConfiguration.SECRET_ID); @@ -396,7 +450,7 @@ private bool ValidateInstanceParams(IReadOnlyDictionary instance } if (!instanceParameters.ContainsKey(DelineaConfiguration.SECRET_FIELD_NAME) || - instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME] == string.Empty) + string.IsNullOrWhiteSpace(instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME])) { Logger.LogError("Instance parameter '{SecretFieldName}' not provided", DelineaConfiguration.SECRET_FIELD_NAME); @@ -405,8 +459,7 @@ private bool ValidateInstanceParams(IReadOnlyDictionary instance $"Instance parameter '{DelineaConfiguration.SECRET_FIELD_NAME}' not provided"); } - Logger.LogDebug("Parsing instance parameter '{SecretId}'", DelineaConfiguration.SECRET_ID); - if (int.TryParse(instanceParameters[DelineaConfiguration.SECRET_ID], out var secretId)) + if (int.TryParse(instanceParameters[DelineaConfiguration.SECRET_ID], out _)) { Logger.LogDebug("Instance parameters are valid"); Logger.MethodExit(); @@ -420,84 +473,44 @@ private bool ValidateInstanceParams(IReadOnlyDictionary instance } /// - /// Validates the server configuration parameters for connecting to Delinea Secret Server. + /// Validates server configuration parameters for the resolved grant type. + /// Throws on failure. /// - /// - /// A read-only dictionary containing server configuration parameters such as Secret Server URL, credentials, and grant - /// type. - /// - /// - /// The OAuth grant type to validate credentials for. Supported values are "password" and "client_credentials". - /// Defaults to "password". - /// - /// - /// True if the server configuration parameters are valid; otherwise, throws an - /// . - /// - /// - /// Thrown if required parameters are missing or invalid for the specified grant type. - /// private bool ValidateServerConfigurationParams( - IReadOnlyDictionary connectionConfiguration) + IReadOnlyDictionary connectionConfiguration, + string grantType) { Logger.MethodEntry(); - Logger.LogDebug("Validating server configuration parameters"); - - var grantType = "password"; - if (connectionConfiguration.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var configuredGrantType) && - !string.IsNullOrEmpty(configuredGrantType)) - { - grantType = configuredGrantType; - } + Logger.LogDebug("Validating server configuration parameters for grant type '{GrantType}'", grantType); - // Validate Secret Server URL - ValidateRequiredParameter(connectionConfiguration, - DelineaConfiguration.SECRET_SERVER_URL, + ValidateRequiredParameter(connectionConfiguration, DelineaConfiguration.SECRET_SERVER_URL, "Server configuration parameter"); - // Validate credentials based on grant type switch (grantType) { case "password": ValidatePasswordGrantCredentials(connectionConfiguration); break; - case "client_credentials": ValidateClientCredentialsGrantCredentials(connectionConfiguration); break; - case "windows": - Logger.LogDebug("Using Windows Authentication, no credentials to validate"); + Logger.LogDebug("Using Windows Authentication — no credential parameters to validate"); break; default: Logger.LogError( - "Invalid grant type '{GrantType}' specified. Supported types are 'password' and 'client_credentials'", + "Invalid grant type '{GrantType}' specified. Supported values are 'password', 'client_credentials', and 'windows'", grantType); Logger.MethodExit(); - throw new Exception( - $"Invalid grant type '{grantType}' specified. Supported types are 'password' and 'client_credentials'"); + throw new InvalidClientConfigurationException( + $"Invalid grant type '{grantType}' specified. Supported values are 'password', 'client_credentials', and 'windows'"); } - Logger.MethodExit(); Logger.LogInformation("Server configuration parameters are valid"); + Logger.MethodExit(); return true; } - /// - /// Validates that a required parameter exists and is not null or empty in the provided configuration dictionary. - /// - /// - /// The configuration dictionary to validate. - /// - /// - /// The name of the parameter to check for existence and non-empty value. - /// - /// - /// A string prefix to include in the error message if validation fails. - /// - /// - /// Thrown if the required parameter is missing or its value is null or empty. - /// private void ValidateRequiredParameter( IReadOnlyDictionary config, string paramName, @@ -506,19 +519,17 @@ private void ValidateRequiredParameter( Logger.MethodEntry(); Logger.LogDebug("Validating parameter '{ParamName}'", paramName); - if (config.ContainsKey(paramName) && !string.IsNullOrEmpty(config[paramName])) return; + if (config.ContainsKey(paramName) && !string.IsNullOrEmpty(config[paramName])) + { + Logger.MethodExit(); + return; + } + Logger.LogError("{ErrorPrefix} '{ParamName}' not provided", errorPrefix, paramName); Logger.MethodExit(); throw new InvalidClientConfigurationException($"{errorPrefix} '{paramName}' not provided"); } - /// - /// Validates that the required username and password parameters exist and are not empty for the password grant type. - /// - /// The configuration dictionary containing client parameters. - /// - /// Thrown if the username or password parameter is missing or empty. - /// private void ValidatePasswordGrantCredentials(IReadOnlyDictionary config) { Logger.MethodEntry(); @@ -527,16 +538,6 @@ private void ValidatePasswordGrantCredentials(IReadOnlyDictionary - /// Validates that the required client ID and client secret parameters exist and are not empty for the client - /// credentials grant type. - /// - /// - /// The configuration dictionary containing client parameters. - /// - /// - /// Thrown if the client ID or client secret parameter is missing or empty. - /// private void ValidateClientCredentialsGrantCredentials(IReadOnlyDictionary config) { Logger.MethodEntry(); @@ -545,23 +546,20 @@ private void ValidateClientCredentialsGrantCredentials(IReadOnlyDictionary - /// Creates a DelineaConfiguration object from the provided parameters. - /// - /// - /// Dictionary containing instance-specific parameters, including the secret ID and field - /// name. - /// - /// Dictionary containing connection and authentication parameters for Secret Server. - /// A fully populated DelineaConfiguration object. - /// Thrown when required parameters are missing or invalid. + // --------------------------------------------------------------------------- + // Configuration builder + // --------------------------------------------------------------------------- + private DelineaConfiguration BuildDelineaConfiguration( IReadOnlyDictionary instanceParameters, IReadOnlyDictionary connectionConfiguration) { Logger.MethodEntry(); Logger.LogInformation("Validating Delinea configuration"); - var validServer = ValidateServerConfigurationParams(connectionConfiguration); + + var grantType = ResolveGrantType(connectionConfiguration); + + var validServer = ValidateServerConfigurationParams(connectionConfiguration, grantType); var validInstance = ValidateInstanceParams(instanceParameters); if (!validServer || !validInstance) @@ -575,25 +573,17 @@ private DelineaConfiguration BuildDelineaConfiguration( var secretId = int.Parse(instanceParameters[DelineaConfiguration.SECRET_ID]); Logger.LogDebug("Secret ID: {SecretId}", secretId); - if (!connectionConfiguration.TryGetValue(DelineaConfiguration.GRANT_TYPE, out var grantType)) - { - Logger.LogWarning( - "\'{GrantType}\' parameter not provided defaulting to 'password' grant", - DelineaConfiguration.GRANT_TYPE); - grantType = "password"; - } - connectionConfiguration.TryGetValue(DelineaConfiguration.SKIP_TLS_VALIDATION, out var skipTlsRaw); var skipTls = string.Equals(skipTlsRaw, "true", StringComparison.OrdinalIgnoreCase); if (skipTls) - Logger.LogWarning("TLS certificate validation is disabled — use only in non-production environments"); + Logger.LogWarning( + "TLS certificate validation is disabled — use only in non-production environments"); + + Logger.LogDebug("Building Delinea configuration for '{GrantType}' grant type", grantType); - Logger.LogDebug("Building Delinea configuration"); switch (grantType) { case "password": - - Logger.LogDebug("Building Delinea configuration for password grant type"); Logger.MethodExit(); return new DelineaConfiguration { @@ -607,20 +597,23 @@ private DelineaConfiguration BuildDelineaConfiguration( }; case "client_credentials": - Logger.LogDebug("Building Delinea configuration for client credentials grant type"); Logger.MethodExit(); return new DelineaConfiguration { SecretServerUrl = connectionConfiguration[DelineaConfiguration.SECRET_SERVER_URL], + // NOTE: For client_credentials the ClientId maps to Username and ClientSecret maps to + // Password in the token request body. This is a Delinea API constraint. + Username = connectionConfiguration[DelineaConfiguration.CLIENT_ID], + Password = connectionConfiguration[DelineaConfiguration.CLIENT_SECRET], ClientId = connectionConfiguration[DelineaConfiguration.CLIENT_ID], ClientSecret = connectionConfiguration[DelineaConfiguration.CLIENT_SECRET], SecretId = secretId, SecretFieldName = instanceParameters[DelineaConfiguration.SECRET_FIELD_NAME], - GrantType = "password", + GrantType = "client_credentials", SkipTlsValidation = skipTls }; + case "windows": - Logger.LogDebug("Building Delinea configuration for windows grant type"); Logger.MethodExit(); return new DelineaConfiguration { @@ -633,18 +626,18 @@ private DelineaConfiguration BuildDelineaConfiguration( default: Logger.LogError( - "Invalid grant type '{GrantType}' specified. Supported types are 'password' and 'client_credentials'", + "Invalid grant type '{GrantType}' — supported values are 'password', 'client_credentials', and 'windows'", grantType); Logger.MethodExit(); - throw new Exception( - $"Invalid grant type '{grantType}' specified. Supported types are 'password' and 'client_credentials'"); + throw new InvalidClientConfigurationException( + $"Invalid grant type '{grantType}' specified. Supported values are 'password', 'client_credentials', and 'windows'"); } } - /// - /// Creates and configures an HttpClient for communicating with Secret Server. - /// - /// A configured HttpClient with a 60-second timeout. + // --------------------------------------------------------------------------- + // HttpClient factory + // --------------------------------------------------------------------------- + private static HttpClient BuildHttpClient(string grantType, bool skipTlsValidation = false) { var handler = new HttpClientHandler(); @@ -658,4 +651,134 @@ private static HttpClient BuildHttpClient(string grantType, bool skipTlsValidati } } -} \ No newline at end of file + // --------------------------------------------------------------------------- + // Concrete PAM type implementations + // --------------------------------------------------------------------------- + + /// + /// Backwards-compatible PAM provider for Delinea Secret Server. + /// Supports all three authentication flows (password, client_credentials, windows) + /// selected at runtime via the GrantType server configuration parameter. + /// Prefer the type-specific variants for new installations. + /// + public class SecretServerPam : SecretServerPamBase, IPAMProvider + { + /// Production constructor — no arguments, required by Keyfactor Command. + public SecretServerPam() + { + Logger = LogHandler.GetClassLogger(); + } + + /// Test constructor — accepts injected dependencies. + internal SecretServerPam(HttpClient httpClient, ILogger logger) + : base(httpClient, logger) + { + } + + /// + public string Name => "Delinea-SecretServer"; + + /// + public string GetPassword( + Dictionary instanceParameters, + Dictionary serverConfigurationParameters) + => GetPasswordCore(instanceParameters, serverConfigurationParameters); + } + + /// + /// PAM provider for Delinea Secret Server using the password grant type (Username + Password). + /// Only the Host, Username, and Password server parameters are required. + /// + public class SecretServerPamPassword : SecretServerPamBase, IPAMProvider + { + /// Production constructor — no arguments, required by Keyfactor Command. + public SecretServerPamPassword() + { + Logger = LogHandler.GetClassLogger(); + } + + /// Test constructor — accepts injected dependencies. + internal SecretServerPamPassword(HttpClient httpClient, ILogger logger) + : base(httpClient, logger) + { + } + + /// + public string Name => "Delinea-SecretServer-Password"; + + /// Always returns "password" — hardcoded for this type. + protected override string ResolveGrantType(IReadOnlyDictionary serverConfigurationParameters) + => "password"; + + /// + public string GetPassword( + Dictionary instanceParameters, + Dictionary serverConfigurationParameters) + => GetPasswordCore(instanceParameters, serverConfigurationParameters); + } + + /// + /// PAM provider for Delinea Secret Server using the client_credentials OAuth2 flow (ClientId + ClientSecret). + /// Only the Host, ClientId, and ClientSecret server parameters are required. + /// + public class SecretServerPamClientCredentials : SecretServerPamBase, IPAMProvider + { + /// Production constructor — no arguments, required by Keyfactor Command. + public SecretServerPamClientCredentials() + { + Logger = LogHandler.GetClassLogger(); + } + + /// Test constructor — accepts injected dependencies. + internal SecretServerPamClientCredentials(HttpClient httpClient, ILogger logger) + : base(httpClient, logger) + { + } + + /// + public string Name => "Delinea-SecretServer-ClientCredentials"; + + /// Always returns "client_credentials" — hardcoded for this type. + protected override string ResolveGrantType(IReadOnlyDictionary serverConfigurationParameters) + => "client_credentials"; + + /// + public string GetPassword( + Dictionary instanceParameters, + Dictionary serverConfigurationParameters) + => GetPasswordCore(instanceParameters, serverConfigurationParameters); + } + + /// + /// PAM provider for Delinea Secret Server using Integrated Windows Authentication (IWA). + /// Only the Host server parameter is required. + /// NOTE: IWA is not supported on Secret Server Cloud. + /// + public class SecretServerPamWindows : SecretServerPamBase, IPAMProvider + { + /// Production constructor — no arguments, required by Keyfactor Command. + public SecretServerPamWindows() + { + Logger = LogHandler.GetClassLogger(); + } + + /// Test constructor — accepts injected dependencies. + internal SecretServerPamWindows(HttpClient httpClient, ILogger logger) + : base(httpClient, logger) + { + } + + /// + public string Name => "Delinea-SecretServer-Windows"; + + /// Always returns "windows" — hardcoded for this type. + protected override string ResolveGrantType(IReadOnlyDictionary serverConfigurationParameters) + => "windows"; + + /// + public string GetPassword( + Dictionary instanceParameters, + Dictionary serverConfigurationParameters) + => GetPasswordCore(instanceParameters, serverConfigurationParameters); + } +} From fcec12dc9775cffc4965608f95acb9bb92363016 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:42:44 -0700 Subject: [PATCH 24/32] test: add xUnit test project covering all four PAM types and auth flows Adds delinea-secretserver-pam.Tests (net8.0) with 38 tests covering: - Happy path for password, client_credentials, and windows grant types - Missing required server and instance parameters - Non-success HTTP responses from token and secret endpoints - Empty/null token responses - Field-not-found in secret response - Token request body field name verification (Delinea API constraint: client_credentials still uses username/password key names) - Windows auth correctly targets winauthwebservices endpoint and never calls the token endpoint - All four PAM type Names are distinct TestHttpMessageHandler fake allows request interception without network access. --- .../Fakes/TestHttpMessageHandler.cs | 33 + .../SecretServerPamTests.cs | 802 ++++++++++++++++++ .../delinea-secretserver-pam.Tests.csproj | 30 + delinea-secretserver-pam.sln | 39 +- 4 files changed, 903 insertions(+), 1 deletion(-) create mode 100644 delinea-secretserver-pam.Tests/Fakes/TestHttpMessageHandler.cs create mode 100644 delinea-secretserver-pam.Tests/SecretServerPamTests.cs create mode 100644 delinea-secretserver-pam.Tests/delinea-secretserver-pam.Tests.csproj diff --git a/delinea-secretserver-pam.Tests/Fakes/TestHttpMessageHandler.cs b/delinea-secretserver-pam.Tests/Fakes/TestHttpMessageHandler.cs new file mode 100644 index 0000000..89f901c --- /dev/null +++ b/delinea-secretserver-pam.Tests/Fakes/TestHttpMessageHandler.cs @@ -0,0 +1,33 @@ +// 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.Net; + +namespace Keyfactor.Extensions.Pam.Delinea.Tests.Fakes; + +/// +/// A test-only whose behaviour is controlled +/// by a delegate, allowing individual tests to script exactly what the fake +/// HTTP server returns without going to the network. +/// +public class TestHttpMessageHandler : HttpMessageHandler +{ + public Func>? HandlerFunc { get; set; } + + public TestHttpMessageHandler( + Func>? handlerFunc = null) + { + HandlerFunc = handlerFunc; + } + + protected override Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + => HandlerFunc != null + ? HandlerFunc(request, cancellationToken) + : Task.FromResult(new HttpResponseMessage(HttpStatusCode.NotImplemented)); +} diff --git a/delinea-secretserver-pam.Tests/SecretServerPamTests.cs b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs new file mode 100644 index 0000000..d785d36 --- /dev/null +++ b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs @@ -0,0 +1,802 @@ +// 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.Net; +using FluentAssertions; +using Keyfactor.Extensions.Pam.Delinea.Tests.Fakes; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Newtonsoft.Json; + +namespace Keyfactor.Extensions.Pam.Delinea.Tests; + +/// +/// Tests for all four concrete PAM provider types and the shared base logic. +/// HTTP is intercepted via — no network calls. +/// +public class SecretServerPamTests +{ + // --------------------------------------------------------------------------- + // Shared test constants + // --------------------------------------------------------------------------- + private const string FakeHost = "https://secretserver.example.com/SecretServer"; + private const string FakeUsername = "svc-account"; + private const string FakePassword = "sup3rS3cret!"; + private const string FakeClientId = "app-client-01"; + private const string FakeClientSecret = "cl13ntS3cr3t!"; + private const string FakeSecretId = "42"; + private const string FakeFieldName = "password"; + private const string FakeFieldValue = "retrieved-credential-value"; + private const string FakeToken = "fake-bearer-token"; + + private static ILogger NullLogger => NullLogger.Instance; + + // --------------------------------------------------------------------------- + // Helpers + // --------------------------------------------------------------------------- + + private static string BuildTokenResponse(string token = FakeToken) + => JsonConvert.SerializeObject(new Dictionary { { "access_token", token } }); + + private static string BuildSecretResponse(string fieldName = FakeFieldName, string fieldValue = FakeFieldValue) + => JsonConvert.SerializeObject(new + { + id = 42, + name = "Test Secret", + items = new[] + { + new { itemId = 1, fieldName = fieldName, slug = fieldName, itemValue = fieldValue, isPassword = true } + } + }); + + /// + /// Creates a that sequences multiple responses: + /// first response for the token endpoint, second for the secret endpoint. + /// + private static TestHttpMessageHandler TwoStageHandler( + HttpResponseMessage tokenResponse, + HttpResponseMessage secretResponse) + { + var callCount = 0; + return new TestHttpMessageHandler((req, ct) => + { + callCount++; + return Task.FromResult(callCount == 1 ? tokenResponse : secretResponse); + }); + } + + private static TestHttpMessageHandler ConstantHandler(HttpResponseMessage response) + => new TestHttpMessageHandler((req, ct) => Task.FromResult(response)); + + // --------------------------------------------------------------------------- + // SecretServerPam (backwards-compatible, GrantType-driven) + // --------------------------------------------------------------------------- + + public class BackwardsCompatibleType + { + [Fact] + public void Name_IsDelineaSecretServer() + { + var sut = new SecretServerPam(); + sut.Name.Should().Be("Delinea-SecretServer"); + } + + [Fact] + public void GetPassword_PasswordGrant_ReturnsSecret() + { + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPam(new HttpClient(handler), NullLogger); + + var result = sut.GetPassword( + InstanceParams(), + ServerParams("password")); + + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_ClientCredentialsGrant_ReturnsSecret() + { + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPam(new HttpClient(handler), NullLogger); + + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "ClientId", FakeClientId }, + { "ClientSecret", FakeClientSecret }, + { "GrantType", "client_credentials" } + }; + + var result = sut.GetPassword(InstanceParams(), serverParams); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_DefaultsToPasswordGrant_WhenGrantTypeAbsent() + { + var tokenRequested = false; + var handler = new TestHttpMessageHandler((req, ct) => + { + if (req.RequestUri!.AbsolutePath.Contains("oauth2/token")) + tokenRequested = true; + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent( + req.RequestUri.AbsolutePath.Contains("oauth2/token") + ? BuildTokenResponse() + : BuildSecretResponse()) + }); + }); + + var sut = new SecretServerPam(new HttpClient(handler), NullLogger); + + // No GrantType key in server params + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword } + }; + + var result = sut.GetPassword(InstanceParams(), serverParams); + result.Should().Be(FakeFieldValue); + tokenRequested.Should().BeTrue(); + } + + [Fact] + public void GetPassword_MissingHost_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPam(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Username", FakeUsername }, + { "Password", FakePassword } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw() + .WithMessage("*Host*"); + } + + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + private static Dictionary ServerParams(string grantType) => new() + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword }, + { "GrantType", grantType } + }; + } + + // --------------------------------------------------------------------------- + // SecretServerPamPassword + // --------------------------------------------------------------------------- + + public class PasswordType + { + [Fact] + public void Name_IsDelineaSecretServerPassword() + { + var sut = new SecretServerPamPassword(); + sut.Name.Should().Be("Delinea-SecretServer-Password"); + } + + [Fact] + public void GetPassword_HappyPath_ReturnsSecret() + { + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + + var result = sut.GetPassword(InstanceParams(), ServerParams()); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_MatchBySlug_ReturnsSecret() + { + // Build a secret where fieldName differs from slug; look up by slug + var secretJson = JsonConvert.SerializeObject(new + { + id = 42, + name = "Test Secret", + items = new[] + { + new + { + itemId = 1, + fieldName = "Display Name", + slug = FakeFieldName, + itemValue = FakeFieldValue, + isPassword = true + } + } + }); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(secretJson) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams()); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_TokenEndpointReturns401_ThrowsHttpRequestException() + { + var handler = ConstantHandler(new HttpResponseMessage(HttpStatusCode.Unauthorized) + { Content = new StringContent("unauthorized") }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), ServerParams()); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_SecretEndpointReturns404_ThrowsHttpRequestException() + { + var callCount = 0; + var handler = new TestHttpMessageHandler((req, ct) => + { + callCount++; + var statusCode = callCount == 1 ? HttpStatusCode.OK : HttpStatusCode.NotFound; + var content = callCount == 1 ? BuildTokenResponse() : "not found"; + return Task.FromResult(new HttpResponseMessage(statusCode) + { Content = new StringContent(content) }); + }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), ServerParams()); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_FieldNotFoundInSecret_ThrowsInvalidSecretConfigurationException() + { + var secretJson = BuildSecretResponse("other-field", "some-value"); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(secretJson) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + + // Request a field name that is not in the secret + var instanceParams = new Dictionary + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", "nonexistent-field" } + }; + + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw() + .WithMessage("*nonexistent-field*"); + } + + [Fact] + public void GetPassword_EmptyToken_ThrowsInvalidTokenException() + { + var tokenJson = JsonConvert.SerializeObject(new Dictionary + { { "access_token", string.Empty } }); + + var handler = ConstantHandler( + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(tokenJson) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), ServerParams()); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_MissingHost_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Username", FakeUsername }, + { "Password", FakePassword } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw().WithMessage("*Host*"); + } + + [Fact] + public void GetPassword_MissingUsername_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "Password", FakePassword } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw().WithMessage("*Username*"); + } + + [Fact] + public void GetPassword_MissingPassword_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "Username", FakeUsername } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw().WithMessage("*Password*"); + } + + [Fact] + public void GetPassword_MissingSecretId_ThrowsInvalidSecretConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var instanceParams = new Dictionary + { + { "SecretFieldName", FakeFieldName } + }; + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw().WithMessage("*SecretId*"); + } + + [Fact] + public void GetPassword_MissingSecretFieldName_ThrowsInvalidSecretConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var instanceParams = new Dictionary + { + { "SecretId", FakeSecretId } + }; + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw().WithMessage("*SecretFieldName*"); + } + + [Fact] + public void GetPassword_NonIntegerSecretId_ThrowsInvalidSecretConfigurationException() + { + var sut = new SecretServerPamPassword(new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var instanceParams = new Dictionary + { + { "SecretId", "not-an-int" }, + { "SecretFieldName", FakeFieldName } + }; + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw().WithMessage("*not-an-int*"); + } + + [Fact] + public void GetPassword_TokenRequestBody_ContainsUsernameAndPassword() + { + // Verify the token POST uses "username"/"password" field names + // (Delinea API constraint — not "client_id"/"client_secret") + string? capturedBody = null; + var callCount = 0; + + var handler = new TestHttpMessageHandler(async (req, ct) => + { + callCount++; + if (callCount == 1) + { + capturedBody = await req.Content!.ReadAsStringAsync(); + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }; + } + + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }; + }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), ServerParams()); + + capturedBody.Should().Contain("username="); + capturedBody.Should().Contain("password="); + capturedBody.Should().Contain("grant_type=password"); + } + + [Fact] + public void GetPassword_TokenRequestUrl_PointsToOAuth2TokenEndpoint() + { + Uri? capturedTokenUri = null; + var callCount = 0; + + var handler = new TestHttpMessageHandler((req, ct) => + { + callCount++; + if (callCount == 1) + { + capturedTokenUri = req.RequestUri; + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }); + } + + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), ServerParams()); + + capturedTokenUri.Should().NotBeNull(); + capturedTokenUri!.AbsolutePath.Should().EndWith("/oauth2/token"); + } + + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + private static Dictionary ServerParams() => new() + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword } + }; + } + + // --------------------------------------------------------------------------- + // SecretServerPamClientCredentials + // --------------------------------------------------------------------------- + + public class ClientCredentialsType + { + [Fact] + public void Name_IsDelineaSecretServerClientCredentials() + { + var sut = new SecretServerPamClientCredentials(); + sut.Name.Should().Be("Delinea-SecretServer-ClientCredentials"); + } + + [Fact] + public void GetPassword_HappyPath_ReturnsSecret() + { + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamClientCredentials(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams()); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_TokenRequestBody_UsesUsernamePasswordFieldNames() + { + // Delinea API constraint: client_credentials flow still sends username/password + // in the token request body — NOT client_id/client_secret + string? capturedBody = null; + var callCount = 0; + + var handler = new TestHttpMessageHandler(async (req, ct) => + { + callCount++; + if (callCount == 1) + { + capturedBody = await req.Content!.ReadAsStringAsync(); + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }; + } + + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }; + }); + + var sut = new SecretServerPamClientCredentials(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), ServerParams()); + + // Must use username= / password= field names (Delinea API constraint) + capturedBody.Should().Contain("username="); + capturedBody.Should().Contain("password="); + // ClientId value should appear as the username value + capturedBody.Should().Contain(Uri.EscapeDataString(FakeClientId)); + // Must NOT contain client_id= key + capturedBody.Should().NotContain("client_id="); + } + + [Fact] + public void GetPassword_MissingClientId_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamClientCredentials( + new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "ClientSecret", FakeClientSecret } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw().WithMessage("*ClientId*"); + } + + [Fact] + public void GetPassword_MissingClientSecret_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamClientCredentials( + new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "ClientId", FakeClientId } + }; + var act = () => sut.GetPassword(InstanceParams(), serverParams); + act.Should().Throw().WithMessage("*ClientSecret*"); + } + + [Fact] + public void GetPassword_TokenEndpointFails_ThrowsHttpRequestException() + { + var handler = ConstantHandler(new HttpResponseMessage(HttpStatusCode.Unauthorized) + { Content = new StringContent("unauthorized") }); + + var sut = new SecretServerPamClientCredentials(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), ServerParams()); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_FieldNotFound_ThrowsInvalidSecretConfigurationException() + { + var secretJson = BuildSecretResponse("different-field", "some-value"); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(secretJson) }); + + var sut = new SecretServerPamClientCredentials(new HttpClient(handler), NullLogger); + + var instanceParams = new Dictionary + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", "missing-field" } + }; + + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw(); + } + + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + private static Dictionary ServerParams() => new() + { + { "Host", FakeHost }, + { "ClientId", FakeClientId }, + { "ClientSecret", FakeClientSecret } + }; + } + + // --------------------------------------------------------------------------- + // SecretServerPamWindows + // --------------------------------------------------------------------------- + + public class WindowsType + { + [Fact] + public void Name_IsDelineaSecretServerWindows() + { + var sut = new SecretServerPamWindows(); + sut.Name.Should().Be("Delinea-SecretServer-Windows"); + } + + [Fact] + public void GetPassword_HappyPath_ReturnsSecret() + { + // Windows auth: no token request, single GET to winauthwebservices endpoint + var handler = ConstantHandler(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamWindows(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams()); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_UsesWinAuthWebServicesEndpoint() + { + Uri? capturedUri = null; + + var handler = new TestHttpMessageHandler((req, ct) => + { + capturedUri = req.RequestUri; + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + }); + + var sut = new SecretServerPamWindows(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), ServerParams()); + + capturedUri.Should().NotBeNull(); + capturedUri!.AbsolutePath.Should().Contain("winauthwebservices"); + } + + [Fact] + public void GetPassword_DoesNotCallTokenEndpoint() + { + var tokenEndpointCalled = false; + + var handler = new TestHttpMessageHandler((req, ct) => + { + if (req.RequestUri!.AbsolutePath.Contains("oauth2/token")) + tokenEndpointCalled = true; + + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }); + }); + + var sut = new SecretServerPamWindows(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), ServerParams()); + + tokenEndpointCalled.Should().BeFalse("Windows auth should not request a token"); + } + + [Fact] + public void GetPassword_MissingHost_ThrowsInvalidClientConfigurationException() + { + var sut = new SecretServerPamWindows( + new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), new Dictionary()); + act.Should().Throw().WithMessage("*Host*"); + } + + [Fact] + public void GetPassword_SecretEndpointFails_ThrowsHttpRequestException() + { + var handler = ConstantHandler(new HttpResponseMessage(HttpStatusCode.Forbidden) + { Content = new StringContent("forbidden") }); + + var sut = new SecretServerPamWindows(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword(InstanceParams(), ServerParams()); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_FieldNotFound_ThrowsInvalidSecretConfigurationException() + { + var secretJson = BuildSecretResponse("other-field", "some-value"); + var handler = ConstantHandler(new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(secretJson) }); + + var sut = new SecretServerPamWindows(new HttpClient(handler), NullLogger); + var instanceParams = new Dictionary + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", "no-such-field" } + }; + var act = () => sut.GetPassword(instanceParams, ServerParams()); + act.Should().Throw(); + } + + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + private static Dictionary ServerParams() => new() + { + { "Host", FakeHost } + }; + } + + // --------------------------------------------------------------------------- + // Shared validation — tested via SecretServerPamPassword as a representative type + // --------------------------------------------------------------------------- + + public class SharedValidation + { + [Theory] + [InlineData("")] + [InlineData(" ")] + public void GetPassword_EmptySecretFieldName_ThrowsInvalidSecretConfigurationException(string fieldName) + { + var sut = new SecretServerPamPassword( + new HttpClient(ConstantHandler(new HttpResponseMessage())), NullLogger); + var instanceParams = new Dictionary + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", fieldName } + }; + var serverParams = new Dictionary + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword } + }; + var act = () => sut.GetPassword(instanceParams, serverParams); + act.Should().Throw(); + } + + [Fact] + public void GetPassword_ErrorResponseTruncatedAt500Chars_NeverLogsFullErrorBody() + { + // We cannot inspect log output directly without a custom ILogger, but we + // can verify the provider still throws rather than swallowing the error, + // confirming the truncation code path is exercised without hanging. + var longError = new string('x', 2000); + + var callCount = 0; + var handler = new TestHttpMessageHandler((req, ct) => + { + callCount++; + HttpStatusCode status; + string body; + if (callCount == 1) + { + // Token request succeeds + status = HttpStatusCode.OK; + body = BuildTokenResponse(); + } + else + { + // Secret request returns a long error body + status = HttpStatusCode.InternalServerError; + body = longError; + } + + return Task.FromResult(new HttpResponseMessage(status) + { Content = new StringContent(body) }); + }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var act = () => sut.GetPassword( + new Dictionary + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }, + new Dictionary + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword } + }); + + act.Should().Throw(); + } + + [Fact] + public void GetPassword_AllFourTypes_HaveDistinctNames() + { + var names = new[] + { + new SecretServerPam().Name, + new SecretServerPamPassword().Name, + new SecretServerPamClientCredentials().Name, + new SecretServerPamWindows().Name + }; + + names.Should().OnlyHaveUniqueItems("all PAM type Names must be distinct"); + } + } +} diff --git a/delinea-secretserver-pam.Tests/delinea-secretserver-pam.Tests.csproj b/delinea-secretserver-pam.Tests/delinea-secretserver-pam.Tests.csproj new file mode 100644 index 0000000..9fa2419 --- /dev/null +++ b/delinea-secretserver-pam.Tests/delinea-secretserver-pam.Tests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + Keyfactor.Extensions.Pam.Delinea.Tests + enable + enable + false + true + + + + + + + + + + + + + + + + + + + + + diff --git a/delinea-secretserver-pam.sln b/delinea-secretserver-pam.sln index 0b636a1..fdc3d6e 100644 --- a/delinea-secretserver-pam.sln +++ b/delinea-secretserver-pam.sln @@ -4,20 +4,57 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "delinea-secretserver-pam", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestConsole", "TestConsole\TestConsole.csproj", "{90C4CEE8-44EE-4488-B464-4063432051D8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "delinea-secretserver-pam.Tests", "delinea-secretserver-pam.Tests\delinea-secretserver-pam.Tests.csproj", "{2600171C-9C51-4629-B515-EC8279B47FF1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|x64.ActiveCfg = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|x64.Build.0 = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|x86.ActiveCfg = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|x86.Build.0 = Debug|Any CPU {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|Any CPU.ActiveCfg = Release|Any CPU {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|Any CPU.Build.0 = Release|Any CPU - {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|x64.ActiveCfg = Release|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|x64.Build.0 = Release|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|x86.ActiveCfg = Release|Any CPU + {6DEC0EF0-9D07-44CF-868C-82764C83D285}.Release|x86.Build.0 = Release|Any CPU {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|x64.ActiveCfg = Debug|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|x64.Build.0 = Debug|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|x86.ActiveCfg = Debug|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Debug|x86.Build.0 = Debug|Any CPU {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|Any CPU.Build.0 = Release|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|x64.ActiveCfg = Release|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|x64.Build.0 = Release|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|x86.ActiveCfg = Release|Any CPU + {90C4CEE8-44EE-4488-B464-4063432051D8}.Release|x86.Build.0 = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|x64.ActiveCfg = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|x64.Build.0 = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|x86.ActiveCfg = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Debug|x86.Build.0 = Debug|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|Any CPU.Build.0 = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|x64.ActiveCfg = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|x64.Build.0 = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|x86.ActiveCfg = Release|Any CPU + {2600171C-9C51-4629-B515-EC8279B47FF1}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal From 9682780c89720ab820143ce29c2a9c8759660714 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:42:55 -0700 Subject: [PATCH 25/32] feat(manifest): register three new grant-type-specific PAM types integration-manifest.json: add Delinea-SecretServer-Password, Delinea-SecretServer-ClientCredentials, and Delinea-SecretServer-Windows PAM type blocks. Each exposes only the fields relevant to its auth flow, removing the Command UI requirement to fill in irrelevant credentials. manifest.json: add InitializationInfo example blocks for the three new types alongside the existing Delinea-SecretServer block. CHANGELOG.md and README.md updated to document all four types, including recommended usage guidance and kfutil commands for the new variants. --- CHANGELOG.md | 20 ++++ README.md | 76 ++++++++++--- delinea-secretserver-pam/manifest.json | 15 ++- integration-manifest.json | 151 +++++++++++++++++++++++-- 4 files changed, 233 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fae24d4..428967b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +# v1.4.0 + +## Features + +- Added three grant-type-specific PAM type variants. Each type exposes only the fields relevant to its authentication flow, resolving the Keyfactor Command UI requirement that all declared fields be populated. + - `Delinea-SecretServer-Password` — Username + Password authentication. Server parameters: `Host`, `Username`, `Password`, `SkipTlsValidation`. + - `Delinea-SecretServer-ClientCredentials` — OAuth2 client credentials flow. Server parameters: `Host`, `ClientId`, `ClientSecret`, `SkipTlsValidation`. + - `Delinea-SecretServer-Windows` — Integrated Windows Authentication (IWA). Server parameters: `Host`, `SkipTlsValidation`. NOTE: IWA is not supported on Secret Server Cloud. +- All shared logic (HTTP, validation, secret retrieval, audit logging) is implemented once in the new `SecretServerPamBase` abstract class. +- The existing `Delinea-SecretServer` type is unchanged and fully backwards compatible. + +## Bug Fixes + +- Fixed `client_credentials` case in `BuildDelineaConfiguration` where `GrantType` was incorrectly set to `"password"` instead of `"client_credentials"` on the resulting `DelineaConfiguration` object. +- Validation of `SecretFieldName` now rejects whitespace-only values (previously only empty string was rejected). + +## Testing + +- Replaced the manual `TestConsole` project with a proper `xUnit` test project (`delinea-secretserver-pam.Tests`, targeting `net8.0`) covering all four PAM types, all auth flows, and error paths including missing parameters, token failures, field-not-found, and non-success HTTP responses. + # v1.3.0 ## Compliance Remediation (SOX/SOC2) diff --git a/README.md b/README.md index bed1c2d..3937e0a 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,32 @@ ## Overview The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports either `password` or `client_credential` authentication methods. For more information on -these authentication methods, see the +Server secret. Supports `password`, `client_credentials`, and `windows` (Integrated Windows Authentication) +authentication methods. For more information on these authentication methods, see the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). +## PAM Types + +This provider ships four PAM types. For new installations, use the type-specific variants — they only expose the +fields relevant to the chosen authentication flow, which simplifies configuration in the Keyfactor Command UI. + +| PAM Type | Auth Method | Required Server Parameters | +| --- | --- | --- | +| `Delinea-SecretServer-Password` | Username + Password | `Host`, `Username`, `Password` | +| `Delinea-SecretServer-ClientCredentials` | OAuth2 Client Credentials | `Host`, `ClientId`, `ClientSecret` | +| `Delinea-SecretServer-Windows` | Integrated Windows Authentication | `Host` | +| `Delinea-SecretServer` | Any (selected via `GrantType`) | `Host`, plus credentials for the chosen grant type | + +> [!NOTE] +> `Delinea-SecretServer` is the original backwards-compatible type. It requires a `GrantType` field and exposes +> all credential fields in the Command UI regardless of which grant type is active. Existing installations using +> this type do not need to change. + ## Authentication Methods For full details on each authentication method, please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). Below are example `manifest.json` snippets for each supported authentication method. -### Password +### Password (type-specific variant — recommended for new installations) ```json { @@ -52,16 +69,15 @@ Below are example `manifest.json` snippets for each supported authentication met } } }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { + "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { "Host": "https://example.secretservercloud.com/SecretServer", "Username": "", - "Password": "", - "GrantType": "password" + "Password": "" } } ``` -### oAuth2 +### OAuth2 Client Credentials (type-specific variant — recommended for new installations) ```json { @@ -73,16 +89,15 @@ Below are example `manifest.json` snippets for each supported authentication met } } }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { + "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { "Host": "https://example.secretservercloud.com/SecretServer", - "ClientId": "", - "ClientSecret": "", - "GrantType": "client_credentials" + "ClientId": "", + "ClientSecret": "" } } ``` -### Windows +### Windows (type-specific variant — recommended for new installations) > [!IMPORTANT] > Integrated Windows Authentication (IWA) does not work on Secret Server Cloud. @@ -97,15 +112,39 @@ Below are example `manifest.json` snippets for each supported authentication met } } }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "GrantType": "windows" + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" } } ``` + Please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) for more information on configuring IWA. +### Backwards-compatible type (existing installations — no change required) + +The original `Delinea-SecretServer` type continues to work unchanged. Use the `GrantType` parameter to select +the authentication flow at runtime. + +```json +{ + "extensions": { + "Keyfactor.Platform.Extensions.IPAMProvider": { + "PAMProviders.Delinea.PAMProvider": { + "assemblyPath": "delinea-secretserver-pam.dll", + "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" + } + } + }, + "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { + "Host": "https://example.secretservercloud.com/SecretServer", + "Username": "", + "Password": "", + "GrantType": "password" + } +} +``` + ## Support The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. @@ -145,8 +184,13 @@ To install Delinea Secret Server PAM Provider, it is recommended you install [kf Create the required PAM Types in the connected Command platform. ```shell -# Delinea-SecretServer +# Backwards-compatible type (supports all grant types via GrantType parameter) kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer + +# Type-specific variants (recommended for new installations) +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API diff --git a/delinea-secretserver-pam/manifest.json b/delinea-secretserver-pam/manifest.json index f064987..73d919f 100644 --- a/delinea-secretserver-pam/manifest.json +++ b/delinea-secretserver-pam/manifest.json @@ -14,5 +14,18 @@ "ClientId": "", "ClientSecret": "", "GrantType": "password|client_credentials|windows" + }, + "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { + "Host": "https://example.secretservercloud.com/SecretServer", + "Username": "", + "Password": "" + }, + "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { + "Host": "https://example.secretservercloud.com/SecretServer", + "ClientId": "", + "ClientSecret": "" + }, + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" } -} \ No newline at end of file +} diff --git a/integration-manifest.json b/integration-manifest.json index 1c3e6ad..07c162f 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -5,7 +5,7 @@ "status": "production", "support_level": "kf-supported", "link_github": true, - "update_catalog": true, + "update_catalog": true, "release_dir": "delinea-secretserver-pam/bin/Release", "release_project": "delinea-secretserver-pam/delinea-secretserver-pam.csproj", "description": "The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret Server secret. A valid username, password and secret share settings are required.", @@ -48,18 +48,145 @@ "InstanceLevel": false }, { - "Name": "ClientSecret", - "DisplayName": "Secret Server Client Secret", - "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, - "InstanceLevel": false - }, + "Name": "ClientSecret", + "DisplayName": "Secret Server Client Secret", + "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "GrantType", + "DisplayName": "Grant Type", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] + }, + "Delinea-SecretServer-Password": { + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, { - "Name": "GrantType", - "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password` or `client_credentials`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatability.", - "DataType": 1, - "InstanceLevel": false + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] + }, + "Delinea-SecretServer-ClientCredentials": { + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] + }, + "Delinea-SecretServer-Windows": { + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false }, { "Name": "SecretId", From 3bad85f68e27a2a06e263dc1cb44ac3aa82fa484 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Thu, 23 Apr 2026 19:44:19 +0000 Subject: [PATCH 26/32] Update generated docs --- README.md | 443 +++++++++++++++--- .../delinea-secretserver-clientcredentials.md | 16 + docs/delinea-secretserver-password.md | 16 + docs/delinea-secretserver-windows.md | 16 + .../delinea-secretserver-clientcredentials.md | 28 ++ docsource/delinea-secretserver-password.md | 28 ++ docsource/delinea-secretserver-windows.md | 28 ++ 7 files changed, 506 insertions(+), 69 deletions(-) create mode 100644 docs/delinea-secretserver-clientcredentials.md create mode 100644 docs/delinea-secretserver-password.md create mode 100644 docs/delinea-secretserver-windows.md create mode 100644 docsource/delinea-secretserver-clientcredentials.md create mode 100644 docsource/delinea-secretserver-password.md create mode 100644 docsource/delinea-secretserver-windows.md diff --git a/README.md b/README.md index 3937e0a..39ff8c6 100644 --- a/README.md +++ b/README.md @@ -32,32 +32,15 @@ ## Overview The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports `password`, `client_credentials`, and `windows` (Integrated Windows Authentication) -authentication methods. For more information on these authentication methods, see the +Server secret. Supports either `password` or `client_credential` authentication methods. For more information on +these authentication methods, see the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). -## PAM Types - -This provider ships four PAM types. For new installations, use the type-specific variants — they only expose the -fields relevant to the chosen authentication flow, which simplifies configuration in the Keyfactor Command UI. - -| PAM Type | Auth Method | Required Server Parameters | -| --- | --- | --- | -| `Delinea-SecretServer-Password` | Username + Password | `Host`, `Username`, `Password` | -| `Delinea-SecretServer-ClientCredentials` | OAuth2 Client Credentials | `Host`, `ClientId`, `ClientSecret` | -| `Delinea-SecretServer-Windows` | Integrated Windows Authentication | `Host` | -| `Delinea-SecretServer` | Any (selected via `GrantType`) | `Host`, plus credentials for the chosen grant type | - -> [!NOTE] -> `Delinea-SecretServer` is the original backwards-compatible type. It requires a `GrantType` field and exposes -> all credential fields in the Command UI regardless of which grant type is active. Existing installations using -> this type do not need to change. - ## Authentication Methods For full details on each authentication method, please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). Below are example `manifest.json` snippets for each supported authentication method. -### Password (type-specific variant — recommended for new installations) +### Password ```json { @@ -69,15 +52,16 @@ Below are example `manifest.json` snippets for each supported authentication met } } }, - "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { + "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { "Host": "https://example.secretservercloud.com/SecretServer", "Username": "", - "Password": "" + "Password": "", + "GrantType": "password" } } ``` -### OAuth2 Client Credentials (type-specific variant — recommended for new installations) +### oAuth2 ```json { @@ -89,43 +73,20 @@ Below are example `manifest.json` snippets for each supported authentication met } } }, - "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { + "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { "Host": "https://example.secretservercloud.com/SecretServer", - "ClientId": "", - "ClientSecret": "" + "ClientId": "", + "ClientSecret": "", + "GrantType": "client_credentials" } } ``` -### Windows (type-specific variant — recommended for new installations) +### Windows > [!IMPORTANT] > Integrated Windows Authentication (IWA) does not work on Secret Server Cloud. -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } -} -``` - -Please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) -for more information on configuring IWA. - -### Backwards-compatible type (existing installations — no change required) - -The original `Delinea-SecretServer` type continues to work unchanged. Use the `GrantType` parameter to select -the authentication flow at runtime. - ```json { "extensions": { @@ -138,12 +99,12 @@ the authentication flow at runtime. }, "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { "Host": "https://example.secretservercloud.com/SecretServer", - "Username": "", - "Password": "", - "GrantType": "password" + "GrantType": "windows" } } ``` +Please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) +for more information on configuring IWA. ## Support The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. @@ -167,10 +128,18 @@ Before proceeding with installation, you should consider which pattern is best f To install Delinea Secret Server PAM Provider, it is recommended you install [kfutil](https://github.com/Keyfactor/kfutil). `kfutil` is a command-line tool that simplifies the process of creating PAM Types in Keyfactor Command. +The Delinea Secret Server PAM Provider implements 4 PAM Types. Depending on your use case, you may elect to install one, or all of these PAM Types. An overview for each type is linked below: +* [Delinea-SecretServer](docs/delinea-secretserver.md) +* [Delinea-SecretServer-Password](docs/delinea-secretserver-password.md) +* [Delinea-SecretServer-ClientCredentials](docs/delinea-secretserver-clientcredentials.md) +* [Delinea-SecretServer-Windows](docs/delinea-secretserver-windows.md) + + +
Delinea-SecretServer #### Requirements @@ -184,13 +153,8 @@ To install Delinea Secret Server PAM Provider, it is recommended you install [kf Create the required PAM Types in the connected Command platform. ```shell -# Backwards-compatible type (supports all grant types via GrantType parameter) +# Delinea-SecretServer kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer - -# Type-specific variants (recommended for new installations) -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API @@ -239,7 +203,7 @@ Below is the payload to `POST` to the Keyfactor Command API { "Name": "GrantType", "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password` or `client_credentials`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatability.", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", "DataType": 1, "InstanceLevel": false }, @@ -340,13 +304,8 @@ Below is the payload to `POST` to the Keyfactor Command API ```json { - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "Username": "", - "Password": "", - "ClientId": "", - "ClientSecret": "", - "GrantType": "password|client_credentials|windows" + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" } } @@ -360,6 +319,270 @@ Below is the payload to `POST` to the Keyfactor Command API +
+ + + + + + + +
Delinea-SecretServer-Password + + +#### Requirements + TODO Requirements is a required section + +#### Create PAM type in Keyfactor Command + + +##### Using `kfutil` +Create the required PAM Types in the connected Command platform. + +```shell +# Delinea-SecretServer-Password +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +``` + +##### Using the API +For full API docs please visit our [product documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/WebAPI/KeyfactorAPI/PAMProvidersPOSTTypes.htm?Highlight=pam%20type) + +Below is the payload to `POST` to the Keyfactor Command API +```json +{ + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] +} +``` + +#### Install PAM provider on Keyfactor Command Host (Local) + + +("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### Install PAM provider on a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ + + + + + + +
Delinea-SecretServer-ClientCredentials + + +#### Requirements + TODO Requirements is a required section + +#### Create PAM type in Keyfactor Command + + +##### Using `kfutil` +Create the required PAM Types in the connected Command platform. + +```shell +# Delinea-SecretServer-ClientCredentials +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +``` + +##### Using the API +For full API docs please visit our [product documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/WebAPI/KeyfactorAPI/PAMProvidersPOSTTypes.htm?Highlight=pam%20type) + +Below is the payload to `POST` to the Keyfactor Command API +```json +{ + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] +} +``` + +#### Install PAM provider on Keyfactor Command Host (Local) + + +("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### Install PAM provider on a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ + + + + + + +
Delinea-SecretServer-Windows + + +#### Requirements + TODO Requirements is a required section + +#### Create PAM type in Keyfactor Command + + +##### Using `kfutil` +Create the required PAM Types in the connected Command platform. + +```shell +# Delinea-SecretServer-Windows +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows +``` + +##### Using the API +For full API docs please visit our [product documentation](https://software.keyfactor.com/Core-OnPrem/Current/Content/WebAPI/KeyfactorAPI/PAMProvidersPOSTTypes.htm?Highlight=pam%20type) + +Below is the payload to `POST` to the Keyfactor Command API +```json +{ + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] +} +``` + +#### Install PAM provider on Keyfactor Command Host (Local) + + +("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### Install PAM provider on a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ @@ -370,6 +593,8 @@ Below is the payload to `POST` to the Keyfactor Command API +
Delinea-SecretServer + #### From Keyfactor Command Host (Local) @@ -392,7 +617,7 @@ Below is the payload to `POST` to the Keyfactor Command API | Password | Secret Server Password | The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type. | | ClientId | Secret Server Client ID | The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type. | | ClientSecret | Secret Server Client Secret | The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type. | -| GrantType | Grant Type | The grant type used to authenticate to the Secret Server instance. Valid values are `password` or `client_credentials`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatability. | +| GrantType | Grant Type | The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility. | 4. Click **Save**. The PAM provider is now available for use in Keyfactor Command. @@ -467,12 +692,92 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and +
+ > [!NOTE] > Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). + + +
Delinea-SecretServer-Password + + +#### From Keyfactor Command Host (Local) + + +("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### From a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ + +> [!NOTE] +> Additional information on Delinea-SecretServer-Password can be found in the [supplemental documentation](docs/delinea-secretserver-password.md). + + + + + +
Delinea-SecretServer-ClientCredentials + + +#### From Keyfactor Command Host (Local) + + +("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### From a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ + +> [!NOTE] +> Additional information on Delinea-SecretServer-ClientCredentials can be found in the [supplemental documentation](docs/delinea-secretserver-clientcredentials.md). + + + + + +
Delinea-SecretServer-Windows + + +#### From Keyfactor Command Host (Local) + + +("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + +#### From a Universal Orchestrator Host (Remote) + + +("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) + + + +
+ + +> [!NOTE] +> Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). + + + ## License Apache License 2.0, see [LICENSE](LICENSE) diff --git a/docs/delinea-secretserver-clientcredentials.md b/docs/delinea-secretserver-clientcredentials.md new file mode 100644 index 0000000..86cdaa4 --- /dev/null +++ b/docs/delinea-secretserver-clientcredentials.md @@ -0,0 +1,16 @@ +## Delinea-SecretServer-ClientCredentials + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + + +## Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + + + + diff --git a/docs/delinea-secretserver-password.md b/docs/delinea-secretserver-password.md new file mode 100644 index 0000000..5f7ab2c --- /dev/null +++ b/docs/delinea-secretserver-password.md @@ -0,0 +1,16 @@ +## Delinea-SecretServer-Password + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + + +## Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + + + + diff --git a/docs/delinea-secretserver-windows.md b/docs/delinea-secretserver-windows.md new file mode 100644 index 0000000..a6fa487 --- /dev/null +++ b/docs/delinea-secretserver-windows.md @@ -0,0 +1,16 @@ +## Delinea-SecretServer-Windows + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + + +## Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + + + + diff --git a/docsource/delinea-secretserver-clientcredentials.md b/docsource/delinea-secretserver-clientcredentials.md new file mode 100644 index 0000000..e8330d9 --- /dev/null +++ b/docsource/delinea-secretserver-clientcredentials.md @@ -0,0 +1,28 @@ +## Overview + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + +## Extension Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Install + +TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Install + +TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Usage + +TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Usage + +TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + diff --git a/docsource/delinea-secretserver-password.md b/docsource/delinea-secretserver-password.md new file mode 100644 index 0000000..e8330d9 --- /dev/null +++ b/docsource/delinea-secretserver-password.md @@ -0,0 +1,28 @@ +## Overview + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + +## Extension Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Install + +TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Install + +TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Usage + +TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Usage + +TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + diff --git a/docsource/delinea-secretserver-windows.md b/docsource/delinea-secretserver-windows.md new file mode 100644 index 0000000..e8330d9 --- /dev/null +++ b/docsource/delinea-secretserver-windows.md @@ -0,0 +1,28 @@ +## Overview + +TODO Overview is a required section + +## Requirements + +TODO Requirements is a required section + +## Extension Mechanics + +TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Install + +TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Install + +TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Platform Usage + +TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + +## Orchestrator Usage + +TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info + From d6f03108b55c7b408814ff1360afdcdcfedcadeb Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:41:27 -0700 Subject: [PATCH 27/32] docs: add docsource files for new PAM types and regenerate docs via doctool - Add docsource/overview.md documenting all four PAM types - Add per-type docsource files for Password, ClientCredentials, Windows variants - Update docsource/delinea-secretserver.md for backwards-compat type - Remove deprecated readme-src/ directory - Regenerate README.md and docs/ via doctool (adam_dotNetVpython_Fixes branch) --- README.md | 999 ++++++++++++------ .../delinea-secretserver-clientcredentials.md | 22 +- docs/delinea-secretserver-password.md | 22 +- docs/delinea-secretserver-windows.md | 38 +- docs/delinea-secretserver.md | 76 +- .../delinea-secretserver-clientcredentials.md | 29 +- docsource/delinea-secretserver-password.md | 29 +- docsource/delinea-secretserver-windows.md | 35 +- docsource/delinea-secretserver.md | 64 +- docsource/overview.md | 84 +- readme-src/readme-config.md | 181 ---- readme-src/readme-paramtable.md | 16 - readme-src/readme-pre.md | 33 - 13 files changed, 777 insertions(+), 851 deletions(-) delete mode 100644 readme-src/readme-config.md delete mode 100644 readme-src/readme-paramtable.md delete mode 100644 readme-src/readme-pre.md diff --git a/README.md b/README.md index 39ff8c6..60c65d7 100644 --- a/README.md +++ b/README.md @@ -11,103 +11,37 @@

- - - Support - - · - - Installation - - · - - License - - · - - Related Integrations - + Support · + Installation · + License · + Related Integrations

## Overview The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports either `password` or `client_credential` authentication methods. For more information on -these authentication methods, see the -[Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). +Server secret. Three authentication methods are supported: `password` (username/password), `client_credentials` +(OAuth2 application account), and `windows` (Integrated Windows Authentication). -## Authentication Methods -For full details on each authentication method, please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). -Below are example `manifest.json` snippets for each supported authentication method. +## PAM Types -### Password +This provider ships four PAM types. For new installations, use the type-specific variants — they only expose the +fields relevant to the chosen authentication flow, which simplifies configuration in the Keyfactor Command UI. -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "Username": "", - "Password": "", - "GrantType": "password" - } -} -``` - -### oAuth2 - -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "ClientId": "", - "ClientSecret": "", - "GrantType": "client_credentials" - } -} -``` - -### Windows - -> [!IMPORTANT] -> Integrated Windows Authentication (IWA) does not work on Secret Server Cloud. +| PAM Type | Auth Method | Server Parameters | +| --- | --- | --- | +| `Delinea-SecretServer-Password` | Username + Password | `Host`, `Username`, `Password` | +| `Delinea-SecretServer-ClientCredentials` | OAuth2 Client Credentials | `Host`, `ClientId`, `ClientSecret` | +| `Delinea-SecretServer-Windows` | Integrated Windows Authentication | `Host` | +| `Delinea-SecretServer` | Any (selected via `GrantType`) | `Host`, plus credentials for the chosen grant type | -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "GrantType": "windows" - } -} -``` -Please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) -for more information on configuring IWA. +> [!NOTE] +> `Delinea-SecretServer` is the original backwards-compatible type retained for existing installations. It requires +> a `GrantType` field and exposes all credential fields in the Keyfactor Command UI regardless of which grant type +> is active. Existing installations do not need to change. ## Support -The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -128,33 +62,30 @@ Before proceeding with installation, you should consider which pattern is best f To install Delinea Secret Server PAM Provider, it is recommended you install [kfutil](https://github.com/Keyfactor/kfutil). `kfutil` is a command-line tool that simplifies the process of creating PAM Types in Keyfactor Command. + The Delinea Secret Server PAM Provider implements 4 PAM Types. Depending on your use case, you may elect to install one, or all of these PAM Types. An overview for each type is linked below: * [Delinea-SecretServer](docs/delinea-secretserver.md) * [Delinea-SecretServer-Password](docs/delinea-secretserver-password.md) * [Delinea-SecretServer-ClientCredentials](docs/delinea-secretserver-clientcredentials.md) * [Delinea-SecretServer-Windows](docs/delinea-secretserver-windows.md) - - - - -
Delinea-SecretServer - #### Requirements - - Delinea Secret Server service account or client credential w/ permission to access the secret(s) being used. See the [Delinea - Secret Server documentation]([Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm).) for more information on how to configure service accounts and client credentials. -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer ``` ##### Using the API @@ -163,72 +94,70 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "Secret Server Client ID", - "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "Secret Server Client Secret", - "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "GrantType", - "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "Secret Server Client ID", + "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "Secret Server Client Secret", + "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "GrantType", + "DisplayName": "Grant Type", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) - - 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -246,7 +175,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -260,7 +189,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -277,15 +206,11 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). - - - #### Install PAM provider on a Universal Orchestrator Host (Remote) - 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -302,46 +227,41 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json - { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } + "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { + "Host": "", + "Username": "", + "Password": "", + "ClientId": "", + "ClientSecret": "", + "GrantType": "" + } } - ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver.md#requirements) section. 3. Restart the Universal Orchestrator service. - - - -
- - - - - -
Delinea-SecretServer-Password - #### Requirements - TODO Requirements is a required section -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Password -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Password ``` ##### Using the API @@ -350,90 +270,158 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Password", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) +1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. -("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: +
Keyfactor Command 11+ -#### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Copy the unzipped assemblies to each of the following directories: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\Extensions\delinea-secretserver-pam` -("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
+
Keyfactor Command 10 + 1. Copy the assemblies to each of the following directories: -
+ * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\delinea-secretserver-pam` + 2. Open a text editor on the Keyfactor Command server as an administrator and open the `web.config` file located in the `WebAgentServices` directory. + 3. In the `web.config` file, locate the ` ` section and add the following registration: + ```xml + + ... + + + + + ``` + 4. Repeat steps 2 and 3 for each of the directories listed in step 1. The configuration files are located in the following paths by default: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\CMSTimerService.exe.config` -
Delinea-SecretServer-ClientCredentials +
+ +3. Restart the Keyfactor Command services (`iisreset`). + +#### Install PAM provider on a Universal Orchestrator Host (Remote) +1. Install the Delinea Secret Server PAM Provider assemblies. + + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + + ```shell + # Windows Server + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions" + + # Linux + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "/opt/keyfactor/orchestrator/extensions" + ``` + + * **Manually**: Download the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. Extract the contents of the archive to: + + * **Windows Server**: `C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions\delinea-secretserver-pam` + * **Linux**: `/opt/keyfactor/orchestrator/extensions/delinea-secretserver-pam` + +2. Included in the release is a `manifest.json` file that contains the following object: + ```json + { + "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { + "Host": "", + "Username": "", + "Password": "", + "SkipTlsValidation": "" + } + } + ``` + + Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-password.md#requirements) section. + +3. Restart the Universal Orchestrator service. + +
+ +
Delinea-SecretServer-ClientCredentials #### Requirements - TODO Requirements is a required section -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-ClientCredentials -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials ``` ##### Using the API @@ -442,90 +430,160 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-ClientCredentials", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "OAuth2 Client ID", - "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "OAuth2 Client Secret", - "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) +1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. -("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: +
Keyfactor Command 11+ -#### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Copy the unzipped assemblies to each of the following directories: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\Extensions\delinea-secretserver-pam` -("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
+
Keyfactor Command 10 + 1. Copy the assemblies to each of the following directories: -
+ * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\delinea-secretserver-pam` + + 2. Open a text editor on the Keyfactor Command server as an administrator and open the `web.config` file located in the `WebAgentServices` directory. + + 3. In the `web.config` file, locate the ` ` section and add the following registration: + + ```xml + + ... + + + + + + ``` + 4. Repeat steps 2 and 3 for each of the directories listed in step 1. The configuration files are located in the following paths by default: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\CMSTimerService.exe.config` +
+3. Restart the Keyfactor Command services (`iisreset`). +#### Install PAM provider on a Universal Orchestrator Host (Remote) +1. Install the Delinea Secret Server PAM Provider assemblies. -
Delinea-SecretServer-Windows + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + + ```shell + # Windows Server + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions" + + # Linux + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "/opt/keyfactor/orchestrator/extensions" + ``` + + * **Manually**: Download the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. Extract the contents of the archive to: + + * **Windows Server**: `C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions\delinea-secretserver-pam` + * **Linux**: `/opt/keyfactor/orchestrator/extensions/delinea-secretserver-pam` + +2. Included in the release is a `manifest.json` file that contains the following object: + ```json + { + "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { + "Host": "", + "ClientId": "", + "ClientSecret": "", + "SkipTlsValidation": "" + } + } + ``` + + Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-clientcredentials.md#requirements) section. +3. Restart the Universal Orchestrator service. + +
+ +
Delinea-SecretServer-Windows #### Requirements - TODO Requirements is a required section -#### Create PAM type in Keyfactor Command +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Windows -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API @@ -534,71 +592,130 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Windows", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) +1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. -("TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: +
Keyfactor Command 11+ -#### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Copy the unzipped assemblies to each of the following directories: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\Extensions\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\Extensions\delinea-secretserver-pam` -("TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
+
Keyfactor Command 10 + 1. Copy the assemblies to each of the following directories: -
+ * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\delinea-secretserver-pam` + 2. Open a text editor on the Keyfactor Command server as an administrator and open the `web.config` file located in the `WebAgentServices` directory. + 3. In the `web.config` file, locate the ` ` section and add the following registration: + ```xml + + ... + + + + + ``` -### Usage + 4. Repeat steps 2 and 3 for each of the directories listed in step 1. The configuration files are located in the following paths by default: + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\web.config` + * `C:\Program Files\Keyfactor\Keyfactor Platform\Service\CMSTimerService.exe.config` +
+3. Restart the Keyfactor Command services (`iisreset`). +#### Install PAM provider on a Universal Orchestrator Host (Remote) -
Delinea-SecretServer +1. Install the Delinea Secret Server PAM Provider assemblies. + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: -#### From Keyfactor Command Host (Local) + ```shell + # Windows Server + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions" + + # Linux + kfutil orchestrator extension -e delinea-secretserver-pam@latest --out "/opt/keyfactor/orchestrator/extensions" + ``` + + * **Manually**: Download the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. Extract the contents of the archive to: + * **Windows Server**: `C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions\delinea-secretserver-pam` + * **Linux**: `/opt/keyfactor/orchestrator/extensions/delinea-secretserver-pam` +2. Included in the release is a `manifest.json` file that contains the following object: + ```json + { + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "", + "SkipTlsValidation": "" + } + } + ``` + + Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-windows.md#requirements) section. + +3. Restart the Universal Orchestrator service. + +
+ +### Usage + +
Delinea-SecretServer + +#### From Keyfactor Command Host (Local) ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -634,13 +751,9 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer** p | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | - - - #### From a Universal Orchestrator Host (Remote) -
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -680,8 +793,7 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} - +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -689,94 +801,277 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+> [!NOTE] +> Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). +
+
Delinea-SecretServer-Password +#### From Keyfactor Command Host (Local) -
- +##### Define a PAM provider in Command +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. -> [!NOTE] -> Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). +2. Select the **Add** button to create a new PAM provider. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-Password**. +> [!IMPORTANT] +> If you're running Keyfactor Command 11+, make sure `Remote Provider` is unchecked. +3. Populate the fields with the necessary information collected in the [requirements](docs/delinea-secretserver-password.md#requirements) section: +| Initialization parameter | Display Name | Description | +| --- | --- | --- | +| Host | Secret Server URL | The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer | +| Username | Secret Server Username | The username used to authenticate to the Secret Server instance. | +| Password | Secret Server Password | The password used to authenticate to the Secret Server instance. | +| SkipTlsValidation | Skip TLS Validation | Set to `true` to disable TLS certificate validation. Use only in non-production environments. | -
Delinea-SecretServer-Password +4. Click **Save**. The PAM provider is now available for use in Keyfactor Command. +##### Using the PAM provider -#### From Keyfactor Command Host (Local) +Now, when defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Password** will be available as a PAM provider option. When defining new Certificate Stores, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Password** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: -("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | #### From a Universal Orchestrator Host (Remote) -("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
Keyfactor Command 11+ + +##### Define a remote PAM provider in Command + +In Command 11 and greater, before using the Delinea-SecretServer-Password PAM type, you must define a Remote PAM Provider in the Command portal. + +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. + +2. Select the **Add** button to create a new PAM provider. + +3. Make sure that `Remote Provider` is checked. + +4. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-Password**. + +5. Give the provider a unique name. +6. Click "Save". +##### Using the PAM provider + +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Password** can be used as a PAM provider. When defining a new Certificate Store, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. + +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Password** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: + +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + +
+ +
Keyfactor Command 10 + +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Password** can be used as a PAM provider. + +When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: + +```json +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +``` + +> We recommend creating this JSON object in a text editor, and copying it into the Secret Value field.
> [!NOTE] > Additional information on Delinea-SecretServer-Password can be found in the [supplemental documentation](docs/delinea-secretserver-password.md). +
+
Delinea-SecretServer-ClientCredentials +#### From Keyfactor Command Host (Local) +##### Define a PAM provider in Command +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. +2. Select the **Add** button to create a new PAM provider. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-ClientCredentials**. -
Delinea-SecretServer-ClientCredentials +> [!IMPORTANT] +> If you're running Keyfactor Command 11+, make sure `Remote Provider` is unchecked. +3. Populate the fields with the necessary information collected in the [requirements](docs/delinea-secretserver-clientcredentials.md#requirements) section: -#### From Keyfactor Command Host (Local) +| Initialization parameter | Display Name | Description | +| --- | --- | --- | +| Host | Secret Server URL | The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer | +| ClientId | OAuth2 Client ID | The client ID (application account name) used for OAuth2 client credentials authentication. | +| ClientSecret | OAuth2 Client Secret | The client secret (application account password) used for OAuth2 client credentials authentication. | +| SkipTlsValidation | Skip TLS Validation | Set to `true` to disable TLS certificate validation. Use only in non-production environments. | -("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +4. Click **Save**. The PAM provider is now available for use in Keyfactor Command. + +##### Using the PAM provider + +Now, when defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-ClientCredentials** will be available as a PAM provider option. When defining new Certificate Stores, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. + +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-ClientCredentials** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: + +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | #### From a Universal Orchestrator Host (Remote) -("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
Keyfactor Command 11+ + +##### Define a remote PAM provider in Command + +In Command 11 and greater, before using the Delinea-SecretServer-ClientCredentials PAM type, you must define a Remote PAM Provider in the Command portal. + +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. + +2. Select the **Add** button to create a new PAM provider. + +3. Make sure that `Remote Provider` is checked. + +4. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-ClientCredentials**. + +5. Give the provider a unique name. +6. Click "Save". +##### Using the PAM provider + +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-ClientCredentials** can be used as a PAM provider. When defining a new Certificate Store, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. + +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-ClientCredentials** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: + +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + +
+ +
Keyfactor Command 10 + +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-ClientCredentials** can be used as a PAM provider. + +When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: + +```json +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +``` + +> We recommend creating this JSON object in a text editor, and copying it into the Secret Value field.
> [!NOTE] > Additional information on Delinea-SecretServer-ClientCredentials can be found in the [supplemental documentation](docs/delinea-secretserver-clientcredentials.md). +
+
Delinea-SecretServer-Windows +#### From Keyfactor Command Host (Local) +##### Define a PAM provider in Command +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. +2. Select the **Add** button to create a new PAM provider. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-Windows**. -
Delinea-SecretServer-Windows +> [!IMPORTANT] +> If you're running Keyfactor Command 11+, make sure `Remote Provider` is unchecked. +3. Populate the fields with the necessary information collected in the [requirements](docs/delinea-secretserver-windows.md#requirements) section: -#### From Keyfactor Command Host (Local) +| Initialization parameter | Display Name | Description | +| --- | --- | --- | +| Host | Secret Server URL | The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud. | +| SkipTlsValidation | Skip TLS Validation | Set to `true` to disable TLS certificate validation. Use only in non-production environments. | -("TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +4. Click **Save**. The PAM provider is now available for use in Keyfactor Command. + +##### Using the PAM provider + +Now, when defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Windows** will be available as a PAM provider option. When defining new Certificate Stores, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. + +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Windows** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: + +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | #### From a Universal Orchestrator Host (Remote) -("TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info",) +
Keyfactor Command 11+ + +##### Define a remote PAM provider in Command + +In Command 11 and greater, before using the Delinea-SecretServer-Windows PAM type, you must define a Remote PAM Provider in the Command portal. + +1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. + +2. Select the **Add** button to create a new PAM provider. + +3. Make sure that `Remote Provider` is checked. + +4. Click the dropdown for **Provider Type** and select **Delinea-SecretServer-Windows**. + +5. Give the provider a unique name. + +6. Click "Save". + +##### Using the PAM provider +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Windows** can be used as a PAM provider. When defining a new Certificate Store, the secret parameter form will display tabs for **Load From Keyfactor Secrets** or **Load From PAM Provider**. + +Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Windows** provider from the list of **Providers**, and populate the fields with the necessary information from the table below: + +| Instance parameter | Display Name | Description | +| --- | --- | --- | +| SecretId | Secret ID | The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server. | +| SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. |
+
Keyfactor Command 10 -> [!NOTE] -> Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). +When defining Certificate Stores (**Locations**->**Certificate Stores**), **Delinea-SecretServer-Windows** can be used as a PAM provider. + +When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: + +```json +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +``` + +> We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. + +
+> [!NOTE] +> Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). +
## License @@ -784,4 +1079,4 @@ Apache License 2.0, see [LICENSE](LICENSE) ## Related Integrations -See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). \ No newline at end of file +See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). diff --git a/docs/delinea-secretserver-clientcredentials.md b/docs/delinea-secretserver-clientcredentials.md index 86cdaa4..5b1c23c 100644 --- a/docs/delinea-secretserver-clientcredentials.md +++ b/docs/delinea-secretserver-clientcredentials.md @@ -1,16 +1,22 @@ ## Delinea-SecretServer-ClientCredentials -TODO Overview is a required section +The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client +credentials (application account name and password). This is the recommended type for service-to-service +integrations where an application account is used instead of a user account. ## Requirements -TODO Requirements is a required section - - -## Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. +The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client +credentials (application account name and password). This is the recommended type for service-to-service +integrations where an application account is used instead of a user account. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. diff --git a/docs/delinea-secretserver-password.md b/docs/delinea-secretserver-password.md index 5f7ab2c..c6472ee 100644 --- a/docs/delinea-secretserver-password.md +++ b/docs/delinea-secretserver-password.md @@ -1,16 +1,22 @@ ## Delinea-SecretServer-Password -TODO Overview is a required section +The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password +(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username +and password is used. ## Requirements -TODO Requirements is a required section - - -## Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. +The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password +(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username +and password is used. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. diff --git a/docs/delinea-secretserver-windows.md b/docs/delinea-secretserver-windows.md index a6fa487..d21f610 100644 --- a/docs/delinea-secretserver-windows.md +++ b/docs/delinea-secretserver-windows.md @@ -1,16 +1,34 @@ ## Delinea-SecretServer-Windows -TODO Overview is a required section - -## Requirements - -TODO Requirements is a required section - - -## Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info +The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows +Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity +of the process running Keyfactor Command or the Universal Orchestrator. +> [!IMPORTANT] +> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible +> with on-premises Secret Server installations. +## Requirements +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. + +The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows +Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity +of the process running Keyfactor Command or the Universal Orchestrator. + +> [!IMPORTANT] +> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible +> with on-premises Secret Server installations. + +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. diff --git a/docs/delinea-secretserver.md b/docs/delinea-secretserver.md index 408e7d4..e3bc369 100644 --- a/docs/delinea-secretserver.md +++ b/docs/delinea-secretserver.md @@ -1,64 +1,30 @@ ## Delinea-SecretServer -The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports either `password` or `client_credential` authentication methods. For more information on -these authentication methods, see the -[Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). +`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods +(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. +The Keyfactor Command UI will display every credential field regardless of which grant type is active. -## Requirements - -- Delinea Secret Server service account or client credential w/ permission to access the secret(s) being used. See the [Delinea - Secret Server documentation]([Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm).) for more information on how to configure service accounts and client credentials. - - -## Mechanics - -When configuring the Delinea Secret Server for use as a PAM Provider with Keyfactor, you will need to ensure that your -instance is configured for API access. This can be done by logging into the Delinea Secret Server as an administrator. -For more details visit the vendor docs [here](https://docs.delinea.com/online-help/secret-server/api-scripting/sdk-devops/using-sdk/index.htm#SetupProcedure). +For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, +`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant +to the chosen authentication method. -Once API access is configured a user account with a username and password is required. That account *MUST* be granted access -to view secret's you'll be using. - -After adding and sharing a secret on SecretServer, you can use the secret's ID (the "Secret ID") and the desired value's -field name (the "Secret Field Name") to retrieve credentials from the Delinea Secret Server as a PAM Provider. - -### Running the PAM provider on Keyfactor Universal Orchestrator (UO) -When installing on the Universal Orchestrator (UO), is installed on and run from the UO host. Below is a sequence diagram -showing the flow of the PAM provider when it is run from the UO. - -```mermaid -sequenceDiagram - KeyfactorCommand->>KeyfactorCommand: New job created. - UO->>KeyfactorCommand: Hello do you have any jobs for me? - KeyfactorCommand->>UO: Yes here's a job. - UO->>SecretServer: Hello here are my client credentials. - SecretServer->>UO: Here's your API token. - UO->>SecretServer: I need secret ID 100, here's my API token. - SecretServer->>SecretServer: Check secret ACL. - SecretServer->>UO: This is allowed, here's the secret. - UO->>UO: Running job. - UO->>KeyfactorCommand: Job completed. -``` - -### Running the PAM provider on the Keyfactor Command Host -When installing the PAM provider on the Keyfactor Command Host, is installed on and run from the Keyfactor Command host. -Below is a sequence diagram showing the flow of the PAM provider when it is run from the Keyfactor Command Host. +## Requirements -```mermaid -sequenceDiagram - KeyfactorCommand->>KeyfactorCommand: Creating a new job. - KeyfactorCommand->>SecretServer: Hello here are my client credentials. - SecretServer->>KeyfactorCommand: Here's your API token. - KeyfactorCommand->>SecretServer: I need secret ID 100, here's my API token. - SecretServer->>SecretServer: Check secret ACL. - SecretServer->>KeyfactorCommand: This is allowed, here's the secret. - UO->>KeyfactorCommand: Hello do you have any jobs for me? - KeyfactorCommand->>UO: Yes here's a job with these credentials I pulled from SecretServer. - UO->>UO: Running job. - UO->>KeyfactorCommand: Job completed. -``` +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. +`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods +(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. +The Keyfactor Command UI will display every credential field regardless of which grant type is active. +For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, +`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant +to the chosen authentication method. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. diff --git a/docsource/delinea-secretserver-clientcredentials.md b/docsource/delinea-secretserver-clientcredentials.md index e8330d9..dd37d3a 100644 --- a/docsource/delinea-secretserver-clientcredentials.md +++ b/docsource/delinea-secretserver-clientcredentials.md @@ -1,28 +1,13 @@ ## Overview -TODO Overview is a required section +The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client +credentials (application account name and password). This is the recommended type for service-to-service +integrations where an application account is used instead of a user account. ## Requirements -TODO Requirements is a required section - -## Extension Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Install - -TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Orchestrator Install - -TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Usage - -TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Orchestrator Usage - -TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. diff --git a/docsource/delinea-secretserver-password.md b/docsource/delinea-secretserver-password.md index e8330d9..7b15ba6 100644 --- a/docsource/delinea-secretserver-password.md +++ b/docsource/delinea-secretserver-password.md @@ -1,28 +1,13 @@ ## Overview -TODO Overview is a required section +The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password +(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username +and password is used. ## Requirements -TODO Requirements is a required section - -## Extension Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Install - -TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Orchestrator Install - -TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Usage - -TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Orchestrator Usage - -TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. diff --git a/docsource/delinea-secretserver-windows.md b/docsource/delinea-secretserver-windows.md index e8330d9..4d70db4 100644 --- a/docsource/delinea-secretserver-windows.md +++ b/docsource/delinea-secretserver-windows.md @@ -1,28 +1,19 @@ ## Overview -TODO Overview is a required section +The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows +Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity +of the process running Keyfactor Command or the Universal Orchestrator. -## Requirements - -TODO Requirements is a required section - -## Extension Mechanics - -TODO Extension Mechanics is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Install - -TODO Platform Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info +> [!IMPORTANT] +> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible +> with on-premises Secret Server installations. -## Orchestrator Install - -TODO Orchestrator Install is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Platform Usage - -TODO Platform Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info - -## Orchestrator Usage +## Requirements -TODO Orchestrator Usage is an optional section. If this section doesn't seem necessary on initial glance, please delete it. Refer to the docs on [Confluence](https://keyfactor.atlassian.net/wiki/x/SAAyHg) for more info +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. diff --git a/docsource/delinea-secretserver.md b/docsource/delinea-secretserver.md index 3e33499..db06567 100644 --- a/docsource/delinea-secretserver.md +++ b/docsource/delinea-secretserver.md @@ -1,59 +1,17 @@ ## Overview -The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports either `password` or `client_credential` authentication methods. For more information on -these authentication methods, see the -[Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). +`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods +(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. +The Keyfactor Command UI will display every credential field regardless of which grant type is active. -## Requirements - -- Delinea Secret Server service account or client credential w/ permission to access the secret(s) being used. See the [Delinea - Secret Server documentation]([Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm).) for more information on how to configure service accounts and client credentials. - -## Extension Mechanics - -When configuring the Delinea Secret Server for use as a PAM Provider with Keyfactor, you will need to ensure that your -instance is configured for API access. This can be done by logging into the Delinea Secret Server as an administrator. -For more details visit the vendor docs [here](https://docs.delinea.com/online-help/secret-server/api-scripting/sdk-devops/using-sdk/index.htm#SetupProcedure). +For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, +`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant +to the chosen authentication method. -Once API access is configured a user account with a username and password is required. That account *MUST* be granted access -to view secret's you'll be using. - -After adding and sharing a secret on SecretServer, you can use the secret's ID (the "Secret ID") and the desired value's -field name (the "Secret Field Name") to retrieve credentials from the Delinea Secret Server as a PAM Provider. - -### Running the PAM provider on Keyfactor Universal Orchestrator (UO) -When installing on the Universal Orchestrator (UO), is installed on and run from the UO host. Below is a sequence diagram -showing the flow of the PAM provider when it is run from the UO. - -```mermaid -sequenceDiagram - KeyfactorCommand->>KeyfactorCommand: New job created. - UO->>KeyfactorCommand: Hello do you have any jobs for me? - KeyfactorCommand->>UO: Yes here's a job. - UO->>SecretServer: Hello here are my client credentials. - SecretServer->>UO: Here's your API token. - UO->>SecretServer: I need secret ID 100, here's my API token. - SecretServer->>SecretServer: Check secret ACL. - SecretServer->>UO: This is allowed, here's the secret. - UO->>UO: Running job. - UO->>KeyfactorCommand: Job completed. -``` +## Requirements -### Running the PAM provider on the Keyfactor Command Host -When installing the PAM provider on the Keyfactor Command Host, is installed on and run from the Keyfactor Command host. -Below is a sequence diagram showing the flow of the PAM provider when it is run from the Keyfactor Command Host. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. -```mermaid -sequenceDiagram - KeyfactorCommand->>KeyfactorCommand: Creating a new job. - KeyfactorCommand->>SecretServer: Hello here are my client credentials. - SecretServer->>KeyfactorCommand: Here's your API token. - KeyfactorCommand->>SecretServer: I need secret ID 100, here's my API token. - SecretServer->>SecretServer: Check secret ACL. - SecretServer->>KeyfactorCommand: This is allowed, here's the secret. - UO->>KeyfactorCommand: Hello do you have any jobs for me? - KeyfactorCommand->>UO: Yes here's a job with these credentials I pulled from SecretServer. - UO->>UO: Running job. - UO->>KeyfactorCommand: Job completed. -``` diff --git a/docsource/overview.md b/docsource/overview.md index a14f1fa..74ad9ff 100644 --- a/docsource/overview.md +++ b/docsource/overview.md @@ -1,76 +1,22 @@ ## Overview The Delinea Secret Server PAM Provider allows for the retrieval of stored account credentials from a Delinea Secret -Server secret. Supports either `password` or `client_credential` authentication methods. For more information on -these authentication methods, see the -[Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). +Server secret. Three authentication methods are supported: `password` (username/password), `client_credentials` +(OAuth2 application account), and `windows` (Integrated Windows Authentication). -## Authentication Methods -For full details on each authentication method, please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm). -Below are example `manifest.json` snippets for each supported authentication method. +## PAM Types -### Password +This provider ships four PAM types. For new installations, use the type-specific variants — they only expose the +fields relevant to the chosen authentication flow, which simplifies configuration in the Keyfactor Command UI. -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "Username": "", - "Password": "", - "GrantType": "password" - } -} -``` +| PAM Type | Auth Method | Server Parameters | +| --- | --- | --- | +| `Delinea-SecretServer-Password` | Username + Password | `Host`, `Username`, `Password` | +| `Delinea-SecretServer-ClientCredentials` | OAuth2 Client Credentials | `Host`, `ClientId`, `ClientSecret` | +| `Delinea-SecretServer-Windows` | Integrated Windows Authentication | `Host` | +| `Delinea-SecretServer` | Any (selected via `GrantType`) | `Host`, plus credentials for the chosen grant type | -### oAuth2 - -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "ClientId": "", - "ClientSecret": "", - "GrantType": "client_credentials" - } -} -``` - -### Windows - -> [!IMPORTANT] -> Integrated Windows Authentication (IWA) does not work on Secret Server Cloud. - -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "GrantType": "windows" - } -} -``` -Please refer to the [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) -for more information on configuring IWA. \ No newline at end of file +> [!NOTE] +> `Delinea-SecretServer` is the original backwards-compatible type retained for existing installations. It requires +> a `GrantType` field and exposes all credential fields in the Keyfactor Command UI regardless of which grant type +> is active. Existing installations do not need to change. \ No newline at end of file diff --git a/readme-src/readme-config.md b/readme-src/readme-config.md deleted file mode 100644 index 980099e..0000000 --- a/readme-src/readme-config.md +++ /dev/null @@ -1,181 +0,0 @@ -## Configuring for PAM Usage -### Delinea Secret Server -When configuring the Delinea Secret Server for use as a PAM Provider with Keyfactor, you will need to ensure that your -instance is configured for API access. This can be done by logging into the Delinea Secret Server as an administrator. -For more details visit the vendor docs [here](https://docs.delinea.com/secrets/current/api-scripting/sdk-cli/index.md#setup_procedure). - -Once API access is configured a user account with a username and password is required. That account *MUST* be granted access -to view secret's you'll be using. - -After adding and sharing a secret on SecretServer, you can use the secret's ID (the "Secret ID") and the desired value's -field name (the "Secret Field Name") to retrieve credentials from the Delinea Secret Server as a PAM Provider. - -### Install PAM provider on Keyfactor Universal Orchestrator (UO) -When installing on the Universal Orchestrator, the PAM Provider is installed as a DLL and configured in the UO. This allows -the UO to use the PAM provider from the UO host/network and retrieve secrets from Delinea Secret Server and pass them -into Orchestrator extensions. - -```mermaid -sequenceDiagram - CreateJob->>Command: New job created. - UO->>Command: Hello do you have any jobs for me? - Command->>UO: Yes here's a job. - UO->>Delinea: Hello here are my client credentials. - Delinea->>UO: Here's your API token. - UO->>Delinea: I need secret ID 100, here's my API token. - Delinea->>Delinea: Check secret ACL. - Delinea->>UO: This is allowed, here's the secret. -``` - -#### Installation -For full UO installation instructions please review the latest product documentation: -- [Windows](https://software.keyfactor.com/Content/InstallingAgents/NetCoreOrchestrator/InstalltheOrchestratorWindows.htm?Highlight=universal%20orchestrator) -- [Linux](https://software.keyfactor.com/Content/InstallingAgents/NetCoreOrchestrator/InstalltheOrchestratorLinux.htm) -- [Container](https://software.keyfactor.com/Content/InstallingAgents/NetCoreOrchestrator/InstalltheOrchestratorLinuxContainer.htm) - -#### Step 1: Download the release and install the extension -For latest product documentation on installing orchestrator extensions please review the -[Keyfactor Universal Orchestrator Docs](https://software.keyfactor.com/Content/InstallingAgents/NetCoreOrchestrator/CustomExtensions.htm). - -On the Universal Orchestrator host, locate the extensions directory within the install directory. By default, this is: -- Windows: `C:\Program Files\Keyfactor\Keyfactor Orchestrator\extensions` -- Linux: `/opt/keyfactor/orchestrator/extensions` - -Then create a new folder named `Delinea-SecretServer` and copy the release contents into this folder. The directory structure -should look like the following: -![](../images/uo_dir.png) -![](images/uo_dir.png) - -#### Step 2: Create or update the manifest.json file in the Delinea-SecretServer folder -This file is used by the UO to communicate with the PAM Provider's API. The `manifest.json` file should be located in the -`Delinea-SecretServer` folder. The `manifest.json` file should look like the following: -```json -{ - "extensions": { - "Keyfactor.Platform.Extensions.IPAMProvider": { - "PAMProviders.Delinea.PAMProvider": { - "assemblyPath": "delinea-secretserver-pam.dll", - "TypeFullName": "Keyfactor.Extensions.Pam.Delinea.SecretServerPam" - } - } - }, - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "https://example.secretservercloud.com/SecretServer", - "Username": "my_secretserver_service_account", - "Password": "xxxxxx" - } -} -``` - -#### Step 3: Restart the UO -Restart the UO service to load the new extension. - -#### Step 4: Usage -After the extension is installed, you can use the PAM Provider when configuring certificate stores. In order to use the PAM -provider from the UO you'll need to use a JSON blob in the Server Password field. The JSON blob should look like the following: -```json -{ - "SecretId": 123, - "SecretFieldName": "password" -} -``` -The `SecretId` is the ID of the secret you want to retrieve from the Delinea Secret Server. The `SecretFieldName` is the -name of the field in the secret you want to retrieve and use as the password value. - -![](../images/usage.png) -![](images/usage.png) - -#### Troubleshooting -If you are having trouble with the PAM Provider, you can review the UO logs for errors by searching for `Delinea`. Please -review the latest product documentation for [configuring logging](https://software.keyfactor.com/Content/InstallingAgents/NetCoreOrchestrator/ConfigureLogging.htm) - - -### Install PAM provider on Keyfactor Command Host -When installing on Keyfactor Command, the PAM Provider is installed as a DLL and configured in the Keyfactor Platform. -This allows the Keyfactor Command Platform to use the PAM provider and retrieve secrets from the Delinea Secret Server -and pass them down to a Universal Orchestrator. - -```mermaid -sequenceDiagram - CreateJob->>Command: New job uses Delinea PAM Provider I need to retrieve the secrets. - Command->>Delinea: Hello here are my client credentials. - Delinea->>Command: Here's your API token. - Command->>Delinea: I need secret ID 100, here's my API token. - Delinea->>Command: This is allowed, here's the secret. - Command->>Command: Adding retrieved secrets to the job. - UO->>Command: Hello do you have any jobs for me? - Command->>UO: Yes here's a job. - UO->>Command: Thanks I'll let you know how it goes. -``` - -#### Installation -For latest product documentation on installing a PAM provider on a Keyfactor Command Server please review the [Keyfactor Command Docs](https://software.keyfactor.com/Content/ReferenceGuide/Preparing%20Third%20Party%20PAM%20Providers%20to%20Work%20with.htm?Highlight=pam). -Specifically the section labeled `Installation on the Keyfactor Command Server` - -#### Step 1: Create the PAM provider type in Keyfactor Command -In order to allow Keyfactor Command to use the new Delinea Secret Server PAM provider, the definition needs to be added -to the application database. This is done by running the provided `kfutil` tool to install the PAM definition, which only -needs to be done one time. It uses API credentials to access the Keyfactor instance and create the PAM definition. - -The `kfutil` tool, after being [configured for API access](https://github.com/Keyfactor/kfutil#quickstart), can be run -in the following manner to install the PAM definition from the Keyfactor repository: - -``` -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer -``` - -**Alternatively** you can also use the Keyfactor Command API directly, please review the product documentation above. - -#### Step 2: Download the release and install the extension -After the installation is run, the DLLs need to be installed to the correct location for the PAM Provider to function. -From the release, the `delinea-secretserver-pam.dll` should be copied to the following folder locations in the Keyfactor -Command installation. Once the DLL has been copied to these folders, edit the corresponding config file. You will need to add a -new Unity entry as follows under ``, next to other `` tags. - -Default Keyfactor Command Install Path: -- Windows: `C:\Program Files\Keyfactor\` - -| Install Location | DLL Binary Folder | Config File | -|------------------|-----------------------|-------------------------------------| -| WebAgentServices | WebAgentServices\bin\ | WebAgentServices\web.config | -| Service | Service\ | Service\CMSTimerService.exe.config | -| KeyfactorAPI | KeyfactorAPI\bin\ | KeyfactorAPI\web.config | -| WebConsole | WebConsole\bin\ | WebConsole\web.config | - -##### Example DLL Install -![](../images/dll_install.png) -![](images/dll_install.png) - -##### Example Unity Entry -```xml - -``` -![](../images/unity_changes.png)] -![](images/unity_changes.png)] - -#### Step 3: Restart the Keyfactor Command Service -The Keyfactor Command service and IIS Server should be restarted after making these changes. - -#### Step 4: Create an instance of the PAM Provider in the Keyfactor Command Platform -For full details and the latest product documentation on creating a PAM Provider instance please review the -[PAM Provider Configuration in Keyfactor Command](https://software.keyfactor.com/Content/ReferenceGuide/PAM%20Configuration%20in%20Keyfactor%20Command.htm?Highlight=delinea) docs. - -In order to use the PAM Provider, the provider's configuration must be set in the Keyfactor Platform. In the settings -menu (upper right cog) you can select the ___Privileged Access Management___ option to configure your provider instance. - -![](../images/setting.png) -![](images/setting.png) - -#### Step 5: Usage -After an instance of the PAM provider is created, you can now use your PAM Provider when configuring certificate stores. -Any field that is treated as a Keyfactor Command secret, such as `Server Password`s and certificate `Store Password`s can -be retrieved from your PAM Provider instead of being entered in directly as a secret. - -![](../images/password.png) -![](images/password.png) - -#### Troubleshooting -If you are having trouble with the PAM Provider, you can review the Keyfactor Command logs for errors by searching for `Delinea`. -Please review the latest product documentation for [configuring logging](https://software.keyfactor.com/Content/ReferenceGuide/Log%20Edit.htm) -on the Keyfactor Command Server. -``` \ No newline at end of file diff --git a/readme-src/readme-paramtable.md b/readme-src/readme-paramtable.md deleted file mode 100644 index f512782..0000000 --- a/readme-src/readme-paramtable.md +++ /dev/null @@ -1,16 +0,0 @@ -### Initialization Parameters for each defined PAM Provider instance -| Initialization parameter | Display Name | Description | -|:------------------------:|:-----------------------:|---------------------------------------------------------------------------| -| Host | Secret Server URL | The IP address or URL of the Vault instance, including any port number | -| Username | Secret Server Username | The username the PAM provider is going to use to connect to SecretServer. | -| Password | Secret Server Password | The username the PAM provider is going to use to connect to SecretServer. | - - - -### Instance Parameters for each retrieved secret field -| Instance parameter | Display Name | Description | -|:------------------:|:------------------------:|------------------------------------------------------------------------| -| SecretId | Secret Server Secret ID | The integer ID of the secret to use. | -| SecretFieldName | Secret Field Name | The name of the field to use when looking up a secret on SecretServer. | - -![](../images/config.png) \ No newline at end of file diff --git a/readme-src/readme-pre.md b/readme-src/readme-pre.md deleted file mode 100644 index 0bf4393..0000000 --- a/readme-src/readme-pre.md +++ /dev/null @@ -1,33 +0,0 @@ -- [Delinea Secret Server PAM Provider](#delinea-secret-server-pam-provider) - - [Integration status: Production - Ready for use in production environments.](#integration-status--production---ready-for-use-in-production-environments) - * [About the Keyfactor Command PAM Provider](#about-the-keyfactor-command-pam-provider) - * [Support for Delinea Secret Server PAM Provider](#support-for-delinea-secret-server-pam-provider) - * [Keyfactor Command Versions Supported](#keyfactor-command-versions-supported) - + [Initial Configuration of PAM Provider](#initial-configuration-of-pam-provider) - + [Configuring Parameters](#configuring-parameters) - + [Initialization Parameters for each defined PAM Provider instance](#initialization-parameters-for-each-defined-pam-provider-instance) - + [Instance Parameters for each retrieved secret field](#instance-parameters-for-each-retrieved-secret-field) - * [Configuring for PAM Usage](#configuring-for-pam-usage) - + [Delinea Secret Server](#delinea-secret-server) - + [On Keyfactor Universal Orchestrator](#on-keyfactor-universal-orchestrator) - - [Installation](#installation) - - [Usage](#usage) - + [In Keyfactor - PAM Provider](#in-keyfactor---pam-provider) - - [Installation](#installation-1) - - [Usage](#usage-1) - - - -## Keyfactor Version Supported - -The minimum version of the Keyfactor Universal Orchestrator Framework needed to run this version of the extension is 10.1 - -| Keyfactor Version | Universal Orchestrator Framework Version | Supported | -|-------------------|------------------------------------------|--------------| -| 10.4.5 | 10.1, 10.2, 10.4 | ✓ | -| 10.4.0 | 10.1, 10.2, 10.4 | ✓ | -| 10.2.1 | 10.1, 10.2, 10.4 | ✓ | -| 10.1.1 | 10.1, 10.2, | ✓ | -| 10.0.0 | 10.1, 10.2 | ✓ | -| 9.10.1 | Not supported on KF 9.X.X | x | -| 9.5.0 | Not supported on KF 9.X.X | x | \ No newline at end of file From 5518604b121dc6a08b6c63739577b7ef9bdb5516 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Thu, 23 Apr 2026 20:43:03 +0000 Subject: [PATCH 28/32] Update generated docs --- README.md | 662 +++++++++++------- .../delinea-secretserver-clientcredentials.md | 7 - docs/delinea-secretserver-password.md | 7 - docs/delinea-secretserver-windows.md | 13 - docs/delinea-secretserver.md | 11 - 5 files changed, 405 insertions(+), 295 deletions(-) diff --git a/README.md b/README.md index 60c65d7..3b28efe 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,22 @@

- Support · - Installation · - License · - Related Integrations + + + Support + + · + + Installation + + · + + License + + · + + Related Integrations +

## Overview @@ -41,7 +53,7 @@ fields relevant to the chosen authentication flow, which simplifies configuratio > is active. Existing installations do not need to change. ## Support -The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -62,30 +74,35 @@ Before proceeding with installation, you should consider which pattern is best f To install Delinea Secret Server PAM Provider, it is recommended you install [kfutil](https://github.com/Keyfactor/kfutil). `kfutil` is a command-line tool that simplifies the process of creating PAM Types in Keyfactor Command. - The Delinea Secret Server PAM Provider implements 4 PAM Types. Depending on your use case, you may elect to install one, or all of these PAM Types. An overview for each type is linked below: * [Delinea-SecretServer](docs/delinea-secretserver.md) * [Delinea-SecretServer-Password](docs/delinea-secretserver-password.md) * [Delinea-SecretServer-ClientCredentials](docs/delinea-secretserver-clientcredentials.md) * [Delinea-SecretServer-Windows](docs/delinea-secretserver-windows.md) + + + + +
Delinea-SecretServer -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account or application account with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts and application accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer ``` ##### Using the API @@ -94,70 +111,72 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "Secret Server Client ID", - "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "Secret Server Client Secret", - "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "GrantType", - "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "Secret Server Client ID", + "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "Secret Server Client Secret", + "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "GrantType", + "DisplayName": "Grant Type", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -175,7 +194,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -189,7 +208,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -206,11 +225,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -227,41 +250,49 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "", - "Username": "", - "Password": "", - "ClientId": "", - "ClientSecret": "", - "GrantType": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-Password -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account with a username and password that has permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Password -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password ``` ##### Using the API @@ -270,56 +301,58 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Password", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -337,7 +370,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -351,7 +384,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -368,11 +401,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -389,39 +426,49 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { - "Host": "", - "Username": "", - "Password": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-password.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-ClientCredentials -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring application accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-ClientCredentials -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials ``` ##### Using the API @@ -430,56 +477,58 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-ClientCredentials", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "OAuth2 Client ID", - "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "OAuth2 Client Secret", - "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -497,7 +546,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -511,7 +560,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -528,11 +577,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -549,41 +602,51 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { - "Host": "", - "ClientId": "", - "ClientSecret": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-clientcredentials.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-Windows -#### Requirements -- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. -- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view - the secrets being retrieved. See the - [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) - for information on configuring IWA access. -- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. +#### Requirements + - On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. + - The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. + - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Windows -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API @@ -592,42 +655,44 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Windows", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -645,7 +710,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -659,7 +724,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -676,11 +741,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -697,26 +766,42 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-windows.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + ### Usage + + + +
Delinea-SecretServer + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -751,9 +836,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer** p | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -793,7 +882,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -801,14 +891,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). -
+ + + +
Delinea-SecretServer-Password + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -841,9 +943,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Pas | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -883,7 +989,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -891,14 +998,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-Password can be found in the [supplemental documentation](docs/delinea-secretserver-password.md). -
+ + + +
Delinea-SecretServer-ClientCredentials + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -931,9 +1050,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Cli | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -973,7 +1096,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -981,14 +1105,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-ClientCredentials can be found in the [supplemental documentation](docs/delinea-secretserver-clientcredentials.md). -
+ + + +
Delinea-SecretServer-Windows + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -1019,9 +1155,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Win | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -1061,7 +1201,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -1069,9 +1210,16 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). -
+ + ## License @@ -1079,4 +1227,4 @@ Apache License 2.0, see [LICENSE](LICENSE) ## Related Integrations -See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). +See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). \ No newline at end of file diff --git a/docs/delinea-secretserver-clientcredentials.md b/docs/delinea-secretserver-clientcredentials.md index 5b1c23c..5f89616 100644 --- a/docs/delinea-secretserver-clientcredentials.md +++ b/docs/delinea-secretserver-clientcredentials.md @@ -11,12 +11,5 @@ integrations where an application account is used instead of a user account. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring application accounts. -The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client -credentials (application account name and password). This is the recommended type for service-to-service -integrations where an application account is used instead of a user account. -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring application accounts. diff --git a/docs/delinea-secretserver-password.md b/docs/delinea-secretserver-password.md index c6472ee..534d90a 100644 --- a/docs/delinea-secretserver-password.md +++ b/docs/delinea-secretserver-password.md @@ -11,12 +11,5 @@ and password is used. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts. -The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password -(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username -and password is used. -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account with a username and password that has permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts. diff --git a/docs/delinea-secretserver-windows.md b/docs/delinea-secretserver-windows.md index d21f610..5f8de9c 100644 --- a/docs/delinea-secretserver-windows.md +++ b/docs/delinea-secretserver-windows.md @@ -17,18 +17,5 @@ of the process running Keyfactor Command or the Universal Orchestrator. for information on configuring IWA access. - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. -The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows -Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity -of the process running Keyfactor Command or the Universal Orchestrator. - -> [!IMPORTANT] -> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible -> with on-premises Secret Server installations. -- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. -- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view - the secrets being retrieved. See the - [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) - for information on configuring IWA access. -- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. diff --git a/docs/delinea-secretserver.md b/docs/delinea-secretserver.md index e3bc369..c017f7f 100644 --- a/docs/delinea-secretserver.md +++ b/docs/delinea-secretserver.md @@ -15,16 +15,5 @@ to the chosen authentication method. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts and application accounts. -`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods -(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. -The Keyfactor Command UI will display every credential field regardless of which grant type is active. -For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, -`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant -to the chosen authentication method. - -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account or application account with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts and application accounts. From fb95b3ea782506622aaab59923da926879c019ea Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:44:35 -0700 Subject: [PATCH 29/32] feat: support KEYFACTOR_PAM_SKIP_TLS_VALIDATION environment variable Allows TLS certificate validation to be disabled via environment variable in addition to the existing SkipTlsValidation configuration parameter. Either setting is sufficient to disable validation; the env var does not need to be set if the config parameter is already true. --- README.md | 12 ++++++++++++ delinea-secretserver-pam/SecretServerPam.cs | 5 ++++- docsource/overview.md | 14 +++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b28efe..ba32eea 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,18 @@ fields relevant to the chosen authentication flow, which simplifies configuratio > a `GrantType` field and exposes all credential fields in the Keyfactor Command UI regardless of which grant type > is active. Existing installations do not need to change. +## TLS Validation + +All PAM types support skipping TLS certificate validation for non-production environments via either: + +- The `SkipTlsValidation` configuration parameter (set to `true` in the PAM provider instance) +- The `KEYFACTOR_PAM_SKIP_TLS_VALIDATION` environment variable (set to `true` or `1` on the host) + +The environment variable takes precedence and overrides the configuration parameter. + +> [!WARNING] +> Disabling TLS validation should only be used in non-production environments. + ## Support The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. diff --git a/delinea-secretserver-pam/SecretServerPam.cs b/delinea-secretserver-pam/SecretServerPam.cs index 0480654..5039892 100644 --- a/delinea-secretserver-pam/SecretServerPam.cs +++ b/delinea-secretserver-pam/SecretServerPam.cs @@ -574,7 +574,10 @@ private DelineaConfiguration BuildDelineaConfiguration( Logger.LogDebug("Secret ID: {SecretId}", secretId); connectionConfiguration.TryGetValue(DelineaConfiguration.SKIP_TLS_VALIDATION, out var skipTlsRaw); - var skipTls = string.Equals(skipTlsRaw, "true", StringComparison.OrdinalIgnoreCase); + var skipTlsEnv = Environment.GetEnvironmentVariable("KEYFACTOR_PAM_SKIP_TLS_VALIDATION"); + var skipTls = string.Equals(skipTlsRaw, "true", StringComparison.OrdinalIgnoreCase) + || string.Equals(skipTlsEnv, "true", StringComparison.OrdinalIgnoreCase) + || string.Equals(skipTlsEnv, "1", StringComparison.OrdinalIgnoreCase); if (skipTls) Logger.LogWarning( "TLS certificate validation is disabled — use only in non-production environments"); diff --git a/docsource/overview.md b/docsource/overview.md index 74ad9ff..08e2731 100644 --- a/docsource/overview.md +++ b/docsource/overview.md @@ -19,4 +19,16 @@ fields relevant to the chosen authentication flow, which simplifies configuratio > [!NOTE] > `Delinea-SecretServer` is the original backwards-compatible type retained for existing installations. It requires > a `GrantType` field and exposes all credential fields in the Keyfactor Command UI regardless of which grant type -> is active. Existing installations do not need to change. \ No newline at end of file +> is active. Existing installations do not need to change. + +## TLS Validation + +All PAM types support skipping TLS certificate validation for non-production environments via either: + +- The `SkipTlsValidation` configuration parameter (set to `true` in the PAM provider instance) +- The `KEYFACTOR_PAM_SKIP_TLS_VALIDATION` environment variable (set to `true` or `1` on the host) + +The environment variable takes precedence and overrides the configuration parameter. + +> [!WARNING] +> Disabling TLS validation should only be used in non-production environments. \ No newline at end of file From e4d45cf96d1bbad239568c1ca970b8e4c598df90 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:53:35 -0700 Subject: [PATCH 30/32] test: add tests for SkipTlsValidation config param and KEYFACTOR_PAM_SKIP_TLS_VALIDATION env var - SkipTlsValidation config param: verified succeeds when set to true - KEYFACTOR_PAM_SKIP_TLS_VALIDATION env var: verified true and 1 both enable skip - Env var set to false does not interfere when config param is also false - client_credentials token body: asserts grant_type=password (Delinea API constraint) - Integration-tested both TLS skip paths against live Secret Server instance --- README.md | 662 +++++++----------- .../SecretServerPamTests.cs | 125 ++++ .../delinea-secretserver-clientcredentials.md | 7 + docs/delinea-secretserver-password.md | 7 + docs/delinea-secretserver-windows.md | 13 + docs/delinea-secretserver.md | 11 + 6 files changed, 420 insertions(+), 405 deletions(-) diff --git a/README.md b/README.md index ba32eea..de79f1c 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,10 @@

- - - Support - - · - - Installation - - · - - License - - · - - Related Integrations - + Support · + Installation · + License · + Related Integrations

## Overview @@ -65,7 +53,7 @@ The environment variable takes precedence and overrides the configuration parame > Disabling TLS validation should only be used in non-production environments. ## Support -The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -86,35 +74,30 @@ Before proceeding with installation, you should consider which pattern is best f To install Delinea Secret Server PAM Provider, it is recommended you install [kfutil](https://github.com/Keyfactor/kfutil). `kfutil` is a command-line tool that simplifies the process of creating PAM Types in Keyfactor Command. + The Delinea Secret Server PAM Provider implements 4 PAM Types. Depending on your use case, you may elect to install one, or all of these PAM Types. An overview for each type is linked below: * [Delinea-SecretServer](docs/delinea-secretserver.md) * [Delinea-SecretServer-Password](docs/delinea-secretserver-password.md) * [Delinea-SecretServer-ClientCredentials](docs/delinea-secretserver-clientcredentials.md) * [Delinea-SecretServer-Windows](docs/delinea-secretserver-windows.md) - - - - -
Delinea-SecretServer - #### Requirements - - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. - - A service account or application account with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts and application accounts. -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer ``` ##### Using the API @@ -123,72 +106,70 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "Secret Server Client ID", - "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "Secret Server Client Secret", - "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "GrantType", - "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "Secret Server Client ID", + "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "Secret Server Client Secret", + "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "GrantType", + "DisplayName": "Grant Type", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) - - 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -206,7 +187,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -220,7 +201,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -237,15 +218,11 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). - - - #### Install PAM provider on a Universal Orchestrator Host (Remote) - 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -262,49 +239,41 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json - { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } + "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { + "Host": "", + "Username": "", + "Password": "", + "ClientId": "", + "ClientSecret": "", + "GrantType": "" + } } - ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver.md#requirements) section. 3. Restart the Universal Orchestrator service. - - - -
- - - - - -
Delinea-SecretServer-Password - #### Requirements - - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. - - A service account with a username and password that has permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts. -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Password -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Password ``` ##### Using the API @@ -313,58 +282,56 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Password", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) - - 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -382,7 +349,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -396,7 +363,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -413,15 +380,11 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). - - - #### Install PAM provider on a Universal Orchestrator Host (Remote) - 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -438,49 +401,39 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json - { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { + "Host": "", + "Username": "", + "Password": "", + "SkipTlsValidation": "" + } } - ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-password.md#requirements) section. 3. Restart the Universal Orchestrator service. - - - -
- - - - - -
Delinea-SecretServer-ClientCredentials - #### Requirements - - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. - - An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring application accounts. -#### Create PAM type in Keyfactor Command +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-ClientCredentials -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials ``` ##### Using the API @@ -489,58 +442,56 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-ClientCredentials", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "OAuth2 Client ID", - "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "OAuth2 Client Secret", - "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) - - 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -558,7 +509,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -572,7 +523,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -589,15 +540,11 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). - - - #### Install PAM provider on a Universal Orchestrator Host (Remote) - 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -614,51 +561,41 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json - { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { + "Host": "", + "ClientId": "", + "ClientSecret": "", + "SkipTlsValidation": "" + } } - ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-clientcredentials.md#requirements) section. 3. Restart the Universal Orchestrator service. - - - -
- - - - - -
Delinea-SecretServer-Windows - #### Requirements - - On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. - - The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view - the secrets being retrieved. See the - [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) - for information on configuring IWA access. - - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. -#### Create PAM type in Keyfactor Command +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. +#### Create PAM type in Keyfactor Command ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Windows -kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows +kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API @@ -667,44 +604,42 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Windows", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) - - 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -722,7 +657,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -736,7 +671,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -753,15 +688,11 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). - - - #### Install PAM provider on a Universal Orchestrator Host (Remote) - 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -778,42 +709,26 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json - { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "https://example.secretserver.internal/SecretServer" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "", + "SkipTlsValidation": "" + } } - ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-windows.md#requirements) section. 3. Restart the Universal Orchestrator service. - - - -
- - - - ### Usage - - - -
Delinea-SecretServer - #### From Keyfactor Command Host (Local) - - ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -848,13 +763,9 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer** p | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | - - - #### From a Universal Orchestrator Host (Remote) -
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -894,8 +805,7 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} - +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -903,26 +813,14 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
- - - -
- - > [!NOTE] > Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). - - - - +
Delinea-SecretServer-Password - #### From Keyfactor Command Host (Local) - - ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -955,13 +853,9 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Pas | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | - - - #### From a Universal Orchestrator Host (Remote) -
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -1001,8 +895,7 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} - +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -1010,26 +903,14 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
- - - -
- - > [!NOTE] > Additional information on Delinea-SecretServer-Password can be found in the [supplemental documentation](docs/delinea-secretserver-password.md). - - - - +
Delinea-SecretServer-ClientCredentials - #### From Keyfactor Command Host (Local) - - ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -1062,13 +943,9 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Cli | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | - - - #### From a Universal Orchestrator Host (Remote) -
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -1108,8 +985,7 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} - +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -1117,26 +993,14 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
- - - -
- - > [!NOTE] > Additional information on Delinea-SecretServer-ClientCredentials can be found in the [supplemental documentation](docs/delinea-secretserver-clientcredentials.md). - - - - +
Delinea-SecretServer-Windows - #### From Keyfactor Command Host (Local) - - ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -1167,13 +1031,9 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Win | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | - - - #### From a Universal Orchestrator Host (Remote) -
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -1213,8 +1073,7 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} - +{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -1222,16 +1081,9 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
- - - -
- - > [!NOTE] > Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). - - +
## License @@ -1239,4 +1091,4 @@ Apache License 2.0, see [LICENSE](LICENSE) ## Related Integrations -See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). \ No newline at end of file +See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). diff --git a/delinea-secretserver-pam.Tests/SecretServerPamTests.cs b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs index d785d36..456911d 100644 --- a/delinea-secretserver-pam.Tests/SecretServerPamTests.cs +++ b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs @@ -799,4 +799,129 @@ public void GetPassword_AllFourTypes_HaveDistinctNames() names.Should().OnlyHaveUniqueItems("all PAM type Names must be distinct"); } } + + // --------------------------------------------------------------------------- + // SkipTlsValidation — config parameter and environment variable + // --------------------------------------------------------------------------- + + public class SkipTlsValidation : IDisposable + { + private const string EnvVar = "KEYFACTOR_PAM_SKIP_TLS_VALIDATION"; + + public void Dispose() => Environment.SetEnvironmentVariable(EnvVar, null); + + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + private static Dictionary ServerParams(bool skipTls = false) => new() + { + { "Host", FakeHost }, + { "Username", FakeUsername }, + { "Password", FakePassword }, + { "SkipTlsValidation", skipTls ? "true" : "false" } + }; + + [Fact] + public void GetPassword_SkipTlsValidationConfig_True_Succeeds() + { + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams(skipTls: true)); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_SkipTlsEnvVar_True_Succeeds() + { + Environment.SetEnvironmentVariable(EnvVar, "true"); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams(skipTls: false)); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_SkipTlsEnvVar_One_Succeeds() + { + Environment.SetEnvironmentVariable(EnvVar, "1"); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams(skipTls: false)); + result.Should().Be(FakeFieldValue); + } + + [Fact] + public void GetPassword_SkipTlsEnvVar_False_DoesNotOverrideConfigFalse() + { + Environment.SetEnvironmentVariable(EnvVar, "false"); + + var handler = TwoStageHandler( + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildTokenResponse()) }, + new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(BuildSecretResponse()) }); + + var sut = new SecretServerPamPassword(new HttpClient(handler), NullLogger); + var result = sut.GetPassword(InstanceParams(), ServerParams(skipTls: false)); + result.Should().Be(FakeFieldValue); + } + } + + // --------------------------------------------------------------------------- + // client_credentials GrantType bug fix — must not send "password" grant type + // --------------------------------------------------------------------------- + + public class ClientCredentialsGrantTypeFix + { + private static Dictionary InstanceParams() => new() + { + { "SecretId", FakeSecretId }, + { "SecretFieldName", FakeFieldName } + }; + + [Fact] + public void GetPassword_ClientCredentials_TokenRequestBody_AlwaysSendsPasswordGrantType() + { + // Delinea API constraint: even for client_credentials flow, the token endpoint + // requires grant_type=password. Do not change this behaviour. + string? capturedBody = null; + var callCount = 0; + + var handler = new TestHttpMessageHandler(async (req, ct) => + { + callCount++; + if (callCount == 1) + { + capturedBody = await req.Content!.ReadAsStringAsync(); + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildTokenResponse()) }; + } + return new HttpResponseMessage(HttpStatusCode.OK) + { Content = new StringContent(BuildSecretResponse()) }; + }); + + var sut = new SecretServerPamClientCredentials(new HttpClient(handler), NullLogger); + sut.GetPassword(InstanceParams(), new Dictionary + { + { "Host", FakeHost }, + { "ClientId", FakeClientId }, + { "ClientSecret", FakeClientSecret } + }); + + capturedBody.Should().Contain("grant_type=password", + "Delinea API constraint: token endpoint always requires grant_type=password"); + } + } } diff --git a/docs/delinea-secretserver-clientcredentials.md b/docs/delinea-secretserver-clientcredentials.md index 5f89616..5b1c23c 100644 --- a/docs/delinea-secretserver-clientcredentials.md +++ b/docs/delinea-secretserver-clientcredentials.md @@ -11,5 +11,12 @@ integrations where an application account is used instead of a user account. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring application accounts. +The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client +credentials (application account name and password). This is the recommended type for service-to-service +integrations where an application account is used instead of a user account. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. diff --git a/docs/delinea-secretserver-password.md b/docs/delinea-secretserver-password.md index 534d90a..c6472ee 100644 --- a/docs/delinea-secretserver-password.md +++ b/docs/delinea-secretserver-password.md @@ -11,5 +11,12 @@ and password is used. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts. +The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password +(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username +and password is used. +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. diff --git a/docs/delinea-secretserver-windows.md b/docs/delinea-secretserver-windows.md index 5f8de9c..d21f610 100644 --- a/docs/delinea-secretserver-windows.md +++ b/docs/delinea-secretserver-windows.md @@ -17,5 +17,18 @@ of the process running Keyfactor Command or the Universal Orchestrator. for information on configuring IWA access. - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. +The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows +Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity +of the process running Keyfactor Command or the Universal Orchestrator. + +> [!IMPORTANT] +> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible +> with on-premises Secret Server installations. +- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. +- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. +- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. diff --git a/docs/delinea-secretserver.md b/docs/delinea-secretserver.md index c017f7f..e3bc369 100644 --- a/docs/delinea-secretserver.md +++ b/docs/delinea-secretserver.md @@ -15,5 +15,16 @@ to the chosen authentication method. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts and application accounts. +`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods +(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. +The Keyfactor Command UI will display every credential field regardless of which grant type is active. +For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, +`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant +to the chosen authentication method. + +- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. +- A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. From 44cc25137eddd95d20977e976a72acb47244bc16 Mon Sep 17 00:00:00 2001 From: Keyfactor Date: Thu, 23 Apr 2026 20:54:48 +0000 Subject: [PATCH 31/32] Update generated docs --- README.md | 662 +++++++++++------- .../delinea-secretserver-clientcredentials.md | 7 - docs/delinea-secretserver-password.md | 7 - docs/delinea-secretserver-windows.md | 13 - docs/delinea-secretserver.md | 11 - 5 files changed, 405 insertions(+), 295 deletions(-) diff --git a/README.md b/README.md index de79f1c..ba32eea 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,22 @@

- Support · - Installation · - License · - Related Integrations + + + Support + + · + + Installation + + · + + License + + · + + Related Integrations +

## Overview @@ -53,7 +65,7 @@ The environment variable takes precedence and overrides the configuration parame > Disabling TLS validation should only be used in non-production environments. ## Support -The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. +The Delinea Secret Server PAM Provider is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com. > 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. @@ -74,30 +86,35 @@ Before proceeding with installation, you should consider which pattern is best f To install Delinea Secret Server PAM Provider, it is recommended you install [kfutil](https://github.com/Keyfactor/kfutil). `kfutil` is a command-line tool that simplifies the process of creating PAM Types in Keyfactor Command. - The Delinea Secret Server PAM Provider implements 4 PAM Types. Depending on your use case, you may elect to install one, or all of these PAM Types. An overview for each type is linked below: * [Delinea-SecretServer](docs/delinea-secretserver.md) * [Delinea-SecretServer-Password](docs/delinea-secretserver-password.md) * [Delinea-SecretServer-ClientCredentials](docs/delinea-secretserver-clientcredentials.md) * [Delinea-SecretServer-Windows](docs/delinea-secretserver-windows.md) + + + + +
Delinea-SecretServer -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account or application account with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts and application accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - A service account or application account with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts and application accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer ``` ##### Using the API @@ -106,70 +123,72 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "Secret Server Client ID", - "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "Secret Server Client Secret", - "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "GrantType", - "DisplayName": "Grant Type", - "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance. NOTE: only applicable if using the `password` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "Secret Server Client ID", + "Description": "The client ID used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "Secret Server Client Secret", + "Description": "The client secret used to authenticate to the Secret Server instance. NOTE: only applicable if using the `client_credentials` grant type.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "GrantType", + "DisplayName": "Grant Type", + "Description": "The grant type used to authenticate to the Secret Server instance. Valid values are `password`, `client_credentials`, or `windows`. Default is `password`. If not provided the default value `password` will be used to maintain backwards compatibility.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -187,7 +206,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -201,7 +220,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -218,11 +237,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -239,41 +262,49 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer:InitializationInfo": { - "Host": "", - "Username": "", - "Password": "", - "ClientId": "", - "ClientSecret": "", - "GrantType": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-Password -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account with a username and password that has permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - A service account with a username and password that has permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring service accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Password -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Password +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Password ``` ##### Using the API @@ -282,56 +313,58 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Password", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Username", - "DisplayName": "Secret Server Username", - "Description": "The username used to authenticate to the Secret Server instance.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "Password", - "DisplayName": "Secret Server Password", - "Description": "The password used to authenticate to the Secret Server instance.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Password", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Username", + "DisplayName": "Secret Server Username", + "Description": "The username used to authenticate to the Secret Server instance.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "Password", + "DisplayName": "Secret Server Password", + "Description": "The password used to authenticate to the Secret Server instance.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -349,7 +382,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -363,7 +396,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -380,11 +413,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -401,39 +438,49 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-Password:InitializationInfo": { - "Host": "", - "Username": "", - "Password": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-password.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-ClientCredentials -#### Requirements -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring application accounts. +#### Requirements + - Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. + - An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the + [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) + for information on configuring application accounts. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-ClientCredentials -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-ClientCredentials ``` ##### Using the API @@ -442,56 +489,58 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-ClientCredentials", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientId", - "DisplayName": "OAuth2 Client ID", - "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "ClientSecret", - "DisplayName": "OAuth2 Client Secret", - "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", - "DataType": 2, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-ClientCredentials", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretservercloud.com/SecretServer", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientId", + "DisplayName": "OAuth2 Client ID", + "Description": "The client ID (application account name) used for OAuth2 client credentials authentication.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "ClientSecret", + "DisplayName": "OAuth2 Client Secret", + "Description": "The client secret (application account password) used for OAuth2 client credentials authentication.", + "DataType": 2, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -509,7 +558,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -523,7 +572,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -540,11 +589,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -561,41 +614,51 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-ClientCredentials:InitializationInfo": { - "Host": "", - "ClientId": "", - "ClientSecret": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-clientcredentials.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + + +
Delinea-SecretServer-Windows -#### Requirements -- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. -- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view - the secrets being retrieved. See the - [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) - for information on configuring IWA access. -- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. +#### Requirements + - On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. + - The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view + the secrets being retrieved. See the + [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) + for information on configuring IWA access. + - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. #### Create PAM type in Keyfactor Command + ##### Using `kfutil` Create the required PAM Types in the connected Command platform. ```shell # Delinea-SecretServer-Windows -kfutil pam-types create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows +kfutil pam types-create -r delinea-secretserver-pam -n Delinea-SecretServer-Windows ``` ##### Using the API @@ -604,42 +667,44 @@ For full API docs please visit our [product documentation](https://software.keyf Below is the payload to `POST` to the Keyfactor Command API ```json { - "Name": "Delinea-SecretServer-Windows", - "Parameters": [ - { - "Name": "Host", - "DisplayName": "Secret Server URL", - "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SkipTlsValidation", - "DisplayName": "Skip TLS Validation", - "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", - "DataType": 1, - "InstanceLevel": false - }, - { - "Name": "SecretId", - "DisplayName": "Secret ID", - "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", - "DataType": 1, - "InstanceLevel": true - }, - { - "Name": "SecretFieldName", - "DisplayName": "Secret Field Name", - "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", - "DataType": 1, - "InstanceLevel": true - } - ] + "Name": "Delinea-SecretServer-Windows", + "Parameters": [ + { + "Name": "Host", + "DisplayName": "Secret Server URL", + "Description": "The URL to the Secret Server instance. Example: https://example.secretserver.internal/SecretServer. NOTE: IWA is not supported on Secret Server Cloud.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SkipTlsValidation", + "DisplayName": "Skip TLS Validation", + "Description": "Set to `true` to disable TLS certificate validation. Use only in non-production environments.", + "DataType": 1, + "InstanceLevel": false + }, + { + "Name": "SecretId", + "DisplayName": "Secret ID", + "Description": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.", + "DataType": 1, + "InstanceLevel": true + }, + { + "Name": "SecretFieldName", + "DisplayName": "Secret Field Name", + "Description": "The name of the field in the secret that contains the credential value. NOTE: The field must exist.", + "DataType": 1, + "InstanceLevel": true + } + ] } ``` #### Install PAM provider on Keyfactor Command Host (Local) + + 1. On the server that hosts Keyfactor Command, download and unzip the latest release of the Delinea Secret Server PAM Provider from the [Releases](../../releases) page. 2. Copy the assemblies to the appropriate directories on the Keyfactor Command server: @@ -657,7 +722,7 @@ Below is the payload to `POST` to the Keyfactor Command API
Keyfactor Command 10 1. Copy the assemblies to each of the following directories: - + * `C:\Program Files\Keyfactor\Keyfactor Platform\WebAgentServices\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\KeyfactorAPI\bin\delinea-secretserver-pam` * `C:\Program Files\Keyfactor\Keyfactor Platform\WebConsole\bin\delinea-secretserver-pam` @@ -671,7 +736,7 @@ Below is the payload to `POST` to the Keyfactor Command API ... - + @@ -688,11 +753,15 @@ Below is the payload to `POST` to the Keyfactor Command API 3. Restart the Keyfactor Command services (`iisreset`). + + + #### Install PAM provider on a Universal Orchestrator Host (Remote) + 1. Install the Delinea Secret Server PAM Provider assemblies. - * **Using kfutil**: On the server that hosts the Universal Orchestrator, run the following command: + * **Using kfutil**: On the server that that hosts the Universal Orchestrator, run the following command: ```shell # Windows Server @@ -709,26 +778,42 @@ Below is the payload to `POST` to the Keyfactor Command API 2. Included in the release is a `manifest.json` file that contains the following object: ```json + { - "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { - "Host": "", - "SkipTlsValidation": "" - } + "Keyfactor:PAMProviders:Delinea-SecretServer-Windows:InitializationInfo": { + "Host": "https://example.secretserver.internal/SecretServer" + } } + ``` Populate the fields in this object with credentials and configuration data collected in the [requirements](docs/delinea-secretserver-windows.md#requirements) section. 3. Restart the Universal Orchestrator service. + + + +
+ + + + ### Usage + + + +
Delinea-SecretServer + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -763,9 +848,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer** p | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -805,7 +894,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -813,14 +903,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer can be found in the [supplemental documentation](docs/delinea-secretserver.md). -
+ + + +
Delinea-SecretServer-Password + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -853,9 +955,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Pas | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -895,7 +1001,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -903,14 +1010,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-Password can be found in the [supplemental documentation](docs/delinea-secretserver-password.md). -
+ + + +
Delinea-SecretServer-ClientCredentials + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -943,9 +1062,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Cli | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -985,7 +1108,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -993,14 +1117,26 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-ClientCredentials can be found in the [supplemental documentation](docs/delinea-secretserver-clientcredentials.md). -
+ + + +
Delinea-SecretServer-Windows + #### From Keyfactor Command Host (Local) + + ##### Define a PAM provider in Command 1. In the Keyfactor Command Portal, hover over the ⚙️ (settings) icon in the top right corner of the screen and select **Priviledged Access Management**. @@ -1031,9 +1167,13 @@ Select the **Load From PAM Provider** tab, choose the **Delinea-SecretServer-Win | SecretFieldName | Secret Field Name | The name of the field in the secret that contains the credential value. NOTE: The field must exist. | + + + #### From a Universal Orchestrator Host (Remote) +
Keyfactor Command 11+ ##### Define a remote PAM provider in Command @@ -1073,7 +1213,8 @@ When defining Certificate Stores (**Locations**->**Certificate Stores**), **Deli When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and populate the **Secret Value** field with the following JSON object: ```json -{"SecretId":"The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName":"The name of the field in the secret that contains the credential value. NOTE: The field must exist."} +{"SecretId": "The ID of the secret in Secret Server. This is the integer ID that is used to retrieve the secret from Secret Server.","SecretFieldName": "The name of the field in the secret that contains the credential value. NOTE: The field must exist."} + ``` > We recommend creating this JSON object in a text editor, and copying it into the Secret Value field. @@ -1081,9 +1222,16 @@ When entering Secret fields, select the **Load From Keyfactor Secrets** tab, and
+ + + +
+ + > [!NOTE] > Additional information on Delinea-SecretServer-Windows can be found in the [supplemental documentation](docs/delinea-secretserver-windows.md). -
+ + ## License @@ -1091,4 +1239,4 @@ Apache License 2.0, see [LICENSE](LICENSE) ## Related Integrations -See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). +See all [Keyfactor PAM Provider extensions](https://github.com/orgs/Keyfactor/repositories?q=pam). \ No newline at end of file diff --git a/docs/delinea-secretserver-clientcredentials.md b/docs/delinea-secretserver-clientcredentials.md index 5b1c23c..5f89616 100644 --- a/docs/delinea-secretserver-clientcredentials.md +++ b/docs/delinea-secretserver-clientcredentials.md @@ -11,12 +11,5 @@ integrations where an application account is used instead of a user account. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring application accounts. -The `Delinea-SecretServer-ClientCredentials` PAM type authenticates to Delinea Secret Server using OAuth2 client -credentials (application account name and password). This is the recommended type for service-to-service -integrations where an application account is used instead of a user account. -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- An application account (Client ID and Client Secret) with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring application accounts. diff --git a/docs/delinea-secretserver-password.md b/docs/delinea-secretserver-password.md index c6472ee..534d90a 100644 --- a/docs/delinea-secretserver-password.md +++ b/docs/delinea-secretserver-password.md @@ -11,12 +11,5 @@ and password is used. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts. -The `Delinea-SecretServer-Password` PAM type authenticates to Delinea Secret Server using a username and password -(OAuth2 `password` grant). This is the recommended type for environments where a service account with a username -and password is used. -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account with a username and password that has permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts. diff --git a/docs/delinea-secretserver-windows.md b/docs/delinea-secretserver-windows.md index d21f610..5f8de9c 100644 --- a/docs/delinea-secretserver-windows.md +++ b/docs/delinea-secretserver-windows.md @@ -17,18 +17,5 @@ of the process running Keyfactor Command or the Universal Orchestrator. for information on configuring IWA access. - The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. -The `Delinea-SecretServer-Windows` PAM type authenticates to Delinea Secret Server using Integrated Windows -Authentication (IWA). No credentials are required in the configuration — the provider uses the Windows identity -of the process running Keyfactor Command or the Universal Orchestrator. - -> [!IMPORTANT] -> Integrated Windows Authentication is not supported on Delinea Secret Server Cloud. This type is only compatible -> with on-premises Secret Server installations. -- On-premises Delinea Secret Server instance accessible from the host running Keyfactor Command or the Universal Orchestrator. -- The Windows service account running Keyfactor Command or the Universal Orchestrator must have permission to view - the secrets being retrieved. See the - [Delinea Secret Server IWA documentation](https://docs.delinea.com/online-help/secret-server/authentication/iwa-webservices/webservice-iwa-powershell/index.htm) - for information on configuring IWA access. -- The Secret Server instance must be configured to allow Integrated Windows Authentication web service access. diff --git a/docs/delinea-secretserver.md b/docs/delinea-secretserver.md index e3bc369..c017f7f 100644 --- a/docs/delinea-secretserver.md +++ b/docs/delinea-secretserver.md @@ -15,16 +15,5 @@ to the chosen authentication method. [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) for information on configuring service accounts and application accounts. -`Delinea-SecretServer` is the original backwards-compatible PAM type. It supports all three authentication methods -(`password`, `client_credentials`, `windows`) selected at runtime via the `GrantType` configuration parameter. -The Keyfactor Command UI will display every credential field regardless of which grant type is active. -For new installations, use the type-specific variants (`Delinea-SecretServer-Password`, -`Delinea-SecretServer-ClientCredentials`, or `Delinea-SecretServer-Windows`) which only show the fields relevant -to the chosen authentication method. - -- Delinea Secret Server instance accessible over HTTPS from the host running Keyfactor Command or the Universal Orchestrator. -- A service account or application account with permission to view the secrets being retrieved. See the - [Delinea Secret Server documentation](https://docs.delinea.com/online-help/secret-server/api-scripting/authentication/script-token-auth/index.htm) - for information on configuring service accounts and application accounts. From ab8e502cef7b5455ba66c73dcc33ebe31258da02 Mon Sep 17 00:00:00 2001 From: spbsoluble <1661003+spbsoluble@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:56:41 -0700 Subject: [PATCH 32/32] test: add integration tests that skip gracefully when env vars are not set Adds IntegrationFactAttribute which sets Skip at attribute construction time if any of the required SECRET_SERVER_* env vars are absent, producing a clean skip rather than a failure in CI environments without live server access. --- .../IntegrationFactAttribute.cs | 29 +++++++++++++ .../SecretServerPamTests.cs | 41 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 delinea-secretserver-pam.Tests/IntegrationFactAttribute.cs diff --git a/delinea-secretserver-pam.Tests/IntegrationFactAttribute.cs b/delinea-secretserver-pam.Tests/IntegrationFactAttribute.cs new file mode 100644 index 0000000..0bb90d4 --- /dev/null +++ b/delinea-secretserver-pam.Tests/IntegrationFactAttribute.cs @@ -0,0 +1,29 @@ +using Xunit.Sdk; + +namespace Keyfactor.Extensions.Pam.Delinea.Tests; + +/// +/// Marks a test as an integration test that requires specific environment variables. +/// The test is skipped (not failed) when any of the named variables are absent or empty. +/// +[AttributeUsage(AttributeTargets.Method)] +public sealed class IntegrationFactAttribute : FactAttribute +{ + private static readonly string[] Required = + { + "SECRET_SERVER_URL", + "SECRET_SERVER_USERNAME", + "SECRET_SERVER_PASSWORD", + "SECRET_SERVER_SECRET_ID" + }; + + public IntegrationFactAttribute() + { + var missing = Required + .Where(v => string.IsNullOrEmpty(Environment.GetEnvironmentVariable(v))) + .ToList(); + + if (missing.Count > 0) + Skip = $"Integration env vars not set: {string.Join(", ", missing)}"; + } +} diff --git a/delinea-secretserver-pam.Tests/SecretServerPamTests.cs b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs index 456911d..bf3382f 100644 --- a/delinea-secretserver-pam.Tests/SecretServerPamTests.cs +++ b/delinea-secretserver-pam.Tests/SecretServerPamTests.cs @@ -924,4 +924,45 @@ public void GetPassword_ClientCredentials_TokenRequestBody_AlwaysSendsPasswordGr "Delinea API constraint: token endpoint always requires grant_type=password"); } } + + // --------------------------------------------------------------------------- + // Integration tests — skipped automatically when env vars are not set + // --------------------------------------------------------------------------- + + public class IntegrationTests + { + private static string Env(string name) => Environment.GetEnvironmentVariable(name)!; + private static bool SkipTls => + string.Equals(Env("SECRET_SERVER_SKIP_TLS_VALIDATION"), "true", StringComparison.OrdinalIgnoreCase); + + [IntegrationFact] + public void LiveServer_PasswordGrant_RetrievesSecret() + { + var sut = new SecretServerPamPassword(); + var result = sut.GetPassword( + new Dictionary { { "SecretId", Env("SECRET_SERVER_SECRET_ID") }, { "SecretFieldName", "username" } }, + new Dictionary { { "Host", Env("SECRET_SERVER_URL") }, { "Username", Env("SECRET_SERVER_USERNAME") }, { "Password", Env("SECRET_SERVER_PASSWORD") }, { "SkipTlsValidation", SkipTls ? "true" : "false" } }); + + result.Should().NotBeNullOrEmpty("live Secret Server should return a non-empty value"); + } + + [IntegrationFact] + public void LiveServer_EnvVarSkipTls_RetrievesSecret() + { + Environment.SetEnvironmentVariable("KEYFACTOR_PAM_SKIP_TLS_VALIDATION", "true"); + try + { + var sut = new SecretServerPamPassword(); + var result = sut.GetPassword( + new Dictionary { { "SecretId", Env("SECRET_SERVER_SECRET_ID") }, { "SecretFieldName", "username" } }, + new Dictionary { { "Host", Env("SECRET_SERVER_URL") }, { "Username", Env("SECRET_SERVER_USERNAME") }, { "Password", Env("SECRET_SERVER_PASSWORD") } }); + + result.Should().NotBeNullOrEmpty("KEYFACTOR_PAM_SKIP_TLS_VALIDATION=true should allow retrieval from live server"); + } + finally + { + Environment.SetEnvironmentVariable("KEYFACTOR_PAM_SKIP_TLS_VALIDATION", null); + } + } + } }