Add plain-text accessors for secrets

InfisicalSecret.GetPlainTextValue() returns the SecureString contents as a managed string for ergonomic PowerShell access. ConvertTo-InfisicalSecretDictionary -AsPlainText emits Dictionary<string,string> instead of Dictionary<string,SecureString>; default behavior unchanged. Export-InfisicalSecrets already writes plain text via secret.UsePlainTextValue(), so no switch was added there.
This commit is contained in:
GraceSolutions
2026-06-02 21:14:43 -04:00
parent 09c577ebd0
commit 7be0b7b420
5 changed files with 81 additions and 49 deletions
@@ -9,6 +9,7 @@ namespace PSInfisicalAPI.Cmdlets
{
[Cmdlet(VerbsData.ConvertTo, "InfisicalSecretDictionary")]
[OutputType(typeof(Dictionary<string, SecureString>))]
[OutputType(typeof(Dictionary<string, string>))]
public sealed class ConvertToInfisicalSecretDictionaryCmdlet : InfisicalCmdletBase
{
[Parameter(Mandatory = true, ValueFromPipeline = true)]
@@ -17,6 +18,9 @@ namespace PSInfisicalAPI.Cmdlets
[Parameter]
public InfisicalDuplicateKeyBehavior DuplicateKeyBehavior { get; set; } = InfisicalDuplicateKeyBehavior.Error;
[Parameter]
public SwitchParameter AsPlainText { get; set; }
private readonly List<InfisicalSecret> _buffer = new List<InfisicalSecret>();
protected override void ProcessRecord()
@@ -36,36 +40,50 @@ namespace PSInfisicalAPI.Cmdlets
{
try
{
Dictionary<string, SecureString> dictionary = new Dictionary<string, SecureString>(StringComparer.OrdinalIgnoreCase);
foreach (InfisicalSecret secret in _buffer)
if (AsPlainText.IsPresent)
{
string key = secret.SecretName ?? string.Empty;
if (dictionary.ContainsKey(key))
{
if (DuplicateKeyBehavior == InfisicalDuplicateKeyBehavior.Error)
{
throw new InfisicalConfigurationException(string.Concat("Duplicate secret name encountered: ", key));
}
if (DuplicateKeyBehavior == InfisicalDuplicateKeyBehavior.LastWins)
{
dictionary[key] = secret.SecretValue;
}
continue;
}
dictionary[key] = secret.SecretValue;
Dictionary<string, string> plain = BuildDictionary<string>(secret => secret.GetPlainTextValue());
WriteObject(plain);
}
else
{
Dictionary<string, SecureString> secure = BuildDictionary<SecureString>(secret => secret.SecretValue);
WriteObject(secure);
}
WriteObject(dictionary);
}
catch (Exception exception)
{
ThrowTerminatingForException("ConvertToInfisicalSecretDictionaryCmdlet", "ConvertToDictionary", exception);
}
}
private Dictionary<string, TValue> BuildDictionary<TValue>(Func<InfisicalSecret, TValue> valueSelector)
{
Dictionary<string, TValue> dictionary = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
foreach (InfisicalSecret secret in _buffer)
{
string key = secret.SecretName ?? string.Empty;
if (dictionary.ContainsKey(key))
{
if (DuplicateKeyBehavior == InfisicalDuplicateKeyBehavior.Error)
{
throw new InfisicalConfigurationException(string.Concat("Duplicate secret name encountered: ", key));
}
if (DuplicateKeyBehavior == InfisicalDuplicateKeyBehavior.LastWins)
{
dictionary[key] = valueSelector(secret);
}
continue;
}
dictionary[key] = valueSelector(secret);
}
return dictionary;
}
}
}
@@ -34,6 +34,12 @@ namespace PSInfisicalAPI.Models
SecureStringUtility.UsePlainText(SecretValue, action);
}
public string GetPlainTextValue()
{
if (SecretValue == null) { return null; }
return SecureStringUtility.UsePlainText(SecretValue, plainText => plainText);
}
public override string ToString()
{
return SecretName;