How to install PowerShell module pushed to Azure Artifacts in Pipelines? - powershell

Following this article I set up Pipelines to push a PowerShell module to my Artifacts feed.
I can install the module on my local machine, but I was wondering how I can do the same in Pipelines? It seems adding the NuGet source is an interactive process, so how can Pipelines add the Artifacts feed as a source?
The issue is that I don't want to have any user interaction in a CI environment.

If you are using self-hosted agent, you need to configure the folder module permission, self-hosted agent run the cmd via service account instead of personal account.
If you are using hosted agent, add the task power shell and enter below script to install the module.
$patToken = "$(pat)" | ConvertTo-SecureString -AsPlainText -Force
$credsAzureDevopsServices = New-Object System.Management.Automation.PSCredential("xxx", $patToken)
Register-PSRepository -Name "PowershellAzureDevopsServices" -SourceLocation "https://pkgs.dev.azure.com/{Org name}/{project name}/_packaging/{feed name}/nuget/v2" -PublishLocation "https://pkgs.dev.azure.com/{Org name}/{project name}/_packaging/{feed name}/nuget/v2" -InstallationPolicy Trusted -Credential $credsAzureDevopsServices
Get-PSRepository
Find-Module -Repository PowershellAzureDevopsServices -Credential $credsAzureDevopsServices
Install-Module -Name Get-Hello -Repository PowershellAzureDevopsServices -Credential $credsAzureDevopsServices
Get-Module -ListAvailable Get-Hello
Result:
Update1
We need to enter the code during the registration of the power supply enclosure repository, the method is Register-PSRepository
This is a certification issue, If we change the authentication method, maybe we don’t need to enter the code.
In addition, We could also install the module via the cmd Install-Module Get-Hello -Scope CurrentUser -Force

Related

Microsoft.IdentityModel.Clients.ActiveDirectory not loading on Azure DevOps PowerShell Release Pipeline

Recently I experienced some issue with Azure DevOps PowerShell when attempting to create a ClientCredential and or ClientAssertion. I have the following code which was working on the past for creating a ClientCredential based on the following variables:
TenantId
ClientID (SPN)
Password (SPN Password)
$ResourceUrl = "https://database.windows.net/"
$AuthorityUrl = "https://login.microsoftonline.com/$($TenantId)"
$objClientCredential = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($ClientId, $Password)
$objAuthenticationContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($AuthorityUrl)
$objAuthenticationResult = $objAuthenticationContext.AcquireTokenAsync($ResourceUrl, $objClientCredential)
but recently this code stop working. It seems that the AzureAD module is not loading correctly. This only happens on Azure DevOps Powershell, on my machine it works fine (I am using PowerShell 7.1)
So far so now I attempted the following:
Run the code as shown above
**Breaks on: **$objClientCredential = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($ClientId, $Password)
Error: Unable to find type [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]
Install AzureAD before running the code
Install-Module -Name AzureAD -Force
Import-Module -Name AzureAD
**Breaks on: **$objClientCredential = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($ClientId, $Password)
Error: Unable to find type [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]
Import the dll Microsoft.IdentityModel.Clients.ActiveDirectory.dll from my machine
Add-Type -Path ".\libraries\Microsoft.IdentityModel.Clients.ActiveDirectory.dll
Doesn't break, however ClientCredential is not created it is returned as null
Have anyone experienced a similar issue? Do you know how should I drive this?
If you run the scripts on local machine. You can check where the assembly is installed and manually import the .dll file. I tested on my local machine. It works fine when i just import the azureAd module:
Install-Module AzureAD -Force
Import-Module -Name AzureAD
If you are run the script in azure pipeline. When you install AzureAD module using Install-Module -Name AzureAD -Force in azure powershell task . You can see from the build log that AzureAD module is installed in folder C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.2.128:
And from the log, we can see assembly Microsoft.IdentityModel.Clients.ActiveDirectory.dll doesnot get loaded automatically.
So you can manually load it from module Azure AD installation folder: See below:
Install-Module AzureAD -Force
Import-Module -Name AzureAD
Add-Type -Path "C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.2.128\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$TenantId= "..."
$ClientID ="..."
$Password = "..."
$ResourceUrl = "https://database.windows.net/"
$AuthorityUrl = "https://login.microsoftonline.com/$($TenantId)"
...
$objAuthenticationResult = $objAuthenticationContext.AcquireTokenAsync($ResourceUrl, $objClientCredential).Result
See below result.

Connect-AzAccount : The term 'Connect-AzAccount' is not recognized as the name of a cmdlet, function, script file, or operable program

I am trying to execute the following PowerShell script in Azure DevOps pipeline by using PowerShell task with inline mode.
$clientId= "xxxxxxxxx"
$clientSecret= "xxxxxxx"
$subscriptionId= "xxxxxxxx"
$tenantId= "xxxxxxxxxxxxx"
# sign in
Write-Host "Logging in...";
$SecurePassword = $clientSecret | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $clientId, $SecurePassword
Connect-AzAccount -ServicePrincipal -Credential $cred-Tenant $tenantId
# set azure context with subscriptionId
Set-AzContext -SubscriptionId $subscriptionId
# select subscription
Write-Host "Selecting subscription '$subscriptionId'";
Select-AzSubscription -SubscriptionId $subscriptionId;
But I am getting the following error:
Connect-AzAccount : The term 'Connect-AzAccount' is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
It is possible that the module this command belongs to - 'Az' isn't present/have to be imported. In which case,
Case-1
Open Powershell as Administrator
Install module - Install-Module Az
Import-Module Az
Your command - Connect-AzAccount should work now.
For case-2
Import module using - Import-Module Az.Accounts
For me this was the issue - AzureRM and AZ both were installed.
In Windows PowerShell, check that you have AzureRM installed:
Get-InstalledModule -name AzureRM
use command Uninstall-AzureRM to remove it.
If above command doesn't work use below one
Get-Module -ListAvailable | Where-Object {$_.Name -like 'AzureRM*'} | Uninstall-Module
Next ->
Set executionPolicy to RemoteSigned for powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Next ->
Install the Az PowerShell Module in Windows PowerShell
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
Next ->
type Connect-AzAccount and complete the signing flow.
I would recommend you to switch to AzurePowershellTask as you find there preinstalled modules:
You can also try install modules on your own as it is shown here but this is pointless since you can leverage existing task.
In my case, AZ wasn't successfully installed because some AZ modules were already installed with AzureRM. I added the parameter -AllowClobber and now all the AZ modules are now installed.
Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -AllowClobber
Uninstalling AzureRM with command Uninstall-AzureRM may also be a great solution, because you're not going to use AzureRM anymore. Microsoft is going to stop supporting it sometimes in February 2024.
Try using
Login-AzAccount
instead of
Connect-AzAccount

Issues with PowerShell Repositories on Azure DevOps Agents

Sorry for the very long post, but I am really stuck and hope someone can help.
I've been back and forth so many times and I am hitting many issues with everything that has to do with PowerShell repositories and Azure DevOps agents.
The end goal is to have the latest versions of some PowerShell modules installed as part of a pipeline.
I write various PowerShell modules, package them as NuGets and push them to different repositories (Azure DevOps artifacts, SonaType Nexus OSS)
I then need these modules installed as part of other pipelines.
As there is no built-in way in Azure DevOps to handle PowerShell repositories and import modules, I wrote a script that takes the repository location, name and credentials as parameters, verifies it is registered and installs the module.
When I run this script on ANY machine, it works perfectly
When this script is a PowerShell task on any pipeline - it has various failures, always with cmdlets from PackageManagement
I thought this is because the agent is running it with -NoProfile, but it works for me when I run the script exactly how the agent runs it - "powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'C:.....'"
I also tried running a cmd task and calling PowerShell to run the script but had the exact same results
The problems I am hitting are:
Get-PSRepository returns NOTHING. Not even PSGallery
When I try to register a repository (using either Register-PSRepository or Register-PackageSource) it throws an error:
PackageManagement\Register-PackageSource : The property 'Values' cannot be found on this object. Verify that the property exists.
as part of my script, I am running these cmdlets to make sure all the required modules are there:
$webclient=New-Object System.Net.WebClient; $webclient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Install-PackageProvider -Name NuGet -RequiredVersion 2.8.5.208 -Force -Confirm:$false -Verbose; Install-Module PowerShellGet -RequiredVersion 2.2.4 -SkipPublisherCheck -Verbose -Force;
Another error that comes up is this:
PackageManagement\Get-PackageSource : Unable to find repository 'PSGallery'. Use Get-PSRepository to see all available repositories.
I spent hours on this.
What is the correct way to install PS modules from a 3rd party repository (NuGet-based)
Thanks
I noticed that you have push your nuget package to Azure Artifacts.
You could add Powershell tasks to the pipeline and run the following scripts:
Register-PSRepository:
$patToken = "PAT" | ConvertTo-SecureString -AsPlainText -Force
$credsAzureDevopsServices = New-Object System.Management.Automation.PSCredential("email address", $patToken)
Register-PSRepository -Name "PowershellAzureDevopsServices" -SourceLocation "https://pkgs.dev.azure.com/<org_name>/<project_name>/_packaging/<feed_name>/nuget/v2" -PublishLocation "https://pkgs.dev.azure.com/<org_name>/<project_name>/_packaging/<feed_name>/nuget/v2" -InstallationPolicy Trusted -Credential $credsAzureDevopsServices
Then you could register successfully.
Note: I suggest that you could create a Project Scope feed. Or you may get some issues.
Then you could run the following scripts to install the module.
Find-Module -Repository PowershellAzureDevopsServices
Install-Module -Name Get-Hello -Repository PowershellAzureDevopsServices
For more detailed information, you could refer to this Guidance Document.

Upgrade AzureRM Powershell on Hosted 2017 Agent (VSTS - Visual Studio Team Services)

I am using release management through Visual Studio Teams Services (online). We use Hosted build Agents and I really want to avoid the overhead of managing custom agents.
One item I do need is the AzureRM PowerShell module. Versions up to 5.1.1 are available on the agent but I need 6.0.0.
What I would like to do is use a step in my release process (PowerShell) to aquire version 6.0.0 and use thart instead, however I cant quite get it to work. I have tried a few approaches that have all come unstuck, the current one is:
Write-Output "------------------ Install package provider ------------------"
Find-PackageProvider -Name "NuGet" | Install-PackageProvider -Scope CurrentUser -Force
Write-Output "------------------ Remove Modules ------------------"
Get-Module -ListAvailable | Where-Object {$_.Name -like 'AzureRM*'} | Remove-Module
Write-Output "------------------ Install the AzureRM version we want - 6.0.1! ------------------"
Install-Package AzureRM -RequiredVersion 6.0.1 -Scope CurrentUser -Force
Write-Output "------------------ Import AzureRM 6.0.1 ------------------"
Import-Module AzureRM -RequiredVersion 6.0.1
This all works fine (i.e. does not crash...) but then when I try and use one of the 6.0.1 cmdlets I get an error.
Get-AzureRmADGroup : The Azure PowerShell session has not been
properly initialized. Please import the module and try again.
Any idea of where I am going wrong or alternate strategies I can use to deploy AzureRM 6.0.1 and use it on a hosted agent?
Thanks to Murray for the initial point in the right direction, to show what I was hoping to do wasn't impossible!
I initially tried to do this within the Azure PowerShell task and got pretty far but hit a dead end with AzureRm.Profile as you cannot unload an old version.
The trick was to understanding how the AzureRM VSTS task does it's dependency setup, it effectively takes the "Azure Powershell Version" string in the VSTS UI and uses it to define an additional search path in the PSModules environmental variable i.e. C:\Modules\azurerm_5.1.1.
It will look in that directory, before searching the user profile, then the global modules path.
As soon as it finds the module it performs the Azure login, which will hamper any hope of removing the module after.
So if you instead use a plain powershell task i.e. one that AzureRM isn't loaded into (as Murray also concluded):
Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
Install-Module -Name AzureRM -RequiredVersion 6.2.1 -Force -Scope CurrentUser -AllowClobber
Notably install-module won't be installing to c:\modules like the vsts image generation project.
I seemed to need AllowClobber to get around problems overriding old powershell versions when experimenting, but I suspect I don't need that anymore.
The elegant solution kicks in when next using the Azure PowerShell script.
The preferred powershell version field filled in with 6.2.1 will add C:\Modules\azurerm_6.2.1 to the PSModules path. This doesn't exist, but thankfully because PSModules still includes the user specific modules path, so our 6.2.1 is loaded by itself!
Luckily the AzureRM.Profile from 5.1.1 is forwards compatible enough that the service principal login performed by the Azure Powershell task still works.
Running
Get-Module AzureRm
Get-AzureRmContext
Will output the versions you are hoping for:
Notably if it weren't able to login, I think System.AccessToken could be used (if the option is switched on in the agent phase level).
Diagnostic Techniques if the workaround needs tweaking:
Things that helped greatly, reading through the code that loads in AzureRM in the task:
https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/AzurePowerShellV3/AzurePowerShell.ps1#L80
https://github.com/Microsoft/vsts-tasks/blob/0703b8869041d64db994934bde97de167787ed2e/Tasks/Common/VstsAzureHelpers_/ImportFunctions.ps1
https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/AzurePowerShellV3/Utility.ps1#L18
And also how the VSTS image is generated:
https://github.com/Microsoft/vsts-image-generation/blob/2f57db26dc30ae0f257a3415d26eaa8eea0febf9/images/win/scripts/Installers/Install-AzureModules.ps1
Enabing System.Debug = true as a environment release variable.
Then using VSCode's Log File Highlighter plugin
I'd encourage anyone who's interested to vote in: https://github.com/Microsoft/vsts-image-generation/issues/149
As the AzureRM version at the time of writing is waaaay out of date on the VSTS Hosted 2017 agent.
Unfortunately I can't submit a PR to upgrade it, as it's pulled in via a zip file hosted privately.
I finally figured it out - adding an answer for anyone else that suffers the same.
The key is to login after the AzureRM module is upgraded.
PowerShell code:
Write-Output "------------------ Start: Upgrade AzureRM on build host ------------------"
Write-Output "- - - - - Install package provider"
Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
Write-Output "- - - - - List Modules Before"
Get-Module -ListAvailable| where {$_.Name -Like “*AzureRM*”} | Select Name, Version
Write-Output "- - - - - Remove alll existing AzureRM Modules"
Get-Module -ListAvailable | Where-Object {$_.Name -like '*AzureRM*'} | Remove-Module -Force
Write-Output "- - - - - Install AzureRM 6.0.1"
Install-Module -Name AzureRM -RequiredVersion 6.0.1 -Force -Scope CurrentUser
Write-Output "- - - - - Import AzureRM 6.0.1"
Import-Module AzureRM -Force -Verbose -Scope Local
Write-Output "- - - - - List Modules After"
Get-Module -ListAvailable| where {$_.Name -Like “*AzureRM*”} | Select Name, Version
Write-Output "------------------ End: Upgrade AzureRM on build host ------------------"
Write-Output "------------------ Start: LoginToAzure ------------------"
$SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
$AdminCredential = New-Object System.Management.Automation.PSCredential ($AdminUserEmailAddress, $SecurePassword)
Login-AzureRmAccount -Credential $AdminCredential
Get-AzureRmSubscription –SubscriptionId $SubscriptionId | Select-AzureRmSubscription
Write-Output "------------------ End: LoginToAzure ------------------"

WARNING: Unable to find module repositories

I tried to install Docker on activated windows server 2016 standard.
I executed “Install-Module -Name DockerMsftProvider -Repository PSGallery -Force” but failed. It suggested that can not find PSGallery. I executed "Get-PSRepository".
The error:
WARNING: Unable to find module repositories.
I googled 3 ways to solve it but none of them worked.
I executed Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Verbose -Force successfully.
I installed chocolatey successfully.
I execute "powershell Register-PSRepository -Name "PSGallery" –SourceLocation "https://www.powershellgallery.com/api/v2/" -InstallationPolicy Trusted" but failed. It asked me to use "Register-PSRepository -Default".
I tried "powershell Register-PSRepository -Default -Name "PSGallery" –SourceLocation "https://www.powershellgallery.com/api/v2/" -InstallationPolicy Trusted" but still failed.
How can I solve this problem?
With the deprecation of TLS 1.0 and 1.1 for PowerShell Gallery as of April 2020, the cmdlets Update-Module and Install-Module became broken. Thus, according to this article, some commands need to be executed to bring them alive again:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-Module PowerShellGet -RequiredVersion 2.2.4 -SkipPublisherCheck
If that still doesn't work, then run the following commands:
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
Register-PSRepository -Default -Verbose
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
TLS 1.0 and 1.1 were also recently deprecated at NuGet.org:
But that was also previously announced.
Simply running Register-PSRepository -Default (without any additional parameters) worked for me. After that, the Gallery was successfully registered:
PS C:\Windows\system32> Get-PSRepository
Name InstallationPolicy SourceLocation
---- ------------------ --------------
PSGallery Untrusted https://www.powershellgallery.com/api/v2/
My problem was the missing Proxy config
best solution from comments:
https://www.zerrouki.com/working-behind-a-proxy/
thanks to #Vadzim
In PowerShell open Profile
PS> notepad $PROFILE
this opens Notepad with your profile setting, will be created of not exists.
then add:
[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://webproxy.yourCompany.com:PORT')
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
somehow my local proxy is set but doesn't work.
same problem later with Docker, =>
> PS> [Environment]::SetEnvironmentVariable("HTTP_PROXY", http://username:password#proxy:port/", [EnvironmentVariableTarget]::Machine)
then restart docker service
I got a similar message. I ran Register-PSRepository -default and it registered ok. Then I ran Set-PSRepository -Name PSGallery -InstallationPolicy Trusted. I didn't combine the commands, but it worked.
I spent over an hour trying to pass credentials to the proxy the same way I do for Exchange Online, but no love. I disconnected and used our guest WiFi instead.
One more thing which hasn't been mentioned.
You would indeed need to run
notepad $profile
and copy paste this bit changing your proxy details:
[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://webproxy.yourCompany.com:PORT')
[system.net.webrequest]::defaultwebproxy.credentials = System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
But if you have HTTPS Inspection turned on, you might want to add the Man-in-the-middle Certificate to the "Trusted Root Certification Authorities"