From 880ff8d49115f78801a7e09160fb1dee6c4414ba Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Thu, 4 Jun 2026 22:13:48 -0400 Subject: [PATCH] refactor!(certificates): remove Search-InfisicalCertificate (use Get-InfisicalCertificate) Search-InfisicalCertificate was a 1:1 duplicate of Get-InfisicalCertificate's List parameter set after the recent filter-surface expansion (bdec5aa). Both cmdlets exposed the same ~27 server-side filters and both hit the same POST /api/v1/projects/{projectId}/certificates/search endpoint. Keeping two PowerShell cmdlets for the same operation added discovery noise without benefit. REMOVED - src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs (cmdlet source, ~140 lines). - 'Search-InfisicalCertificate' from CmdletsToExport in the source manifest (Module/PSInfisicalAPI/PSInfisicalAPI.psd1) and from the two generators in build.ps1 (Write-Manifest cmdlet list + Test-ModuleImports $expectedCmds). - block for Search-InfisicalCertificate from the help XML (Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml). - README PKI table row for Search-InfisicalCertificate. - "For advanced filtering ... use Search-InfisicalCertificate instead" sentence from the Get-InfisicalCertificate Notes block (no longer true). RETAINED (internal) - InfisicalPkiClient.SearchCertificates, InfisicalCertificateSearchQuery, InfisicalEndpointNames.SearchCertificates and the endpoint registry entry. Get-InfisicalCertificate and Request-InfisicalCertificate still call them to walk the search endpoint. MIGRATION # Before Search-InfisicalCertificate -ProjectId $p -Search 'web' -Status 'active' # After Get-InfisicalCertificate -ProjectId $p -Search 'web' -Status 'active' Parameter names, defaults, and paging behavior are identical. TESTS - 216/216 passing (one unrelated time-based test in CsrAndRequestCmdletTests was flaky on the run; passes deterministically when invoked in isolation). --- Module/PSInfisicalAPI/PSInfisicalAPI.psd1 | 1 - .../en-US/PSInfisicalAPI.dll-Help.xml | 46 +----- README.md | 1 - build.ps1 | 3 +- .../SearchInfisicalCertificateCmdlet.cs | 140 ------------------ 5 files changed, 2 insertions(+), 189 deletions(-) delete mode 100644 src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs diff --git a/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 b/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 index 5002b4e..10a9d8d 100644 --- a/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 +++ b/Module/PSInfisicalAPI/PSInfisicalAPI.psd1 @@ -40,7 +40,6 @@ 'Get-InfisicalCertificateProfile', 'Get-InfisicalCertificatePolicy', 'Get-InfisicalCertificate', - 'Search-InfisicalCertificate', 'Request-InfisicalCertificate', 'ConvertTo-InfisicalCertificate', 'Install-InfisicalCertificate', diff --git a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml index 5d82499..f67e148 100644 --- a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml +++ b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml @@ -1060,7 +1060,7 @@ $GetInfisicalCertificateAuthorityResult = Get-InfisicalCertificateAuthority @Get Notes - For advanced filtering (validity window, key algorithm, extended key usage, etc.) use Search-InfisicalCertificate instead. Single mode returns metadata only; to obtain certificate and chain PEM material use ConvertTo-InfisicalCertificate or Export-InfisicalCertificate. Accepts pipeline input by property name on -SerialNumber. + Single mode returns metadata only; to obtain certificate and chain PEM material use ConvertTo-InfisicalCertificate or Export-InfisicalCertificate. Accepts pipeline input by property name on -SerialNumber. @@ -1219,50 +1219,6 @@ $GetInfisicalCertificatePolicyResult = Get-InfisicalCertificatePolicy @GetInfisi - - - Search-InfisicalCertificate - Searches Infisical certificates with advanced filters and automatic paging. - Search - InfisicalCertificate - - - Performs a server-side search across certificates with filters for friendly name, common name, free-text search, status, CA/profile/application/enrollment scope, key/signature algorithm, source, and validity window (-NotBeforeFrom/-NotBeforeTo/-NotAfterFrom/-NotAfterTo). Results are paged automatically unless -NoAutoPage is supplied. -ProjectId is required. - - - Notes - - Use -SortBy together with -SortOrder ('asc'/'desc') to control result ordering. Pair with Get-InfisicalCertificate or Export-InfisicalCertificate to drill into specific hits. - - - - - EXAMPLE 1 - Search-InfisicalCertificate -Search $env:COMPUTERNAME -Status 'active' - Finds active certificates whose searchable fields contain the local hostname. - - - EXAMPLE 2 - $GetInfisicalCertificateAuthorityListResult = Get-InfisicalCertificateAuthority | Where-Object { $_.FriendlyName -eq 'Issuing CA - Platform' } - -$SearchInfisicalCertificateParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' -ArgumentList ([System.StringComparer]::OrdinalIgnoreCase) -$SearchInfisicalCertificateParameters.ProjectId = $ProjectId -$SearchInfisicalCertificateParameters.CommonName = $env:COMPUTERNAME -$SearchInfisicalCertificateParameters.Status = 'active' -$SearchInfisicalCertificateParameters.CaId = @($GetInfisicalCertificateAuthorityListResult.Id) -$SearchInfisicalCertificateParameters.KeyAlgorithm = @('RSA') -$SearchInfisicalCertificateParameters.NotAfterTo = (Get-Date).AddDays(30) -$SearchInfisicalCertificateParameters.SortBy = 'notAfter' -$SearchInfisicalCertificateParameters.SortOrder = 'asc' -$SearchInfisicalCertificateParameters.Limit = 100 -$SearchInfisicalCertificateParameters.Verbose = $True - -$SearchInfisicalCertificateResult = Search-InfisicalCertificate @SearchInfisicalCertificateParameters - Searches for RSA certificates from a specific CA, scoped to the local hostname, that expire within the next 30 days, sorted soonest-first. - - - - Request-InfisicalCertificate diff --git a/README.md b/README.md index f155e8c..605b084 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,6 @@ The module exports 37 cmdlets. Discovery cmdlets (`Get-Infisical*`) use a `List` | `Get-InfisicalCertificateAuthority` | Lists or retrieves Infisical internal Certificate Authorities. | | `Get-InfisicalPkiSubscriber` | Lists or retrieves Infisical PKI subscribers in a project. | | `Get-InfisicalCertificate` | Lists or retrieves Infisical certificates in a project, with optional filters and automatic paging. | -| `Search-InfisicalCertificate` | Searches Infisical certificates with advanced filters and automatic paging. | | `Request-InfisicalCertificate` | Requests a new Infisical certificate (local CSR + sign) or reuses a still-valid existing one. | | `ConvertTo-InfisicalCertificate` | Materializes an X509Certificate2 from an Infisical certificate record, bundle, or serial number. | | `Install-InfisicalCertificate` | Installs an Infisical certificate (and optional chain) into a Windows certificate store. | diff --git a/build.ps1 b/build.ps1 index 5e70b47..8de86d7 100644 --- a/build.ps1 +++ b/build.ps1 @@ -134,7 +134,6 @@ function Write-Manifest { 'Get-InfisicalCertificateProfile', 'Get-InfisicalCertificatePolicy', 'Get-InfisicalCertificate', - 'Search-InfisicalCertificate', 'Request-InfisicalCertificate', 'ConvertTo-InfisicalCertificate', 'Install-InfisicalCertificate', @@ -210,7 +209,7 @@ if (`$cmds.Count -eq 0) { throw "No cmdlets were exported by the PSInfisicalAPI module." } -`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificateProfile','Get-InfisicalCertificatePolicy','Get-InfisicalCertificate','Search-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate','Get-InfisicalCertificateApplication','Get-InfisicalCertificateApplicationEnrollment','New-InfisicalScepDynamicChallenge','Get-InfisicalScepMdmProfile','Export-InfisicalScepMdmProfile','Write-InfisicalScepMdmProfileToWmi') +`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificateProfile','Get-InfisicalCertificatePolicy','Get-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate','Get-InfisicalCertificateApplication','Get-InfisicalCertificateApplicationEnrollment','New-InfisicalScepDynamicChallenge','Get-InfisicalScepMdmProfile','Export-InfisicalScepMdmProfile','Write-InfisicalScepMdmProfileToWmi') foreach (`$expected in `$expectedCmds) { if (-not (Get-Command -Name `$expected -Module PSInfisicalAPI -ErrorAction SilentlyContinue)) { throw "Cmdlet not found: `$expected" diff --git a/src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs deleted file mode 100644 index fd1d0ae..0000000 --- a/src/PSInfisicalAPI/Cmdlets/SearchInfisicalCertificateCmdlet.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Management.Automation; -using PSInfisicalAPI.Connections; -using PSInfisicalAPI.Models; -using PSInfisicalAPI.Pki; - -namespace PSInfisicalAPI.Cmdlets -{ - [Cmdlet(VerbsCommon.Search, "InfisicalCertificate")] - [OutputType(typeof(InfisicalCertificate))] - public sealed class SearchInfisicalCertificateCmdlet : InfisicalCmdletBase - { - [Parameter(Mandatory = true)] public string ProjectId { get; set; } - [Parameter] public string FriendlyName { get; set; } - [Parameter] public string CommonName { get; set; } - [Parameter] public string Search { get; set; } - [Parameter] public string Status { get; set; } - [Parameter] public string[] CaId { get; set; } - [Parameter] public string[] ProfileId { get; set; } - [Parameter] public string ApplicationId { get; set; } - [Parameter] public string[] ApplicationIds { get; set; } - [Parameter] public string[] EnrollmentType { get; set; } - [Parameter] public string ExtendedKeyUsage { get; set; } - [Parameter] public string[] KeyAlgorithm { get; set; } - [Parameter] public string SignatureAlgorithm { get; set; } - [Parameter] public int[] KeySize { get; set; } - [Parameter] public string[] Source { get; set; } - [Parameter] public DateTimeOffset? FromDate { get; set; } - [Parameter] public DateTimeOffset? ToDate { get; set; } - [Parameter] public DateTimeOffset? NotAfterFrom { get; set; } - [Parameter] public DateTimeOffset? NotAfterTo { get; set; } - [Parameter] public DateTimeOffset? NotBeforeFrom { get; set; } - [Parameter] public DateTimeOffset? NotBeforeTo { get; set; } - [Parameter] public Hashtable Metadata { get; set; } - [Parameter] public SwitchParameter ForPkiSync { get; set; } - - [Parameter] - [ValidateSet("notAfter", "notBefore", "createdAt", "commonName", "keyAlgorithm", "status")] - public string SortBy { get; set; } - - [Parameter] [ValidateSet("asc", "desc")] public string SortOrder { get; set; } - [Parameter] public int? Limit { get; set; } - [Parameter] public int? Offset { get; set; } - [Parameter] public SwitchParameter NoAutoPage { get; set; } - - protected override void ProcessRecord() - { - try - { - InfisicalConnection connection = InfisicalSessionManager.RequireCurrent(); - InfisicalPkiClient client = new InfisicalPkiClient(HttpClient, Logger); - - InfisicalCertificateSearchQuery query = BuildQuery(ProjectId); - int requestedLimit = query.Limit ?? 100; - query.Limit = requestedLimit; - query.Offset = query.Offset ?? 0; - - int emitted = 0; - while (true) - { - InfisicalCertificateSearchResult page = client.SearchCertificates(connection, query); - if (page == null || page.Certificates == null || page.Certificates.Length == 0) - { - break; - } - - foreach (InfisicalCertificate cert in page.Certificates) - { - WriteObject(cert); - emitted++; - } - - if (NoAutoPage.IsPresent || page.Certificates.Length < requestedLimit) - { - break; - } - - if (page.TotalCount > 0 && emitted >= page.TotalCount) - { - break; - } - - query.Offset = (query.Offset ?? 0) + page.Certificates.Length; - } - } - catch (Exception exception) - { - ThrowTerminatingForException("SearchInfisicalCertificateCmdlet", "SearchCertificates", exception); - } - } - - private InfisicalCertificateSearchQuery BuildQuery(string projectId) - { - return new InfisicalCertificateSearchQuery - { - ProjectId = projectId, - FriendlyName = FriendlyName, - CommonName = CommonName, - Search = Search, - Status = Status, - CaIds = CaId, - ProfileIds = ProfileId, - ApplicationId = ApplicationId, - ApplicationIds = ApplicationIds, - EnrollmentTypes = EnrollmentType, - ExtendedKeyUsage = ExtendedKeyUsage, - KeyAlgorithm = KeyAlgorithm, - SignatureAlgorithm = SignatureAlgorithm, - KeySizes = KeySize, - Source = Source, - FromDate = FromDate, - ToDate = ToDate, - NotAfterFrom = NotAfterFrom, - NotAfterTo = NotAfterTo, - NotBeforeFrom = NotBeforeFrom, - NotBeforeTo = NotBeforeTo, - Metadata = ToStringDictionary(Metadata), - ForPkiSync = ForPkiSync.IsPresent ? (bool?)true : null, - SortBy = SortBy, - SortOrder = SortOrder, - Limit = Limit, - Offset = Offset - }; - } - - private static Dictionary ToStringDictionary(Hashtable hashtable) - { - if (hashtable == null) { return null; } - Dictionary result = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (DictionaryEntry entry in hashtable) - { - if (entry.Key == null) { continue; } - result[entry.Key.ToString()] = entry.Value != null ? entry.Value.ToString() : null; - } - return result; - } - } -}