チュートリアル: Service Connector を使用してデータベース サービスへのパスワードレス接続を作成する
[アーティクル]
パスワードレス接続では、マネージド ID を使用して Azure サービスにアクセスします。 この方法では、マネージド ID のシークレットを手動で追跡および管理する必要はありません。 これらのタスクは、Azure 内部で安全に処理されます。
Service Connector を使用すると、Azure Spring Apps、Azure App Service、Azure Container Apps などのアプリ ホスティング サービスでマネージド ID を使用できます。 また、Service Connector により、Azure Database for PostgreSQL、Azure Database for MySQL、Azure SQL Database などのデータベース サービスはマネージド ID を受け入れるように構成されます。
このチュートリアルでは、Azure CLI を使用して以下のタスクを実了します。
Azure CLI を使用して初期環境を確認する。
Service Connector を使用してパスワードレス接続を作成する。
Service Connector によって生成された環境変数または構成を使用して、データベース サービスにアクセスする。
Service Connector は次の権限をユーザーに割り当てます。これらの権限を取り消し、要件に基づいて権限を調整できます。
GRANT ALL PRIVILEGES ON DATABASE "$DATABASE_NAME" TO "username";
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "username";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "username";
GRANT ALL PRIVILEGES ON $DATABASE_NAME.* TO 'username'@'%';
GRANT CONTROL ON DATABASE::"$DATABASE_NAME" TO "username";
using Azure.Identity;
using Azure.Core;
using Npgsql;
// Uncomment the following lines corresponding to the authentication type you want to use.
// For system-assigned identity.
// var sqlServerTokenProvider = new DefaultAzureCredential();
// For user-assigned identity.
// var sqlServerTokenProvider = new DefaultAzureCredential(
// new DefaultAzureCredentialOptions
// {
// ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTID");
// }
// );
// For service principal.
// var tenantId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_TENANTID");
// var clientId = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTID");
// var clientSecret = Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CLIENTSECRET");
// var sqlServerTokenProvider = new ClientSecretCredential(tenantId, clientId, clientSecret);
// Acquire the access token.
AccessToken accessToken = await sqlServerTokenProvider.GetTokenAsync(
new TokenRequestContext(scopes: new string[]
{
"https://ossrdbms-aad.database.windows.net/.default"
}));
// Combine the token with the connection string from the environment variables provided by Service Connector.
string connectionString =
$"{Environment.GetEnvironmentVariable("AZURE_POSTGRESQL_CONNECTIONSTRING")};Password={accessToken.Token}";
// Establish the connection.
using (var connection = new NpgsqlConnection(connectionString))
{
Console.WriteLine("Opening connection using access token...");
connection.Open();
}
pip install azure-identity
pip install psycopg2-binary
pip freeze > requirements.txt # Save the dependencies to a file
azure-identity ライブラリを使用してアクセス トークンを取得し、トークンをパスワードとして使用します。 Service Connector によって追加された環境変数から接続情報を取得します。 次のコードを使用する場合は、使用する認証型のコード スニペットの一部をコメント解除します。
from azure.identity import DefaultAzureCredential
import psycopg2
# Uncomment the following lines corresponding to the authentication type you want to use.
# For system-assigned identity.
# cred = DefaultAzureCredential()
# For user-assigned identity.
# managed_identity_client_id = os.getenv('AZURE_POSTGRESQL_CLIENTID')
# cred = ManagedIdentityCredential(client_id=managed_identity_client_id)
# For service principal.
# tenant_id = os.getenv('AZURE_POSTGRESQL_TENANTID')
# client_id = os.getenv('AZURE_POSTGRESQL_CLIENTID')
# client_secret = os.getenv('AZURE_POSTGRESQL_CLIENTSECRET')
# cred = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
# Acquire the access token
accessToken = cred.get_token('https://ossrdbms-aad.database.windows.net/.default')
# Combine the token with the connection string from the environment variables added by Service Connector to establish the connection.
conn_string = os.getenv('AZURE_POSTGRESQL_CONNECTIONSTRING')
conn = psycopg2.connect(conn_string + ' password=' + accessToken.token)
依存関係をインストールします。
pip install azure-identity
Service Connector によって追加された環境変数を使用することで、azure-identity ライブラリを使用してアクセス トークンを取得します。 次のコードを使用する場合は、使用する認証型のコード スニペットの一部をコメント解除します。
from azure.identity import DefaultAzureCredential
import psycopg2
# Uncomment the following lines corresponding to the authentication type you want to use.
# For system-assigned identity.
# credential = DefaultAzureCredential()
# For user-assigned identity.
# managed_identity_client_id = os.getenv('AZURE_POSTGRESQL_CLIENTID')
# cred = ManagedIdentityCredential(client_id=managed_identity_client_id)
# For service principal.
# tenant_id = os.getenv('AZURE_POSTGRESQL_TENANTID')
# client_id = os.getenv('AZURE_POSTGRESQL_CLIENTID')
# client_secret = os.getenv('AZURE_POSTGRESQL_CLIENTSECRET')
# cred = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
# Acquire the access token.
accessToken = cred.get_token('https://ossrdbms-aad.database.windows.net/.default')
import { DefaultAzureCredential, ClientSecretCredential } from "@azure/identity";
const { Client } = require('pg');
// Uncomment the following lines corresponding to the authentication type you want to use.
// For system-assigned identity.
// const credential = new DefaultAzureCredential();
// For user-assigned identity.
// const clientId = process.env.AZURE_POSTGRESQL_CLIENTID;
// const credential = new DefaultAzureCredential({
// managedIdentityClientId: clientId
// });
// For service principal.
// const tenantId = process.env.AZURE_POSTGRESQL_TENANTID;
// const clientId = process.env.AZURE_POSTGRESQL_CLIENTID;
// const clientSecret = process.env.AZURE_POSTGRESQL_CLIENTSECRET;
// Acquire the access token.
var accessToken = await credential.getToken('https://ossrdbms-aad.database.windows.net/.default');
// Use the token and the connection information from the environment variables added by Service Connector to establish the connection.
(async () => {
const client = new Client({
host: process.env.AZURE_POSTGRESQL_HOST,
user: process.env.AZURE_POSTGRESQL_USER,
password: accesstoken.token,
database: process.env.AZURE_POSTGRESQL_DATABASE,
port: Number(process.env.AZURE_POSTGRESQL_PORT) ,
ssl: process.env.AZURE_POSTGRESQL_SSL
});
await client.connect();
await client.end();
})();
PHP の場合、パスワードレス接続用のプラグインやライブラリはありません。 マネージド ID またはサービス プリンシパルのアクセス トークンを取得し、データベースに接続するためのパスワードとして使用できます。 アクセス トークンは Azure REST API を使って取得できます。
コードで、お気に入りのライブラリを使用して REST API を使用してアクセス トークンを取得します。
ユーザー割り当て ID とシステム割り当て ID については、App Service と Container Apps が内部的にアクセスできる REST エンドポイントを提供しており、2 つの環境変数 IDENTITY_ENDPOINT と IDENTITY_HEADER を定義することで、マネージド ID のトークンを取得できます。 詳細については、「REST エンドポイント リファレンス」を参照してください。
ID エンドポイントに対して HTTP GET 要求を行ってアクセス トークンを取得し、クエリの resource として https://ossrdbms-aad.database.windows.net を使います。 ユーザー割り当て ID の場合、Service Connector によって追加された環境変数のクライアント ID もクエリに含めてください。
サービス プリンシパルについては、Azure AD サービス間アクセス トークン要求に関するページを参照して、アクセス トークンの取得方法の詳細を確認してください。 POST 要求を https://ossrdbms-aad.database.windows.net/.default のスコープにして、Service Connector によって追加された環境変数のサービス プリンシパルのテナント ID、クライアント ID、クライアント シークレットを指定します。
az extension add --name rdbms-connect
az postgres flexible-server execute -n <postgres-name> -u <owner-username> -p "<owner-password>" -d <database-name> --querytext "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"<aad-username>\";GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"<aad username>\";"
using Azure.Core;
using Azure.Identity;
using MySqlConnector;
// Uncomment the following lines corresponding to the authentication type you want to use.
// For system-assigned managed identity.
// var credential = new DefaultAzureCredential();
// For user-assigned managed identity.
// var credential = new DefaultAzureCredential(
// new DefaultAzureCredentialOptions
// {
// ManagedIdentityClientId = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTID");
// });
// For service principal.
// var tenantId = Environment.GetEnvironmentVariable("AZURE_MYSQL_TENANTID");
// var clientId = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTID");
// var clientSecret = Environment.GetEnvironmentVariable("AZURE_MYSQL_CLIENTSECRET");
// var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var tokenRequestContext = new TokenRequestContext(
new[] { "https://ossrdbms-aad.database.windows.net/.default" });
AccessToken accessToken = await credential.GetTokenAsync(tokenRequestContext);
// Open a connection to the MySQL server using the access token.
string connectionString =
$"{Environment.GetEnvironmentVariable("AZURE_MYSQL_CONNECTIONSTRING")};Password={accessToken.Token}";
using var connection = new MySqlConnection(connectionString);
Console.WriteLine("Opening connection using access token...");
await connection.OpenAsync();
// do something
from azure.identity import ManagedIdentityCredential, ClientSecretCredential
import mysql.connector
import os
# Uncomment the following lines corresponding to the authentication type you want to use.
# For system-assigned managed identity.
# cred = ManagedIdentityCredential()
# For user-assigned managed identity.
# managed_identity_client_id = os.getenv('AZURE_MYSQL_CLIENTID')
# cred = ManagedIdentityCredential(client_id=managed_identity_client_id)
# For service principal
# tenant_id = os.getenv('AZURE_MYSQL_TENANTID')
# client_id = os.getenv('AZURE_MYSQL_CLIENTID')
# client_secret = os.getenv('AZURE_MYSQL_CLIENTSECRET')
# cred = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
# acquire token
accessToken = cred.get_token('https://ossrdbms-aad.database.windows.net/.default')
# open connect to Azure MySQL with the access token.
host = os.getenv('AZURE_MYSQL_HOST')
database = os.getenv('AZURE_MYSQL_NAME')
user = os.getenv('AZURE_MYSQL_USER')
password = accessToken.token
cnx = mysql.connector.connect(user=user,
password=password,
host=host,
database=database)
cnx.close()
依存関係をインストールします。
pip install azure-identity
Service Connector によって追加された環境変数を使って、azure-identity ライブラリ経由でアクセス トークンを取得します。 次のコードを使用する場合は、使用する認証型のコード スニペットの一部をコメント解除します。
from azure.identity import ManagedIdentityCredential, ClientSecretCredential
import os
# Uncomment the following lines corresponding to the authentication type you want to use.
# system-assigned managed identity
# cred = ManagedIdentityCredential()
# user-assigned managed identity
# managed_identity_client_id = os.getenv('AZURE_MYSQL_CLIENTID')
# cred = ManagedIdentityCredential(client_id=managed_identity_client_id)
# service principal
# tenant_id = os.getenv('AZURE_MYSQL_TENANTID')
# client_id = os.getenv('AZURE_MYSQL_CLIENTID')
# client_secret = os.getenv('AZURE_MYSQL_CLIENTSECRET')
# cred = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
# acquire token
accessToken = cred.get_token('https://ossrdbms-aad.database.windows.net/.default')
ファイルの設定で、Service Connector サービスによって追加された環境変数から Azure MySQL データベース情報を取得します。 前の手順で取得した accessToken を使用し、データベースにアクセスします。
# in your setting file, eg. settings.py
host = os.getenv('AZURE_MYSQL_HOST')
database = os.getenv('AZURE_MYSQL_NAME')
user = os.getenv('AZURE_MYSQL_USER')
password = accessToken.token # this is accessToken acquired from above step.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': database,
'USER': user,
'PASSWORD': password,
'HOST': host
}
}
依存関係をインストールします。
go get "github.com/go-sql-driver/mysql"
go get "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
go get "github.com/Azure/azure-sdk-for-go/sdk/azcore"
コードでは、azidentity を介してアクセス トークンを取得し、そのトークンで Azure MySQL に接続します。 次のコードを使用する場合は、使用する認証型のコード スニペットの一部をコメント解除します。
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/go-sql-driver/mysql"
)
func main() {
// Uncomment the following lines corresponding to the authentication type you want to use.
// for system-assigned managed identity
// cred, err := azidentity.NewDefaultAzureCredential(nil)
// for user-assigned managed identity
// clientid := os.Getenv("AZURE_MYSQL_CLIENTID")
// azidentity.ManagedIdentityCredentialOptions.ID := clientid
// options := &azidentity.ManagedIdentityCredentialOptions{ID: clientid}
// cred, err := azidentity.NewManagedIdentityCredential(options)
// for service principal
// clientid := os.Getenv("AZURE_MYSQL_CLIENTID")
// tenantid := os.Getenv("AZURE_MYSQL_TENANTID")
// clientsecret := os.Getenv("AZURE_MYSQL_CLIENTSECRET")
// cred, err := azidentity.NewClientSecretCredential(tenantid, clientid, clientsecret, &azidentity.ClientSecretCredentialOptions{})
if err != nil {
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string("https://ossrdbms-aad.database.windows.net/.default"),
})
connectionString := os.Getenv("AZURE_MYSQL_CONNECTIONSTRING") + ";Password=" + token.Token
db, err := sql.Open("mysql", connectionString)
}
using Microsoft.Data.SqlClient;
string connectionString =
Environment.GetEnvironmentVariable("AZURE_SQL_CONNECTIONSTRING")!;
using var connection = new SqlConnection(connectionString);
connection.Open();
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
public class Main {
public static void main(String[] args) {
// AZURE_SQL_CONNECTIONSTRING should be one of the following:
// For system-assigned managed identity: "jdbc:sqlserver://{SQLName}.database.windows.net:1433;databaseName={SQLDbName};authentication=ActiveDirectoryMSI;"
// For user-assigned managed identity: "jdbc:sqlserver://{SQLName}.database.windows.net:1433;databaseName={SQLDbName};msiClientId={UserAssignedMiClientId};authentication=ActiveDirectoryMSI;"
// For service principal: "jdbc:sqlserver://{SQLName}.database.windows.net:1433;databaseName={SQLDbName};user={ServicePrincipalClientId};password={spSecret};authentication=ActiveDirectoryServicePrincipal;"
String connectionString = System.getenv("AZURE_SQL_CONNECTIONSTRING");
SQLServerDataSource ds = new SQLServerDataSource();
ds.setURL(connectionString);
try (Connection connection = ds.getConnection()) {
System.out.println("Connected successfully.");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
import os
import pyodbc
server = os.getenv('AZURE_SQL_SERVER')
port = os.getenv('AZURE_SQL_PORT')
database = os.getenv('AZURE_SQL_DATABASE')
authentication = os.getenv('AZURE_SQL_AUTHENTICATION')
# Uncomment the following lines corresponding to the authentication type you want to use.
# For system-assigned managed identity.
# connString = f'Driver={{ODBC Driver 18 for SQL Server}};Server=tcp:{server},{port};Database={database};Authentication={authentication};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30'
# For user-assigned managed identity.
# clientID = os.getenv('AZURE_SQL_USER')
# connString = f'Driver={{ODBC Driver 18 for SQL Server}};Server=tcp:{server},{port};Database={database};UID={clientID};Authentication={authentication};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30'
# For service principal.
# user = os.getenv('AZURE_SQL_USER')
# password = os.getenv('AZURE_SQL_PASSWORD')
# connString = f'Driver={{ODBC Driver 18 for SQL Server}};Server=tcp:{server},{port};Database={database};UID={user};PWD={password};Authentication={authentication};Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30'
conn = pyodbc.connect(connString)
Azure CLI ログイン ユーザーがデータベース サーバーの Microsoft Entra 管理者であるかどうかを確認するために必要
Microsoft.Sql/servers/administrators/write
Azure CLI ログイン ユーザーをデータベース サーバーの Microsoft Entra 管理者として追加するために必要
場合によっては、アクセス許可は必要ありません。 たとえば、Azure CLI で認証されたユーザーが既に SQL Server の Active Directory 管理者である場合、Microsoft.Sql/servers/administrators/write アクセス許可は必要ありません。
Microsoft Entra ID
エラー ERROR: AADSTS530003: Your device is required to be managed to access this resource. が発生した場合は、このデバイスを Microsoft Entra ID に参加させる方法について IT 部門に問い合わせてください。 詳細については、「Microsoft Entra 参加済みデバイス」を参照してください。
Service Connector は、アカウントの情報とホスティング サービスのマネージド ID を取得するために、Microsoft Entra ID にアクセスする必要があります。 次のコマンドを使用して、デバイスが Microsoft Entra ID にアクセスできるかどうかを確認できます。
az ad signed-in-user show
対話形式でログインしない場合、エラーと Interactive authentication is needed が表示される場合もあります。 エラーを解決するには、az login コマンドを使用してログインします。