Files
PSInfisicalAPI/src/PSInfisicalAPI.Tests/InfisicalEnvironmentPatternTests.cs
T
GraceSolutions cffda99591 refactor!(scoping): mandate explicit -ProjectId/-Environment; add -Type/-IncludeRoles to Get-InfisicalProject
BREAKING CHANGES
- Connect-Infisical no longer accepts -ProjectId, -Environment, or -SecretPath.
- InfisicalConnection no longer carries ProjectId, Environment, or DefaultSecretPath.
- Every cmdlet that previously inherited those fields now requires -ProjectId
  and/or -Environment as Mandatory=true. -SecretPath / -Path remain optional
  and default to "/" at the client layer.
- INFISICAL_PROJECT_ID, INFISICAL_ENVIRONMENT, INFISICAL_SECRET_PATH env-var
  scanning removed from Connect-Infisical.
- Resolve{ProjectId,Environment,SecretPath} helpers removed from
  InfisicalCmdletBase. ResolveOrganizationId retained.

ADDED
- Get-InfisicalProject -Type <enum> filters the list by product surface
  (secret-manager, cert-manager, kms, ssh, secret-scanning, pam, ai) with
  IntelliSense via ValidateSet.
- Get-InfisicalProject -IncludeRoles switch maps to includeRoles=true/false
  query parameter (always sent).

RATIONALE
- Implicit connection scoping caused 400 Bad Request when the active
  connection's ProjectId belonged to a different product surface than the
  cmdlet's target (e.g. secret-manager project id passed to /cert-manager/*).
- Explicit parameters make scope unambiguous and make scripts portable
  across projects.
- The new -Type filter on Get-InfisicalProject lets callers discover the
  correct project id for each subsequent CRUD invocation without needing
  connection-level inheritance.

INTERNAL
- All client classes (Secrets / Folders / Environments / Tags / Projects /
  Pki) now receive scoping as explicit arguments rather than reading the
  InfisicalConnection object.
- Client-layer SecretPath / Path defaulting to "/" is preserved via
  FirstNonEmpty(...).
- Help XML updated to remove all "session-pinned" / "active connection"
  phrasing; OrderedDictionary splatting examples now include the mandatory
  parameters.
- 216/216 unit tests passing.
2026-06-04 21:16:52 -04:00

98 lines
4.0 KiB
C#

using System.Text.RegularExpressions;
using PSInfisicalAPI.Authentication;
using Xunit;
namespace PSInfisicalAPI.Tests
{
public class InfisicalEnvironmentPatternTests
{
[Theory]
[InlineData("INFISICAL_API_URL")]
[InlineData("INFISICAL_BASE_URL")]
[InlineData("INFISICAL_BASE_URI")]
[InlineData("INFISICAL_HOST")]
[InlineData("CLOUDINIT_INFISICAL_APIURL")]
public void BaseUriPatterns_Match_Expected_Names(string name)
{
Assert.True(MatchesAny(name, InfisicalEnvironmentResolver.BaseUriPatterns), "Expected match for " + name);
}
[Theory]
[InlineData("INFISICAL_ORG_ID")]
[InlineData("INFISICAL_ORGANIZATION_ID")]
[InlineData("CLOUDINIT_INFISICAL_ORGANIZATIONID")]
public void OrganizationIdPatterns_Match_Expected_Names(string name)
{
Assert.True(MatchesAny(name, InfisicalEnvironmentResolver.OrganizationIdPatterns), "Expected match for " + name);
}
[Theory]
[InlineData("INFISICAL_CLIENT_ID")]
[InlineData("INFISICAL_UNIVERSAL_AUTH_CLIENT_ID")]
[InlineData("INFISICAL_MACHINE_IDENTITY_CLIENT_ID")]
[InlineData("CLOUDINIT_INFISICAL_CLIENTID")]
[InlineData("myapp_infisical_client_id")]
public void ClientIdPatterns_Match_Standard_And_Custom_Prefixed_Names(string name)
{
Assert.True(MatchesAny(name, InfisicalEnvironmentResolver.ClientIdPatterns), "Expected match for " + name);
}
[Theory]
[InlineData("INFISICAL_CLIENT_SECRET")]
[InlineData("INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET")]
[InlineData("INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET")]
[InlineData("CLOUDINIT_INFISICAL_CLIENTSECRET")]
[InlineData("myapp_infisical_client_secret")]
public void ClientSecretPatterns_Match_Standard_And_Custom_Prefixed_Names(string name)
{
Assert.True(MatchesAny(name, InfisicalEnvironmentResolver.ClientSecretPatterns), "Expected match for " + name);
}
[Theory]
[InlineData("INFISICAL_TOKEN")]
[InlineData("INFISICAL_ACCESS_TOKEN")]
[InlineData("INFISICAL_AUTH_TOKEN")]
[InlineData("CLOUDINIT_INFISICAL_TOKEN")]
public void AccessTokenPatterns_Match_Expected_Names(string name)
{
Assert.True(MatchesAny(name, InfisicalEnvironmentResolver.AccessTokenPatterns), "Expected match for " + name);
}
[Theory]
[InlineData("INFISICAL_SECRET_PATH")]
[InlineData("INFISICAL_DEFAULT_SECRET_PATH")]
[InlineData("CLOUDINIT_INFISICAL_SECRETPATH")]
public void ClientSecretPatterns_Do_Not_Match_SecretPath_Variables(string name)
{
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.ClientSecretPatterns), "ClientSecretPatterns should NOT match " + name);
}
[Theory]
[InlineData("PATH")]
[InlineData("USERNAME")]
[InlineData("HOME")]
[InlineData("PROCESSOR_ARCHITECTURE")]
public void Patterns_Do_Not_Match_Unrelated_System_Variables(string name)
{
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.ClientIdPatterns));
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.ClientSecretPatterns));
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.AccessTokenPatterns));
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.BaseUriPatterns));
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.OrganizationIdPatterns));
Assert.False(MatchesAny(name, InfisicalEnvironmentResolver.ApiVersionPatterns));
}
private static bool MatchesAny(string input, Regex[] patterns)
{
for (int i = 0; i < patterns.Length; i++)
{
if (patterns[i].IsMatch(input))
{
return true;
}
}
return false;
}
}
}