使用托管标识连接到 Azure Database for PostgreSQL

适用于:Azure Database for PostgreSQL 单一服务器

重要

Azure Database for PostgreSQL - 单一服务器即将停用。 我们强烈建议升级到 Azure Database for PostgreSQL 灵活服务器。 有关迁移到 Azure Database for PostgreSQL 灵活服务器的详细信息,请参阅 Azure Database for PostgreSQL 单一服务器的最新动态

可以使用系统分配的托管标识和用户分配的托管标识,向 Azure Database for PostgreSQL 进行身份验证。 本文介绍如何使用 Azure 虚拟机 (VM) 的系统分配的托管标识来访问 Azure Database for PostgreSQL 服务器。 托管标识由 Azure 自动管理,可用于向支持 Microsoft Entra 身份验证的服务进行身份验证,这样就无需在代码中插入凭据了。

学习如何:

  • 授予 VM 对 Azure Database for PostgreSQL 服务器的访问权限
  • 在数据库中创建一个代表 VM 的系统分配标识的用户
  • 使用 VM 标识获取访问令牌,并使用它查询 Azure Database for PostgreSQL 服务器
  • 在 C# 示例应用程序中实现令牌检索

先决条件

为 VM 创建系统分配的托管标识

az vm identity assignidentity assign 命令配合使用,为现有 VM 启用系统分配标识:

az vm identity assign -g myResourceGroup -n myVm

检索系统分配的托管标识的应用程序 ID,在接下来几个步骤中将需要此 ID:

# Get the client ID (application ID) of the system-assigned managed identity

az ad sp list --display-name vm-name --query [*].appId --out tsv

为托管标识创建 PostgreSQL 用户

现在,以 Microsoft Entra 管理员用户身份连接到 PostgreSQL 数据库,并运行以下 SQL 语句,将 CLIENT_ID 替换为你为系统分配的托管标识检索的客户端 ID:

SET aad_validate_oids_in_tenant = off;
CREATE ROLE myuser WITH LOGIN PASSWORD 'CLIENT_ID' IN ROLE azure_ad_user;

使用用户名 myuser(替换为你选择的名称)进行身份验证时,托管标识现在具有访问权限。

从 Azure 实例元数据服务检索访问令牌

应用程序现在可以从 Azure 实例元数据服务检索访问令牌,并将其用于向数据库进行身份验证。

此令牌检索是通过向 http://169.254.169.254/metadata/identity/oauth2/token 发出 HTTP 请求并传递以下参数来完成的:

  • api-version = 2018-02-01
  • resource = https://ossrdbms-aad.database.chinacloudapi.cn
  • client_id = CLIENT_ID(之前检索到的)

将返回包含 access_token 字段的 JSON 结果 - 此长文本值是托管标识访问令牌,在连接到数据库时应将其用作密码。

出于测试目的,可以在 shell 中运行以下命令。 请注意,需要安装 curljqpsql 客户端。

# Retrieve the access token

export PGPASSWORD=`curl -s 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fossrdbms-aad.database.chinacloudapi.cn&client_id=CLIENT_ID' -H Metadata:true | jq -r .access_token`

# Connect to the database

psql -h SERVER --user USER@SERVER DBNAME

你现在已连接到之前配置的数据库。

通过 C# 使用托管标识进行连接

本部分介绍如何使用 VM 的用户分配托管标识获取访问令牌,并使用它调用 Azure Database for PostgreSQL。 Azure Database for PostgreSQL 以原生方式支持 Microsoft Entra 身份验证,因此可以直接接受使用 Azure 资源托管标识获取的访问令牌。 创建到 PostgreSQL 的连接时,在密码字段中传递访问令牌。

以下 .NET 代码示例使用访问令牌来与 PostgreSQL 建立连接。 此代码必须在 VM 上运行,才能使用系统分配的托管标识从 Microsoft Entra ID 获取访问令牌。 替换 HOST、USER、DATABASE 和 CLIENT_ID 的值。

using System;
using System.Net;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
using Npgsql;
using Azure.Identity;

namespace Driver
{
    class Script
    {
        // Obtain connection string information from the portal for use in the following variables
        private static string Host = "HOST";
        private static string User = "USER";
        private static string Database = "DATABASE";

        static async Task Main(string[] args)
        {
            //
            // Get an access token for PostgreSQL.
            //
            Console.Out.WriteLine("Getting access token from Azure AD...");

            // Azure AD resource ID for Azure Database for PostgreSQL is https://ossrdbms-aad.database.chinacloudapi.cn/
            string accessToken = null;

            try
            {
                // Call managed identities for Azure resources endpoint.
                var sqlServerTokenProvider = new DefaultAzureCredential();
                accessToken = (await sqlServerTokenProvider.GetTokenAsync(
                    new Azure.Core.TokenRequestContext(scopes: new string[] { "https://ossrdbms-aad.database.chinacloudapi.cn/.default" }) { })).Token;

            }
            catch (Exception e)
            {
                Console.Out.WriteLine("{0} \n\n{1}", e.Message, e.InnerException != null ? e.InnerException.Message : "Acquire token failed");
                System.Environment.Exit(1);
            }

            //
            // Open a connection to the PostgreSQL server using the access token.
            //
            string connString =
                String.Format(
                    "Server={0}; User Id={1}; Database={2}; Port={3}; Password={4}; SSLMode=Prefer",
                    Host,
                    User,
                    Database,
                    5432,
                    accessToken);

            using (var conn = new NpgsqlConnection(connString))
            {
                Console.Out.WriteLine("Opening connection using access token...");
                conn.Open();

                using (var command = new NpgsqlCommand("SELECT version()", conn))
                {

                    var reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine("\nConnected!\n\nPostgres version: {0}", reader.GetString(0));
                    }
                }
            }
        }
    }
}

运行时,此命令将返回如下所示的输出:

Getting access token from Azure AD...
Opening connection using access token...

Connected!

Postgres version: PostgreSQL 11.11, compiled by Visual C++ build 1800, 64-bit

后续步骤