Commands/Package/Eigenverft.Manifested.Package.Cmd.SearchPackage.ps1
|
<#
Public package search command surface. #> function Get-PackageSearchSettings { [CmdletBinding()] param() $globalDocumentInfo = Read-PackageJsonDocument -Path (Get-PackageConfigPath) Assert-PackageConfigSchema -PackageConfigDocumentInfo $globalDocumentInfo $packageGlobalConfig = $globalDocumentInfo.Document.package $applicationRootDirectory = Resolve-PackageApplicationRootDirectory -PackageConfiguration $packageGlobalConfig $catalogTrustPolicy = 'strict' $catalogTrustUnknownSignedKeyPolicy = 'prompt' $catalogTrustAllowUnsignedPublisherIds = @() $catalogTrustBlockedPublisherIds = @() if ($packageGlobalConfig.PSObject.Properties['catalogTrust'] -and $packageGlobalConfig.catalogTrust) { if ($packageGlobalConfig.catalogTrust.PSObject.Properties['policy'] -and -not [string]::IsNullOrWhiteSpace([string]$packageGlobalConfig.catalogTrust.policy)) { $catalogTrustPolicy = [string]$packageGlobalConfig.catalogTrust.policy } if ($packageGlobalConfig.catalogTrust.PSObject.Properties['unknownSignedKeyPolicy'] -and -not [string]::IsNullOrWhiteSpace([string]$packageGlobalConfig.catalogTrust.unknownSignedKeyPolicy)) { $catalogTrustUnknownSignedKeyPolicy = [string]$packageGlobalConfig.catalogTrust.unknownSignedKeyPolicy } if ($packageGlobalConfig.catalogTrust.PSObject.Properties['allowUnsignedPublisherIds'] -and $null -ne $packageGlobalConfig.catalogTrust.allowUnsignedPublisherIds) { $catalogTrustAllowUnsignedPublisherIds = @( foreach ($configuredPublisherId in @($packageGlobalConfig.catalogTrust.allowUnsignedPublisherIds)) { $normalizedPublisherId = ([string]$configuredPublisherId).Trim() if (-not [string]::IsNullOrWhiteSpace($normalizedPublisherId)) { $normalizedPublisherId } } ) } if ($packageGlobalConfig.catalogTrust.PSObject.Properties['blockedPublisherIds'] -and $null -ne $packageGlobalConfig.catalogTrust.blockedPublisherIds) { $catalogTrustBlockedPublisherIds = @( foreach ($configuredPublisherId in @($packageGlobalConfig.catalogTrust.blockedPublisherIds)) { $normalizedPublisherId = ([string]$configuredPublisherId).Trim() if (-not [string]::IsNullOrWhiteSpace($normalizedPublisherId)) { $normalizedPublisherId } } ) } } $releaseTrack = 'none' if ($packageGlobalConfig.PSObject.Properties['selectionDefaults'] -and $packageGlobalConfig.selectionDefaults -and $packageGlobalConfig.selectionDefaults.PSObject.Properties['releaseTrack'] -and -not [string]::IsNullOrWhiteSpace([string]$packageGlobalConfig.selectionDefaults.releaseTrack)) { $releaseTrack = [string]$packageGlobalConfig.selectionDefaults.releaseTrack } return [pscustomobject]@{ ApplicationRootDirectory = $applicationRootDirectory ReleaseTrack = $releaseTrack CatalogTrustPolicy = $catalogTrustPolicy CatalogTrustAllowUnsignedPublisherIds = @($catalogTrustAllowUnsignedPublisherIds) CatalogTrustBlockedPublisherIds = @($catalogTrustBlockedPublisherIds) CatalogTrustUnknownSignedKeyPolicy = $catalogTrustUnknownSignedKeyPolicy } } function Get-PackageSearchCandidateRows { [CmdletBinding()] param( [AllowNull()] [string]$EndpointName = $null, [Parameter(Mandatory = $true)] [psobject]$Settings, [Parameter(Mandatory = $true)] [psobject]$TrustInventoryDocument ) $endpointInventoryInfo = Get-PackageEndpointInventoryInfo $sourceRows = @(Get-PackageEnabledEndpointSources -EndpointInventoryDocument $endpointInventoryInfo.Document) if (-not [string]::IsNullOrWhiteSpace($EndpointName)) { $sourceRows = @($sourceRows | Where-Object { [string]::Equals([string]$_.EndpointName, [string]$EndpointName, [System.StringComparison]::OrdinalIgnoreCase) }) } $candidateRows = New-Object System.Collections.Generic.List[object] foreach ($sourceRow in @($sourceRows)) { try { $scanRootPath = Resolve-PackageEndpointRootPath -EndpointName ([string]$sourceRow.EndpointName) -Source $sourceRow.Source -ApplicationRootDirectory ([string]$Settings.ApplicationRootDirectory) foreach ($candidate in @(Select-PackageDefinitionCandidatesFromEndpointScanRoot -EndpointName ([string]$sourceRow.EndpointName) -EndpointSource $sourceRow.Source -ScanRootPath $scanRootPath -TrustInventoryDocument $TrustInventoryDocument)) { $candidate | Add-Member -MemberType NoteProperty -Name EndpointSearchOrder -Value ([int]$sourceRow.SearchOrder) -Force $candidateRows.Add($candidate) | Out-Null } } catch { Write-Warning ("Skipped package endpoint '{0}' during search: {1}" -f [string]$sourceRow.EndpointName, $_.Exception.Message) } } return @($candidateRows.ToArray()) } function Get-PackageSearchTextFields { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Definition ) $fields = New-Object System.Collections.Generic.List[string] if ($Definition.PSObject.Properties['definitionPublication'] -and $Definition.definitionPublication) { foreach ($name in @('definitionId', 'publisherId', 'publisherName')) { if ($Definition.definitionPublication.PSObject.Properties[$name] -and -not [string]::IsNullOrWhiteSpace([string]$Definition.definitionPublication.$name)) { $fields.Add([string]$Definition.definitionPublication.$name) | Out-Null } } } if ($Definition.PSObject.Properties['display'] -and $Definition.display.PSObject.Properties['default'] -and $Definition.display.default) { foreach ($name in @('name', 'publisher', 'corporation', 'summary')) { if ($Definition.display.default.PSObject.Properties[$name] -and -not [string]::IsNullOrWhiteSpace([string]$Definition.display.default.$name)) { $fields.Add([string]$Definition.display.default.$name) | Out-Null } } } if ($Definition.PSObject.Properties['discovery'] -and $Definition.discovery.PSObject.Properties['presence'] -and $Definition.discovery.presence) { $presence = $Definition.discovery.presence foreach ($command in @($presence.commands)) { if ($null -eq $command) { continue } if ($command.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$command.name)) { $fields.Add([string]$command.name) | Out-Null } if ($command.PSObject.Properties['relativePath'] -and -not [string]::IsNullOrWhiteSpace([string]$command.relativePath)) { $fields.Add([string]$command.relativePath) | Out-Null } } foreach ($app in @($presence.apps)) { if ($null -eq $app) { continue } if ($app.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$app.name)) { $fields.Add([string]$app.name) | Out-Null } } foreach ($module in @($presence.powerShellModules)) { if ($null -eq $module) { continue } if ($module.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$module.name)) { $fields.Add([string]$module.name) | Out-Null } } foreach ($file in @($presence.files)) { if (-not [string]::IsNullOrWhiteSpace([string]$file)) { $fields.Add([string]$file) | Out-Null } } } return @($fields.ToArray() | Select-Object -Unique) } function Test-PackageSearchQueryMatch { [CmdletBinding()] param( [AllowNull()] [string]$Query = $null, [AllowNull()] [string[]]$Fields = @() ) if ([string]::IsNullOrWhiteSpace($Query)) { return $true } foreach ($term in @(([string]$Query).Split([char[]]@(' ', "`t", "`r", "`n"), [System.StringSplitOptions]::RemoveEmptyEntries))) { $termMatched = $false foreach ($field in @($Fields)) { if ($null -ne $field -and ([string]$field).IndexOf($term, [System.StringComparison]::OrdinalIgnoreCase) -ge 0) { $termMatched = $true break } } if (-not $termMatched) { return $false } } return $true } function Get-PackageSearchEntryPointNames { [CmdletBinding()] param( [AllowNull()] [psobject]$Definition ) if (-not $Definition -or -not $Definition.PSObject.Properties['discovery'] -or -not $Definition.discovery.PSObject.Properties['presence'] -or -not $Definition.discovery.presence) { return [pscustomobject]@{ Commands = @(); Apps = @(); PowerShellModules = @() } } $presence = $Definition.discovery.presence return [pscustomobject]@{ Commands = @($presence.commands | ForEach-Object { if ($null -ne $_ -and $_.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$_.name)) { [string]$_.name } } | Select-Object -Unique) Apps = @($presence.apps | ForEach-Object { if ($null -ne $_ -and $_.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$_.name)) { [string]$_.name } } | Select-Object -Unique) PowerShellModules = @($presence.powerShellModules | ForEach-Object { if ($null -ne $_ -and $_.PSObject.Properties['name'] -and -not [string]::IsNullOrWhiteSpace([string]$_.name)) { [string]$_.name } } | Select-Object -Unique) } } function Get-PackageSearchTargetSummaries { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Definition ) return @( foreach ($target in @($Definition.artifacts.targets)) { $constraints = if ($target.PSObject.Properties['constraints']) { $target.constraints } else { [pscustomobject]@{} } $os = if ($constraints.PSObject.Properties['os']) { @($constraints.os) } else { @('*') } $cpu = if ($constraints.PSObject.Properties['cpu']) { @($constraints.cpu) } else { @('*') } [pscustomobject]@{ TargetId = [string]$target.id ReleaseTrack = [string]$target.releaseTrack ArtifactDistributionVariant = [string]$target.artifactDistributionVariant Os = @($os) Cpu = @($cpu) } } ) } function Resolve-PackageSearchSelectedVersion { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Definition, [Parameter(Mandatory = $true)] [string]$DefinitionId, [Parameter(Mandatory = $true)] [string]$Platform, [Parameter(Mandatory = $true)] [string]$Architecture, [Parameter(Mandatory = $true)] [string]$ReleaseTrack ) try { $packageConfig = [pscustomobject]@{ Definition = $Definition DefinitionId = $DefinitionId Platform = $Platform Architecture = $Architecture ReleaseTrack = $ReleaseTrack } $package = Resolve-PackageEffectivePackage_1_9 -PackageConfig $packageConfig return [pscustomobject]@{ Available = $true Version = [string]$package.version TargetId = [string]$package.artifactTargetId ReleaseTrack = [string]$package.releaseTrack ArtifactDistributionVariant = [string]$package.artifactDistributionVariant Error = $null } } catch { return [pscustomobject]@{ Available = $false Version = $null TargetId = $null ReleaseTrack = $ReleaseTrack ArtifactDistributionVariant = $null Error = $_.Exception.Message } } } function Search-Package { <# .SYNOPSIS Searches enabled package definition endpoints. .DESCRIPTION Scans enabled moduleLocal and filesystem endpoints, applies catalog trust eligibility, and returns package definition rows that match the query. #> [CmdletBinding()] param( [Parameter(Position = 0)] [AllowNull()] [string]$Query = $null, [AllowNull()] [string]$PublisherId = $null, [AllowNull()] [string]$EndpointName = $null, [AllowNull()] [string]$Platform = $null, [AllowNull()] [string]$Architecture = $null, [AllowNull()] [string]$ReleaseTrack = $null, [switch]$CurrentPlatformOnly, [switch]$IncludeIneligible ) $settings = Get-PackageSearchSettings $runtimeContext = Get-PackageRuntimeContext $effectivePlatform = if ([string]::IsNullOrWhiteSpace($Platform)) { [string]$runtimeContext.Platform } else { ([string]$Platform).Trim() } $effectiveArchitecture = if ([string]::IsNullOrWhiteSpace($Architecture)) { [string]$runtimeContext.Architecture } else { ([string]$Architecture).Trim() } $effectiveReleaseTrack = if ([string]::IsNullOrWhiteSpace($ReleaseTrack)) { [string]$settings.ReleaseTrack } else { ([string]$ReleaseTrack).Trim() } $trustInventoryInfo = Get-PackageTrustInventoryInfo $rows = New-Object System.Collections.Generic.List[object] foreach ($candidate in @(Get-PackageSearchCandidateRows -EndpointName $EndpointName -Settings $settings -TrustInventoryDocument $trustInventoryInfo.Document)) { if (-not [string]::IsNullOrWhiteSpace($PublisherId) -and -not [string]::Equals([string]$candidate.PublisherId, [string]$PublisherId, [System.StringComparison]::OrdinalIgnoreCase)) { continue } $trust = Resolve-PackageDefinitionCandidateTrustEligibility -Candidate $candidate -CatalogTrustPolicy ([string]$settings.CatalogTrustPolicy) -CatalogTrustAllowUnsignedPublisherIds @($settings.CatalogTrustAllowUnsignedPublisherIds) -CatalogTrustBlockedPublisherIds @($settings.CatalogTrustBlockedPublisherIds) -UnknownSignedKeyPolicy ([string]$settings.CatalogTrustUnknownSignedKeyPolicy) if (-not $trust.Eligible -and -not $IncludeIneligible.IsPresent) { continue } try { $definitionInfo = Read-PackageJsonDocument -Path ([string]$candidate.DefinitionPath) Assert-PackageDefinitionSchema -DefinitionDocumentInfo $definitionInfo -DefinitionId ([string]$candidate.DefinitionId) -PublisherId ([string]$candidate.PublisherId) } catch { Write-Warning ("Skipped package definition '{0}' during search: {1}" -f [string]$candidate.DefinitionPath, $_.Exception.Message) continue } $definition = $definitionInfo.Document $fields = @(Get-PackageSearchTextFields -Definition $definition) if (-not (Test-PackageSearchQueryMatch -Query $Query -Fields $fields)) { continue } $selection = Resolve-PackageSearchSelectedVersion -Definition $definition -DefinitionId ([string]$candidate.DefinitionId) -Platform $effectivePlatform -Architecture $effectiveArchitecture -ReleaseTrack $effectiveReleaseTrack if ($CurrentPlatformOnly.IsPresent -and -not [bool]$selection.Available) { continue } $display = $definition.display.default $entryPoints = Get-PackageSearchEntryPointNames -Definition $definition $targetSummaries = @(Get-PackageSearchTargetSummaries -Definition $definition) $invokeCommand = if ([string]::IsNullOrWhiteSpace([string]$candidate.PublisherId)) { "Invoke-Package -DefinitionId '$($candidate.DefinitionId)'" } else { "Invoke-Package -DefinitionId '$($candidate.DefinitionId)' -PublisherId '$($candidate.PublisherId)'" } $rows.Add([pscustomobject]@{ DefinitionId = [string]$candidate.DefinitionId PublisherId = [string]$candidate.PublisherId PublisherName = [string]$candidate.PublisherName Name = [string]$display.name DisplayPublisher = [string]$display.publisher Corporation = [string]$display.corporation Summary = [string]$display.summary Version = [string]$selection.Version PlatformAvailable = [bool]$selection.Available Platform = $effectivePlatform Architecture = $effectiveArchitecture ReleaseTrack = $effectiveReleaseTrack SelectedTargetId = [string]$selection.TargetId SelectedArtifactDistributionVariant = [string]$selection.ArtifactDistributionVariant SelectionError = [string]$selection.Error Commands = @($entryPoints.Commands) Apps = @($entryPoints.Apps) PowerShellModules = @($entryPoints.PowerShellModules) Targets = @($targetSummaries) EndpointName = [string]$candidate.EndpointName EndpointSearchOrder = [int]$candidate.EndpointSearchOrder EndpointSourceKind = [string]$candidate.EndpointSourceKind DefinitionRevision = [int]$candidate.DefinitionRevision PublishedAtUtc = [string]$candidate.PublishedAtUtc CatalogTrustStatus = [string]$trust.TrustStatus CatalogTrustReason = [string]$trust.TrustReason CatalogTrustEligible = [bool]$trust.Eligible SignatureStatus = [string]$candidate.SignatureStatus SignatureValid = [bool]$candidate.SignatureValid SignatureTrusted = [bool]$candidate.SignatureTrusted SignatureKeyThumbprint = if ([string]::IsNullOrWhiteSpace([string]$candidate.SignatureKeyThumbprint)) { $null } else { [string]$candidate.SignatureKeyThumbprint } DefinitionPath = [string]$candidate.DefinitionPath InvokeCommand = $invokeCommand }) | Out-Null } return @($rows.ToArray() | Sort-Object -Property DefinitionId, PublisherId, EndpointSearchOrder, EndpointName, DefinitionRevision) } |