Open Jaykul opened 5 years ago
I ran into the same problem as many here, where you are constantly taken to the device flow even thought it seems like you should not be. But using the troubleshooting tips for the Azure Artifacts Credential Provider I figured out that our Azure DevOps authentication setup required multifactor authentication. Maybe that's why I was getting the device flow so much? But even if that's not it, I found a reasonable alternative that means I don't need to enter credentials all the time.
The key is to setup the VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
environment variable as talked about here. You follow mostly the steps in Use an Azure Artifacts feed as a private PowerShell repository but instead of passing credentials, you rely on VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
.
So basically this:
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
to something like: '{"endpointCredentials": [{"endpoint":"https://pkgs.dev.azure.com/<organization>/_packaging/<feed>/nuget/v2", "username":"<youremail>, "password":"<pat>"}]}'
Register-PSRepository -Name "YourFeedName" -SourceLocation "https://pkgs.dev.azure.com/<organization>/_packaging/<feed>/nuget/v2" -PublishLocation "https://pkgs.dev.azure.com/<organization>/_packaging/<feed>/nuget/v2" -InstallationPolicy Trusted
Register-PackageSource -Name "YourFeedName" -Location "https://pkgs.dev.azure.com/<organization>/_packaging/<feed>/nuget/v2" -ProviderName NuGet -Trusted -SkipValidate
Install-Module
to work.Find-Module -Repository YourFeedName
Setting up the VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
environment variable may make you uneasy. But for me it's like using a PAT in a nuget.config
like I've done in the past. But you do have to remember to re-generate the PAT and update the environment variable when it expires.
@twinter-amosfivesix can you try using our latest prerelease version (can be found here). There is an integration with the SecretMangement module that allows for a smoother experience with handling credentials and credential persistence.
@twinter-amosfivesix that's a pretty hefty amount of prerequisites. I was just trying to come up with some simple instructions for people to install a utility module from our Azure Artifacts. For CI/CD that's fine, but just to get a module that's a lot of hoops.
@alerickson I tried the latest prerelease and couldn't get it working but maybe the steps are different since all the commands changed in psg 3.0. IDK... I'm giving up on this and telling people to store their pat in a file and pass -Credential everywhere. Nothing else works.
@CodyBatt Yes credential management is different in PowerShellGetV3. It relies on Microsoft.PowerShell.SecretsManagement module, and you can look at this blogpost to get familiar with SecretsManagement, install that module and set up a vault. In order for credential persistence to work with PSGet, it needs SecretsManagement, otherwise if it's not there it will automatically give an error. After the vault is set up with SecretsManagement then all you need to do is create a PSCredentialInfo object like this example here (which assumes you have a vault named "testvault"
already).
You should register (or set) the repository with the -CredentialInfo
, like this example here
We'll put out a blogpost by end of this month to show all the steps for working with Credentials in PSGetV3, thank you for sharing this feedback!
@anamnavi Right, I tried to set it up with SecretsManagment and didn't get anywhere. Succinct documentation for getting it set up will be a big help.
@twinter-amosfivesix In case you rely on the command during a pipeline, you don't even need to do it manually. It suffices to add a NuGet Authenticate step which creates the environment variable for you. That way you don't need to store a PAT somewhere. Instead it will be generated with the appropriate permissions that the agent actually has.
Sorry I never got any notifications about replies. I was just trying this again recently and I was not getting the repeated prompt for credentials. Still using PSGetV2. So not sure what was going on there.
And yes NuGet Authenticate is what you'd use in an Azure DevOps pipeline. I haven't gotten there yet.
@twinter-amosfivesix are you able to try using PowerShellGetV3? If so, please see my earlier message about using credential management with PSGetV3, thanks!
I did a deep dive today to come up with a cleaner process for using Azure Artifact Feeds that I could hand off to non-technical people. During that dive I found that the "easiest" work-around may just be to have Visual Studio installed. There's more detail below if anyone is interested.
The cleaner process for downloading from feeds using PowerShellGet v2 that I came up with today follows.
One time do this:
install-module powershellget -force -allowclobber
iex "& { $(irm https://aka.ms/install-artifacts-credprovider.ps1) } -AddNetfx"
That gets you the latest version of PowerShellGet and installs the Azure Artifacts Credential Provider. You will need to restart your PowerShell window after you've done the above steps.
Then in PowerShell you can do this:
$repositoryName = <your repository name>
$packageLocation = <your artifacts feed v2 uri>
$vssCredentialProvider = "$env:UserProfile\.nuget\plugins\netfx\CredentialProvider.Microsoft\CredentialProvider.Microsoft.exe"
$tokenJson = ConvertFrom-Json (& $vssCredentialProvider -U $packageLocation -F Json)
$pscred = new-object PSCredential -ArgumentList $tokenJson.Username, (ConvertTo-SecureString $tokenJson.Password -AsPlainText -Force)
Register-PsRepository $repositoryName -SourceLocation $packageLocation -PublishLocation $packageLocation -InstallationPolicy Trusted -Credential $pscred
$moduleName = <name of your module>
install-module $moduleName -SkipPublisherCheck -Credential $pscred
import-module $moduleName -Force
The VssCredentialProvider variable can have "netfx" replaced with "netcore" if you're running in PowerShell Core.
You can get around the credentials request by installing Visual Studio due to a bug where PowerShellGet presumes that $env:NUGET_PLUGIN_PATHS
will be set to the location of the credential provider. This always fails on Windows since that environment variable is the root directory where Nuget gets its plugins not a direct pointer to the credential provider. The module really needs to go looking for the credential provider. Linux and MacOS work though since that case falls through to a .NET Core specific scenario and builds out the entire path to the credential provider.
Windows thus always fails the first check for the credential provider and falls back to "vswhere" to locate the provider. If you don't have Visual Studio installed then the check fails.
However, even if you solve the problem by pointing $env:NUGET_PLUGIN_PATHS to the credential provider you've only won half the battle. Your registration will work and even Find-Package
will work but install-module
and install-package
will fail because they cannot authenticate to the feed. I've tried install-package -verbose -debug
to narrow down what exactly is going wrong but without something to debug into the output isn't useful. I cannot even locate the source that is raising the issue.
I hope this helps anyone else having the same issue.
We'll put out a blogpost by end of this month to show all the steps for working with Credentials in PSGetV3, thank you for sharing this feedback!
@anamnavi did the blog post get created? Can you link it here?
What is the status of this? It seems that Install-PSResource
and Find-PSResource
still do not work properly with Azure Artifacts and the Azure Artifacts Credential Provider in Microsoft.PowerShell.PSResourceGet v1.0.3; they result in a 401 (Not Authorized)
error.
The Install-Module
and Find-Module
commands work properly though when registered with the same repository URI, so I know that the Azure Artifacts Credential Provider is setup properly.
What's worse though is it seems that the latest version 3.0.23 of PowerShellGet has broken the Install-Module
and Find-Module
commands completely; see https://github.com/PowerShell/PowerShellGet/issues/58. Luckily I still have PowerShellGet v3.0.12 installed so the commands still work on my local machine, but new servers that I'm setting up are not able to connect to our Azure Artifacts feed without the -Credential
parameter.
I created the AzureArtifactsPowerShellModuleHelper module a while back to help solve this issue, but found that sometimes even with that module PowerShellGet 2.2.5 still couldn't access the feed and we'd need to use the prerelease v3 version. With v3.0.23 broken though, and older v3 versions delisted and thus can't be installed, there's not much we can do when v2.2.5 has issues.
Here's a screenshot showing the issue. If you need any other information for troubleshooting let me know; I'm happy to provide anything that can help get this issue resolved.
I noticed afterward that this issue is for PowerShellGet v2. I've opened this new issue in the PSResourceGet repo: https://github.com/PowerShell/PSResourceGet/issues/1601
I don't know why PowerShell/PowerShellGetv2#133 was closed when this is still so COMPLETELY BROKEN
We cannot work with repositories that require credentials unless we ... ... pass credentials ... with every, ... single ... call.
That's not how any of this is supposed to work.
For example, following the docs for the Azure Artifacts CredProvider, and the blog post from earlier this month we should be able to install the credential provider:
Set something like this:
Register the feed:
And get a list of modules:
But what actually happens is that with no error I get no results.
But if I try it with nuget:
It works fine, and I get a list of modules...
YOU'RE DOING IT WRONG
The problem is that PowerShellGet isn't looking up the credentials against the feed address.
Instead, it's looking up (or rather, relying on nuget to) the credentials against the final url with all the parameters in it. So we can make the
Find-Module
command work if we change the stored endpoint to this:And then re-run:
But this is because I've hard-coded the token to a particular search.
Of course the result is that when we don't use the environment variable (i.e.
Remove-Item ENV:VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
) and do aFind-Module
we get a "devicelogin" from the credential provider, but the credentials are cached for that specific URL, so if weFind-Module
for any other specific module, or try anything else (likeInstall-Module
), they will fail to find the cached credentials, and require going through the "devicelogin" again...The worst part is that each time we go through the device login, you're creating a new PAT token that you'll never re-use...
Please, fix it again.