PowerShell / PSResourceGet

PSResourceGet is the package manager for PowerShell
https://www.powershellgallery.com/packages/Microsoft.PowerShell.PSResourceGet
MIT License
495 stars 94 forks source link

Sonatype Nexus v2 feeds does not work #1466

Open oed-metzb opened 1 year ago

oed-metzb commented 1 year ago

Prerequisites

Steps to reproduce

We are trying Sonatype Nexus as a Nuget feed provider and with PowerShellGetV2 we were already able to reach the repository. With PSResourceGet 1.0.0 it is unfortunately no longer possible to use the same repository.

Register the Repository

$RepoName = "Nexus-Powershell"
$RepoUrl = "https://nexus.domain/repository/ps-all-test"
$VaultName = "NexusVault"
$CredentialName = "NexusInstall"

$Splat = @{
    Name = $RepoName
    Uri = $RepoUrl
    Trusted = $true
    CredentialInfo = ([Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo]::new($VaultName, $CredentialName))
}
Register-PSResourceRepository @Splat

Repository type will not be detected by default and set to unknown

Find-PSResource -Repository $RepoName -Name "Test.Module" -Verbose -Debug
Find-PSResource: Repository 'Nexus-Powershell' is not a known repository type that is supported. Please file an issue for support at https://github.com/PowerShell/PSResourceGet/issues

Set ApiVersion to v2

Set-PSResourceRepository -Name $RepoName -ApiVersion v2

Try to find the Module again

Find-PSResource -Repository $RepoName -Name "Test.Module" -Verbose -Debug

Expected behavior

Find/Install the module as like in PowerShellGetV2

PS C:\> Get-Module PowerShellGet

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Script     2.2.5                 PowerShellGet                       {Find-Command, Find-DscResource, Find-Module, Find-RoleCapability…}

PS C:\> Get-PSRepository

Name                      InstallationPolicy   SourceLocation
----                      ------------------   --------------
Nexus-Powershell          Trusted              https://nexus.domain/repository/ps-all-test/
PSGallery                 Trusted              https://www.powershellgallery.com/api/v2

PS C:\> Find-Module Test.Module -Repository Nexus-Powershell -Credential $Cred

Version              Name                                Repository           Description
-------              ----                                ----------           -----------
0.0.1                Test.Module                         Nexus-Powershell     Test.Module Description

Actual behavior

PS> Find-PSResource -Repository $RepoName -Name "Test.Module" -Verbose -Debug
DEBUG: In FindPSResource::ProcessResourceNameParameterSet()
DEBUG: Filtering package name(s) on wildcards
DEBUG: In FindHelper::FindByResourceName()
DEBUG: Parameters passed in >>> Name: 'Test.Module'; ResourceType: 'None'; VersionRange: ''; NuGetVersion: ''; VersionType: 'NoVersion'; Version: ''; Prerelease: 'False'; Tag: ''; Repository: 'Nexus-Powershell'; IncludeDependencies 'False'
VERBOSE: credential successfully read from vault and set for repository: Nexus-Powershell
DEBUG: Searching through repository 'Nexus-Powershell'
DEBUG: In FindHelper::SearchByNames()
DEBUG: No version specified, package name is specified
DEBUG: In V2ServerAPICalls::FindName()
DEBUG: In V2ServerAPICalls::HttpRequestCall()
DEBUG: Request url is 'https://nexus.domain/repository/ps-all-test/FindPackagesById()?id='Test.Module'&$inlinecount=allpages&$filter=IsLatestVersion and Id eq 'Test.Module''
Find-PSResource: TryConvertFromXml: Cannot parse PSResourceInfo from XmlNode with error: Object reference not set to an instance of an object.

Error details

PS> get-error

Exception             :
    Type    : Microsoft.PowerShell.PSResourceGet.UtilClasses.XmlParsingException
    Message : TryConvertFromXml: Cannot parse PSResourceInfo from XmlNode with error: Object reference not set to an instance of an object.
    HResult : -2146233088
TargetObject          : Microsoft.PowerShell.PSResourceGet.Cmdlets.FindHelper
CategoryInfo          : ObjectNotFound: (Microsoft.PowerShel….Cmdlets.FindHelper:FindHelper) [Find-PSResource], XmlParsingException
FullyQualifiedErrorId : FindNameConvertToPSResourceFailure,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource
InvocationInfo        :
    MyCommand        : Find-PSResource
    ScriptLineNumber : 1
    OffsetInLine     : 1
    HistoryId        : 150
    Line             : Find-PSResource -Repository $RepoName -Name "Test.Module" -Verbose -Debug
    PositionMessage  : At line:1 char:1
                       + Find-PSResource -Repository $RepoName -Name "Test.Module" -Verbose …
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    InvocationName   : Find-PSResource
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo :

Environment data

Get-Module Microsoft.PowerShell.PSResourceGet

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Binary     1.0.0                 Microsoft.PowerShell.PSResourceGet  {Find-PSResource, Get-InstalledPSResource, Get-PSResourceRepository, Get-PSScriptFileInfo…}

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.3.9
PSEdition                      Core
GitCommitId                    7.3.9
OS                             Microsoft Windows 10.0.22621
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

SydneyhSmith commented 1 year ago

Thanks for opening the issue @oed-metzb we are looking into it

oed-metzb commented 1 year ago

Additional information: The same behavior also occurs with Install-PSResource.

PS> Install-PSResource Microsoft.PowerShell.SecretManagement -Repository PSGallery-Proxy -TrustRepository -Debug -Verbose
VERBOSE: All paths to search: 'C:\Users\Administrator\Documents\WindowsPowerShell\Modules'
VERBOSE: All paths to search: 'C:\Users\Administrator\Documents\WindowsPowerShell\Scripts'
VERBOSE: Retrieving directories in the path 'C:\Users\Administrator\Documents\WindowsPowerShell\Modules'
VERBOSE: Retrieving directories in the path 'C:\Users\Administrator\Documents\WindowsPowerShell\Scripts'
DEBUG: In GetHelper::GetPackagesFromPath()
DEBUG: In GetHelper::FilterPkgPathsByName()
DEBUG: In GetHelper::FilterPkgPathsByVersion()
DEBUG: In InstallPSResource::ProcessInstallHelper()
DEBUG: In InstallHelper::BeginInstallPackages()
DEBUG: Parameters passed in >>> Name: 'Microsoft.PowerShell.SecretManagement'; VersionRange: ''; NuGetVersion: ''; VersionType: 'NoVersion'; Version: ''; Prerelease: 'False'; Repository: 'PSGallery-Proxy'; AcceptLicense: 'False'; Quiet: 'False'; Reinstall:
'False'; TrustRepository: 'True'; NoClobber: 'False'; AsNupkg: 'False'; IncludeXml 'True'; SavePackage 'False'; TemporaryPath ''; SkipDependencyCheck: 'False'; AuthenticodeCheck: 'False'; PathsToInstallPkg:
'C:\Users\Administrator\Documents\WindowsPowerShell\Modules,C:\Users\Administrator\Documents\WindowsPowerShell\Scripts'; Scope 'CurrentUser'
DEBUG: In InstallHelper::ProcessRepositories()
VERBOSE: Attempting to search for packages in 'PSGallery-Proxy'
DEBUG: In InstallHelper::InstallPackages()
DEBUG: In InstallHelper::InstallPackage()
DEBUG: In V2ServerAPICalls::FindName()
DEBUG: In V2ServerAPICalls::HttpRequestCall()
DEBUG: Request url is 'https://nexus.domain/repository/psgallery-proxy/FindPackagesById()?id='Microsoft.PowerShell.SecretManagement'&$inlinecount=allpages&$filter=IsLatestVersion and Id eq 'Microsoft.PowerShell.SecretManagement''
VERBOSE: Attempting to delete 'C:\Users\Administrator\AppData\Local\Temp\2\af43e635-c4cb-4910-beff-ede455034cb2'
VERBOSE: Successfully deleted 'C:\Users\Administrator\AppData\Local\Temp\2\af43e635-c4cb-4910-beff-ede455034cb2'
Install-PSResource : Object reference not set to an instance of an object.
At line:1 char:1
+ Install-PSResource Microsoft.PowerShell.SecretManagement -Repository  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-PSResource], NullReferenceException
    + FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.PSResourceGet.Cmdlets.InstallPSResource

When I call the URL from the debug information, I get the following response:

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<feed xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom" xml:base="https://nexus.domain/repository/psgallery-proxy/">
<title type="text">FindPackagesById</title>
<id>https://nexus.domain/repository/psgallery-proxy/FindPackagesById</id>
<updated>2023-11-20T08:55:28.149Z</updated>
<link rel="self" title="FindPackagesById" href="FindPackagesById"/>
<m:count>1</m:count>
<entry>
<id>https://nexus.domain/repository/psgallery-proxy/Packages(Id='Microsoft.PowerShell.SecretManagement',Version='1.1.2')</id>
<title type="text">Microsoft.PowerShell.SecretManagement</title>
<summary type="text" m:null="true"/>
<updated>2023-11-20T09:46:58.487Z</updated>
<author>
<name>Microsoft Corporation</name>
</author>
<link rel="edit-media" title="V2FeedPackage" href="Packages(Id='Microsoft.PowerShell.SecretManagement',Version='1.1.2')/$value"/>
<link rel="edit" title="V2FeedPackage" href="Packages(Id='Microsoft.PowerShell.SecretManagement',Version='1.1.2')"/>
<category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<content type="application/zip" src="https://nexus.domain/repository/psgallery-proxy/Microsoft.PowerShell.SecretManagement/1.1.2"/>
<m:properties>
<d:Version>1.1.2</d:Version>
<d:Copyright>(c) Microsoft Corporation. All rights reserved.</d:Copyright>
<d:Created m:type="Edm.DateTime">2022-01-27T18:16:33.530Z</d:Created>
<d:Dependencies/>
<d:Description> This module provides a convenient way for a user to store and retrieve secrets. The secrets are stored in registered extension vaults. An extension vault can store secrets locally or remotely. SecretManagement coordinates access to the secrets through the registered vaults. Go to GitHub for more information about the module and to submit issues: https://github.com/powershell/SecretManagement </d:Description>
<d:DownloadCount m:type="Edm.Int32">568807</d:DownloadCount>
<d:GalleryDetailsUrl>https://www.powershellgallery.com/packages/Microsoft.PowerShell.SecretManagement/1.1.2</d:GalleryDetailsUrl>
<d:IconUrl m:null="true"/>
<d:IsLatestVersion m:type="Edm.Boolean">true</d:IsLatestVersion>
<d:IsAbsoluteLatestVersion m:type="Edm.Boolean">true</d:IsAbsoluteLatestVersion>
<d:IsPrerelease m:type="Edm.Boolean">false</d:IsPrerelease>
<d:Published m:type="Edm.DateTime">2022-01-27T18:16:33.530Z</d:Published>
<d:Language m:null="true"/>
<d:LicenseUrl>https://github.com/PowerShell/SecretManagement/blob/master/LICENSE</d:LicenseUrl>
<d:PackageHash>Y1BTgdI/Y48pYLwZdJFmfzPoySGbURC3LD6UgJEMd/S3ShjeY0ukrH4BaidHkuoDqXiz7gWuro84tkatAF6jYQ==</d:PackageHash>
<d:PackageHashAlgorithm>SHA512</d:PackageHashAlgorithm>
<d:PackageSize m:type="Edm.Int64">84356</d:PackageSize>
<d:ProjectUrl>https://github.com/powershell/secretmanagement</d:ProjectUrl>
<d:ReportAbuseUrl>https://www.powershellgallery.com/packages/Microsoft.PowerShell.SecretManagement/1.1.2/ReportAbuse</d:ReportAbuseUrl>
<d:ReleaseNotes m:null="true"/>
<d:RequireLicenseAcceptance m:type="Edm.Boolean">false</d:RequireLicenseAcceptance>
<d:Tags>PSModule PSEdition_Core PSCmdlet_Register-SecretVault PSCommand_Register-SecretVault PSCmdlet_Unregister-SecretVault PSCommand_Unregister-SecretVault PSCmdlet_Get-SecretVault PSCommand_Get-SecretVault PSCmdlet_Set-SecretVaultDefault PSCommand_Set-SecretVaultDefault PSCmdlet_Test-SecretVault PSCommand_Test-SecretVault PSCmdlet_Set-Secret PSCommand_Set-Secret PSCmdlet_Set-SecretInfo PSCommand_Set-SecretInfo PSCmdlet_Get-Secret PSCommand_Get-Secret PSCmdlet_Get-SecretInfo PSCommand_Get-SecretInfo PSCmdlet_Remove-Secret PSCommand_Remove-Secret PSCmdlet_Unlock-SecretVault PSCommand_Unlock-SecretVault PSIncludes_Cmdlet</d:Tags>
<d:Title m:null="true"/>
<d:VersionDownloadCount m:type="Edm.Int32">477864</d:VersionDownloadCount>
</m:properties>
</entry>
</feed>
alerickson commented 10 months ago

Adding this comment here to help with adding CI tests for this scenario: https://github.com/PowerShell/PSResourceGet/issues/1536#issuecomment-1907957488

jackmtpt commented 5 months ago

I can confirm that this still doesn't work, using PSResourceGet 1.0.5 and nexus repository PRO 3.68.1-02.

PSResourceGet ends up making a request such as https://nexus-repository.domain.com/repository/powershell/FindPackagesById()?$filter=Id+eq+%27MyPackage%27+and+NormalizedVersion+eq+%271.0.50%27&$inlinecount=allpages&id=%27MyPackage%27 for MyPackage version 1.0.50

The repository server seems to not support that query syntax, and instead it returns metadata xml for a bunch of unrelated packages. PowerShellGet on the other hand just requests /FindPackagesById()?id=%27MyPackage%27 which works fine.

Gijsreyn commented 3 weeks ago

I haven't tried it with the latest preview-2 release, but I tried a different approach.

Simple install NexusIQ with choco install nexus-repository. When it is finished up, set the admin password. You can add the source when you have the dotnet.exe by running: dotnet nuget add source http://localhost:8081/repository/nuget-hosted --name NexusIQ --username --password.

With the new Compress-PSResource, the .nupkg file is generated. You can push this with dotnet nuget push.

It's not natively PSResourceGet, but a combination of both. There is a PowerShell module (NexuShell) where you can interact with NexusIQ. Would love to see the support for NexusIQ in the future.