具有基于证书的身份验证的DefaultazureCrecreCredential:如何使其正常工作
#安全 #node #azure

tl; dr;

使用DefaultAzureCredential时,生成PEM证书和私钥文件。

  • 需要将cert.pem上传到您的AAD申请注册。
  • 然后,创建一个包含 的新的BOTH.pem文件,证书和私钥。这是您需要在AZURE_CLIENT_CERTIFICATE_PATH中引用的文件

身份验证流

DefaultazureCrecrecreCredental类

DefaultAzureCredential默认凭证能够自动处理大多数Azure SDK身份验证方案。

身份它使用取决于环境。当需要一个访问令牌时,它依次使用这些身份,然后在提供令牌时停止:

  • 环境 - DefaultAzureCredential将读取通过environment variables指定的帐户信息并使用它来验证。
  • Workload Identity - 如果将应用程序部署到具有启用工作负载身份的Azure主机,则DefaultAzureCredential将使用该帐户进行身份验证。
  • 托管身份 - 如果将应用程序部署到具有托管身份的Azure主机,则DefaultAzureCredential将使用该帐户进行身份验证。
  • 等...

环境划线类

通过指定environment variables,我们指示DefaultAzureCredential使用EnvironmentCredential类。

基于环境变量名称的EnvironmentCredential确定其应如何验证。它有效地充当ClientSecretCredentialClientCertificateCredentialUsernamePasswordCredential的包装器。
在所有情况下,AZURE_TENANT_IDAZURE_CLIENT_ID环境变量都应在识别您的应用程序时使用此凭据。然后将尝试以下环境变量:

  • AZURE_CLIENT_SECRET-与ClientSecretCredential一起使用的客户秘密
  • AZURE_CLIENT_CERTIFICATE_PATH-在部署环境中 中的路径ClientCertificateCredential一起使用
  • AZURE_USERNAMEAZURE_PASSWORD-与UsernamePasswordCredential一起使用的用户名和密码对

ClientCertificatecredential类

建议使用证书进行身份验证,因为它通常比使用客户端秘密更安全。

要使用此身份验证方法,您必须在应用程序注册的“证书和秘密”页面中生成自己的PEM格式证书和register it

接下来,您指定以下环境变量:

可变名称 value
AZURE_CLIENT_ID Azure AD应用程序的ID
AZURE_TENANT_ID 应用程序的Azure AD租户的ID
AZURE_CLIENT_CERTIFICATE_PATH PFX或PEM 编码的证书文件,包括私有密钥ðÖ
AZURE_CLIENT_CERTIFICATE_PASSWORD (可选)保护证书文件的密码(当前仅支持PFX(PKCS12)证书)
AZURE_CLIENT_SEND_CERTIFICATE_CHAIN (可选)X5C标头中的发送证书链以支持主题名称 /发行人身份验证< / td>

msalclientcertificate类

ClientCertificateCredential创建了MsalClientCertificate类的实例。根据Using certificate credentials with MSAL NodeMSAL Node需要以下配置:

const config = {
    auth: {
        clientId: "YOUR_CLIENT_ID",
        authority: "https://login.microsoftonline.com/YOUR_TENANT_ID",
        clientCertificate: {
            thumbprint: "CERT_THUMBPRINT", // a 40-digit hexadecimal string 
            privateKey: "CERT_PRIVATE_KEY",
        }
    }
};

MsalClientCertificate类从MsalNode继承,并接管生成证书Thumbprint 私有密钥参数的工作。

它首先执行koude34以基于AZURE_CLIENT_CERTIFICATE_PATH中引用的PEM文件生成证书Thumbprint ,以确保该文件包含-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----

接下来,如果存在certificatePassword,它将解码AZURE_CLIENT_CERTIFICATE_PATH文件中提供的private key。否则,它将从AZURE_CLIENT_CERTIFICATE_PATH文件返回私钥

您看到发生了什么事吗? MsalClientCertificate类期望您的本地PEM文件包含ð兼有证书文件(您上传到Azure)和 private键。 ð

包起来

生成证书

您可以使用以下命令生成PEM证书:

openssl req `
    -x509 `
    -days 365 `
    -newkey rsa:2048 `
    -keyout keyencrypted.pem `
    -out cert.pem `
    -subj '/CN=AuthTestWithPassword/C=CH/ST=Zurich/L=Zurich' `
    -passout pass:HereIsMySuperPass

根据koude46版本9。

,确保关键大小至少为2048位。

创建服务主体后(请参阅Application and service principal objects in Azure Active Directory),将cert.pem保存到“证书和秘密”

接下来,创建一个新的PEM文件,其中包含 ,证书和私钥。该文件应具有以下格式:

两者

-----BEGIN CERTIFICATE-----
MIIDfTCCAmWgAwIBAgIUKoqrm/mWZ2EoC/a60vBoAXxoEMEwDQYJKoZIhvcNAQEL
...
tjs1jav+97FKR1lLnyGS90e2LjtTjLzqy1O5k8T1+6sv
-----END CERTIFICATE-----
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIZ6SyJiacCZwCAggA
...
UaTp6QTCR5NvDEb3iPNbQw==
-----END ENCRYPTED PRIVATE KEY-----

添加环境变量

您可以使用PowerShell($env:Path = 'C:\foo;')设置环境变量,但我更喜欢使用.env文件。根据需要交换配置更容易。但是,请记住仅在开发模式下导入它=)

在项目的根部创建.env.cert文件,并设置所需值:

.env.cert

TenantName= "{tenant-name}"
AZURE_CLIENT_ID= "{client-id}"
AZURE_TENANT_ID= "{tenant-id}"
AZURE_CLIENT_CERTIFICATE_PATH= "./temp/BOTH.pem"
AZURE_CLIENT_CERTIFICATE_PASSWORD= "HereIsMySuperPass"

AZURE_CLOUD_INSTANCE= "https://login.microsoftonline.com/"
GRAPH_API_ENDPOINT= "https://graph.microsoft.com/"

或者,如果您正在编写 Azure函数,只需使用local.settings.json

local.settings.json

{
  "IsEncrypted": false,
  "Values": {
    //...
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "FUNCTIONS_EXTENSION_VERSION": "~4",
    "WEBSITE_NODE_DEFAULT_VERSION": "~18",
    "TenantName": "{tenant-name}",
    "AZURE_CLIENT_ID": "{client-id}",
    "AZURE_TENANT_ID": "{tenant-id}",
    "AZURE_CLIENT_CERTIFICATE_PATH": "./temp/BOTH.pem",
    "AZURE_CLIENT_CERTIFICATE_PASSWORD": "HereIsMySuperPass",
    "AZURE_CLOUD_INSTANCE": "https://login.microsoftonline.com/",
    "GRAPH_API_ENDPOINT": "https://graph.microsoft.com/"
    }
}

您的代码

现在已经准备就绪设置,您可以使用DefaultAzureCredential进行身份验证。确保从.env.cert导入环境变量

import dotenv from "dotenv"
import { AccessToken, DefaultAzureCredential } from "@azure/identity";

if (process.env.NODE_ENV !== 'production') {
    dotenv.config({ path: "./.env.cert" })
}

const credential = new DefaultAzureCredential()

const resultGraph: AccessToken = await credential.getToken("https://graph.microsoft.com/.default")
const resultSPO: AccessToken = await credential.getToken(`https://${process.env.TenantName}.sharepoint.com/.default`)

console.log("Auth SPO: ", resultSPO.token.slice(0, 10) + "...")
console.log("Auth Graph: ", resultGraph.token.slice(0, 10) + "...")

错误

如果您不提供正确的本地PEM文件,则可能期望以下错误:

指定路径的文件不包含PEM编码的证书。

Exception: EnvironmentCredential authentication failed. To troubleshoot, visit https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot. Status code: 400
More details:
The file at the specified path does not contain a PEM-encoded certificate.

原因:引用文件仅包含私钥。

无法阅读私钥

Failed to read private key
Stack: AuthenticationError: EnvironmentCredential authentication failed. To troubleshoot, visit <https://aka.ms/azsdk/js/identity/environmentcredential/troubleshoot>. Status code: 400

原因:引用文件仅包含证书。