From 09c577ebd0fd570d42a0e7ff844dc95064f0c938 Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Tue, 2 Jun 2026 21:01:37 -0400 Subject: [PATCH] Add lazy API version negotiation (v4 -> v3 fallback) with -ApiVersion override - Endpoint registry now stores ordered candidate lists per logical operation; Get/TryGet preserve prior behavior, new GetCandidates(name) exposes the ladder. Added v3 fallbacks (/api/v3/secrets/raw and /api/v3/secrets/raw/{secretName}) after v4. - InfisicalConnection gains PinnedApiVersion and a ResolvedEndpointVersions cache so the chosen version sticks for the session. - InfisicalSecretsClient.SendWithVersionFallback walks candidates in pin -> cached -> registry order, falls back on routing-style failures (404 without an Infisical JSON envelope, 405, or 400 mentioning workspaceId/projectSlug) when no version is pinned, and surfaces real application errors immediately. - Get-InfisicalSecret(s) expose -ApiVersion; Connect-Infisical sets PinnedApiVersion only when -ApiVersion is explicitly bound on the command line (env-var/default values do not pin). - Logger.Error routes via WriteWarning to avoid premature terminating errors that masked InfisicalApiException details; EnsureSuccess no longer redacts non-2xx bodies so server error envelopes are visible. - InfisicalSecretsClient sends both projectId and workspaceId so it works against both new and legacy server-side validators. --- CHANGELOG.md | 30 +++ Module/PSInfisicalAPI/PSInfisicalAPI.psd1 | 4 +- Module/PSInfisicalAPI/bin/PSInfisicalAPI.dll | Bin 70656 -> 73728 bytes .../Cmdlets/ConnectInfisicalCmdlet.cs | 3 + .../Cmdlets/GetInfisicalSecretCmdlet.cs | 2 + .../Cmdlets/GetInfisicalSecretsCmdlet.cs | 2 + .../Connections/InfisicalConnection.cs | 4 + .../Endpoints/InfisicalEndpointRegistry.cs | 145 ++++++++---- src/PSInfisicalAPI/Logging/PSCmdletLogger.cs | 8 +- .../Secrets/InfisicalSecretQuery.cs | 2 + .../Secrets/InfisicalSecretsClient.cs | 209 +++++++++++++++--- 11 files changed, 327 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31e359d..187bd42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,36 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos ## 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 - Build produced from commit c86676010532. diff --git a/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 b/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 index 706ba22..e313a14 100644 --- a/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 +++ b/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'PSInfisicalAPI.psm1' - ModuleVersion = '2026.06.03.0032' + ModuleVersion = '2026.06.03.0057' GUID = 'b8a2f3d4-7c51-4d2f-9e6a-1f0c8b3d4e51' Author = 'Grace Solutions' CompanyName = 'Grace Solutions' @@ -27,7 +27,7 @@ LicenseUri = 'https://www.gnu.org/licenses/agpl-3.0.html' ProjectUri = 'https://prod.git.gracesolution.info/gsadmin/PSInfisicalAPI' ReleaseNotes = 'See CHANGELOG.md in the project repository for release history.' - CommitHash = 'c86676010532' + CommitHash = '7e5209190ac2' } } } \ No newline at end of file diff --git a/Module/PSInfisicalAPI/bin/PSInfisicalAPI.dll b/Module/PSInfisicalAPI/bin/PSInfisicalAPI.dll index acef9b69d20ec9eed9854e6e99de127d116d2ff9..6f0a94e1d413daed75e597f9aa1f194f7f2c6c2a 100644 GIT binary patch literal 73728 zcmd442Yggj{x<$ScV_OiBxF)19THNQB$H4CqzMUN0aQQ~QBe~V0Y$FNfTAH7L{StA zt76wg*Mhy5wFNu26+4QU*w(r>beC1(|9rpaOfmsWoh-l1UV>;#t7*94DJE?iyFPTID!l7P(FiF3m{G?TV&bO-$msFgbaEs)7L) z)gmsKL$1}p0_`P|57)q!++Ym0le|s=WTX(_jUS@OKFzK|7-@5&tSrg}RRsfFbTZ;X z6^C4rB6yAlGH81?#|r;06EkFWV9P^$X zUCsYN+IACTkMt~iyIle=aWrlqf)=T+sOoJsfw-&sTCQdxFrY59K?n>eh&Bj;0jX(& z5Ew99XoCOZrUIuDJ~2^ z?H~j`G5oYaNRm$sN$ns6J~0ZlK}eEMj7RMt1U}L4wLu6B7=PLzBq?a`goBWTgXv!i zqm%!v8Y`PQFO zXIF9BGmthaMyEYSr;W*n(`I!(hNPq&McQ>H?R#{*sAAi>Q*%_2?c5DWq``p)y=3$7 z#uB3khY%Qw69yqLV9n7!gusAarVT=1z*?aVLSR6*(*_|hlqU>AU_fWoK7_!4l|mbY zz<}PV4MJe3Oc;bDMk^f9leAAEFkmgw1|cv+69yqLpk=fVAu!Y?3_@T)dubm+U_fuz z1|cw@6}3SK4Cw#bAOr@qtu_crRK3^F*w|oyS&D(ST-B98BOT6 za>8+pHoF-k!i_zOk2Y9DSQH0q5x5+-5Y8`j?sdnCd} zv%RtN5oVW&kKQTbCne&9^^YTN+$rog5;kG|mgAlsVI`j%L`AeVKZ_u|5cy;f?GE8QTLq zG64*RiMU97@H+{-=A|uZ8TR&YI;J{3^^(=Zy(+dRLdB*5oJWzC<%&HE?sg7^h z<;{w;KxF!?ChmD5pYs)@V`K8k^h13Q74p}(vZ}oyzcUhwQ?!$#|1A-HCU(yi$u5Vu zknof6zCAyr*8!|>7X4EV?`Nfv{0+61+-c=v3c_C6M>n9)r~H>b?{?;LF0jT2qQTfT zNFshX?~&vC!%`l51qSWKIRJ)0cLzTn!FC!VK^Y<`J{cljsZyT|kp%BKMCK=A*lCFP zVm*h*f`q@{86v*e$CArMiGtLmx*ZnIfygpO%QtYA+_;?>%&8eJUcWI=e6e37WWqWH z)=YPXTUN&iCV@cmAUhdhGd&p|J<4i)G2NlN%zxaYm+Tx`52Y^iABR3|=g@kDcbWev zbdTN}bSD}#b~LDrfkba!A#NujsTfn+XL>XGr}So9_hv8mW^c&Wz1gdKv)92evt=KX z+-KVmk3^s8+o?DIi(O1__EjbB1+8<=(fv1bfR`RtM5*Y%?g&b2clAAwbh}f!=GCCf zSq0(Fu$+U?WEHm87g>(Xr1~Aq!hxC*1!lI5?S*{_0=s#hJzIF5R~C+g;qUtL{McP= zj9^X<=uwcB=?-Ulh6Rujf5_uZheM|Aa^grXWT$!3?8uMYFkZ_A=?;0*ypc26;KNwQ zI$;;TfMGePETN)^r+?UF7Zr#z0GnrzK*(1W@`dck3J%;gQFwA@=pt-)X9m17M#I|` z{vQe)9X%=JkDLMT(K$)=U6d&414$))Nte{5$Hn|uECrZ?Mj!{7!Hi&ckH5aWFcz{C z)!;mVBtm{nz^;)0v=DNX=?QssuEu<^eaDUvR^D($>`;VoOZ7>QitmefPviUfUr_;= zoI-JI$^rp>S6?&A;`I#M-y*MbI7o_5s={SF0OsMdnEIamix7_YV_o!Ckpe0RPd?|X|9=Ibg@)DLFZ%w!5BDO?K)Wvq}mF~Fu z_p)UsPoyL_7QDYcANj)K80s2VpCS;(l_h;1M>fg5DL0nwW!F5*`2u~Z$8alP7d_m# z!{APl2aPjQbN24+#oXo0#Kjq>`7Gwx6|sL=Ua@78`z@}sr;)c1_qV=sz7fIhCJ;Xg z(EJM)WV?wmR)Tb6{Q)xg+|F@`AX?>e&cziw!l`hHPXs?rn{X6T%10sC_5>n+q)8;^O=HWoUC`A=HZ^4af=hF|pgwRrP3Vge72ljLVH(&!=z-db-A2O7Fzl@EaU3 zTIFs-`DASNQrpA1n53Lph=o@OZ7=ZhYLF^^ihO#cR*i^Yqa8q>jI<|Li(QrYUv2y; zIJC^>a-7`bt}O>K>BG(D;XaLek&6{p9=!Ke;>m zK~{E-CvRszNO5OB`MdRVT6d8Wx14j4Tg%-%&y=YEdzZP`duO9ee7{-VRcx2@9?F*$ znS;cz-5$aY2k43BO*rVm>vuUUDyqFM=WQld6DJT`2;W^(?%5Es4|*3qct5jF40$?* zT;A17L*B<`nPQ#C;8QzCkki1Tez;A*39!R4=#*2naE^yFdeB=4>zn{?>&X%ucF+&l zdLmP+iA!Akxr^vl zWHDS_4qKd)K~v$gqs!T+1#&6#_$eF{?gNi^mN0Wp1&hn_`*(m8+i8NsB6K&E>G9zX^9@)L$b cXv$@QYM?j_oW(Xl@6uUq+PP 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 literal 70656 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⩔U=>v%&?bXCUC)FK42ishh`1|Jc8j6ZU<|^kxkDz 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 OAGE^%FZX|w1pYTeQH<;W diff --git a/src/PSInfisicalAPI/Cmdlets/ConnectInfisicalCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/ConnectInfisicalCmdlet.cs index 478ee7b..f5e6bdd 100644 --- a/src/PSInfisicalAPI/Cmdlets/ConnectInfisicalCmdlet.cs +++ b/src/PSInfisicalAPI/Cmdlets/ConnectInfisicalCmdlet.cs @@ -89,10 +89,13 @@ namespace PSInfisicalAPI.Cmdlets throw new InfisicalAuthenticationException("Authentication did not produce an access token."); } + bool apiVersionExplicitlyBound = MyInvocation.BoundParameters.ContainsKey("ApiVersion"); + InfisicalConnection connection = new InfisicalConnection { BaseUri = BaseUri, ApiVersion = ApiVersion, + PinnedApiVersion = apiVersionExplicitlyBound ? ApiVersion : null, AuthType = authType, OrganizationId = OrganizationId, ProjectId = ProjectId, diff --git a/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretCmdlet.cs index 6bb770a..6db8d78 100644 --- a/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretCmdlet.cs +++ b/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretCmdlet.cs @@ -16,6 +16,7 @@ namespace PSInfisicalAPI.Cmdlets [Parameter] public string ProjectId { get; set; } [Parameter] public string Environment { get; set; } [Parameter] public string SecretPath { get; set; } + [Parameter] public string ApiVersion { get; set; } [Parameter] public int? Version { get; set; } [Parameter] public InfisicalSecretType Type { get; set; } = InfisicalSecretType.Shared; [Parameter] public SwitchParameter ViewSecretValue { get; set; } @@ -34,6 +35,7 @@ namespace PSInfisicalAPI.Cmdlets ProjectId = ProjectId, Environment = Environment, SecretPath = SecretPath, + ApiVersion = ApiVersion, Version = Version, Type = Type.ToString(), ViewSecretValue = ViewSecretValue.IsPresent, diff --git a/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretsCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretsCmdlet.cs index 9695aa1..938b5f4 100644 --- a/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretsCmdlet.cs +++ b/src/PSInfisicalAPI/Cmdlets/GetInfisicalSecretsCmdlet.cs @@ -15,6 +15,7 @@ namespace PSInfisicalAPI.Cmdlets [Parameter] public string ProjectId { get; set; } [Parameter] public string Environment { get; set; } [Parameter] public string SecretPath { get; set; } + [Parameter] public string ApiVersion { get; set; } [Parameter] public SwitchParameter Recursive { get; set; } [Parameter] public SwitchParameter IncludeImports { get; set; } [Parameter] public SwitchParameter IncludePersonalOverrides { get; set; } @@ -34,6 +35,7 @@ namespace PSInfisicalAPI.Cmdlets ProjectId = ProjectId, Environment = Environment, SecretPath = SecretPath, + ApiVersion = ApiVersion, Recursive = Recursive.IsPresent, IncludeImports = IncludeImports.IsPresent, IncludePersonalOverrides = IncludePersonalOverrides.IsPresent, diff --git a/src/PSInfisicalAPI/Connections/InfisicalConnection.cs b/src/PSInfisicalAPI/Connections/InfisicalConnection.cs index 7fcfad8..ef4d04c 100644 --- a/src/PSInfisicalAPI/Connections/InfisicalConnection.cs +++ b/src/PSInfisicalAPI/Connections/InfisicalConnection.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Security; using PSInfisicalAPI.Models; @@ -8,6 +9,7 @@ namespace PSInfisicalAPI.Connections { public Uri BaseUri { get; set; } public string ApiVersion { get; set; } + public string PinnedApiVersion { get; set; } public InfisicalAuthType AuthType { get; set; } public string OrganizationId { get; set; } public string ProjectId { get; set; } @@ -17,6 +19,8 @@ namespace PSInfisicalAPI.Connections public DateTimeOffset? ExpiresAtUtc { get; set; } public bool IsConnected { get; set; } + public Dictionary ResolvedEndpointVersions { get; } = new Dictionary(StringComparer.Ordinal); + internal SecureString AccessToken { get; set; } public override string ToString() diff --git a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs index 9e3dfe7..997d14f 100644 --- a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs +++ b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs @@ -5,67 +5,88 @@ namespace PSInfisicalAPI.Endpoints { public static class InfisicalEndpointRegistry { - private static readonly Dictionary Definitions = - new Dictionary + private static readonly Dictionary> Candidates = + new Dictionary> { { InfisicalEndpointNames.UniversalAuthLogin, - new InfisicalEndpointDefinition + new List { - Name = InfisicalEndpointNames.UniversalAuthLogin, - Resource = "Authentication", - Version = "v1", - Method = "POST", - Template = "/api/v1/auth/universal-auth/login", - RequiresAuthorization = false, - ContainsSecretMaterialInRequest = true, - ContainsSecretMaterialInResponse = true + new InfisicalEndpointDefinition + { + Name = InfisicalEndpointNames.UniversalAuthLogin, + Resource = "Authentication", + Version = "v1", + Method = "POST", + Template = "/api/v1/auth/universal-auth/login", + RequiresAuthorization = false, + ContainsSecretMaterialInRequest = true, + ContainsSecretMaterialInResponse = true + } } }, { InfisicalEndpointNames.ListSecrets, - new InfisicalEndpointDefinition + new List { - Name = InfisicalEndpointNames.ListSecrets, - Resource = "Secrets", - Version = "v4", - Method = "GET", - Template = "/api/v4/secrets", - RequiresAuthorization = true, - ContainsSecretMaterialInRequest = false, - ContainsSecretMaterialInResponse = true + new InfisicalEndpointDefinition + { + Name = InfisicalEndpointNames.ListSecrets, + Resource = "Secrets", + Version = "v4", + Method = "GET", + Template = "/api/v4/secrets", + RequiresAuthorization = true, + ContainsSecretMaterialInRequest = false, + 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, - new InfisicalEndpointDefinition + new List { - Name = InfisicalEndpointNames.RetrieveSecret, - Resource = "Secrets", - Version = "v4", - Method = "GET", - Template = "/api/v4/secrets/{secretName}", - RequiresAuthorization = true, - ContainsSecretMaterialInRequest = false, - ContainsSecretMaterialInResponse = true + new InfisicalEndpointDefinition + { + Name = InfisicalEndpointNames.RetrieveSecret, + Resource = "Secrets", + Version = "v4", + Method = "GET", + Template = "/api/v4/secrets/{secretName}", + RequiresAuthorization = true, + ContainsSecretMaterialInRequest = false, + 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) { - if (string.IsNullOrEmpty(name)) - { - 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; + List list = GetCandidatesInternal(name); + return list[0]; } public static bool TryGet(string name, out InfisicalEndpointDefinition definition) @@ -76,12 +97,50 @@ namespace PSInfisicalAPI.Endpoints return false; } - return Definitions.TryGetValue(name, out definition); + List list; + if (!Candidates.TryGetValue(name, out list) || list == null || list.Count == 0) + { + definition = null; + return false; + } + + definition = list[0]; + return true; + } + + public static IReadOnlyList GetCandidates(string name) + { + return GetCandidatesInternal(name); } public static IEnumerable All() { - return Definitions.Values; + List result = new List(); + foreach (List list in Candidates.Values) + { + foreach (InfisicalEndpointDefinition definition in list) + { + result.Add(definition); + } + } + + return result; + } + + private static List GetCandidatesInternal(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new InfisicalConfigurationException("Endpoint name must be provided."); + } + + List list; + if (!Candidates.TryGetValue(name, out list) || list == null || list.Count == 0) + { + throw new InfisicalConfigurationException(string.Concat("Unknown endpoint name: ", name)); + } + + return list; } } } diff --git a/src/PSInfisicalAPI/Logging/PSCmdletLogger.cs b/src/PSInfisicalAPI/Logging/PSCmdletLogger.cs index 69b6d30..178d189 100644 --- a/src/PSInfisicalAPI/Logging/PSCmdletLogger.cs +++ b/src/PSInfisicalAPI/Logging/PSCmdletLogger.cs @@ -39,13 +39,7 @@ namespace PSInfisicalAPI.Logging public void Error(string component, string message) { string line = InfisicalLogFormatter.FormatNow(InfisicalLogLevel.Error, component, message); - ErrorRecord record = new ErrorRecord( - new InvalidOperationException(message ?? string.Empty), - "PSInfisicalAPI.Error", - ErrorCategory.NotSpecified, - component); - record.ErrorDetails = new ErrorDetails(line); - _cmdlet.WriteError(record); + _cmdlet.WriteWarning(line); } } } diff --git a/src/PSInfisicalAPI/Secrets/InfisicalSecretQuery.cs b/src/PSInfisicalAPI/Secrets/InfisicalSecretQuery.cs index fd3561a..8ede056 100644 --- a/src/PSInfisicalAPI/Secrets/InfisicalSecretQuery.cs +++ b/src/PSInfisicalAPI/Secrets/InfisicalSecretQuery.cs @@ -7,6 +7,7 @@ namespace PSInfisicalAPI.Secrets public string ProjectId { get; set; } public string Environment { get; set; } public string SecretPath { get; set; } + public string ApiVersion { get; set; } public bool Recursive { get; set; } public bool? IncludeImports { get; set; } public bool IncludePersonalOverrides { get; set; } @@ -22,6 +23,7 @@ namespace PSInfisicalAPI.Secrets public string ProjectId { get; set; } public string Environment { get; set; } public string SecretPath { get; set; } + public string ApiVersion { get; set; } public int? Version { get; set; } public string Type { get; set; } public bool? ViewSecretValue { get; set; } diff --git a/src/PSInfisicalAPI/Secrets/InfisicalSecretsClient.cs b/src/PSInfisicalAPI/Secrets/InfisicalSecretsClient.cs index 8013cc5..aa9d7a7 100644 --- a/src/PSInfisicalAPI/Secrets/InfisicalSecretsClient.cs +++ b/src/PSInfisicalAPI/Secrets/InfisicalSecretsClient.cs @@ -32,10 +32,11 @@ namespace PSInfisicalAPI.Secrets if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (query == null) { throw new ArgumentNullException(nameof(query)); } - InfisicalEndpointDefinition definition = InfisicalEndpointRegistry.Get(InfisicalEndpointNames.ListSecrets); + string resolvedProjectId = FirstNonEmpty(query.ProjectId, connection.ProjectId); List> queryParameters = new List>(); - 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, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/")); queryParameters.Add(new KeyValuePair("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 { _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(response.Body); response.Clear(); @@ -88,12 +94,13 @@ namespace PSInfisicalAPI.Secrets if (query == null) { throw new ArgumentNullException(nameof(query)); } if (string.IsNullOrEmpty(query.SecretName)) { throw new InfisicalConfigurationException("SecretName is required."); } - InfisicalEndpointDefinition definition = InfisicalEndpointRegistry.Get(InfisicalEndpointNames.RetrieveSecret); - Dictionary pathParameters = new Dictionary { { "secretName", query.SecretName } }; + string resolvedProjectId = FirstNonEmpty(query.ProjectId, connection.ProjectId); + List> queryParameters = new List>(); - 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, "secretPath", FirstNonEmpty(query.SecretPath, connection.DefaultSecretPath, "/")); 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("expandSecretReferences", query.ExpandSecretReferences.Value ? "true" : "false")); } if (query.IncludeImports.HasValue) { queryParameters.Add(new KeyValuePair("includeImports", query.IncludeImports.Value ? "true" : "false")); } - Uri uri = InfisicalUriBuilder.Build(connection.BaseUri, definition, pathParameters, queryParameters); - InfisicalHttpResponse response = ExecuteAuthorized(connection, definition, "RetrieveSecret", uri, null); - try { _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(response.Body); response.Clear(); @@ -124,6 +136,160 @@ namespace PSInfisicalAPI.Secrets } } + private InfisicalHttpResponse SendWithVersionFallback( + InfisicalConnection connection, + string endpointName, + string perCallApiVersion, + string operationName, + Dictionary pathParameters, + List> queryParameters, + string body) + { + IReadOnlyList allCandidates = InfisicalEndpointRegistry.GetCandidates(endpointName); + + string pinned = FirstNonEmpty(perCallApiVersion, connection.PinnedApiVersion); + string cached; + connection.ResolvedEndpointVersions.TryGetValue(endpointName, out cached); + + List 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 OrderCandidates( + IReadOnlyList allCandidates, + string pinned, + string cached) + { + List ordered = new List(); + + 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) { Dictionary headers = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -157,23 +323,6 @@ namespace PSInfisicalAPI.Secrets 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> list, string key, string value) { if (!string.IsNullOrEmpty(value))