Azure DevOps中PowerShell注册Azure AD应用失败问题排查
New-AzureADApplication cmdlet未识别的问题 咱们先把问题根源理清楚:你本地能正常运行这条命令,是因为本地已经装了AzureAD模块(或AzureADPreview模块),但Azure DevOps的托管代理(不管是微软托管还是你自己的自托管代理)默认并没有预装这个模块——而且你用的Azure PowerShell任务是基于Az模块的,和AzureAD模块是完全独立的两套体系,这就是为啥会出现cmdlet不被识别的报错。
下面是具体的解决步骤,一步步来就能搞定:
1. 在脚本里先安装并导入AzureAD模块
直接在你的PowerShell脚本开头加上安装和导入模块的命令,用-Force和-AllowClobber参数避开可能的冲突:
# 安装AzureAD模块(如果代理机器上还没装) Install-Module -Name AzureAD -Force -AllowClobber -Scope CurrentUser # 导入模块到当前会话 Import-Module AzureAD -Force
如果是用微软托管代理,每次运行都安装可能会有点慢,要是你用的是自托管代理,建议提前在代理机器上把AzureAD模块装好,以后就不用每次都安装了。
2. 给AzureAD模块单独做身份认证
注意哦,Connect-AzAccount是给Az模块登录用的,AzureAD模块得单独用Connect-AzureAD登录。你可以用服务主体直接登录,或者利用Az模块已经登录好的上下文来获取token,不用重复输入凭证:
方式一:用服务主体直接登录
# 把服务主体密码转换成安全字符串 $securePassword = ConvertTo-SecureString "你的服务主体密码" -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential("服务主体的应用ID", $securePassword) # 登录AzureAD Connect-AzureAD -Credential $credential -TenantId "你的租户ID"
方式二:复用Az模块的登录上下文(更省心)
如果你的Azure PowerShell任务已经用服务主体登录了Az模块,可以直接拿当前上下文的token来登录AzureAD,不用再单独管理凭证:
$context = Get-AzContext $token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken Connect-AzureAD -AadAccessToken $token -AccountId $context.Account.Id -TenantId $context.Tenant.Id
3. 处理Az和AzureRM模块的冲突(可选)
从你提供的日志里看到有Az和AzureRM模块共存的警告,虽然这不是直接导致cmdlet未识别的原因,但为了避免后续出其他问题,建议在Azure DevOps任务的Azure PowerShell版本选项里,明确指定用Az模块的最新版本;要是你完全不用AzureRM模块,也可以在脚本开头加一行卸载命令:
# 卸载AzureRM模块(如果不需要的话) Uninstall-AzureRm -Force -ErrorAction SilentlyContinue
完整示例脚本
把这些步骤整合起来,你的脚本应该是这样的:
# 安装并导入AzureAD模块 Install-Module -Name AzureAD -Force -AllowClobber -Scope CurrentUser Import-Module AzureAD -Force # 复用Az模块的登录上下文登录AzureAD $context = Get-AzContext $token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.windows.net").AccessToken Connect-AzureAD -AadAccessToken $token -AccountId $context.Account.Id -TenantId $context.Tenant.Id # 创建Azure AD应用 $appName = "MyApplication" $appURI = "https://myapplication.azurewebsites.net" $appHomePageUrl = "https://myapplication.xxxxx.nl" $appReplyURLs = @($appURI, $appHomePageUrl, "https://localhost:12345") $myApp = New-AzureADApplication -DisplayName $appName -IdentifierUris $appURI -Homepage $appHomePageUrl -ReplyUrls $appReplyURLs # 后续的其他操作...
另外提一句:AzureAD模块现在已经处于维护状态了,微软推荐迁移到Microsoft Graph PowerShell模块(用New-MgApplication代替New-AzureADApplication),而且Azure DevOps的托管代理现在已经预装了Microsoft Graph模块,这样连安装步骤都省了,你也可以考虑往这个方向迁移哦。
内容的提问来源于stack exchange,提问作者Kamal Nandan

