Azure / azure-powershell

Microsoft Azure PowerShell
Other
4.25k stars 3.85k forks source link

Connect-AzAccount: "The term 'Connect-AzAccount' is not recognized as a name of a cmdlet" when run as a non-root user in Azure DevOps #19177

Open ElvenSpellmaker opened 2 years ago

ElvenSpellmaker commented 2 years ago

Description

Azure DevOps uses the vsts_azpcontainer user which it directly injects into the container at run-time.

This breaks the build as the module seems to have moved from /usr/local/share/powershell/Modules to /root/.local/share/powershell/Modules which obviously can't be accessed by non-root users.

The container that works: image

The container that doesn't: image

As you'll see the location, of the module has moved which breaks non-root users such as those injected by Azure DevOps: image

This appears similar to #18928 but I'm not sure it it's the same cause.

SHA of an image that worked and didn't: ✅: sha256:163586739f74a02282a4c2b7f12805b596d6ada983a0ff729196af18ec8c823a ❌: sha256:d7da797d627a135b31acb15329c8a949f06caa963e7c99fc04e63b70d839df75

Issue script & Debug output

set-pwsh-az-context.ps1: /__w/_temp/fe2972d1-5061-468f-a7ba-0d58d439707f.ps1:2
Line |
   2 |  . '/__w/1/pipeline-scripts/Azure/set-pwsh-az-context.ps1' -clientID ' …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The term 'Connect-AzAccount' is not recognized as a name of a
     | cmdlet, function, script file, or executable program. Check
     | the spelling of the name, or if a path was included, verify
     | that the path is correct and try again.

##[error]PowerShell exited with code '1'.

set-pwsh-az-context.ps1:

param(
  [Parameter(Mandatory = $true)]
  [string]
  $clientID,

  [Parameter(Mandatory = $true)]
  [string]
  $clientSecret,

  [Parameter(Mandatory = $true)]
  [string]
  $tentantID,

  [Parameter(Mandatory = $true)]
  [string]
  $subscriptionID
)

Import-Module -Name Az

$secureClientSecret = ConvertTo-SecureString -String $clientSecret -AsPlainText -Force
$pscredential = New-Object System.Management.Automation.PSCredential($clientID, $secureClientSecret)
Connect-AzAccount -ServicePrincipal -Credential $pscredential -Tenant $tentantID -Subscription $subscriptionID

The Import-Module -Name Az was added to see if trying to import it would work, but it doesn't as the user doesn't have access to /root where the module now resides.

Environment data

Tag was latest which is how we noticed the problem, the SHA that doesn't work is: sha256:d7da797d627a135b31acb15329c8a949f06caa963e7c99fc04e63b70d839df75

Module versions

PS /> Import-Module Az
PS /> Get-Module Az*

ModuleType Version    PreRelease Name                                ExportedComman
                                                                     ds
---------- -------    ---------- ----                                --------------
Script     8.2.0                 Az
Script     2.9.1                 Az.Accounts                         {Add-AzEnviro…
Script     1.1.2                 Az.Advisor                          {Disable-AzAd…
Script     4.2.1                 Az.Aks                              {Disable-AzAk…
Script     1.1.4                 Az.AnalysisServices                 {Add-AzAnalys…
Script     3.0.0                 Az.ApiManagement                    {Add-AzApiMan…
Script     1.1.0                 Az.AppConfiguration                 {Get-AzAppCon…
Script     2.1.0                 Az.ApplicationInsights              {Get-AzApplic…
Script     1.0.0                 Az.Attestation                      {Add-AzAttest…
Script     1.7.3                 Az.Automation                       {Export-AzAut…
Script     3.2.0                 Az.Batch                            {Disable-AzBa…
Script     2.0.0                 Az.Billing                          {Get-AzBillin…
Script     2.1.0                 Az.Cdn                              {Clear-AzCdnE…
Script     1.1.0                 Az.CloudService                     {Get-AzCloudS…
Script     1.11.0                Az.CognitiveServices                {Add-AzCognit…
Script     4.30.0                Az.Compute                          {Add-AzImageD…
Script     1.0.0                 Az.ConfidentialLedger               {Get-AzConfid…
Script     3.1.0                 Az.ContainerInstance                {Add-AzContai…
Script     3.0.0                 Az.ContainerRegistry                {Connect-AzCo…
Script     1.8.2                 Az.CosmosDB                         {Get-AzCosmos…
Script     1.1.0                 Az.DataBoxEdge                      {Get-AzDataBo…
Script     1.2.0                 Az.Databricks                       {Get-AzDatabr…
Script     1.16.8                Az.DataFactory                      {Add-AzDataFa…
Script     1.0.2                 Az.DataLakeAnalytics                {Add-AzDataLa…
Script     1.3.0                 Az.DataLakeStore                    {Add-AzDataLa…
Script     1.0.1                 Az.DataShare                        {Get-AzDataSh…
Script     1.1.0                 Az.DeploymentManager                {Get-AzDeploy…
Script     3.1.0                 Az.DesktopVirtualization            {Disconnect-A…
Script     1.0.2                 Az.DevTestLabs                      {Get-AzDtlAll…
Script     1.1.2                 Az.Dns                              {Add-AzDnsRec…
Script     1.3.0                 Az.EventGrid                        {Get-AzEventG…
Script     2.2.0                 Az.EventHub                         {Add-AzEventH…
Script     1.9.0                 Az.FrontDoor                        {Disable-AzFr…
Script     4.0.3                 Az.Functions                        {Get-AzFuncti…
Script     5.0.1                 Az.HDInsight                        {Add-AzHDInsi…
Script     2.0.0                 Az.HealthcareApis                   {Get-AzHealth…
Script     2.7.4                 Az.IotHub                           {Add-AzIotHub…
Script     4.6.1                 Az.KeyVault                         {Add-AzKeyVau…
Script     2.1.0                 Az.Kusto                            {Add-AzKustoC…
Script     1.5.0                 Az.LogicApp                         {Get-AzIntegr…
Script     1.1.3                 Az.MachineLearning                  {Add-AzMlWebS…
Script     1.2.0                 Az.Maintenance                      {Get-AzApplyU…
Script     1.0.0                 Az.ManagedServiceIdentity           {Get-AzSystem…
Script     3.0.0                 Az.ManagedServices                  {Get-AzManage…
Script     1.0.2                 Az.MarketplaceOrdering              {Get-AzMarket…
Script     1.1.1                 Az.Media                            {Get-AzMediaS…
Script     1.1.3                 Az.Migrate                          {Get-AzMigrat…
Script     3.0.1                 Az.Monitor                          {Add-AzAutosc…
Script     1.0.0                 Az.MySql                            {Get-AzMySqlC…
Script     4.19.0                Az.Network                          {Add-AzApplic…
Script     1.1.1                 Az.NotificationHubs                 {Get-AzNotifi…
Script     3.1.0                 Az.OperationalInsights              {Disable-AzOp…
Script     1.5.0                 Az.PolicyInsights                   {Get-AzPolicy…
Script     1.1.0                 Az.PostgreSql                       {Get-AzPostgr…
Script     1.2.0                 Az.PowerBIEmbedded                  {Get-AzPowerB…
Script     1.0.3                 Az.PrivateDns                       {Add-AzPrivat…
Script     5.4.1                 Az.RecoveryServices                 {Add-AzRecove…
Script     1.6.0                 Az.RedisCache                       {Export-AzRed…
Script     1.1.0                 Az.RedisEnterpriseCache             {Export-AzRed…
Script     1.0.3                 Az.Relay                            {Get-AzRelayA…
Script     1.1.0                 Az.ResourceMover                    {Add-AzResour…
Script     6.1.0                 Az.Resources                        {Export-AzRes…
Script     1.3.0                 Az.Security                         {Add-AzSecuri…
Script     1.1.0                 Az.SecurityInsights                 {Get-AzSentin…
Script     1.10.0                Az.ServiceBus                       {Add-AzServic…
Script     3.1.0                 Az.ServiceFabric                    {Add-AzServic…
Script     1.4.1                 Az.SignalR                          {Get-AzSignal…
Script     3.11.0                Az.Sql                              {Add-AzSqlDat…
Script     1.1.0                 Az.SqlVirtualMachine                {Get-AzAvaila…
Script     1.3.0                 Az.StackHCI                         {Add-AzStackH…
Script     4.8.0                 Az.Storage                          {Add-AzRmStor…
Script     1.7.0                 Az.StorageSync                      {Get-AzStorag…
Script     2.0.0                 Az.StreamAnalytics                  {Get-AzStream…
Script     1.0.0                 Az.Support                          {Get-AzSuppor…
Script     1.5.0                 Az.Synapse                          {Add-AzSynaps…
Script     1.1.0                 Az.TrafficManager                   {Add-AzTraffi…
Script     2.11.3                Az.Websites                         {Add-AzWebApp…

Error output

set-pwsh-az-context.ps1: /__w/_temp/fe2972d1-5061-468f-a7ba-0d58d439707f.ps1:2
Line |
   2 |  . '/__w/1/pipeline-scripts/Azure/set-pwsh-az-context.ps1' -clientID ' …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The term 'Connect-AzAccount' is not recognized as a name of a
     | cmdlet, function, script file, or executable program. Check
     | the spelling of the name, or if a path was included, verify
     | that the path is correct and try again.

##[error]PowerShell exited with code '1'.
dingmeng-xue commented 2 years ago

@ElvenSpellmaker , do you know base image of non-working environment? Could you help check version of Linux distro? We are not familiar to vsts_azpcontainer. Please share us how you use it in ADO. We will try to reproduce it.

ElvenSpellmaker commented 2 years ago

@ElvenSpellmaker , do you know base image of non-working environment? Could you help check version of Linux distro? We are not familiar to vsts_azpcontainer. Please share us how you use it in ADO. We will try to reproduce it.

Hi there, AzDo runs the container and then injects its own user into the container and runs the tasks under that user.

This is roughly how it's used in AzDo in the Pipeline:

containers:
  - container: az_pwsh
    image: mcr.microsoft.com/azure-powershell:latest
...
pool:
  vmImage: 'ubuntu-20.04'
...
- job: AzCommandsToRun
  container: az_pwsh

And then it's called via a task:

  - task: PowerShell@2
    displayName: "Login: Azure CLI"
    inputs:
      filePath: "${{ parameters.pipeline_scripts_directory }}/Azure/set-pwsh-az-context.ps1"
      arguments: >
        -clientID '${{ parameters.azureClientID }}'
        -clientSecret '${{ parameters.azureClientSecret }}'
        -tentantID '${{ parameters.azureTenantID }}'
        -subscriptionID '${{ parameters.azureSubscriptionID }}'

I hope that helps a bit

KANNIBALAMK commented 2 years ago

Hi

I don't want to pass the ClientId/SecretID as parameters. Want to get it dynamically while deploying through CI CD. How to achieve it?

dingmeng-xue commented 2 years ago

@ElvenSpellmaker , My understanding is task PowerShell still runs on agent pool image ubuntu-20.04. Please install Azure PowerShell module at first. You also can leverage another ADO task AzurePowerShell which will handle authentication Connect-AzAccount internally.

ElvenSpellmaker commented 2 years ago

@dingmeng-xue Not quite as the job is run under the container:

- job: AzCommandsToRun
  container: az_pwsh

This means Azure DevOps will inject its own node into the container and run the tasks in this case PowerShell@2 within the container.

As the module moved to root between the two SHAs listed it can't be accessed any more by the non-root user.

dingmeng-xue commented 2 years ago

@KANNIBALAMK , 2 choices in my mind if you are using Azure DevOps

  1. You need to create a service connection to target subscription, and then create a task AzurePowerShell with that connection. Task will help you to handle authentication. You only need to add azure powershell cmdlet to do operations on Azure.

  2. Define appid and secret as pipeline variable. and use them in your script. Here is one example https://github.com/Azure/azure-powershell/blob/76c8995ba80e5976d421003be1922490e0de1261/.azure-pipelines/util/smoke-test-steps.yml#L94. We use it to do smoke test in ADO pipeline.