Get-CredentialInfo cmdlet request
Prerequisites
- [X] Write a descriptive title.
- [X] Make sure you are able to repro it on the latest released version
- [X] Search the existing issues.
Steps to reproduce
Hi,
I was following the this article in order to register an Azure artifact reposistory. It specifically mentions: You can also use with the -Credential parameter.
I used the following snippet to try the register the PsResource:
import-module Microsoft.PowerShell.PSResourceGet -force
$Credential = Get-Credential -UserName "[email protected]" -Message "Enter your ADO credentials" #generated the PAT as described in the article
$FriendlyName = "MyFriendlyName"
$ProjectName = "MyProjectName"
Register-PSResourceRepository -Name $FriendlyName -Uri "https://pkgs.dev.azure.com/$($ProjectName)/_packaging/$($ProjectName)/nuget/v3/index.json" -Credential $Credential
But I get the following error:
Cannot bind parameter 'CredentialInfo'. Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type
| "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
I guess this is a
Expected behavior
It should register the repository
Actual behavior
Cannot bind parameter 'CredentialInfo'. Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type
| "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
Error details
Exception :
Type : System.Management.Automation.ParameterBindingException
Message : Cannot bind parameter 'CredentialInfo'. Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
ParameterName : CredentialInfo
ParameterType : Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo
TypeSpecified : psobject
ErrorId : CannotConvertArgumentNoMessage
Line : 1
Offset : 166
CommandInvocation :
MyCommand : Register-PSResourceRepository
BoundParameters :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys :
Length : 4
Length : 3
Values :
Length : 13
Length : 93
SyncRoot :
Comparer : System.OrdinalIgnoreCaseComparer
Count : 2
Keys : …
Values : …
SyncRoot : …
ScriptLineNumber : 1
OffsetInLine : 1
HistoryId : 26
Line : Register-PSResourceRepository -Name "FeedDistrict2" -Uri "https://pkgs.dev.azure.com/DigitalDistrict01/_packaging/DigitalDistrict01/nuget/v3/index.json" -Credential $Credential
PositionMessage : At line:1 char:1
+ Register-PSResourceRepository -Name "FeedDistrict2" -Uri "https://pkg …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InvocationName : Register-PSResourceRepository
PipelineLength : 1
PipelinePosition : 1
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot bind parameter 'CredentialInfo'. Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
HResult : -2146233087
CategoryInfo : InvalidArgument: (:) [Register-PSResourceRepository], ParentContainsErrorRecordException
FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.PSResourceGet.Cmdlets.RegisterPSResourceRepository
InvocationInfo :
MyCommand : Register-PSResourceRepository
ScriptLineNumber : 1
OffsetInLine : 166
HistoryId : 26
Line : Register-PSResourceRepository -Name "FeedDistrict2" -Uri "https://pkgs.dev.azure.com/DigitalDistrict01/_packaging/DigitalDistrict01/nuget/v3/index.json" -Credential $Credential
PositionMessage : At line:1 char:166
+ … kaging/DigitalDistrict01/nuget/v3/index.json" -Credential $Credential
+ ~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
TargetSite :
Name : CoerceTypeAsNeeded
DeclaringType : System.Management.Automation.ParameterBinderBase, System.Management.Automation, Version=7.3.4.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35
MemberType : Method
Module : System.Management.Automation.dll
Data : System.Collections.ListDictionaryInternal
InnerException :
Type : System.Management.Automation.PSInvalidCastException
ErrorRecord :
Exception :
Type : System.Management.Automation.ParentContainsErrorRecordException
Message : Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
HResult : -2146233087
CategoryInfo : InvalidArgument: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : ConvertToFinalInvalidCastException
TargetSite :
Name : ThrowInvalidCastException
DeclaringType : System.Management.Automation.LanguagePrimitives
MemberType : Method
Module : System.Management.Automation.dll
Message : Cannot convert the "System.Management.Automation.PSCredential" value of type "System.Management.Automation.PSCredential" to type "Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo".
Source : System.Management.Automation
HResult : -2147467262
StackTrace :
at System.Management.Automation.LanguagePrimitives.ThrowInvalidCastException(Object valueToConvert, Type resultType)
at System.Management.Automation.LanguagePrimitives.ConvertNoConversion(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
at System.Management.Automation.LanguagePrimitives.ConversionData`1.Invoke(Object valueToConvert, Type resultType, Boolean recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion, IFormatProvider formatProvider, TypeTable backupTypeTable)
at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
Source : System.Management.Automation
HResult : -2146233087
StackTrace :
at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
at System.Management.Automation.CmdletParameterBinderController.BindNamedParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter)
at System.Management.Automation.ParameterBinderController.BindNamedParameters(UInt32 parameterSets, Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location ---
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo : InvalidArgument: (:) [Register-PSResourceRepository], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.PSResourceGet.Cmdlets.RegisterPSResourceRepository
InvocationInfo :
MyCommand : Register-PSResourceRepository
ScriptLineNumber : 1
OffsetInLine : 166
HistoryId : 26
Line : Register-PSResourceRepository -Name "FeedDistrict2" -Uri "https://pkgs.dev.azure.com/DigitalDistrict01/_packaging/DigitalDistrict01/nuget/v3/index.json" -Credential $Credential
PositionMessage : At line:1 char:166
+ … kaging/DigitalDistrict01/nuget/v3/index.json" -Credential $Credential
+ ~~~~~~~~~~~
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
Environment data
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Binary 0.5.22 beta22 Microsoft.PowerShell.PSResourceGet {Find-PSResource, Get-InstalledPSResource, Get-PSResourceRepository, Get-PSScriptFileInfo…}
Name Value
---- -----
PSVersion 7.3.4
PSEdition Core
GitCommitId 7.3.4
OS Microsoft Windows 10.0.22000
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
The problem is literally in the error message you provided: the "Credential" parameter for this cmdlet doesn't accept a pscredential object like you would expect it to, but instead is looking for a "PSCredentialinfo" object that is native to the psresourceget module (Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo). The actual problem is that Microsoft, in its infinite wisdom, has not created documentation that tells us how to create instances of this new object, since the documentation that they link to on the main github page literally links to help content for the very first version of the module, which is completely unacceptable. I would tell microsoft to get its act together, but it is clear where their priorities lie, and it is not in making this an easy to use, quality module.
I for one, had to use Ilspy to look at the resources defined in the psresourceget module in order to find the answer on my own (thanks for absolutely nothing, Microsoft), and this is what I found:
public PSCredentialInfo(string vaultName, string secretName, PSCredential credential = null)
{
VaultName = vaultName;
SecretName = secretName;
Credential = credential;
}
So, this would indicate to me that, in order to create the pscredentialinfo object, you need to install the Microsoft.PowerShell.SecretManagement and Microsoft.PowerShell.SecretStore powershell modules, which allows you to create local secret vaults in which you can store and pull secrets. But, this is just an educated guess, as, again, microsoft hasn't said a thing about this.
Hi @youngturk2, there's no need for aggressive comments, you can read the code of conduct we abide by and ask users to abide by as well here: code of conduct. We are currently working on documentation, you can look at the tests in this repository for examples of how to use the PSCredentialInfo object in the meanwhile: PSCredentialInfoTests The parameter also takes a hashtable, so it's not necessary to pass in the object itself.
Hi @alerickson
It was very clear to me that a PsCredentialInfo instance was requested. What surprised me, is the fact that up until now, is that the -Credential has been used on so many different cmdlets, and it standardly asks for an object of type pscredential.
In this case, t_o me that actually felt like a bug_, as I was actually expecting the the parameter -credential to expect a pscredential NOT a PscredentialInfo
Just for completness, I add the extract to the article released on the powershell blog not so long ago:
Azure DevOps Feeds To get the uri for your feed go to dev.azure.com > Artifacts > select desired feed > click “Connect to Feed” > choose “NuGet.exe”. then runRegister-PSResourceRepository -Name "AdoFeedName" -Uri <My_ADO_Feed_Uri> If it is a public feed creds arent needed. If it is a private feed go to dev.azure.com > User Settings in top right corner > Personal Access Tokens > Create PAT token. In your PowerShell terminal, create credential with your username as your email account used for ADO, password will be PAT token from prior step. To use the credential persistence feature of PSResourceGet reference the docs. You can also use with the -Credential parameter.
to me, how it is written there, it sounds like you can either use the persistance feature OR use the (good old) -credential parameter.
In other terms, IF you don't wan't to use the credential persistence feautre, you don't have to. But in this case, it doesn't work I would say.
This would make sense, as it would follow the standard that has been in place since the beginning of powershell. It would become quite a mess and very confusing for the users if suddently we would have official cmdlets that would accept a PsCredential object, and others that would accept PsCredentialInfo.
I feel like the intention of -Credential was not to be able to pass a PsCredentialInfo, but that it was for (the good old) PsCredential type. (which would feel completley logic to me).
may be the good choise will be renaming -Credential to -CredentialInfo to show that they are different types
Yes, I agree that we should rename the -Credential parameter as it brings to much confusion. tagging @SydneyhSmith for visibility.
I completely agree, -CredentialInfo makes more sense here
I just took a closer look to address this issue, but Register-PSResourceRepository actually does not have a -Credential parameter, only a -CredentialInfo parameter. Somehow the parameter binding mapped it to CredentialInfo which caused a bit of confusion. So really the issue is that the blog post should have said -CredentialInfo. Sorry for the confusion about that, I should've caught that earlier. If there's any other issues with Credentials, comment here and I can reopen this issue, or feel free to open up a new issue.
Hi, you are right @alerickson , my bad, I didn't see it as well.
I still think there is some confusing around the -CredentialInfo parameter. There seem to be no existing cmdlet that allows one to get the object of type CredentialInfo.
Look at this example:
In order to register a PsRessource registry, I need to pass a PsCredentialInfo, but neither of the cmdlets actually return me an object of that type.
Get-Secret returns a System.Management.Automation.PSCredential
Get-SecretInfo returns a Microsoft.PowerShell.SecretManagement.SecretInformation
Maybe I missed it, but the only way I found to get a PsCredentialInfo is via the example below.
$PsCredentialInfo = [Microsoft.PowerShell.PSResourceGet.UtilClasses.PSCredentialInfo]::new("SecretStore","mod_prd")
$url = "https://pkgs.dev.azure.com/MyLongURL"
Register-PSResourceRepository -Name "syn_mod_prd" -Uri $Url -Force -CredentialInfo $PsCredentialInfo -Trusted
I am surprised, as I was really thinking that Get-SecretInfo would give me the right type. (Or perhaps I am doing something wrong?)
I believe this is a bit confusing, as we have 3 different type of credentials now, and the one we actually need for the Register-PsSressourceRepository can only be created using this method above, which might not be very accessible to everyone.
Wouldn't it make sense to have a Get-CredentialInfo cmdlet?
@alerickson could you please re-open the ticket? looks like i cant my self
One thing to consider is that -CredentialInfo also takes a hash table like -CredentialInfo @{ VaultName = 'VaultName'; SecretName = 'SecretName' }... but agree that a cmdlet would be a good feature request!
Sorry if this appears as just a "+1" comment, but I'd like to re-iterate how confusing the current setup and documentation is. (Found this GH issue searching for similar answers, even though I have the version of the module that at least has the correct parameter name. Somehow I ended up trying to use [Microsoft.PowerShell.PowerShellGet.UtilClasses.PSCredentialInfo] which of course doesn't exist.)
Thinking about this a bit, I think there's two main contributors:
Parameter/Object Type(Class?) name:
CredentialInfo/PSCredentialInfo are misleading names - there's nothing there that would lead me to think it was related to the SecretManagement modules. This is especially problematic because PSCredential is such a commonly used Type.
Why is creating and passing in a new type (that I've never encountered before) even required? (It's fine/preferred to keep supporting it, of course). I'd request/suggest a new parameter set for the PSResourceRepository commands that just takes the same two strings we currently use to create the credentialinfo object.
My personal preference/wish would be to rename PSCredentialInfo to something like PSSecretManagementInfo, or whatever Class is already used in SecretManagementInfo. (I realize that's a bigger lift.)
Documentation:
Having both PowershellGet and PSResourceGet under the same documentation area, combined with how the version selection works is confusing. It's weird, at best, to be at https://learn.microsoft.com/en-us/powershell/gallery/powershellget/how-to/credential-persistence?view=powershellget-2.x , reading about PSResourceGet. I've been working w/ Powershell for around 10 years now, and I was still getting confused - I can't imagine how it must be for someone coming in fresh.
I believe the documentation should better call out:
- That you're just setting up a reference - that the vault/store will need to be unlocked per the usual rules when used in the future, or any other subtleties in how it works.
- The object in the secretstore must be a
PSCredential. (I know it's the same as using the -credential param, but it's still surprising because if you're using a PAT, the username is not used)
Update to the above, just stumbled upon another PSCredentialInfo class https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.commands.automation.model.credentialinfo - different namespaces, but still.
But why is it not possible to call Register-PSResourceRepository using a PSCredential instance? Why do you need to have this as Secret management objects?
It was mentioned somewhere that PSCredential was possible to pass in to the Install-PSResource cmdlet. But what should you then pass in the Repository parameter? According to documentation, if Repository is not specified, it will search all registered repositories. So would the Repository parameter then have to be the full web address for the repository to use?
Same thing goes for the Publish-PSResource. It takes a Repository parameter being a string, and the examnple uses the value TestRepository. But if this is not already registered, how does Publish-PSResource find out where it is? Or shold this also be a full web address for the repository?
Right now, I'm trying to publish a Powershell module to my organizations GitHub Packages repository. Earlier in 2024, I was able to call Register-PSResourceRepository passing in a PSCredential instance and then use my freindly name for the repository. However, I happended to unregister this repository, and now I'm not able to re-register the repository.
And what if you have a local file based repository? How to you call Register-PSResourceRepository to allow installing and publishing to a LocalNuget repository located for example in C:\LocalNuget. What should I pass in as PSCredentialInfo? Simply dummy values?
I really do not see this as user freindly.