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:
-
-
-
-#### 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.
-
-
-
-
-#### 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
-
-
-
-##### Example Unity Entry
-```xml
-
-```
-]
-]
-
-#### 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.
-
-
-
-
-#### 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.
-
-
-
-
-#### 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. |
-
-
\ 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);
+ }
+ }
+ }
}