Rebrand to Grace Solutions; add README, about_ help, Gitea CI/CD, track Module bin #1

Merged
gsadmin merged 8 commits from dev into main 2026-06-03 01:53:11 +00:00
11 changed files with 327 additions and 82 deletions
Showing only changes of commit 09c577ebd0 - Show all commits
+30
View File
@@ -6,6 +6,36 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
## Unreleased ## Unreleased
## 2026.06.03.0057
- Build produced from commit 7e5209190ac2.
## Unreleased (carried forward)
## 2026.06.03.0056
- Build produced from commit 7e5209190ac2.
## Unreleased (carried forward)
## 2026.06.03.0055
- Build produced from commit 7e5209190ac2.
## Unreleased (carried forward)
## 2026.06.03.0047
- Build produced from commit 7e5209190ac2.
## Unreleased (carried forward)
## 2026.06.03.0046
- Build produced from commit 7e5209190ac2.
## Unreleased (carried forward)
## 2026.06.03.0032 ## 2026.06.03.0032
- Build produced from commit c86676010532. - Build produced from commit c86676010532.
+2 -2
View File
@@ -1,6 +1,6 @@
@{ @{
RootModule = 'PSInfisicalAPI.psm1' RootModule = 'PSInfisicalAPI.psm1'
ModuleVersion = '2026.06.03.0032' ModuleVersion = '2026.06.03.0057'
GUID = 'b8a2f3d4-7c51-4d2f-9e6a-1f0c8b3d4e51' GUID = 'b8a2f3d4-7c51-4d2f-9e6a-1f0c8b3d4e51'
Author = 'Grace Solutions' Author = 'Grace Solutions'
CompanyName = 'Grace Solutions' CompanyName = 'Grace Solutions'
@@ -27,7 +27,7 @@
LicenseUri = 'https://www.gnu.org/licenses/agpl-3.0.html' LicenseUri = 'https://www.gnu.org/licenses/agpl-3.0.html'
ProjectUri = 'https://prod.git.gracesolution.info/gsadmin/PSInfisicalAPI' ProjectUri = 'https://prod.git.gracesolution.info/gsadmin/PSInfisicalAPI'
ReleaseNotes = 'See CHANGELOG.md in the project repository for release history.' ReleaseNotes = 'See CHANGELOG.md in the project repository for release history.'
CommitHash = 'c86676010532' CommitHash = '7e5209190ac2'
} }
} }
} }
Binary file not shown.
@@ -89,10 +89,13 @@ namespace PSInfisicalAPI.Cmdlets
throw new InfisicalAuthenticationException("Authentication did not produce an access token."); throw new InfisicalAuthenticationException("Authentication did not produce an access token.");
} }
bool apiVersionExplicitlyBound = MyInvocation.BoundParameters.ContainsKey("ApiVersion");
InfisicalConnection connection = new InfisicalConnection InfisicalConnection connection = new InfisicalConnection
{ {
BaseUri = BaseUri, BaseUri = BaseUri,
ApiVersion = ApiVersion, ApiVersion = ApiVersion,
PinnedApiVersion = apiVersionExplicitlyBound ? ApiVersion : null,
AuthType = authType, AuthType = authType,
OrganizationId = OrganizationId, OrganizationId = OrganizationId,
ProjectId = ProjectId, ProjectId = ProjectId,
@@ -16,6 +16,7 @@ namespace PSInfisicalAPI.Cmdlets
[Parameter] public string ProjectId { get; set; } [Parameter] public string ProjectId { get; set; }
[Parameter] public string Environment { get; set; } [Parameter] public string Environment { get; set; }
[Parameter] public string SecretPath { get; set; } [Parameter] public string SecretPath { get; set; }
[Parameter] public string ApiVersion { get; set; }
[Parameter] public int? Version { get; set; } [Parameter] public int? Version { get; set; }
[Parameter] public InfisicalSecretType Type { get; set; } = InfisicalSecretType.Shared; [Parameter] public InfisicalSecretType Type { get; set; } = InfisicalSecretType.Shared;
[Parameter] public SwitchParameter ViewSecretValue { get; set; } [Parameter] public SwitchParameter ViewSecretValue { get; set; }
@@ -34,6 +35,7 @@ namespace PSInfisicalAPI.Cmdlets
ProjectId = ProjectId, ProjectId = ProjectId,
Environment = Environment, Environment = Environment,
SecretPath = SecretPath, SecretPath = SecretPath,
ApiVersion = ApiVersion,
Version = Version, Version = Version,
Type = Type.ToString(), Type = Type.ToString(),
ViewSecretValue = ViewSecretValue.IsPresent, ViewSecretValue = ViewSecretValue.IsPresent,
@@ -15,6 +15,7 @@ namespace PSInfisicalAPI.Cmdlets
[Parameter] public string ProjectId { get; set; } [Parameter] public string ProjectId { get; set; }
[Parameter] public string Environment { get; set; } [Parameter] public string Environment { get; set; }
[Parameter] public string SecretPath { get; set; } [Parameter] public string SecretPath { get; set; }
[Parameter] public string ApiVersion { get; set; }
[Parameter] public SwitchParameter Recursive { get; set; } [Parameter] public SwitchParameter Recursive { get; set; }
[Parameter] public SwitchParameter IncludeImports { get; set; } [Parameter] public SwitchParameter IncludeImports { get; set; }
[Parameter] public SwitchParameter IncludePersonalOverrides { get; set; } [Parameter] public SwitchParameter IncludePersonalOverrides { get; set; }
@@ -34,6 +35,7 @@ namespace PSInfisicalAPI.Cmdlets
ProjectId = ProjectId, ProjectId = ProjectId,
Environment = Environment, Environment = Environment,
SecretPath = SecretPath, SecretPath = SecretPath,
ApiVersion = ApiVersion,
Recursive = Recursive.IsPresent, Recursive = Recursive.IsPresent,
IncludeImports = IncludeImports.IsPresent, IncludeImports = IncludeImports.IsPresent,
IncludePersonalOverrides = IncludePersonalOverrides.IsPresent, IncludePersonalOverrides = IncludePersonalOverrides.IsPresent,
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Security; using System.Security;
using PSInfisicalAPI.Models; using PSInfisicalAPI.Models;
@@ -8,6 +9,7 @@ namespace PSInfisicalAPI.Connections
{ {
public Uri BaseUri { get; set; } public Uri BaseUri { get; set; }
public string ApiVersion { get; set; } public string ApiVersion { get; set; }
public string PinnedApiVersion { get; set; }
public InfisicalAuthType AuthType { get; set; } public InfisicalAuthType AuthType { get; set; }
public string OrganizationId { get; set; } public string OrganizationId { get; set; }
public string ProjectId { get; set; } public string ProjectId { get; set; }
@@ -17,6 +19,8 @@ namespace PSInfisicalAPI.Connections
public DateTimeOffset? ExpiresAtUtc { get; set; } public DateTimeOffset? ExpiresAtUtc { get; set; }
public bool IsConnected { get; set; } public bool IsConnected { get; set; }
public Dictionary<string, string> ResolvedEndpointVersions { get; } = new Dictionary<string, string>(StringComparer.Ordinal);
internal SecureString AccessToken { get; set; } internal SecureString AccessToken { get; set; }
public override string ToString() public override string ToString()
@@ -5,11 +5,13 @@ namespace PSInfisicalAPI.Endpoints
{ {
public static class InfisicalEndpointRegistry public static class InfisicalEndpointRegistry
{ {
private static readonly Dictionary<string, InfisicalEndpointDefinition> Definitions = private static readonly Dictionary<string, List<InfisicalEndpointDefinition>> Candidates =
new Dictionary<string, InfisicalEndpointDefinition> new Dictionary<string, List<InfisicalEndpointDefinition>>
{ {
{ {
InfisicalEndpointNames.UniversalAuthLogin, InfisicalEndpointNames.UniversalAuthLogin,
new List<InfisicalEndpointDefinition>
{
new InfisicalEndpointDefinition new InfisicalEndpointDefinition
{ {
Name = InfisicalEndpointNames.UniversalAuthLogin, Name = InfisicalEndpointNames.UniversalAuthLogin,
@@ -21,9 +23,12 @@ namespace PSInfisicalAPI.Endpoints
ContainsSecretMaterialInRequest = true, ContainsSecretMaterialInRequest = true,
ContainsSecretMaterialInResponse = true ContainsSecretMaterialInResponse = true
} }
}
}, },
{ {
InfisicalEndpointNames.ListSecrets, InfisicalEndpointNames.ListSecrets,
new List<InfisicalEndpointDefinition>
{
new InfisicalEndpointDefinition new InfisicalEndpointDefinition
{ {
Name = InfisicalEndpointNames.ListSecrets, Name = InfisicalEndpointNames.ListSecrets,
@@ -34,10 +39,24 @@ namespace PSInfisicalAPI.Endpoints
RequiresAuthorization = true, RequiresAuthorization = true,
ContainsSecretMaterialInRequest = false, ContainsSecretMaterialInRequest = false,
ContainsSecretMaterialInResponse = true ContainsSecretMaterialInResponse = true
},
new InfisicalEndpointDefinition
{
Name = InfisicalEndpointNames.ListSecrets,
Resource = "Secrets",
Version = "v3",
Method = "GET",
Template = "/api/v3/secrets/raw",
RequiresAuthorization = true,
ContainsSecretMaterialInRequest = false,
ContainsSecretMaterialInResponse = true
}
} }
}, },
{ {
InfisicalEndpointNames.RetrieveSecret, InfisicalEndpointNames.RetrieveSecret,
new List<InfisicalEndpointDefinition>
{
new InfisicalEndpointDefinition new InfisicalEndpointDefinition
{ {
Name = InfisicalEndpointNames.RetrieveSecret, Name = InfisicalEndpointNames.RetrieveSecret,
@@ -48,24 +67,26 @@ namespace PSInfisicalAPI.Endpoints
RequiresAuthorization = true, RequiresAuthorization = true,
ContainsSecretMaterialInRequest = false, ContainsSecretMaterialInRequest = false,
ContainsSecretMaterialInResponse = true ContainsSecretMaterialInResponse = true
},
new InfisicalEndpointDefinition
{
Name = InfisicalEndpointNames.RetrieveSecret,
Resource = "Secrets",
Version = "v3",
Method = "GET",
Template = "/api/v3/secrets/raw/{secretName}",
RequiresAuthorization = true,
ContainsSecretMaterialInRequest = false,
ContainsSecretMaterialInResponse = true
}
} }
} }
}; };
public static InfisicalEndpointDefinition Get(string name) public static InfisicalEndpointDefinition Get(string name)
{ {
if (string.IsNullOrEmpty(name)) List<InfisicalEndpointDefinition> list = GetCandidatesInternal(name);
{ return list[0];
throw new InfisicalConfigurationException("Endpoint name must be provided.");
}
InfisicalEndpointDefinition definition;
if (!Definitions.TryGetValue(name, out definition))
{
throw new InfisicalConfigurationException(string.Concat("Unknown endpoint name: ", name));
}
return definition;
} }
public static bool TryGet(string name, out InfisicalEndpointDefinition definition) public static bool TryGet(string name, out InfisicalEndpointDefinition definition)
@@ -76,12 +97,50 @@ namespace PSInfisicalAPI.Endpoints
return false; return false;
} }
return Definitions.TryGetValue(name, out definition); List<InfisicalEndpointDefinition> list;
if (!Candidates.TryGetValue(name, out list) || list == null || list.Count == 0)
{
definition = null;
return false;
}
definition = list[0];
return true;
}
public static IReadOnlyList<InfisicalEndpointDefinition> GetCandidates(string name)
{
return GetCandidatesInternal(name);
} }
public static IEnumerable<InfisicalEndpointDefinition> All() public static IEnumerable<InfisicalEndpointDefinition> All()
{ {
return Definitions.Values; List<InfisicalEndpointDefinition> result = new List<InfisicalEndpointDefinition>();
foreach (List<InfisicalEndpointDefinition> list in Candidates.Values)
{
foreach (InfisicalEndpointDefinition definition in list)
{
result.Add(definition);
}
}
return result;
}
private static List<InfisicalEndpointDefinition> GetCandidatesInternal(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new InfisicalConfigurationException("Endpoint name must be provided.");
}
List<InfisicalEndpointDefinition> list;
if (!Candidates.TryGetValue(name, out list) || list == null || list.Count == 0)
{
throw new InfisicalConfigurationException(string.Concat("Unknown endpoint name: ", name));
}
return list;
} }
} }
} }
+1 -7
View File
@@ -39,13 +39,7 @@ namespace PSInfisicalAPI.Logging
public void Error(string component, string message) public void Error(string component, string message)
{ {
string line = InfisicalLogFormatter.FormatNow(InfisicalLogLevel.Error, component, message); string line = InfisicalLogFormatter.FormatNow(InfisicalLogLevel.Error, component, message);
ErrorRecord record = new ErrorRecord( _cmdlet.WriteWarning(line);
new InvalidOperationException(message ?? string.Empty),
"PSInfisicalAPI.Error",
ErrorCategory.NotSpecified,
component);
record.ErrorDetails = new ErrorDetails(line);
_cmdlet.WriteError(record);
} }
} }
} }
@@ -7,6 +7,7 @@ namespace PSInfisicalAPI.Secrets
public string ProjectId { get; set; } public string ProjectId { get; set; }
public string Environment { get; set; } public string Environment { get; set; }
public string SecretPath { get; set; } public string SecretPath { get; set; }
public string ApiVersion { get; set; }
public bool Recursive { get; set; } public bool Recursive { get; set; }
public bool? IncludeImports { get; set; } public bool? IncludeImports { get; set; }
public bool IncludePersonalOverrides { get; set; } public bool IncludePersonalOverrides { get; set; }
@@ -22,6 +23,7 @@ namespace PSInfisicalAPI.Secrets
public string ProjectId { get; set; } public string ProjectId { get; set; }
public string Environment { get; set; } public string Environment { get; set; }
public string SecretPath { get; set; } public string SecretPath { get; set; }
public string ApiVersion { get; set; }
public int? Version { get; set; } public int? Version { get; set; }
public string Type { get; set; } public string Type { get; set; }
public bool? ViewSecretValue { get; set; } public bool? ViewSecretValue { get; set; }
@@ -32,10 +32,11 @@ namespace PSInfisicalAPI.Secrets
if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (connection == null) { throw new ArgumentNullException(nameof(connection)); }
if (query == null) { throw new ArgumentNullException(nameof(query)); } if (query == null) { throw new ArgumentNullException(nameof(query)); }
InfisicalEndpointDefinition definition = InfisicalEndpointRegistry.Get(InfisicalEndpointNames.ListSecrets); string resolvedProjectId = FirstNonEmpty(query.ProjectId, connection.ProjectId);
List<KeyValuePair<string, string>> queryParameters = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> queryParameters = new List<KeyValuePair<string, string>>();
AddIfNotNull(queryParameters, "projectId", FirstNonEmpty(query.ProjectId, connection.ProjectId)); AddIfNotNull(queryParameters, "workspaceId", resolvedProjectId);
AddIfNotNull(queryParameters, "projectId", resolvedProjectId);
AddIfNotNull(queryParameters, "environment", FirstNonEmpty(query.Environment, connection.Environment)); AddIfNotNull(queryParameters, "environment", FirstNonEmpty(query.Environment, connection.Environment));
AddIfNotNull(queryParameters, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/")); AddIfNotNull(queryParameters, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/"));
queryParameters.Add(new KeyValuePair<string, string>("recursive", query.Recursive ? "true" : "false")); queryParameters.Add(new KeyValuePair<string, string>("recursive", query.Recursive ? "true" : "false"));
@@ -60,13 +61,18 @@ namespace PSInfisicalAPI.Secrets
} }
} }
Uri uri = InfisicalUriBuilder.Build(connection.BaseUri, definition, null, queryParameters);
InfisicalHttpResponse response = ExecuteAuthorized(connection, definition, "RetrieveSecrets", uri, null);
try try
{ {
_logger.Information(Component, "Attempting to retrieve Infisical secrets. Please Wait..."); _logger.Information(Component, "Attempting to retrieve Infisical secrets. Please Wait...");
EnsureSuccess(response, definition);
InfisicalHttpResponse response = SendWithVersionFallback(
connection,
InfisicalEndpointNames.ListSecrets,
query.ApiVersion,
"RetrieveSecrets",
null,
queryParameters,
null);
InfisicalSecretListResponseDto dto = _serializer.Deserialize<InfisicalSecretListResponseDto>(response.Body); InfisicalSecretListResponseDto dto = _serializer.Deserialize<InfisicalSecretListResponseDto>(response.Body);
response.Clear(); response.Clear();
@@ -88,12 +94,13 @@ namespace PSInfisicalAPI.Secrets
if (query == null) { throw new ArgumentNullException(nameof(query)); } if (query == null) { throw new ArgumentNullException(nameof(query)); }
if (string.IsNullOrEmpty(query.SecretName)) { throw new InfisicalConfigurationException("SecretName is required."); } if (string.IsNullOrEmpty(query.SecretName)) { throw new InfisicalConfigurationException("SecretName is required."); }
InfisicalEndpointDefinition definition = InfisicalEndpointRegistry.Get(InfisicalEndpointNames.RetrieveSecret);
Dictionary<string, string> pathParameters = new Dictionary<string, string> { { "secretName", query.SecretName } }; Dictionary<string, string> pathParameters = new Dictionary<string, string> { { "secretName", query.SecretName } };
string resolvedProjectId = FirstNonEmpty(query.ProjectId, connection.ProjectId);
List<KeyValuePair<string, string>> queryParameters = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> queryParameters = new List<KeyValuePair<string, string>>();
AddIfNotNull(queryParameters, "projectId", FirstNonEmpty(query.ProjectId, connection.ProjectId)); AddIfNotNull(queryParameters, "workspaceId", resolvedProjectId);
AddIfNotNull(queryParameters, "projectId", resolvedProjectId);
AddIfNotNull(queryParameters, "environment", FirstNonEmpty(query.Environment, connection.Environment)); AddIfNotNull(queryParameters, "environment", FirstNonEmpty(query.Environment, connection.Environment));
AddIfNotNull(queryParameters, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/")); AddIfNotNull(queryParameters, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/"));
AddIfNotNull(queryParameters, "type", string.IsNullOrEmpty(query.Type) ? "shared" : query.Type.ToLowerInvariant()); AddIfNotNull(queryParameters, "type", string.IsNullOrEmpty(query.Type) ? "shared" : query.Type.ToLowerInvariant());
@@ -102,13 +109,18 @@ namespace PSInfisicalAPI.Secrets
if (query.ExpandSecretReferences.HasValue) { queryParameters.Add(new KeyValuePair<string, string>("expandSecretReferences", query.ExpandSecretReferences.Value ? "true" : "false")); } if (query.ExpandSecretReferences.HasValue) { queryParameters.Add(new KeyValuePair<string, string>("expandSecretReferences", query.ExpandSecretReferences.Value ? "true" : "false")); }
if (query.IncludeImports.HasValue) { queryParameters.Add(new KeyValuePair<string, string>("includeImports", query.IncludeImports.Value ? "true" : "false")); } if (query.IncludeImports.HasValue) { queryParameters.Add(new KeyValuePair<string, string>("includeImports", query.IncludeImports.Value ? "true" : "false")); }
Uri uri = InfisicalUriBuilder.Build(connection.BaseUri, definition, pathParameters, queryParameters);
InfisicalHttpResponse response = ExecuteAuthorized(connection, definition, "RetrieveSecret", uri, null);
try try
{ {
_logger.Information(Component, string.Concat("Attempting to retrieve Infisical secret '", query.SecretName, "'. Please Wait...")); _logger.Information(Component, string.Concat("Attempting to retrieve Infisical secret '", query.SecretName, "'. Please Wait..."));
EnsureSuccess(response, definition);
InfisicalHttpResponse response = SendWithVersionFallback(
connection,
InfisicalEndpointNames.RetrieveSecret,
query.ApiVersion,
"RetrieveSecret",
pathParameters,
queryParameters,
null);
InfisicalSecretSingleResponseDto dto = _serializer.Deserialize<InfisicalSecretSingleResponseDto>(response.Body); InfisicalSecretSingleResponseDto dto = _serializer.Deserialize<InfisicalSecretSingleResponseDto>(response.Body);
response.Clear(); response.Clear();
@@ -124,6 +136,160 @@ namespace PSInfisicalAPI.Secrets
} }
} }
private InfisicalHttpResponse SendWithVersionFallback(
InfisicalConnection connection,
string endpointName,
string perCallApiVersion,
string operationName,
Dictionary<string, string> pathParameters,
List<KeyValuePair<string, string>> queryParameters,
string body)
{
IReadOnlyList<InfisicalEndpointDefinition> allCandidates = InfisicalEndpointRegistry.GetCandidates(endpointName);
string pinned = FirstNonEmpty(perCallApiVersion, connection.PinnedApiVersion);
string cached;
connection.ResolvedEndpointVersions.TryGetValue(endpointName, out cached);
List<InfisicalEndpointDefinition> candidates = OrderCandidates(allCandidates, pinned, cached);
if (candidates.Count == 0)
{
throw new InfisicalConfigurationException(string.Concat(
"No matching endpoint candidate for '", endpointName,
"' with ApiVersion='", pinned ?? string.Empty, "'."));
}
InfisicalApiException lastException = null;
for (int index = 0; index < candidates.Count; index++)
{
InfisicalEndpointDefinition definition = candidates[index];
Uri uri = InfisicalUriBuilder.Build(connection.BaseUri, definition, pathParameters, queryParameters);
InfisicalHttpResponse response = ExecuteAuthorized(connection, definition, operationName, uri, body);
if (response.StatusCode >= 200 && response.StatusCode < 300)
{
connection.ResolvedEndpointVersions[endpointName] = definition.Version;
return response;
}
InfisicalApiException exception = BuildApiException(response, definition);
response.Clear();
bool hasMoreCandidates = (index + 1) < candidates.Count;
bool pinnedHere = !string.IsNullOrEmpty(pinned);
if (!pinnedHere && hasMoreCandidates && IsVersionMismatch(exception))
{
_logger.Warning(Component, string.Concat(
"Endpoint '", endpointName, "' version '", definition.Version,
"' rejected by server (", exception.StatusCode.ToString(CultureInfo.InvariantCulture),
"); falling back to next candidate."));
lastException = exception;
continue;
}
throw exception;
}
throw lastException ?? new InfisicalApiException(string.Concat(
"All API version candidates exhausted for '", endpointName, "'."));
}
private static List<InfisicalEndpointDefinition> OrderCandidates(
IReadOnlyList<InfisicalEndpointDefinition> allCandidates,
string pinned,
string cached)
{
List<InfisicalEndpointDefinition> ordered = new List<InfisicalEndpointDefinition>();
if (!string.IsNullOrEmpty(pinned))
{
foreach (InfisicalEndpointDefinition candidate in allCandidates)
{
if (string.Equals(candidate.Version, pinned, StringComparison.OrdinalIgnoreCase))
{
ordered.Add(candidate);
}
}
return ordered;
}
if (!string.IsNullOrEmpty(cached))
{
foreach (InfisicalEndpointDefinition candidate in allCandidates)
{
if (string.Equals(candidate.Version, cached, StringComparison.OrdinalIgnoreCase))
{
ordered.Add(candidate);
break;
}
}
foreach (InfisicalEndpointDefinition candidate in allCandidates)
{
if (!string.Equals(candidate.Version, cached, StringComparison.OrdinalIgnoreCase))
{
ordered.Add(candidate);
}
}
return ordered;
}
foreach (InfisicalEndpointDefinition candidate in allCandidates)
{
ordered.Add(candidate);
}
return ordered;
}
private static bool IsVersionMismatch(InfisicalApiException exception)
{
string body = exception.SanitizedBody;
bool hasInfisicalErrorEnvelope = !string.IsNullOrEmpty(body)
&& body.IndexOf("\"reqId\"", StringComparison.OrdinalIgnoreCase) >= 0
&& body.IndexOf("\"error\"", StringComparison.OrdinalIgnoreCase) >= 0;
if (exception.StatusCode == 405)
{
return true;
}
if (exception.StatusCode == 404 && !hasInfisicalErrorEnvelope)
{
return true;
}
if (exception.StatusCode == 400 && !string.IsNullOrEmpty(body))
{
if (body.IndexOf("projectSlug", StringComparison.OrdinalIgnoreCase) >= 0 ||
body.IndexOf("workspaceId", StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
}
return false;
}
private static InfisicalApiException BuildApiException(InfisicalHttpResponse response, InfisicalEndpointDefinition definition)
{
InfisicalApiException exception = new InfisicalApiException(string.Concat(
"Infisical API returned ",
response.StatusCode.ToString(CultureInfo.InvariantCulture),
" (", response.ReasonPhrase ?? string.Empty, ")."));
exception.StatusCode = response.StatusCode;
exception.ReasonPhrase = response.ReasonPhrase;
exception.EndpointName = definition.Name;
exception.RequestMethod = definition.Method;
exception.SanitizedBody = response.Body;
return exception;
}
private InfisicalHttpResponse ExecuteAuthorized(InfisicalConnection connection, InfisicalEndpointDefinition definition, string operationName, Uri uri, string body) private InfisicalHttpResponse ExecuteAuthorized(InfisicalConnection connection, InfisicalEndpointDefinition definition, string operationName, Uri uri, string body)
{ {
Dictionary<string, string> headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); Dictionary<string, string> headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -157,23 +323,6 @@ namespace PSInfisicalAPI.Secrets
return _httpClient.Send(request); return _httpClient.Send(request);
} }
private static void EnsureSuccess(InfisicalHttpResponse response, InfisicalEndpointDefinition definition)
{
if (response.StatusCode >= 200 && response.StatusCode < 300)
{
return;
}
InfisicalApiException exception = new InfisicalApiException(string.Concat("Infisical API returned ", response.StatusCode.ToString(CultureInfo.InvariantCulture), " (", response.ReasonPhrase ?? string.Empty, ")."));
exception.StatusCode = response.StatusCode;
exception.ReasonPhrase = response.ReasonPhrase;
exception.EndpointName = definition.Name;
exception.RequestMethod = definition.Method;
exception.SanitizedBody = definition.ContainsSecretMaterialInResponse ? "[REDACTED]" : response.Body;
response.Clear();
throw exception;
}
private static void AddIfNotNull(List<KeyValuePair<string, string>> list, string key, string value) private static void AddIfNotNull(List<KeyValuePair<string, string>> list, string key, string value)
{ {
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))