feat: gate -Prefix to skip already-prefixed names; add -ForcePrefix override on ConvertTo/Import/Export/Start cmdlets
This commit is contained in:
@@ -295,7 +295,7 @@ $CopyInfisicalSecretResult = Copy-InfisicalSecret @CopyInfisicalSecretParameters
|
|||||||
<command:noun>InfisicalSecretDictionary</command:noun>
|
<command:noun>InfisicalSecretDictionary</command:noun>
|
||||||
</command:details>
|
</command:details>
|
||||||
<maml:description>
|
<maml:description>
|
||||||
<maml:para>Aggregates an incoming pipeline of InfisicalSecret objects into a case-insensitive Dictionary keyed by SecretName. By default values are SecureString; pass -AsPlainText to materialize string values. Duplicate keys are handled via the -DuplicateKeyBehavior parameter (Error, FirstWins, LastWins). -Prefix prepends a string to every dictionary key (e.g. SecretName 'API_KEY' with -Prefix 'MYAPP_' becomes key 'MYAPP_API_KEY'); the underlying InfisicalSecret objects are not mutated.</maml:para>
|
<maml:para>Aggregates an incoming pipeline of InfisicalSecret objects into a case-insensitive Dictionary keyed by SecretName. By default values are SecureString; pass -AsPlainText to materialize string values. Duplicate keys are handled via the -DuplicateKeyBehavior parameter (Error, FirstWins, LastWins). -Prefix prepends a string to every dictionary key (e.g. SecretName 'API_KEY' with -Prefix 'MYAPP_' becomes key 'MYAPP_API_KEY'); the underlying InfisicalSecret objects are not mutated. A SecretName that already starts with -Prefix (case-insensitive) is left as-is to avoid double-prefixing; pass -ForcePrefix to always prepend.</maml:para>
|
||||||
</maml:description>
|
</maml:description>
|
||||||
<maml:alertSet>
|
<maml:alertSet>
|
||||||
<maml:title>Notes</maml:title>
|
<maml:title>Notes</maml:title>
|
||||||
@@ -338,7 +338,7 @@ $ConvertToInfisicalSecretDictionaryResult = ConvertTo-InfisicalSecretDictionary
|
|||||||
<command:noun>InfisicalSecrets</command:noun>
|
<command:noun>InfisicalSecrets</command:noun>
|
||||||
</command:details>
|
</command:details>
|
||||||
<maml:description>
|
<maml:description>
|
||||||
<maml:para>Buffers an incoming pipeline of InfisicalSecret objects and writes them to a file in the requested format (DotEnv, Json, Yaml, EnvironmentVariables, etc.) or sets them as environment variables on the chosen scope (Process, User, Machine). -Encoding controls text encoding for file outputs. -Prefix prepends a string to every emitted variable name regardless of format.</maml:para>
|
<maml:para>Buffers an incoming pipeline of InfisicalSecret objects and writes them to a file in the requested format (DotEnv, Json, Yaml, EnvironmentVariables, etc.) or sets them as environment variables on the chosen scope (Process, User, Machine). -Encoding controls text encoding for file outputs. -Prefix prepends a string to every emitted variable name regardless of format; names that already start with -Prefix (case-insensitive) are left as-is to avoid double-prefixing. Pass -ForcePrefix to always prepend.</maml:para>
|
||||||
</maml:description>
|
</maml:description>
|
||||||
<maml:alertSet>
|
<maml:alertSet>
|
||||||
<maml:title>Notes</maml:title>
|
<maml:title>Notes</maml:title>
|
||||||
@@ -382,7 +382,7 @@ $ExportInfisicalSecretsResult = Export-InfisicalSecrets @ExportInfisicalSecretsP
|
|||||||
<command:noun>InfisicalSecret</command:noun>
|
<command:noun>InfisicalSecret</command:noun>
|
||||||
</command:details>
|
</command:details>
|
||||||
<maml:description>
|
<maml:description>
|
||||||
<maml:para>Loads the file at -Path (which must exist) using the parser matching -Format and returns a case-insensitive Dictionary keyed by SecretName. By default values are SecureString; pass -AsPlainText for a plain string dictionary. -Prefix prepends to every emitted key. -DuplicateKeyBehavior controls collision handling (Error, FirstWins, LastWins). The EnvironmentVariables format is intentionally not supported here; use [Environment]::GetEnvironmentVariable or Get-InfisicalEnvironmentVariable for environment-backed values.</maml:para>
|
<maml:para>Loads the file at -Path (which must exist) using the parser matching -Format and returns a case-insensitive Dictionary keyed by SecretName. By default values are SecureString; pass -AsPlainText for a plain string dictionary. -Prefix prepends to every emitted key; keys already starting with -Prefix (case-insensitive) are left as-is to avoid double-prefixing, and -ForcePrefix overrides that gate. -DuplicateKeyBehavior controls collision handling (Error, FirstWins, LastWins). The EnvironmentVariables format is intentionally not supported here; use [Environment]::GetEnvironmentVariable or Get-InfisicalEnvironmentVariable for environment-backed values.</maml:para>
|
||||||
</maml:description>
|
</maml:description>
|
||||||
<maml:alertSet>
|
<maml:alertSet>
|
||||||
<maml:title>Notes</maml:title>
|
<maml:title>Notes</maml:title>
|
||||||
@@ -1705,7 +1705,7 @@ $WriteInfisicalScepMdmProfileToWmiResult = Write-InfisicalScepMdmProfileToWmi @W
|
|||||||
<command:noun>InfisicalProcess</command:noun>
|
<command:noun>InfisicalProcess</command:noun>
|
||||||
</command:details>
|
</command:details>
|
||||||
<maml:description>
|
<maml:description>
|
||||||
<maml:para>Launches the executable specified by -FilePath, captures stdout/stderr, validates the exit code against -AcceptableExitCodeList, and optionally parses output with -ParsingExpression. InfisicalSecret objects supplied via -Secret (pipeline or by name) are decrypted into the ProcessStartInfo.Environment dictionary only, never written to the user or machine scope; -Prefix prepends a string to each injected variable name. -EnvironmentVariables adds additional non-secret values. -ExecutionTimeout, -NoWait, -CreateNoWindow, -WindowStyle, -Priority, -StandardInputObjectList, -SecureArgumentList, -LogOutput, and -ContinueOnError mirror the semantics of the upstream Start-ProcessWithOutput helper. Honors -WhatIf and -Confirm.</maml:para>
|
<maml:para>Launches the executable specified by -FilePath, captures stdout/stderr, validates the exit code against -AcceptableExitCodeList, and optionally parses output with -ParsingExpression. InfisicalSecret objects supplied via -Secret (pipeline or by name) are decrypted into the ProcessStartInfo.Environment dictionary only, never written to the user or machine scope; -Prefix prepends a string to each injected variable name, skipping names that already start with -Prefix (case-insensitive) unless -ForcePrefix is supplied. -EnvironmentVariables adds additional non-secret values. -ExecutionTimeout, -NoWait, -CreateNoWindow, -WindowStyle, -Priority, -StandardInputObjectList, -SecureArgumentList, -LogOutput, and -ContinueOnError mirror the semantics of the upstream Start-ProcessWithOutput helper. Honors -WhatIf and -Confirm.</maml:para>
|
||||||
</maml:description>
|
</maml:description>
|
||||||
<maml:alertSet>
|
<maml:alertSet>
|
||||||
<maml:title>Notes</maml:title>
|
<maml:title>Notes</maml:title>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
using PSInfisicalAPI.Common;
|
||||||
using PSInfisicalAPI.Errors;
|
using PSInfisicalAPI.Errors;
|
||||||
using PSInfisicalAPI.Models;
|
using PSInfisicalAPI.Models;
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public SwitchParameter ForcePrefix { get; set; }
|
||||||
|
|
||||||
private readonly List<InfisicalSecret> _buffer = new List<InfisicalSecret>();
|
private readonly List<InfisicalSecret> _buffer = new List<InfisicalSecret>();
|
||||||
|
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecord()
|
||||||
@@ -63,11 +67,10 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
private Dictionary<string, TValue> BuildDictionary<TValue>(Func<InfisicalSecret, TValue> valueSelector)
|
private Dictionary<string, TValue> BuildDictionary<TValue>(Func<InfisicalSecret, TValue> valueSelector)
|
||||||
{
|
{
|
||||||
Dictionary<string, TValue> dictionary = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, TValue> dictionary = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
|
||||||
string prefix = Prefix ?? string.Empty;
|
|
||||||
|
|
||||||
foreach (InfisicalSecret secret in _buffer)
|
foreach (InfisicalSecret secret in _buffer)
|
||||||
{
|
{
|
||||||
string key = string.Concat(prefix, secret.SecretName ?? string.Empty);
|
string key = InfisicalPrefix.Apply(secret.SecretName ?? string.Empty, Prefix, ForcePrefix.IsPresent);
|
||||||
|
|
||||||
if (dictionary.ContainsKey(key))
|
if (dictionary.ContainsKey(key))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using PSInfisicalAPI.Common;
|
||||||
using PSInfisicalAPI.Errors;
|
using PSInfisicalAPI.Errors;
|
||||||
using PSInfisicalAPI.Exports;
|
using PSInfisicalAPI.Exports;
|
||||||
using PSInfisicalAPI.Models;
|
using PSInfisicalAPI.Models;
|
||||||
@@ -40,6 +41,9 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public SwitchParameter ForcePrefix { get; set; }
|
||||||
|
|
||||||
private readonly List<InfisicalSecret> _buffer = new List<InfisicalSecret>();
|
private readonly List<InfisicalSecret> _buffer = new List<InfisicalSecret>();
|
||||||
|
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecord()
|
||||||
@@ -71,7 +75,7 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
|
|
||||||
InfisicalExportRequest request = new InfisicalExportRequest
|
InfisicalExportRequest request = new InfisicalExportRequest
|
||||||
{
|
{
|
||||||
Secrets = ApplyPrefix(_buffer, Prefix),
|
Secrets = ApplyPrefix(_buffer, Prefix, ForcePrefix.IsPresent),
|
||||||
Format = Format,
|
Format = Format,
|
||||||
Path = Path,
|
Path = Path,
|
||||||
Scope = Scope,
|
Scope = Scope,
|
||||||
@@ -88,7 +92,7 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InfisicalSecret[] ApplyPrefix(List<InfisicalSecret> source, string prefix)
|
private static InfisicalSecret[] ApplyPrefix(List<InfisicalSecret> source, string prefix, bool force)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(prefix)) { return source.ToArray(); }
|
if (string.IsNullOrEmpty(prefix)) { return source.ToArray(); }
|
||||||
|
|
||||||
@@ -104,7 +108,7 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
Environment = original.Environment,
|
Environment = original.Environment,
|
||||||
Version = original.Version,
|
Version = original.Version,
|
||||||
Type = original.Type,
|
Type = original.Type,
|
||||||
SecretName = string.Concat(prefix, original.SecretName),
|
SecretName = InfisicalPrefix.Apply(original.SecretName, prefix, force),
|
||||||
SecretValue = original.SecretValue,
|
SecretValue = original.SecretValue,
|
||||||
SecretValueHidden = original.SecretValueHidden,
|
SecretValueHidden = original.SecretValueHidden,
|
||||||
SecretPath = original.SecretPath,
|
SecretPath = original.SecretPath,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
using PSInfisicalAPI.Common;
|
||||||
using PSInfisicalAPI.Errors;
|
using PSInfisicalAPI.Errors;
|
||||||
using PSInfisicalAPI.Imports;
|
using PSInfisicalAPI.Imports;
|
||||||
using PSInfisicalAPI.Models;
|
using PSInfisicalAPI.Models;
|
||||||
@@ -31,6 +32,9 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public SwitchParameter ForcePrefix { get; set; }
|
||||||
|
|
||||||
protected override void EndProcessing()
|
protected override void EndProcessing()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -66,12 +70,11 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
Func<string, TValue> valueSelector)
|
Func<string, TValue> valueSelector)
|
||||||
{
|
{
|
||||||
Dictionary<string, TValue> dictionary = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, TValue> dictionary = new Dictionary<string, TValue>(StringComparer.OrdinalIgnoreCase);
|
||||||
string prefix = Prefix ?? string.Empty;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> pair in pairs)
|
foreach (KeyValuePair<string, string> pair in pairs)
|
||||||
{
|
{
|
||||||
if (pair.Key == null) { continue; }
|
if (pair.Key == null) { continue; }
|
||||||
string key = string.Concat(prefix, pair.Key);
|
string key = InfisicalPrefix.Apply(pair.Key, Prefix, ForcePrefix.IsPresent);
|
||||||
|
|
||||||
if (dictionary.ContainsKey(key))
|
if (dictionary.ContainsKey(key))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public SwitchParameter ForcePrefix { get; set; }
|
||||||
|
|
||||||
private readonly List<InfisicalSecret> _secretBuffer = new List<InfisicalSecret>();
|
private readonly List<InfisicalSecret> _secretBuffer = new List<InfisicalSecret>();
|
||||||
|
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecord()
|
||||||
@@ -135,7 +138,8 @@ namespace PSInfisicalAPI.Cmdlets
|
|||||||
LogOutput = LogOutput.IsPresent,
|
LogOutput = LogOutput.IsPresent,
|
||||||
ContinueOnError = ContinueOnError.IsPresent,
|
ContinueOnError = ContinueOnError.IsPresent,
|
||||||
Secrets = _secretBuffer.ToArray(),
|
Secrets = _secretBuffer.ToArray(),
|
||||||
Prefix = Prefix
|
Prefix = Prefix,
|
||||||
|
ForcePrefix = ForcePrefix.IsPresent
|
||||||
};
|
};
|
||||||
|
|
||||||
InfisicalProcessResult result = InfisicalProcessRunner.Run(options, Logger);
|
InfisicalProcessResult result = InfisicalProcessRunner.Run(options, Logger);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PSInfisicalAPI.Common
|
||||||
|
{
|
||||||
|
public static class InfisicalPrefix
|
||||||
|
{
|
||||||
|
public static string Apply(string original, string prefix, bool force)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(prefix)) { return original ?? string.Empty; }
|
||||||
|
if (original == null) { return prefix; }
|
||||||
|
if (!force && original.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { return original; }
|
||||||
|
return string.Concat(prefix, original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,5 +26,6 @@ namespace PSInfisicalAPI.Process
|
|||||||
public bool ContinueOnError { get; set; }
|
public bool ContinueOnError { get; set; }
|
||||||
public InfisicalSecret[] Secrets { get; set; }
|
public InfisicalSecret[] Secrets { get; set; }
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
public bool ForcePrefix { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using PSInfisicalAPI.Common;
|
||||||
using PSInfisicalAPI.Logging;
|
using PSInfisicalAPI.Logging;
|
||||||
using PSInfisicalAPI.Models;
|
using PSInfisicalAPI.Models;
|
||||||
using PSInfisicalAPI.Security;
|
using PSInfisicalAPI.Security;
|
||||||
@@ -39,7 +40,7 @@ namespace PSInfisicalAPI.Process
|
|||||||
foreach (InfisicalSecret secret in options.Secrets)
|
foreach (InfisicalSecret secret in options.Secrets)
|
||||||
{
|
{
|
||||||
if (secret == null || string.IsNullOrEmpty(secret.SecretName) || secret.SecretValue == null) { continue; }
|
if (secret == null || string.IsNullOrEmpty(secret.SecretName) || secret.SecretValue == null) { continue; }
|
||||||
string name = string.IsNullOrEmpty(options.Prefix) ? secret.SecretName : string.Concat(options.Prefix, secret.SecretName);
|
string name = InfisicalPrefix.Apply(secret.SecretName, options.Prefix, options.ForcePrefix);
|
||||||
SecureStringUtility.UsePlainText(secret.SecretValue, plain =>
|
SecureStringUtility.UsePlainText(secret.SecretValue, plain =>
|
||||||
{
|
{
|
||||||
processEnv[name] = plain;
|
processEnv[name] = plain;
|
||||||
|
|||||||
Reference in New Issue
Block a user