PowerShell / PSResourceGet

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

[Feature Request]: Ability to configure PSRepository on a system-wide level #84

Open Glober777 opened 6 years ago

Glober777 commented 6 years ago

It would be great if there was a way to register a PSRepository on the system-wide level, so that if configured once, it would work for all the users on a particular system.

Expected Behavior

Register-PSRepository should have a -Scope parameter added, to control whether a particular PSRepository needs to be registered for just the current user of for the whole system (similar to the behavior of Execution Policy). It would also be great to have an extra scope option, that would register PSRepository just for the current session (like mentioned in PowerShell/PowerShellGet#65)

Apart from the Register-PSRepository, the remaining set of the *-PSRepository cmdlets should also have the -Scope parameter. Set-PSRepository and Unregister-PSRepository cmdlets should require admin privileges to work against system-wide PSRepository settings and 'Get-PSRepository' cmdlet should not require admin privileges at all.

Current Behavior

Currently Register-PSRepository only works for the user that is executing the cmdlet.

Context

Having an ability to register PSRepository on a system-wide level would allow us to pre-configure our internal Repositories in the Virtual Machine templates, thus making the provisioning process much simpler.

Additionally, that would simplify maintaining existing PSRepository configurations in a consistent fashion across all our systems.

Your Environment


PS C:\Users> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.15063.726
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.15063.726
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

PS C:\Users>
PS C:\Users> Get-Module

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   3.1.0.0    Microsoft.PowerShell.Utility        {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
Script     1.2        PSReadline                          {Get-PSReadlineKeyHandler, Get-PSReadlineOption, Remove-PS...

PS C:\Users>
PS C:\Users> Get-Module -ListAvailable PowerShellGet,PackageManagement

    Directory: C:\Program Files\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     1.1.7.0    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-Packa...
Script     1.1.1.0    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-Packa...
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-Packa...
Script     1.6.0      PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}
Script     1.1.2.0    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}
Script     1.0.0.1    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}

    Directory: C:\Program Files (x86)\WindowsPowerShell\Modules

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-Packa...
Script     1.0.0.1    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}

PS C:\Users>
PS C:\Users> Get-PackageProvider

Name                     Version          DynamicOptions
----                     -------          --------------
msi                      3.0.0.0          AdditionalArguments
msu                      3.0.0.0
NuGet                    2.8.5.210        Destination, ExcludeVersion, Scope, SkipDependencies, Headers, FilterOnTag...
PowerShellGet            1.6.0.0          PackageManagementProvider, Type, Scope, AllowClobber, SkipPublisherCheck, ...
Programs                 3.0.0.0          IncludeWindowsInstaller, IncludeSystemComponent

PS C:\Users> Get-PackageProvider -ListAvailable

Name                     Version          DynamicOptions
----                     -------          --------------
msi                      3.0.0.0          AdditionalArguments
msu                      3.0.0.0
nuget                    2.8.5.208
NuGet                    2.8.5.210        Destination, ExcludeVersion, Scope, SkipDependencies, Headers, FilterOnTag...
NuGetProvider            2.8.5.208
PowerShellGet            1.6.0.0          PackageManagementProvider, Type, Scope, AllowClobber, SkipPublisherCheck, ...
PowerShellGet            1.1.2.0
PowerShellGet            1.0.0.1
Programs                 3.0.0.0          IncludeWindowsInstaller, IncludeSystemComponent
KevinMarquette commented 6 years ago

I also support this request.

If an admin runs Install-Module -Scope AllUsers on a system, a different admin has to first register this repository in order to call Update-Module. Every time I touch a system and want to install or update a module, I first have to check to see if the repository is registered. Even if we fully automate the onboarding of that system, I still have to register a repository by hand.

What I do now is just include the repository registration logic in any and all scripts that install modules.

sam-bryant commented 6 years ago

+1 for this enhancement.

bradleywehmeier commented 6 years ago

Windows PowerShell team, any guidance on where the "AllUsers" repositories configuration file would live? I see 2 options:

  1. $script:ProgramFilesPSPath as this is where the AllUsers Modules are installed
  2. $script:PSGetProgramDataPath seems like the place for this configuration but might not work for "AllUsers" on Linux/OSX
bmanikm commented 6 years ago

@bradleywehmeie, thanks for looking into this feature request. Yes, $script:PSGetProgramDataPath is the right place for this configuration file.

For non-Windows platforms, please update the $script:PSGetProgramDataPath to '/usr/local/share/powershellget'.

Current:

    $script:PSGetProgramDataPath = Microsoft.PowerShell.Management\Join-Path -Path ([System.Management.Automation.Platform]::SelectProductNameForDirectory('CONFIG')) -ChildPath 'PowerShellGet'

Expected:

    $script:PSGetProgramDataPath = '/usr/local/share/powershellget'
bradleywehmeier commented 6 years ago

Main Question

How do we expect Unregister-PSRepository to function when the Scope parameter is omitted? Should it be allowed to modify the AllUsers scope if the Scope is omitted OR should the Scope be required anytime the AllUsers scope is being modified?

Example:

Register-PSRepository -Name Test -Scope AllUsers ...

# Should this be allowed?
Unregister-PSRepository -Name Test

# Or should we require the Scope?
Unregister-PSRepository -Name Test -Scope AllUsers

Additional Context

With either implementation, the Set/Unregister-PSRepository cmdlets work as you would expect but I ran into a limitation with the Unregister-PackageSource cmdlet and pipelining. The value for Scope is not pipelined to the Unregister-PackageSource cmdlet so there are occasions where it will produce the incorrect result when attempting to work on the AllUsers scope.

For example:

Register-PSRepository -Name Test -Scope AllUsers ...

Get-PackageSource -Name Test -Scope AllUsers | Unregister-PackageSource

If we are strict about requiring the AllUsers to be specified, this will result in a Not Found error because no scope will end up being passed to Remove-PackageSource so it will assume "CurrentUser" scope. If we aren't strict, then Remove-PackageSource won't assume a scope and will find the Test PackageSource and remove it.

In both implementations if the PackageSource exists in both the CurrentUser and AllUsers (a case which is possible), Get-PackageSource -Name Test -Scope AllUsers | Unregister-PackageSource will remove the wrong PackageSource. It will find Test in the CurrentUsers scope and remove it from there instead of the AllUsers scope which was pipelined. For this reason maybe this additional context is a moot point and we should simply state that using *-PackageSource for AllUsers scope is not recommended/supported.

bmanikm commented 6 years ago

@bradleywehmeier If a user is trying to unregister an AllUsers scoped repository, it is required to ensure that user has the admin privileges similar to the Uninstall and Update cmdlets.

As part of this enhancement, are you allowing the duplicate PSRepository names? I think we should allow this as the users and admin may give the same name for the psrepositories. if not, can we follow the same design as the Uninstall and Update cmdlets where -Scope parameter is not required on Unregister-PSRepository.

If we are allowing the duplicate psrepository names

Above is also applicable to the Set-PSRepository cmdlet.

We need to add -Scope optional parameter in PowerShellGet provider dynamic options for the sources at https://github.com/PowerShell/PowerShellGet/blob/development/PowerShellGet/public/providerfunctions/Get-DynamicOptions.ps1#L31 similar to https://github.com/PowerShell/PowerShellGet/blob/development/PowerShellGet/public/providerfunctions/Get-DynamicOptions.ps1#L44 For more details, please take a look at the ScriptSourceLocation dynamic option implementation in PowerShellGet provider functions.

For the pipeline operations with scope, it is required to specify -Provider PowerShellGet like below

Get-PackageSource -Name Test -Provider PowerShellGet -Scope AllUsers | Unregister-PackageSource
bradleywehmeier commented 6 years ago

@bmanikm Yes admin is required for modifications to AllUsers Scope. Dynamic Parameters have been taken care of.

Duplicate Repository names have to be supported because there is no way to avoid a situation where an admin defines an AllUsers repo that overlaps with a setting that a user has already set. In this case the user will get the instance they defined (CurrentUser scope) not the AllUsers scope.

“Scope parameter is optional for the AllUsers scoped psrepositories” answers my real question here.

With the rest having been taken care of look for a pull request in the next couple of days after I look it over one last time.

bmanikm commented 6 years ago

Also please consider validating the install and update scenarios with the duplicate psrepository names as the source locations can be different.

bradleywehmeier commented 6 years ago

Regarding the case of duplicate PSRepository names with different source locations:

The name overlap does cause problems for Update. It wants to use the PSRepository source location defined in CurrentUser regardless of what source location was used for the install.

bradleywehmeier commented 6 years ago

The more I think about it, I'm not sure if my assumption was correct.

When there are duplicate PSRepository names and one is chosen to be the "winner", I can also make an argument to treat that scenario in the same way we treat the PSRepository source location having been changed and using the source location from the "winner".

There are other rough edges with PowerShellGet like the current behavior of using a "CurrentUser" PSRepository to install "AllUsers" modules. If those are not causing issues, then maybe this confusion will also be negligible.

One alternative would be to Prefix the AllUsers scoped PSRepositories so that name collisions were not possible. I originally avoided that so that PackageManagement cmdlets (e.g. Register-PackageSource) and PowerShellGet cmdlets (e.g. Register-PSRepository) would have the same/similar parameters. If that's not something that matters since most people will be using the PowerShellGet cmdlets, I can spend some time implementing that approach to see if it has fewer issues.

Thanks all for your input on this. I appreciate the effort in helping me get this right.

bmanikm commented 6 years ago

@bradleywehmeier thanks for looking into this feature!

Some thoughts

maxwell-clarke-intranel commented 6 years ago

I also support this. I had a very confusing few hours the other day, trying to configure a proxy PowerShellGet package source through DSC. Since DSC runs as the system user, I couldn't see the repositories it was registering. I am now trying to figure out how to configure the proxy repository for all users. (Does anyone have any good solutions to that?)

tmmruk commented 5 years ago

Agreed this is much needed feature. I'm trying to use the PackageManagement DSC resource to configure our internal/proxy nexus repository as part of an OS deployment but is only applied under the NT Autority\System account. The modules install fine from the internal repo as part of the DSC config, however normal users still see the default PSGallery repo meaning they cannot pull approved and custom internal modules when required.

hematic commented 5 years ago

I just want to chime in that this causes problems using Jenkins automation as well. Jenkins agents sometimes run under system or certain service account logins and i have no good way to configure the psrepository for them.

mrhockeymonkey commented 5 years ago

+1 for this feature. We've want to move to using PowerShellGet exclusively for module distribution but we get constant requests for assistance with setting up the right repos which is slowing down adoption. This feature would solve that.

jzabroski commented 5 years ago

@SteveL-MSFT As a quick observation, this is actually a OneGet issue and not a PowerShellGet issue.

I created the following issue in OneGet to ALIGN the two projects. https://github.com/OneGet/oneget/issues/468

As Program Manager for PowerShell Core, you can facilitate, advocate for, and resource a solution to this problem!

VerdonTrigance commented 4 years ago

I can not use Register-PackageSource (or psrepository) by my service build account that has no local logon permissions. So how do I need to use all this package management mess? Should I use another solutions?

ThomasNieto commented 4 years ago

@SydneyhSmith any chance this can be added to 3.0? This is a huge missing feature in a multi-user environment.

sam-bryant commented 3 years ago

Any updates on this? Our job scheduling tools uses temporary user profiles so full automation of things that utilize that tool is not possible unless I use @KevinMarquette's solution, which I'd like to avoid.

jpatigny commented 3 years ago

Hello,

Is there any update on this topic ? This is a a much needed feature for me as my configuration manager runs as system, I cannot register PSRepositories / install modules

awickham10 commented 3 years ago

Also plus 1. Definitely needed for enterprises trying to run private repositories.

alerickson commented 3 years ago

Thanks all! We'll definitely prioritize this scenario since it's been a popular request

CasperStekelenburg commented 2 years ago

+1 for this feature!

Leenton commented 2 years ago

+1 for this feature!

Make that + 2!

SydneyhSmith commented 2 years ago

Tracking this feature work in https://github.com/PowerShell/PowerShellGet/issues/616

rvigliotti-sf commented 1 year ago

+1!

robinmalik commented 1 year ago

+1, looking forward to being able to set this and remove a fair bit of workaround code :)

XtratusCloud commented 1 year ago

+1

jakauppila commented 1 year ago

Would love to see this in an upcoming release as we would like to push out a default configuration to all of our workstations/servers to point at our PowerShell repositories in Artifactory. I see it was included in 3.0 then pulled out?

TobiasSonndag commented 2 weeks ago

Faced this issue today as well, so seems still relevant.