Skip to content

Using AzureAD module requires an awkward workaround #232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
abigailbuckholdt opened this issue May 23, 2019 · 34 comments
Closed

Using AzureAD module requires an awkward workaround #232

abigailbuckholdt opened this issue May 23, 2019 · 34 comments
Assignees
Labels
documentation Related to docs or examples of usage
Milestone

Comments

@abigailbuckholdt
Copy link

I've created a powershell function app on a consumption plan and I'm trying to use the AzureAD module in my project. I'm getting this error

Exception: The current processor architecture is: X86. The module 'D:\home\site\wwwroot\Modules\AzureAD\2.0.2.16\AzureAD.psd1' requires the following architecture: Amd64.

I've set the platform settings to 64 bit, restarted the app, and ran the following commands in a http trigger

[Environment]::Is64BitProcess
[Environment]::Is64BitOperatingSystem

and got the following output

2019-05-23T20:18:23.336 [Information] OUTPUT: False
2019-05-23T20:18:23.337 [Information] OUTPUT: True

Is there any reason why setting the platform settings to 64 bit would not convert the platform to using a 64 bit process?

@TylerLeonhardt
Copy link
Member

This is because the PowerShell worker relies on the dotnet.exe that's available in the App Service sandbox. The dotnet.exe is always the 32bit executable. You can set your Function App to use a 64bit OS but the dotnet.exe is still 32bit.

cc @eamonoreilly @anirudhgarg The AzureAD module seems like a very good reason to speak to the App Service team about updating the dotnet.exe to the 64bit on the 64bit operating system.

@TylerLeonhardt
Copy link
Member

Actually... @abigailbuckholdt I don't think the AzureAD module works in PowerShell Core yet which is what the PowerShell worker uses...

@edyoung + @maertendMSFT : do you guys no anything about the AzureAD module working in Core?

@maertendMSFT
Copy link
Member

A preview AAD module for PowerShell is available in Azure Cloud Shell. We are working with the module owners to update the version on the gallery after validating with partner teams.

@mblanquer
Copy link

mblanquer commented May 29, 2019

@maertendMSFT, if I correct understand, Azure AAD module is already available on Azure Cloud Shell.
When you said that you are working to update the version on the gallery, does it mean that the module AAD will be also available on function App ?
I have the same issue as described by @abigailbuckholdt

@maertendMSFT
Copy link
Member

Yes, I believe any module from the gallery can be pulling into a function.
@TylerLeonhardt, correct me if I am wrong.

@mdrakiburrahman
Copy link

mdrakiburrahman commented Jun 9, 2019

@abigailbuckholdt I was able to connect to AzureAD via a Powershell Azure Function to get a list of users back. It wasn't easy, but here are the steps:

As @maertendMSFT mentioned above, there is a secret "preview" AzureAD module available in Azure Cloud Shell today, that's supported on x86 (since Azure Shell uses PowerShell Core). There's no way to get the x64 version of AzureAD working on Azure Function, unless Microsoft decides to support that architecture in Azure Function. Thus, we're going to be waiting until this secret preview module is available for use in Azure Function etc, which obviously will take a lot of time. I decided to get this module out of the Cloud Shell, and import it as a standard module in my function, which is supported today in Azure Function (provided the module works on PowerShell Core of course)

Step 1: Getting that Preview PowerShell module out of Cloud Shell
To do this, I first initiated a Cloud Shell instance, which in turn created a File Share. By running the two powershell commands in the screenshot below, you're able to copy the entire Module Folder from the machine hosting Cloud Shell, and see it in the File Share.
1

Then, I used Storage Explorer to download it to my local:
2

Which looked like this:
3

Step 2: Getting the module uploaded to Azure Function, and getting it to work
This part was really, really difficult. The thing is, I'm trying to use a Service Account to automate the task of Connect to Azure AD. But, Connect-AzureAD does not support connecting to a Service Account by using the ClientID and AppKey. You need to use a self-signed Cert and pass in the thumbprint.

This works fine and dandy on my local, but this cert based authentication feature is not supported in this Preview AzureAD (you can try it on Azure Cloud Shell, it's going to return a .NETCORE error):
7

So - we now have the preview module that'll work on Azure Function.....but it doesn't support Cert based authentication with service principals (i.e. it's useless, since the only reason I'm building the function is to automate stuff)

So, I did a lot of digging around, and am basically doing the following to get this to work:

  1. First, using Visual Studio Code, create a "Modules" folder in the root of your function directory and paste the Preview Module in:
    4

When you deploy to the function with VSCode, this whole folder will get uploaded to the machine hosting the Azure Function.

  1. To get around the limitation with the cert based authentication limitation I mentioned, what I did in run.ps1 was:
  • Sign into Az module (which is available OOTB in the Azure Function)
  • Extract the context token from the machine's cache
  • Pass the token into Connect-AzureAD, at which point I'm able to connect to my Azure AD tenant and get a list of users

Here are all the steps in a screenshot:
5

Now when I use a REST Client (I use Insomnia) to make a call to the function, I'm getting the first user in my Tenant back, via the AzureAD module:
8

Hope this helps! Judging by all the technical hurdles Microsoft is going to have to have to overcome (specially supporting the Cert based authentication on an unsupported .NET Core platform), I'm willing to bet it'll be some time before we see this AzureAD module functionality supported out of the box. None of this would be an issue if instead of Powershell Core, the regular 64-bit version was supported in Azure Function though....

@TylerLeonhardt
Copy link
Member

@mdrakiburrahman Windows PowerShell is available in the sandbox so you could call out to Windows PowerShell like:

powershell.exe -c "Import-Module AzureAD.old.one; Invoke-Something"

@anirudhgarg
Copy link
Member

Turns out we do have the 64 bit version of dotnet.exe in the Sandbox but there looks like there is a bug where-in if we change the platform to 64 bit the path does not change to point to the 64 bit version. We are going to look to fix it, meanwhile since we know the location of the 64 bit version of dotnet in the Sandbox we are going to see if we can first check if we are on 64 bit and invoke the 64 bit version of dotnet from the hardcoded path.

@eamonoreilly
Copy link

eamonoreilly commented Sep 30, 2019

Until we fix this, I have been putting the following code into my profile.ps1 and then using it to run the AzureAD cmdlets.

##Profile.ps1
##Get path to PowerShell 64bit process

$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
##Function code

$Script={
    param ()
   ##Save AzureAD module to the modules folder before publishing
    Import-Module .\modules\AzureAD
    ##Create a credential object $MyCreds and login with it.
    ##Connect-AzureAD -Credential $MyCreds
}

&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script   

@AnatoliB
Copy link
Contributor

AnatoliB commented Oct 2, 2019

The Azure/azure-functions-host#5011 PR resolves the problem literally stated in the title of this issue. As a result of this fix, the bitness of the PowerShell worker will match the bitness of the Host, which matches the Platform setting on the Function app (when running on the cloud). As a result, PowerShell functions will be able to use x64-only PS Core modules.

Unfortunately, we discovered that this will not really help AzureAD because it requires Windows PowerShell, and cannot work on PowerShell Core. In order to do that, the appropriate version of powershell.exe should be discovered. The bitness of the PowerShell worker process would help if Windows PowerShell followed the regular convention and could be located under either Program Files or Program Files (x86). However, this is not the case.

So, we want to fix the PowerShell worker process bitness anyway, but the AzureAD users will have to use the workaround (to be documented).

@AnatoliB AnatoliB added the documentation Related to docs or examples of usage label Oct 2, 2019
@AnatoliB
Copy link
Contributor

AnatoliB commented Oct 2, 2019

Adding @eamonoreilly for documenting the AzureAD workaround.

@eamonoreilly
Copy link

Added sample to https://github.com/eamonoreilly/ManageAzureActiveDirectoryWithPowerShellFunction for AzureAD. Will work on documentation and publish this to serverlesslibrary.net

@ghost
Copy link

ghost commented Oct 10, 2019

Hi,

Is there any ETA on fixing this issue for 64-bit dotnet.exe in the Sandbox?

@AnatoliB
Copy link
Contributor

AnatoliB commented Oct 10, 2019

The fix I mentioned (Azure/azure-functions-host#5011) should be deployed by October 30.

@sunnydewangan Let's make sure it addresses your actual issue, though. Please be aware that the AzureAD problem is not caused by the dotnet.exe bitness. The fix will help the situation when someone want to use 64bit-only .NET Core code in a PowerShell function, and I'm not aware of any complaints about this yet. If what you really need is to use the AzureAD module (or any other module that requires Windows PowerShell as opposed to PowerShell Core), you have two options:

  • Wait for the AzureAD to be migrated to PS Core.
  • In the meantime, use the workaround provided earlier (spawning a powershell.exe process).

@TylerLeonhardt
Copy link
Member

the AzureAD problem

Side note, the Azure AD module should "just work" in PowerShell 7 so once Azure Functions adopts PowerShell 7, this scenario should be fixed

@anirudhgarg
Copy link
Member

@TylerLeonhardt is this because in PowerShell 7 we have added additional support for API's that are being used by the Azure AD module ?

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Nov 6, 2019

Correct. The Azure AD module loads Windows GUI dll which was not possible to load in PowerShell Core 6. In 7, they can be loaded.

Of course, a Function App can't do anything with Windows GUIs so the user needs to do whatever they need to do with a "non-interactive mindset" in mind.

This also applies to the Exchange Online module and a few others.

@bwarren18
Copy link

bwarren18 commented Jan 10, 2020

Until we fix this, I have been putting the following code into my profile.ps1 and then using it to run the AzureAD cmdlets.

`
##Profile.ps1
##Get path to PowerShell 64bit process

$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
`

`
##Function code

$Script={
param ()
##Save AzureAD module to the modules folder before publishing
Import-Module .\modules\AzureAD
##Create a credential object $MyCreds and login with it.
##Connect-AzureAD -Credential $MyCreds
}

&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script
`

I modified this workaround a little to improve the speed (from 13 seconds to 1).

$script = { Write-Output "Is 64-bit Process: $([Environment]::Is64BitProcess)" }

$PowerShell64bitPath = Get-ChildItem -Path $Env:Windir\WinSxS | Where-Object {$_.FullName -match "amd64_microsoft-windows-powershell-exe"}
$PowerShell64bitPath = Get-ChildItem -Path $PowerShell64bitPath.FullName -Filter PowerShell.exe | Select-Object -ExpandProperty FullName

Invoke-Command -ScriptBlock $script
& $PowerShell64bitPath -NoLogo -NoProfile -WindowStyle Hidden -NonInteractive -Command $Script

Is 64-bit Process: False
Is 64-bit Process: True

@AnatoliB AnatoliB changed the title Unable to use x64 modules Using AzureAD module requires an awkward workaround Feb 7, 2020
@AnatoliB AnatoliB modified the milestones: GA, Backlog Feb 7, 2020
@ceylon23
Copy link

ceylon23 commented Apr 4, 2020

Until we fix this, I have been putting the following code into my profile.ps1 and then using it to run the AzureAD cmdlets.

`
##Profile.ps1
##Get path to PowerShell 64bit process

$64bitPowerShellPath = Get-ChildItem -Path $Env:Windir\WinSxS -Filter PowerShell.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.FullName -match "amd64"}
$env:64bitPowerShellPath=$64bitPowerShellPath.VersionInfo.FileName
`

`
##Function code

$Script={
param ()
##Save AzureAD module to the modules folder before publishing
Import-Module .\modules\AzureAD
##Create a credential object $MyCreds and login with it.
##Connect-AzureAD -Credential $MyCreds
}

&$env:64bitPowerShellPath -WindowStyle Hidden -NonInteractive -Command $Script
`

This is still the best workaround. April 4, 2020

@TylerLeonhardt
Copy link
Member

I'd also like to recommend the Microsoft Graph module that has a lot of the same functionality as the Azure AD module:

https://developer.microsoft.com/en-us/office/blogs/microsoft-graph-powershell-preview-now-on-powershell-gallery/

@AnatoliB
Copy link
Contributor

AnatoliB commented Apr 5, 2020

I'd also like to recommend the Microsoft Graph module that has a lot of the same functionality as the Azure AD module:

Just remember about the issue and the workaround: microsoftgraph/msgraph-sdk-powershell#113

@wsf11
Copy link

wsf11 commented Jun 10, 2020

AzureAD works out of the box with Powershell 7! Import AzureAD with the -UseWindowsPowershell switch.
Import-Module AzureAD -UseWindowsPowerShell

@JeretSB
Copy link

JeretSB commented Jun 22, 2020

Looking at previous comments - still unable to get things working.

@wsf11 - I got an invalid param for "-UseWindowsPowerShell" when running within my AzureFuntion.

@bwarren18 - Does your entire code go in the profile.ps1 or is it split up in some way?

Thanks in advance!

@AnatoliB
Copy link
Contributor

@JeretSB "-UseWindowsPowerShell" is a PowerShell 7 feature, and Function apps use PowerShell 6 by default. In order to migrate your app to PowerShell 7, please use these instructions: #371 (comment)

@JeretSB
Copy link

JeretSB commented Jun 23, 2020

For anyone else who may stumble on this. (Until they've finished correcting this.) The following finally got things working for me.

  1. Setting the application to run as x64 bit: Function App> Configuration > General Settings > Platform > 64 Bit
  2. Setting the app to run on Powershell 7 instead of 6 on this thread
  3. Used: Import-Module AzureAD -UseWindowsPowerShell

Thanks all for the feedback. Took me a couple hours to get this working. 😔

Big thanks @AnatoliB!

EDITED: Import-Function replaced with Import-Module, as this was a typo.

@AnatoliB
Copy link
Contributor

I'm closing this issue as we now have a reasonable and verified way of using AzureAD.

@ebenezermakinde
Copy link

ebenezermakinde commented Jul 28, 2020

This also works for MSOnline module. Thanks for pointing me in the right direction @AnatoliB

@adriennn
Copy link

Is this solution still working? When trying with the -UseWindowsPowerShell flag PowerShell tells me to use another flag

 Module AzureAD is loaded in Windows PowerShell using WinPSCompatSession remoting session;
 please note that all input and output of commands from this module will be deserialized objects.
 If you want to load this module into PowerShell Core please use 'Import-Module -SkipEditionCheck' syntax

And using the other flag is causing further errors.

Moreover, it seems that Az-Connect isn't being forwarded to Windows PowerShell because if I'm trying to run a command after having used Az-Connect in profile.ps1, PowerShell warns that Az-Connect needs to be ran first.

@ebenezermakinde
Copy link

ebenezermakinde commented Nov 20, 2020

Is this solution still working? When trying with the -UseWindowsPowerShell flag PowerShell tells me to use another flag

 Module AzureAD is loaded in Windows PowerShell using WinPSCompatSession remoting session;
 please note that all input and output of commands from this module will be deserialized objects.
 If you want to load this module into PowerShell Core please use 'Import-Module -SkipEditionCheck' syntax

And using the other flag is causing further errors.

Moreover, it seems that Az-Connect isn't being forwarded to Windows PowerShell because if I'm trying to run a command after having used Az-Connect in profile.ps1, PowerShell warns that Az-Connect needs to be ran first.

This is just a warning @adriennn . It just simply explains the windows compatibility feature and how it works. Because you are simply using the windows feature of Powershell. In this case, you can choose to ignore the use of that flag(SkipEditionCheck),

I hope this helps.

@adriennn
Copy link

thanks @ebenezermakinde, my mistake was not to have realized AzureAD module uses its own authentication method and is entirely independent of the auth in Az module.

@regionw
Copy link

regionw commented Mar 29, 2021

Was able to load the module (apparently) using the steps provided here. However I still get error : The term 'Connect-AzureAD' is not recognized as the name of a cmdlet, function, script file, or operable program.
the function runs the Import-Module AzureAD -UserWindowsPowershell with no errors

@AnatoliB
Copy link
Contributor

@regionw Please note the typo: the switch name is UseWindowsPowerShell, not Use_r_WindowsPowershell

@regionw
Copy link

regionw commented Apr 2, 2021

Tks AnatoliB,

it was a typo on the question. The actual command was correct. Was getting inconsistent results, then it started working.
Tks for answering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Related to docs or examples of usage
Projects
None yet
Development

No branches or pull requests