使用服务主体进行 Azure SDK for Go 身份验证

在本教程中,你将使用 Azure SDK for Go 通过机密或证书通过 Azure 服务主体向 Azure 进行身份验证。

Azure 服务主体定义 Microsoft Entra 租户中的访问策略和权限,从而在登录期间启用身份验证和资源访问期间授权等核心功能。 他们无需使用个人帐户来访问 Azure 资源。 你可以为服务主体分配应用所需的确切权限,并针对这些权限进行开发,而不是使用租户中可能比应用所需的权限更多的个人帐户。 还可以将服务主体用于托管在本地且需要使用 Azure 资源的应用。 Azure SDK for Go Azure 标识 模块提供了一种使用环境变量和机密或证书通过服务主体向 Azure 进行身份验证的便捷方法。

按照此教程,使用服务主体创建 Azure SDK for Go 并向其进行身份验证。

先决条件

  • Azure 订阅:如果没有 Azure 订阅,请在开始之前创建一个免费帐户。

1.创建 Azure 资源

在开始之前,请创建新的资源组和密钥保管库实例。

az group create --name go-on-azure --location eastus

az keyvault create --location eastus --name <keyVaultName> --resource-group go-on-azure --enable-rbac-authorization

<keyVaultName> 替换为全局唯一名称。

记下 id 命令输出中的 az keyvault create 属性。 在下一部分中,你将使用它来定义服务主体的授权范围。 该值id采用以下形式: /subscriptions/<subscriptionId>/resourceGroups/go-on-azure/providers/Microsoft.KeyVault/vaults/<keyVaultName>

2. 创建 Azure 服务主体

使用以下方法之一创建 Azure 服务主体,并在密钥保管库上为其分配“密钥库机密办公室r”角色:

要详细了解 Azure 服务主体,请参阅服务主体对象

将“密钥库机密办公室r”角色分配给服务主体,授权它在密钥保管库中创建、读取、更新和删除机密。 若要详细了解 Azure 密钥保管库的内置角色,请参阅使用 Azure 基于角色的访问控制提供对密钥库密钥、证书和机密的访问权限。 若要详细了解 Azure 中的内置角色,请参阅 Azure 内置角色

选项 1:使用机密创建 Azure 服务主体

运行以下命令以创建 Azure 服务主体,并在密钥保管库上为其分配“密钥库机密办公室r”角色。

az ad sp create-for-rbac --name <servicePrincipalName> --role "Key Vault Secrets Officer" --scope <keyVaultId>

<servicePrincipalName><keyVaultId> 替换为相应的值。

记下输出中的 password属性 tenantappId 属性。 下一部分需要这些信息。

创建后,无法检索服务主体密码。 如果忘记了密码,可以 重置服务主体凭据

选项 2:使用证书创建 Azure 服务主体

运行以下命令,创建使用证书的 Azure 服务主体,并在密钥保管库上为其分配“密钥库机密办公室r”角色。

az ad sp create-for-rbac --name <servicePrincipalName> --create-cert --role "Key Vault Secrets Officer" --scope <keyVaultId>

<servicePrincipalName><keyVaultId> 替换为相应的值。

记下输出中的 fileWithCertAndPrivateKey属性 tenantIdappId 属性。 下一部分需要这些信息。

3. 使用服务主体向 Azure 进行身份验证

通过使用 DefaultAzureCredential,可以避免编写特定于环境的代码以向 Azure 进行身份验证。 通过 DefaultAzureCredential定义环境变量,可以配置服务主体凭据。

选择以下选项之一来配置服务主体凭据:

要了解有关 DefaultAzureCredential 的详细信息,请参阅使用 Azure SDK for Go 进行 Azure 身份验证

选项 1:使用机密进行身份验证

定义以下环境变量:

变量名称
AZURE_CLIENT_ID Azure 服务主体的应用程序 ID
AZURE_TENANT_ID 应用程序的 Microsoft Entra 租户的 ID
AZURE_CLIENT_SECRET Azure 服务主体的密码
export AZURE_TENANT_ID="<active_directory_tenant_id>"
export AZURE_CLIENT_ID="<service_principal_appid>"
export AZURE_CLIENT_SECRET="<service_principal_password>"

选项 2:使用证书进行身份验证

变量名称
AZURE_CLIENT_ID Azure 服务主体的应用程序 ID
AZURE_TENANT_ID 应用程序的 Microsoft Entra 租户的 ID
AZURE_CLIENT_CERTIFICATE_PATH PEM 或 PKCS12 证书文件的路径,包括私钥。 如果遵循了 Azure CLI 的步骤,则该文件不受密码保护。 如果遵循 Azure PowerShell 的步骤,则该文件受密码保护,还需要设置 AZURE_CLIENT_CERTIFICATE_PASSWORD 环境变量。
AZURE_CLIENT_CERTIFICATE_PASSWORD 创建服务主体时输入的密码。 仅当遵循 Azure PowerShell 的步骤时才需要。
export AZURE_TENANT_ID="<active_directory_tenant_id>"
export AZURE_CLIENT_ID="<service_principal_appid>"
export AZURE_CLIENT_CERTIFICATE_PATH="<azure_client_certificate_path>"

使用 DefaultAzureCredential 对资源客户端进行身份验证

设置环境变量后,可以在 DefaultAzureCredential Azure 标识模块中使用对资源客户端进行身份验证。 以下代码演示如何获取 . 的 DefaultAzureCredential实例。

cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
    log.Fatalf("failed to obtain a credential: %v", err)
}

4. 使用 Go 创建密钥保管库机密

使用以下代码示例验证服务主体是否向 Azure 进行身份验证,并具有对密钥保管库的适当权限。

  1. 在主目录中创建名为 go-on-azure 的新目录。

    mkdir ~/go-on-azure
    
  2. 切换到 go-on-azure 目录。

    cd ~/go-on-azure
    
  3. 运行 go mod init 以创建 go.mod 文件。

    go mod init go-on-azure
    
  4. 运行 go get 以安装所需的 Go 模块。

    go get "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    go get "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
    
  5. 创建一个名为 main.go 的文件,并添加以下代码。

    package main
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"os"
    
    	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
        "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
    )
    
    func createSecret(name, value string) {
    	keyVaultName := os.Getenv("KEY_VAULT_NAME")
    	keyVaultUrl := fmt.Sprintf("https://%s.vault.azure.net/", keyVaultName)
    
    	cred, err := azidentity.NewDefaultAzureCredential(nil)
    	if err != nil {
    		log.Fatalf("failed to obtain a credential: %v", err)
    	}
    
    	client, err := azsecrets.NewClient(keyVaultUrl, cred, nil)
    	if err != nil {
    		log.Fatalf("failed to create a client: %v", err)
    	}
    
        params := azsecrets.SetSecretParameters{Value: &value}
        resp, err := client.SetSecret(context.TODO(), name, params, nil)
    	if err != nil {
    		log.Fatalf("failed to create a secret: %v", err)
    	}
    
    	fmt.Printf("Name: %s, Value: %s\n", *resp.ID, *resp.Value)
    }
    
    func main() {
    	createSecret("ExamplePassword", "hVFkk965BuUv")
    }
    
    
  6. 创建一个名为 KEY_VAULT_NAME 的环境变量。 将环境变量值设置为之前创建的 Azure 密钥保管库的名称。

    export KEY_VAULT_NAME=<keyVaultName>
    

    替换为 <keyVaultName> Azure 密钥库 实例的名称。

  7. go run运行命令以创建新的密钥保管库机密。

     go run main.go
    

    成功后,输出类似于以下内容:

    Name: https://<keyVaultName>.vault.azure.net/secrets/ExamplePassword/1e697f71d0014761a65641226f2f057b, Value: hVFkk965BuUv
    

5.清理资源

如果不想再使用本文中创建的 Azure 资源,最好将其删除。 删除未使用的资源有助于避免产生持续费用,并使订阅保持整洁。 删除本教程中使用的资源的最简单方法是删除资源组。

az group delete --name go-on-azure --yes

--yes 参数告知命令不要要求确认。

上述命令对资源组中的密钥保管库执行 软删除 。 若要永久将其从订阅中删除,请输入以下命令:

az keyvault purge --name <keyVaultName> --no-wait

<keyVaultName> 替换为你的密钥保管库名称。

最后,应删除应用注册和服务主体。

az ad app delete --id <servicePrincipalAppId>

替换为 <servicePrincipalAppId> 服务主体的应用 ID。

后续步骤