无法使用服务主体在Azure自动化中连接-AZAccount

huangapple go评论62阅读模式
英文:

Unable to connect-AZAccount in Azure Automation with a Service Principal

问题

我有一个Azure自动化Runbook,需要使用Connect-AzAccount连接到Automation帐户中的Blob存储帐户导出CSV。我的服务主体有一个ApplicationID和一个Secret。根据Connect-AzAccount的文档,-Credential参数可以接受这些信息。

然而,当我尝试通过以下方式传递它:

$Credential = New-Object -TypeName System.Management.Automation.PSCredential($ApplicationID, $AppSecret)
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential

我收到以下错误消息:

无法将参数'Credential'绑定到参数,因为它为null。

有人能指出我哪里出错吗?

英文:

I have an Azure Automation Runbook that needs to Connect-AzAccount to export a CSV from the Automation Account to a Blob Storage Account. My Service Principal has an ApplicationID and a Secret. per the documentation for Connect-AzAccount -Credential can accept this.

However when I attempt to feed it in via:

$Credential = New-Object -TypeName System.Management.Automation.PSCredential($ApplicationID, $AppSecret)
Connect-AzAccount -ServicePrincipal -TenantId $TenantId -Credential $Credential

I get the following error:

Cannot bind argument to parameter 'Credential' because it is null

Would anyone be able to point me to where I am messing up?

答案1

得分: 2

以下是您要求的中文翻译:

**tl;dr**

由于 _根本原因_ 是以下错误:

> `找不到“PSCredential”的重载和参数计数:“2”。`

这意味着 **在您的 `New-Object -TypeName PSCredential` 调用中,`$AppSecret` 参数不是 [`[securestring]`](https://learn.microsoft.com/en-US/dotnet/api/System.Security.SecureString) 类型,这是[相关 `[pscredential]` 构造函数重载](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.pscredential.-ctor#system-management-automation-pscredential-ctor(system-string-system-security-securestring))所需要的。

将其改为 `[securestring]` 实例解决了您的问题。

---

可以通过几种方式构建或获取 `[securestring]` 实例:

* 最好的方式是从秘密管理系统加载密钥,例如支持各种扩展模块的 [`Microsoft.PowerShell.SecretManagement`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.secretmanagement/?view=ps-modules) 模块,例如用于本地文件系统存储的 [`Microsoft.PowerShell.SecretStore`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.secretstore/?view=ps-modules) 和用于从Azure密钥保管库检索密钥的 [`Az.KeyVault`](https://www.powershellgallery.com/packages/Az.KeyVault) 模块。

* [出于安全原因不建议] 使用 [`ConvertTo-SecureString`](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/convertto-securestring) `-AsPlainText` 将密钥的纯文本表示转换为 `[securestring]`。

或者,您可以以不同的方式获取整个 `[pscredential]` 实例:

 * 以 _交互方式_,通过 [`Get-Credential`](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/get-credential):

       # 提示输入应用程序密钥(密码)并返回一个 [pscredential] 实例。
       $Credential = Get-Credential $ApplicationID
      

* 仅在Windows上,导入以前使用 [`Export-Clixml`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/export-clixml) 持久保存到 _文件_ 的 `[pscredential]` 实例,然后使用 [`Import-Clixml`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/import-clixml) - 请参阅[此答案](https://stackoverflow.com/a/40029496/45375)。

一般警告:`[securestring]` 在Windows上提供了 _有限的_ 安全性,在类Unix平台上几乎没有安全性,甚至没有使用加密 - 请参阅[此答案](https://stackoverflow.com/a/60406968/45375)。

---

至于 **您尝试的内容** 和您看到的 **错误消息**:

> `New-Object -TypeName System.Management.Automation.PSCredential($ApplicationID, $AppSecret)`

这个命令可以简化为:

```shell
New-Object pscredential $ApplicationID, $AppSecret
# 等同于:
#  New-Object -TypeName pscredential -ArgumentList $ApplicationID, $AppSecret

注意:

New-Object 调用转化为.NET中的 构造函数 调用,在PowerShell 5及以上版本中,现在有了一种使用PowerShell在类型上公开的静态 ::new() 方法直接调用构造函数的方式。因此,上述命令的等效方式是:

# 与上述相同的PSv5+版本。
# 请注意,这种语法确实需要方法调用语法。
[pscredential]::new($ApplicationID, $AppSecret)

这种方法的优点是您可以通过简单访问 ::new 不带 (...) 部分 来轻松检查构造函数的 重载(具有不同参数的变体):

# 打印构造函数的重载
[pscredential]::new

输出:

OverloadDefinitions
-------------------
pscredential new(string userName, securestring password)
pscredential new(psobject pso)

第一个重载 - 唯一接受 两个 参数的重载 - 还显示了参数的 类型,并且确实显示第二个参数需要一个 [securestring] 实例作为其参数。

不幸的是,当参数的 数量 正确但 类型 错误时,您获得的 错误消息 有点误导

> 找不到“PSCredential”的重载和参数计数:“2”。

显然,您确实传递了 2 个参数,但是第二个参数的类型不正确触发了错误,而消息使其听起来好像您传递了错误的 参数数量

改进此错误消息已经在 GitHub问题 #3658 中得到批准,但到目前为止还没有人采取行动来实现它。


<details>
<summary>英文:</summary>

&lt;!-- language-all: sh --&gt;

**tl;dr**

Since the _root_ cause turned out to be the following error:

&gt; `Cannot find overload for &quot;PSCredential&quot; and the argument count: &quot;2&quot;.`

the implication is that **the `$AppSecret` argument in your `New-Object -TypeName PSCredential` call was _not_ of type [`[securestring]`](https://learn.microsoft.com/en-US/dotnet/api/System.Security.SecureString)**, which is what the [relevant `[pscredential]` constructor overload](https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.pscredential.-ctor#system-management-automation-pscredential-ctor(system-string-system-security-securestring)) requires.

Making it a `[securestring]` instance solved your problem.

---

A `[securestring]` instance can be constructed or obtained in several ways:

* Preferably, load the secret from a secrets-management system, such as the [`Microsoft.PowerShell.SecretManagement`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.secretmanagement/?view=ps-modules) module, which supports various extension modules implementing _vaults_ (secrets stores), such as [`Microsoft.PowerShell.SecretStore`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.secretstore/?view=ps-modules) for local file-system storage and the [`Az.KeyVault`](https://www.powershellgallery.com/packages/Az.KeyVault) module for retrieving secrets from an Azure Key Vault.

* [Not advisable for security reasons] Use [`ConvertTo-SecureString`](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/convertto-securestring) `-AsPlainText` to convert a plain-text representation of the secret to a `[securestring]`.


Alternatively, you could obtain the entire `[pscredential]` instance differently:

 * _Interactively_, via [`Get-Credential`](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/get-credential):

       # Prompts for the app secret (password) and returns a [pscredential] instance.
       $Credential = Get-Credential $ApplicationID
      

* On Windows only, import a `[pscredential]` instance that was previously persisted to a _file_ with [`Export-Clixml`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/export-clixml) with [`Import-Clixml`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/import-clixml) - see [this answer](https://stackoverflow.com/a/40029496/45375).

A general caveat: `[securestring]` offers _limited_ security on Windows, and *virtually none* on Unix-like platforms, where encryption isn&#39;t even employed - see [this answer](https://stackoverflow.com/a/60406968/45375).

---

As for **what you tried** and the **error message** you saw:

&gt; `New-Object -TypeName System.Management.Automation.PSCredential($ApplicationID, $AppSecret)`

This command can be simplified to:

New-Object pscredential $ApplicationID, $AppSecret

Short for:

New-Object -TypeName pscredential -ArgumentList $ApplicationID, $AppSecret


Note:

* The use of short name `pscredential`, given that it is a [type accelerator](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Type_Accelerators) for the full type name, [`System.Management.Automation.PSCredential`](https://learn.microsoft.com/en-US/dotnet/api/System.Management.Automation.PSCredential).

* The absence of `(...)` around the arguments, as that amounts to _pseudo method syntax_ that is best avoided - see [this answer](https://stackoverflow.com/a/50636061/45375).

`New-Object` calls translate into .NET _constructor_ calls, and in PowerShell 5 and above there&#39;s now a a **more direct way to call constructors, using the static `::new()` method** exposed by PowerShell on *types*. Therefore, the equivalent of the command above is:

PSv5+ equivalent of the above.

Note that this syntax does require method-call syntax.

pscredential::new($ApplicationID, $AppSecret)


The advantage of this approach is that you can **easily inspect the constructor *overloads*** (variants with different parameters), simply by **accessing `::new` _without the `(...)` part_**:

Print constructor overloads


Output:

```none
OverloadDefinitions
-------------------
pscredential new(string userName, securestring password)
pscredential new(psobject pso)

The first overload - the only one to accept two arguments - also reveals the parameter types, and indeed shows that the second parameter requires a [securestring] instance as its argument.

Unfortunately, the error message you get when the count of arguments is correct but the type isn't is somewhat misleading:

> Cannot find overload for &quot;PSCredential&quot; and the argument count: &quot;2&quot;.

Clearly, you did pass 2 arguments, but it was the fact that the 2nd argument had the wrong type that triggered the error, whereas the message makes it sound like you passed the wrong number of arguments.

Improving this error message has been green-lit in GitHub issue #3658, but so far no one has stepped up to implement it.

huangapple
  • 本文由 发表于 2023年2月18日 02:06:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75487842.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定