使用托管标识连接到 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

为托管标识创建 Azure Database for PostgreSQL 灵活服务器用户

现在,以 Microsoft Entra 管理员用户身份连接到 Azure Database for PostgreSQL 灵活服务器数据库,并运行以下 SQL 语句,将 <identity_name> 替换为你为其创建了系统分配的托管标识的资源的名称:

请注意,必须对 Postgres 数据库运行 pgaadauth_create_principal。

select * from pgaadauth_create_principal('<identity_name>', false, false);

成功时会如下所示:

    pgaadauth_create_principal
-----------------------------------
 Created role for "<identity_name>"
(1 row)

有关管理已启用 Microsoft Entra ID 的数据库角色的详细信息,请参阅如何管理已启用 Microsoft Entra ID 的 Azure Database for PostgreSQL - 灵活服务器角色

使用标识名称作为角色名称并使用 Microsoft Entra 令牌作为密码进行身份验证时,托管标识现在可以进行访问。

注意

如果托管标识无效,则会返回错误:ERROR: Could not validate AAD user <ObjectId> because its name is not found in the tenant. [...]

注意

如果看到“无函数匹配...”之类的错误,请确保连接到 postgres 数据库,而不是连接到你创建的其他数据库。

从 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 DBNAME

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

使用托管标识进行连接

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

在 Python 中使用托管标识进行连接

有关 Python 代码示例,请参阅快速入门:使用 Python 连接和查询 Azure Database for PostgreSQL 灵活服务器中的数据

在 Java 中使用托管标识进行连接

有关 Java 代码示例,请参阅快速入门:将 Java 和 JDBC 与 Azure Database for PostgreSQL 灵活服务器配合使用

在 C# 中使用托管标识进行连接

下面是使用访问令牌打开与 Azure Database for PostgreSQL 灵活服务器的连接的 .NET 代码示例。 此代码必须在 VM 上运行,才能使用系统分配的托管标识从 Microsoft Entra ID 获取访问令牌。 替换 HOST、USER(带有 <identity_name>)和 DATABASE 的值。

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 Flexible Server 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 

后续步骤