Tutorial: Verbindungsherstellung mit Azure-Datenbanken über App Service ohne Geheimnisse mithilfe einer verwalteten Identität
Artikel
App Service bietet einen hochgradig skalierbaren Webhostingdienst mit Self-Patching in Azure. Außerdem steht eine verwaltete Identität für Ihre App zur Verfügung, wobei es sich um eine vorgefertigte Lösung zum Schutz des Zugriffs auf Azure-Datenbank handelt, einschließlich:
Verwaltete Identitäten in App Service machen Ihre App frei von Geheimnissen (wie etwa Anmeldeinformationen in Verbindungszeichenfolgen) und verbessern so die Sicherheit Ihrer App. In diesem Tutorial wird gezeigt, wie Sie eine Verbindung mit den oben erwähnten Datenbanken aus App Service mithilfe verwalteter Identitäten herstellen.
Sie lernen Folgendes:
Konfigurieren eines Azure AD-Benutzers als Administrator für Ihre Azure-Datenbank.
Herstellen einer Verbindung mit Ihrer Datenbank als Azure AD-Benutzer.
Konfigurieren einer systemseitig oder benutzerseitig zugewiesenen verwalteten Identität für eine App Service-App.
Gewähren von Datenbankzugriff auf die verwaltete Identität.
Herstellen einer Verbindung mit der Azure-Datenbank aus Ihrem Code (.NET Framework 4.8, .NET 6, Node.js, Python, Java) mithilfe einer verwalteten Identität.
Herstellen einer Verbindung mit der Azure-Datenbank aus Ihrer Entwicklungsumgebung mithilfe des Azure AD-Benutzers.
Erstellen Sie eine App in App Service, basierend auf .NET, Node.js, Python oder Java.
Erstellen Sie einen Datenbankserver mit Azure SQL-Datenbank, Azure Database for MySQL oder Azure Database for PostgreSQL.
Sie sollten mit dem Standardkonnektivitätsmuster (mit Benutzername und Kennwort) vertraut und in der Lage sein, eine erfolgreiche Verbindung von Ihrer App Service-App mit Ihrer ausgewählten Datenbank herzustellen.
Wenn Sie CLI-Referenzbefehle lieber lokal ausführen, installieren Sie die Azure CLI. Wenn Sie Windows oder macOS ausführen, sollten Sie die Azure CLI in einem Docker-Container ausführen. Weitere Informationen finden Sie unter Ausführen der Azure CLI in einem Docker-Container.
Wenn Sie eine lokale Installation verwenden, melden Sie sich mithilfe des Befehls az login bei der Azure CLI an. Führen Sie die in Ihrem Terminal angezeigten Schritte aus, um den Authentifizierungsprozess abzuschließen. Informationen zu anderen Anmeldeoptionen finden Sie unter Anmelden mit der Azure CLI.
Installieren Sie die Azure CLI-Erweiterung beim ersten Einsatz, wenn Sie dazu aufgefordert werden. Weitere Informationen zu Erweiterungen finden Sie unter Verwenden von Erweiterungen mit der Azure CLI.
Führen Sie az version aus, um die installierte Version und die abhängigen Bibliotheken zu ermitteln. Führen Sie az upgrade aus, um das Upgrade auf die aktuelle Version durchzuführen.
1. Gewähren von Datenbankzugriff für Azure AD-Benutzer
Aktivieren Sie zunächst die Azure Active Directory-Authentifizierung für die Azure-Datenbank, indem Sie einen Azure AD-Benutzer als Administrator des Servers zuweisen. Für das Szenario im Tutorial verwenden Sie diesen Benutzer, um eine Verbindung mit Ihrer Azure-Datenbank aus der lokalen Entwicklungsumgebung herzustellen. Später richten Sie die verwaltete Identität für Ihre App Service-App ein, um eine Verbindung aus Azure heraus herzustellen.
Hinweis
Dieser Benutzer unterscheidet sich von dem Microsoft-Konto, das Sie bei der Registrierung für Ihr Azure-Abonnement verwendet haben. Es muss sich um einen Benutzer handeln, den Sie in Azure AD erstellt, importiert, synchronisiert oder eingeladen haben. Weitere Informationen zu zulässigen Azure AD-Benutzern finden Sie unter Funktionen und Einschränkungen von Azure AD.
Ermitteln Sie die Objekt-ID des Azure AD-Benutzers mithilfe von az ad user list, und ersetzen Sie den Platzhalter az ad user list. Das Ergebnis wird in einer Variablen gespeichert.
azureaduser=$(az ad user list --filter "userPrincipalName eq '<user-principal-name>'" --query [].id --output tsv)
Fügen Sie diesen Azure AD-Benutzer in Cloud Shell mithilfe des Befehls az sql server ad-admin create als Active Directory-Administrator hinzu. Ersetzen Sie im folgenden Befehl <group-name> und <server-name> durch Ihre eigenen Parameter.
az sql server ad-admin create --resource-group <group-name> --server-name <server-name> --display-name ADMIN --object-id $azureaduser
Fügen Sie diesen Azure AD-Benutzer in Cloud Shell mithilfe des Befehls az mysql server ad-admin create als Active Directory-Administrator hinzu. Ersetzen Sie im folgenden Befehl <group-name> und <server-name> durch Ihre eigenen Parameter.
az mysql server ad-admin create --resource-group <group-name> --server-name <server-name> --display-name <user-principal-name> --object-id $azureaduser
Hinweis
Der Befehl ist zurzeit für Azure Database for MySQL – Flexible Server nicht verfügbar.
Fügen Sie diesen Azure AD-Benutzer in Cloud Shell mithilfe des Befehls az postgres server ad-admin create als Active Directory-Administrator hinzu. Ersetzen Sie im folgenden Befehl <group-name> und <server-name> durch Ihre eigenen Parameter.
az postgres server ad-admin create --resource-group <group-name> --server-name <server-name> --display-name <user-principal-name> --object-id $azureaduser
Hinweis
Der Befehl ist zurzeit für Azure Database for PostgreSQL – Flexible Server nicht verfügbar.
2. Konfigurieren einer verwalteten Identität für die App
Als Nächstes konfigurieren Sie Ihre App Service-App so, dass sie beim Herstellen der Verbindung mit SQL-Datenbank eine verwaltete Identität verwendet.
Aktivieren Sie mit dem Befehl az webapp identity assign in Cloud Shell eine verwaltete Identität für Ihre App Service-App. Ersetzen Sie im folgenden Befehl den Platzhalter app-name>.
az webapp identity assign --resource-group <group-name> --name <app-name>
az webapp identity assign --resource-group <group-name> --name <app-name> --output tsv --query principalId
az ad sp show --id <output-from-previous-command> --output tsv --query appId
Die Ausgabe von az ad sp show ist die Anwendungs-ID der systemseitig zugewiesenen Identität. Sie benötigen die Information später.
az webapp identity assign --resource-group <group-name> --name <app-name> --output tsv --query principalId
az ad sp show --id <output-from-previous-command> --output tsv --query appId
Die Ausgabe von az ad sp show ist die Anwendungs-ID der systemseitig zugewiesenen Identität. Sie benötigen die Information später.
# Create a user-assigned identity and get its client ID
az identity create --name <identity-name> --resource-group <group-name> --output tsv --query "id"
# assign identity to app
az webapp identity assign --resource-group <group-name> --name <app-name> --identities <output-of-previous-command>
# get client ID of identity for later
az webapp identity show --name <identity-name> --resource-group <group-name> --output tsv --query "clientId"
Die Ausgabe von az ad sp show ist die Anwendungs-ID der systemseitig zugewiesenen Identität. Sie benötigen die Information später.
Hinweis
Wenn Sie eine verwaltete Identität für einen Bereitstellungsslot aktivieren möchten, fügen Sie hinzu, und verwenden Sie in slot-name> den Namen des Slots.
Der Identität müssen Berechtigungen für den Zugriff auf die Datenbank gewährt werden. Melden Sie sich in Cloud Shell mit dem folgenden Befehl bei Ihrer Datenbank an. Ersetzen Sie <server-name> durch den Namen Ihres Servers, <database-name> durch den von Ihrer App verwendeten Datenbanknamen sowie <aad-user-name> und <aad-password> durch die Anmeldeinformationen Ihres Azure AD-Benutzers aus 1. Gewähren von Datenbankzugriff für Azure AD-Benutzer.
# Sign into Azure using the Azure AD user from "1. Grant database access to Azure AD user"
az login --allow-no-subscriptions
# Get access token for MySQL with the Azure AD user
az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken
# Sign into the MySQL server using the token
mysql -h <server-name>.mysql.database.azure.com --user <aad-user-name>@<server-name> --enable-cleartext-plugin --password=<token-output-from-last-command> --ssl
Der vollständige Benutzername <aad-user-name>@<server-name> sieht wie admin1@contoso.onmicrosoft.com@mydbserver1 aus.
# Sign into Azure using the Azure AD user from "1. Grant database access to Azure AD user"
az login --allow-no-subscriptions
# Get access token for PostgreSQL with the Azure AD user
az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken
# Sign into the Postgres server
psql "host=<server-name>.postgres.database.azure.com port=5432 dbname=<database-name> user=<aad-user-name>@<server-name> password=<token-output-from-last-command>"
Der vollständige Benutzername <aad-user-name>@<server-name> sieht wie admin1@contoso.onmicrosoft.com@mydbserver1 aus.
Führen Sie die folgenden Datenbankbefehle aus, um die Berechtigungen zu erteilen, die Ihre App benötigt. Beispiel:
CREATE USER [<app-name>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<app-name>];
ALTER ROLE db_datawriter ADD MEMBER [<app-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<app-name>];
GO
Verwenden Sie für einen Bereitstellungsslot anstelle von <app-name><app-name>/slots/<slot-name>.
CREATE USER [<identity-name>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<identity-name>];
ALTER ROLE db_datawriter ADD MEMBER [<identity-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<identity-name>];
GO
SET aad_auth_validate_oids_in_tenant = OFF;
CREATE AADUSER '<mysql-user-name>' IDENTIFIED BY '<application-id-of-system-assigned-identity>';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON *.* TO '<mysql-user-name>'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Unabhängig davon, welchen Namen Sie für <mysql-user-name> auswählen, handelt es sich um den MySQL-Benutzer, den Sie später aus Ihrem Code in App Service verwenden werden, um eine Verbindung mit der Datenbank herzustellen.
SET aad_auth_validate_oids_in_tenant = OFF;
CREATE AADUSER '<mysql-user-name>' IDENTIFIED BY '<client-id-of-user-assigned-identity>';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER ON *.* TO '<mysql-user-name>'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Unabhängig davon, welchen Namen Sie für <mysql-user-name> auswählen, handelt es sich um den MySQL-Benutzer, den Sie später aus Ihrem Code in App Service verwenden werden, um eine Verbindung mit der Datenbank herzustellen.
SET aad_validate_oids_in_tenant = off;
CREATE ROLE <postgresql-user-name> WITH LOGIN PASSWORD '<application-id-of-system-assigned-identity>' IN ROLE azure_ad_user;
Unabhängig davon, welchen Namen Sie für <postgresql-user-name> auswählen, handelt es sich um den PostgreSQL-Benutzer, den Sie später aus Ihrem Code in App Service verwenden werden, um eine Verbindung mit der Datenbank herzustellen.
SET aad_validate_oids_in_tenant = off;
CREATE ROLE <postgresql-user-name> WITH LOGIN PASSWORD '<application-id-of-user-assigned-identity>' IN ROLE azure_ad_user;
Unabhängig davon, welchen Namen Sie für <postgresql-user-name> auswählen, handelt es sich um den PostgreSQL-Benutzer, den Sie später aus Ihrem Code in App Service verwenden werden, um eine Verbindung mit der Datenbank herzustellen.
3. Ändern Ihres Codes
In diesem Abschnitt folgt die Verbindung mit der Azure-Datenbank in Ihrem Code dem DefaultAzureCredential-Muster für alle Sprachenstapel. DefaultAzureCredential ist flexibel genug, um sich sowohl an die Entwicklungsumgebung als auch an die Azure-Umgebung anzupassen. Bei der lokalen Ausführung kann der angemeldete Azure-Benutzer aus der Umgebung Ihrer Wahl (Visual Studio, Visual Studio Code, Azure CLI oder Azure PowerShell) abgerufen werden. Bei Ausführung in Azure wird die verwaltete Identität abgerufen. Auf diese Weise ist es möglich, sowohl zur Entwicklungszeit als auch in der Produktion eine Verbindung mit der Datenbank zu haben. Das Muster ist wie folgt:
Instanziieren eines DefaultAzureCredential aus der Azure Identity-Clientbibliothek. Wenn Sie eine benutzerseitig zugewiesene Identität verwenden, geben Sie die Client-ID der Identität an.
Abrufen eines Zugriffstokens für den Ressourcen-URI entsprechend dem Datenbanktyp.
Für Azure SQL-Datenbank: https://database.windows.net/.default
Für Azure Database for MySQL: https://ossrdbms-aad.database.windows.net/.default
Für Azure Database for PostgreSQL: https://ossrdbms-aad.database.windows.net/.default
Hinzufügen des Tokens zu Ihrer Verbindungszeichenfolge.
Öffnen Sie die Verbindung.
Für Azure Database for MySQL und Azure Database for PostgreSQL wird der Datenbankbenutzernamen, den Sie in 2. Konfigurieren einer verwalteten Identität für die App erstellt haben, auch in der Verbindungszeichenfolge benötigt.
Stellen Sie eine Verbindung mit der Azure-Datenbank her, indem Sie ein Zugriffstoken hinzufügen. Wenn Sie eine benutzerseitig zugewiesene Identität verwenden, stellen Sie sicher, dass Sie die Auskommentierung der entsprechenden Zeilen aufheben.
// Uncomment one of the two lines depending on the identity type
//var credential = new Azure.Identity.DefaultAzureCredential(); // system-assigned identity
//var credential = new Azure.Identity.DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure SQL Database
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://database.windows.net/.default" }));
// Add the token to the SQL connection
var connection = new System.Data.SqlClient.SqlConnection("Server=tcp:<server-name>.database.windows.net;Database=<database-name>;TrustServerCertificate=True");
connection.AccessToken = token.Token;
// Open the SQL connection
connection.Open();
using Azure.Identity;
...
// Uncomment one of the two lines depending on the identity type
//var credential = new DefaultAzureCredential(); // system-assigned identity
//var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for MySQL
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }));
// Set MySQL user depending on the environment
string user;
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT")))
user = "<aad-user-name>@<server-name>";
else user = "<mysql-user-name>@<server-name>";
// Add the token to the MySQL connection
var connectionString = "Server=<server-name>.mysql.database.azure.com;" +
"Port=3306;" +
"SslMode=Required;" +
"Database=<database-name>;" +
"Uid=" + user+ ";" +
"Password="+ token.Token;
var connection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
connection.Open();
using Azure.Identity;
...
// Uncomment one of the two lines depending on the identity type
//var credential = new DefaultAzureCredential(); // system-assigned identity
//var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for PostgreSQL
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }));
// Check if in Azure and set user accordingly
string postgresqlUser;
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT")))
postgresqlUser = "<aad-user-name>@<server-name>";
else postgresqlUser = "<postgresql-user-name>@<server-name>";
// Add the token to the PostgreSQL connection
var connectionString = "Server=<server-name>.postgres.database.azure.com;" +
"Port=5432;" +
"Database=<database-name>;" +
"User Id=" + postgresqlUser + ";" +
"Password="+ token.Token;
var connection = new Npgsql.NpgsqlConnection(connectionString);
connection.Open();
Installieren Sie die .NET-Pakete, die Sie in Ihrem .NET-Projekt benötigen:
Stellen Sie eine Verbindung mit der Azure-Datenbank her, indem Sie ein Zugriffstoken hinzufügen. Wenn Sie eine benutzerseitig zugewiesene Identität verwenden, stellen Sie sicher, dass Sie die Auskommentierung der entsprechenden Zeilen aufheben.
using Microsoft.Data.SqlClient;
...
// Uncomment one of the two lines depending on the identity type
//SqlConnection connection = new SqlConnection("Server=tcp:<server-name>.database.windows.net;Database=<database-name>;Authentication=Active Directory Default;TrustServerCertificate=True"); // system-assigned identity
//SqlConnection connection = new SqlConnection("Server=tcp:<server-name>.database.windows.net;Database=<database-name>;Authentication=Active Directory Default;User Id=<client-id-of-user-assigned-identity>;TrustServerCertificate=True"); // user-assigned identity
// Open the SQL connection
connection.Open();
Microsoft.Data.SqlClient bietet integrierte Unterstützung der Azure AD-Authentifizierung. In diesem Fall verwendet der Active Directory-StandardDefaultAzureCredential, um das erforderliche Token für Sie abzurufen, und fügt es der Datenbankverbindung direkt hinzu.
using Azure.Identity;
...
// Uncomment one of the two lines depending on the identity type
//var credential = new DefaultAzureCredential(); // system-assigned identity
//var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for MySQL
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }));
// Set MySQL user depending on the environment
string user;
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT")))
user = "<aad-user-name>@<server-name>";
else user = "<mysql-user-name>@<server-name>";
// Add the token to the MySQL connection
var connectionString = "Server=<server-name>.mysql.database.azure.com;" +
"Port=3306;" +
"SslMode=Required;" +
"Database=<database-name>;" +
"Uid=" + user+ ";" +
"Password="+ token.Token;
var connection = new MySql.Data.MySqlClient.MySqlConnection(connectionString);
connection.Open();
using Azure.Identity;
...
// Uncomment one of the two lines depending on the identity type
//var credential = new DefaultAzureCredential(); // system-assigned identity
//var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for PostgreSQL
var token = credential.GetToken(new Azure.Core.TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }));
// Check if in Azure and set user accordingly
string postgresqlUser;
if (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT")))
postgresqlUser = "<aad-user-name>@<server-name>";
else postgresqlUser = "<postgresql-user-name>@<server-name>";
// Add the token to the PostgreSQL connection
var connectionString = "Server=<server-name>.postgres.database.azure.com;" +
"Port=5432;" +
"Database=<database-name>;" +
"User Id=" + postgresqlUser + ";" +
"Password="+ token.Token;
var connection = new Npgsql.NpgsqlConnection(connectionString);
connection.Open();
Stellen Sie eine Verbindung mit der Azure-Datenbank her, indem Sie ein Zugriffstoken hinzufügen. Wenn Sie eine benutzerseitig zugewiesene Identität verwenden, stellen Sie sicher, dass Sie die Auskommentierung der entsprechenden Zeilen aufheben.
const mysql = require('mysql2');
const { DefaultAzureCredential } = require("@azure/identity");
// Uncomment one of the two lines depending on the identity type
//const credential = new DefaultAzureCredential(); // system-assigned identity
//const credential = new DefaultAzureCredential({ managedIdentityClientId: '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for MySQL
const accessToken = await credential.getToken("https://ossrdbms-aad.database.windows.net/.default");
// Set MySQL user depending on the environment
if(process.env.IDENTITY_ENDPOINT) {
var mysqlUser = '<mysql-user-name>@<server-name>';
} else {
var mysqlUser = '<aad-user-name>@<server-name>';
}
// Add the token to the MySQL connection
var config =
{
host: '<server-name>.mysql.database.azure.com',
user: mysqlUser,
password: accessToken.token,
database: '<database-name>',
port: 3306,
insecureAuth: true,
authPlugins: {
mysql_clear_password: () => () => {
return Buffer.from(accessToken.token + '\0')
}
}
};
const conn = new mysql.createConnection(config);
// Open the database connection
conn.connect(
function (err) {
if (err) {
console.log("!!! Cannot connect !!! Error:");
throw err;
}
else
{
...
}
});
Die if-Anweisung legt den MySQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die MySQL-Standardverbindung als Kennwort der Azure-Identität übergeben.
const pg = require('pg');
const { DefaultAzureCredential } = require("@azure/identity");
// Uncomment one of the two lines depending on the identity type
//const credential = new DefaultAzureCredential(); // system-assigned identity
//const credential = new DefaultAzureCredential({ managedIdentityClientId: '<client-id-of-user-assigned-identity>' }); // user-assigned identity
// Get token for Azure Database for PostgreSQL
const accessToken = await credential.getToken("https://ossrdbms-aad.database.windows.net/.default");
// Set PosrgreSQL user depending on the environment
if(process.env.IDENTITY_ENDPOINT) {
var postgresqlUser = '<postgresql-user-name>@<server-name>';
} else {
var postgresqlUser = '<aad-user-name>@<server-name>';
}
// Add the token to the PostgreSQL connection
var config =
{
host: '<server-name>.postgres.database.azure.com',
user: postgresqlUser,
password: accessToken.token,
database: '<database-name>',
port: 5432
};
const client = new pg.Client(config);
// Open the database connection
client.connect(err => {
if (err) throw err;
else {
// Do something with the connection...
}
});
Die if-Anweisung legt den PostgreSQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die PostgreSQL-Standardverbindung als Kennwort der Azure-Identität übergeben.
Installieren Sie in Ihrem Python-Projekt die erforderlichen Pakete.
Der erforderliche ODBC-Treiber 17 für SQL Server ist bereits in App Service installiert. Um denselben Code lokal auszuführen, installieren Sie ihn auch in Ihrer lokalen Umgebung.
from azure.identity import DefaultAzureCredential
import pyodbc, struct
# Uncomment one of the two lines depending on the identity type
#credential = DefaultAzureCredential() # system-assigned identity
#credential = DefaultAzureCredential(managed_identity_client_id='<client-id-of-user-assigned-identity>') # user-assigned identity
# Get token for Azure SQL Database and convert to UTF-16-LE for SQL Server driver
token = credential.get_token("https://database.windows.net/.default").token.encode("UTF-16-LE")
token_struct = struct.pack(f'<I{len(token)}s', len(token), token)
# Connect with the token
SQL_COPT_SS_ACCESS_TOKEN = 1256
connString = f"Driver={{ODBC Driver 17 for SQL Server}};SERVER=<server-name>.database.windows.net;DATABASE=<database-name>"
conn = pyodbc.connect(connString, attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct})
Der ODBC-Treiber 17 für SQL Server unterstützt auch den Authentifizierungstyp ActiveDirectoryMsi. Sie können eine Verbindung von App Service herstellen, ohne selbst das Token abzurufen – einfach mit der Verbindungszeichenfolge Driver={{ODBC Driver 17 for SQL Server}};SERVER=<server-name>.database.windows.net;DATABASE=<database-name>;Authentication=ActiveDirectoryMsi. Der Unterschied zum obigen Code besteht darin, dass das Token mit DefaultAzureCredential abgerufen wird, was sowohl in App Service als auch in Ihrer lokalen Entwicklungsumgebung funktioniert.
from azure.identity import DefaultAzureCredential
import mysql.connector
import os
# Uncomment one of the two lines depending on the identity type
#credential = DefaultAzureCredential() # system-assigned identity
#credential = DefaultAzureCredential(managed_identity_client_id='<client-id-of-user-assigned-identity>') # user-assigned identity
# Get token for Azure Database for MySQL
token = credential.get_token("https://ossrdbms-aad.database.windows.net/.default")
# Set MySQL user depending on the environment
if 'IDENTITY_ENDPOINT' in os.environ:
mysqlUser = '<mysql-user-name>@<server-name>'
else:
mysqlUser = '<aad-user-name>@<server-name>'
# Connect with the token
os.environ['LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN'] = '1'
config = {
'host': '<server-name>.mysql.database.azure.com',
'database': '<database-name>',
'user': mysqlUser,
'password': token.token
}
conn = mysql.connector.connect(**config)
print("Connection established")
Die if-Anweisung legt den MySQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die MySQL-Standardverbindung als Kennwort der Azure-Identität übergeben.
from azure.identity import DefaultAzureCredential
import psycopg2
# Uncomment one of the two lines depending on the identity type
#credential = DefaultAzureCredential() # system-assigned identity
#credential = DefaultAzureCredential(managed_identity_client_id='<client-id-of-user-assigned-identity>') # user-assigned identity
# Get token for Azure Database for PostgreSQL
token = credential.get_token("https://ossrdbms-aad.database.windows.net/.default")
# Set PostgreSQL user depending on the environment
if 'IDENTITY_ENDPOINT' in os.environ:
postgresUser = '<postgres-user-name>@<server-name>'
else:
postgresUser = '<aad-user-name>@<server-name>'
# Connect with the token
host = "<server-name>.postgres.database.azure.com"
dbname = "<database-name>"
conn_string = "host={0} user={1} dbname={2} password={3}".format(host, postgresUser, dbname, token.token)
conn = psycopg2.connect(conn_string)
Die if-Anweisung legt den PostgreSQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die PostgreSQL-Standardverbindung als Kennwort der Azure-Identität übergeben.
import com.azure.identity.*;
import com.azure.core.credential.*;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import java.sql.*;
...
// Uncomment one of the two lines depending on the identity type
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build(); // system-assigned identity
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().managedIdentityClientId('<client-id-of-user-assigned-identity>")'build(); // user-assigned identity
// Get the token
TokenRequestContext request = new TokenRequestContext();
request.addScopes("https://database.windows.net//.default");
AccessToken token=creds.getToken(request).block();
// Set token in your SQL connection
SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("<server-name>.database.windows.net");
ds.setDatabaseName("<database-name>");
ds.setAccessToken(token.getToken());
// Connect
try {
Connection connection = ds.getConnection();
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT SUSER_SNAME()");
if (rs.next()) {
System.out.println("Signed into database as: " + rs.getString(1));
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
Der [JDBC-Treiber für SQL Server] verfügt auch über einen Authentifizierungstyp ActiveDirectoryMsi, der sich einfacher für App Service verwenden lässt. Der obige Code ruft das Token mit DefaultAzureCredential ab, was sowohl in App Service als auch in Ihrer lokalen Entwicklungsumgebung funktioniert.
import com.azure.identity.*;
import com.azure.core.credential.*;
import java.sql.*;
...
// Uncomment one of the two lines depending on the identity type
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build(); // system-assigned identity
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().managedIdentityClientId('<client-id-of-user-assigned-identity>")'build(); // user-assigned identity
// Get the token
TokenRequestContext request = new TokenRequestContext();
request.addScopes("https://ossrdbms-aad.database.windows.net/.default");
AccessToken token=creds.getToken(request).block();
// Set MySQL user depending on the environment
String mysqlUser;
if (System.getenv("IDENTITY_ENDPOINT" != null)) {
mysqlUser = "<aad-user-name>@<server-name>";
}
else {
mysqlUser = "<mysql-user-name>@<server-name>";
}
// Set token in your SQL connection
try {
Connection connection = DriverManager.getConnection(
"jdbc:mysql://<server-name>.mysql.database.azure.com/<database-name>",
mysqlUser,
token.getToken());
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT USER();");
if (rs.next()) {
System.out.println("Signed into database as: " + rs.getString(1));
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
Die if-Anweisung legt den MySQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die MySQL-Standardverbindung als Kennwort der Azure-Identität übergeben.
import com.azure.identity.*;
import com.azure.core.credential.*;
import java.sql.*;
...
// Uncomment one of the two lines depending on the identity type
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build(); // system-assigned identity
//DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().managedIdentityClientId('<client-id-of-user-assigned-identity>")'build(); // user-assigned identity
// Get the token
TokenRequestContext request = new TokenRequestContext();
request.addScopes("https://ossrdbms-aad.database.windows.net/.default");
AccessToken token=creds.getToken(request).block();
// Set PostgreSQL user depending on the environment
String postgresUser;
if (System.getenv("IDENTITY_ENDPOINT") != null) {
postgresUser = "<aad-user-name>@<server-name>";
}
else {
postgresUser = "<postgresql-user-name>@<server-name>";
}
// Set token in your SQL connection
try {
Connection connection = DriverManager.getConnection(
"jdbc:postgresql://<server-name>.postgres.database.azure.com:5432/<database-name>",
postgresUser,
token.getToken());
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select current_user;");
if (rs.next()) {
System.out.println("Signed into database as: " + rs.getString(1));
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
Die if-Anweisung legt den PostgreSQL-Benutzernamen auf Grundlage der Identität fest, für die das Token gilt. Das Token wird dann an die PostgreSQL-Standardverbindung als Kennwort der Identität übergeben. Informationen dazu, wie Sie dies auf ähnliche Weise mit bestimmten Frameworks erreichen können, finden Sie unter:
In diesem Beispielcode wird DefaultAzureCredential dazu verwendet, ein nutzbares Token für Ihre Azure-Datenbank aus Azure Active Directory abzurufen, das dann der Datenbankverbindung hinzugefügt wird. Sie können DefaultAzureCredential zwar anpassen, doch es ist bereits standardmäßig sehr vielseitig. Es ruft ein Token vom angemeldeten Azure AD-Benutzer oder von einer verwalteten Identität ab, je nachdem, ob Sie es lokal in Ihrer Entwicklungsumgebung oder in App Service ausführen.
Ohne weitere Änderungen ist Ihr Code zur Ausführung in Azure bereit. Um Ihren Code lokal zu debuggen, benötigt Ihre Entwicklungsumgebung jedoch einen angemeldeten Azure AD-Benutzer. In diesem Schritt konfigurieren Sie die Umgebung Ihrer Wahl, indem Sie sich mit Ihrem Azure AD-Benutzer anmelden.
Visual Studio für Windows ist in die Azure AD-Authentifizierung integriert. Fügen Sie in Visual Studio den Azure AD-Benutzer hinzu, um in Visual Studio entwickeln und debuggen zu können. Wählen Sie dazu über das Menü DateiKontoeinstellungen und anschließend Anmelden oder Hinzufügen aus.
Wählen Sie über das Menü ExtrasOptionen und anschließend Azure Service Authentication (Azure-Dienstauthentifizierung)Kontoauswahl aus, um den Azure AD-Benutzer für die Azure-Dienstauthentifizierung festzulegen. Wählen Sie den Azure AD-Benutzer aus, den Sie hinzugefügt haben, und wählen Sie dann OK aus.
Visual Studio für Mac ist nicht mit Azure AD-Authentifizierung integriert. Die Azure Identity-Clientbibliothek, die Sie später verwenden werden, kann jedoch Token auch aus der Azure CLI abrufen. Um die Entwicklung und das Debuggen in Visual Studio zu ermöglichen, installieren Sie die Azure CLI auf dem lokalen Computer.
Melden Sie sich mit dem folgenden Befehl unter Verwendung Ihres Azure AD-Benutzers bei der Azure CLI an:
az login --allow-no-subscriptions
Visual Studio Code ist mit der Azure AD-Authentifizierung über die Azure-Erweiterung integriert. Installieren Sie die Azure-Tools-Erweiterung in Visual Studio Code.
Wählen Sie auf der Aktivitätsleiste in Visual Studio Code das Azure-Logo aus.
Wählen Sie im App Service-Explorer die Option Bei Azure anmelden... aus, und befolgen Sie die Anweisungen.
Von der Azure Identity-Clientbibliothek, die Sie später verwenden, können Tokens aus der Azure CLI verwendet werden. Zum Unterstützen der befehlszeilenbasierten Entwicklung installieren Sie die Azure CLI auf dem lokalen Computer.
Melden Sie sich mit dem folgenden Befehl unter Verwendung des Azure AD-Benutzers bei Azure an:
az login --allow-no-subscriptions
Von der Azure Identity-Clientbibliothek, die Sie später verwenden, können Tokens aus Azure PowerShell verwendet werden. Zum Aktivieren der befehlszeilenbasierten Entwicklung installieren Sie Azure PowerShell auf dem lokalen Computer.
Melden Sie sich mit dem folgenden Cmdlet unter Verwendung des Azure AD-Benutzers bei der Azure CLI an:
Connect-AzAccount
Weitere Informationen zum Einrichten der Entwicklungsumgebung für die Azure Active Directory-Authentifizierung finden Sie unter Azure Identity-Clientbibliothek für .NET.
Nun können Sie Ihre App mit der SQL-Datenbank als Back-End entwickeln und debuggen und dabei die Azure AD-Authentifizierung verwenden.
5. Testen und Veröffentlichen
Führen Sie Ihren Code in Ihrer Entwicklungsumgebung aus. Ihr Code verwendet den angemeldeten Azure AD-Benutzer in Ihrer Umgebung, um eine Verbindung mit der Back-End-Datenbank herzustellen. Der Benutzer kann auf die Datenbank zugreifen, da er als Azure AD-Administrator für die Datenbank konfiguriert ist.
Veröffentlichen Sie Ihren Code mithilfe der bevorzugten Veröffentlichungsmethode in Azure. In App Service verwendet Ihr Code die verwaltete Identität der App, um eine Verbindung mit der Back-End-Datenbank herzustellen.
Azure Active Directory und verwaltete Identitäten werden für lokale SQL Server-Instanzen nicht unterstützt.
Ich erhalte den Fehler Login failed for user '<token-identified principal>'..
Die verwaltete Identität, für die Sie versuchen, ein Token anzufordern, ist nicht berechtigt, auf die Azure-Datenbank zuzugreifen.
Ich habe Änderungen an der App Service-Authentifizierung oder der zugehörigen App-Registrierung vorgenommen. Warum erhalte ich weiterhin das alte Token?
Die Back-End-Dienste verwalteter Identitäten verwalten darüber hinaus einen Tokencache, der das Token für eine Zielressource nur bei Ablauf aktualisiert. Wenn Sie die Konfiguration ändern, nachdem Sie versucht haben, mit Ihrer App ein Token abzurufen, erhalten Sie tatsächlich erst dann ein neues Token mit den aktualisierten Berechtigungen, wenn das zwischengespeicherte Token abläuft. Die beste Möglichkeit, um dies zu umgehen, besteht darin, Ihre Änderungen mit einem neuen InPrivate (Edge)/privatem (Safari)/Incognito (Chrome)-Fenster zu testen. Auf diese Weise können Sie sicher sein, dass Sie mit einer neuen authentifizierten Sitzung beginnen.
Gewusst wie: Hinzufügen der verwalteten Identität zu einer Azure AD-Gruppe
Sie können die Identität einer Azure AD-Gruppe hinzufügen und anschließend der Azure AD-Gruppe (und nicht der Identität) Zugriff erteilen. Mit den folgenden Befehlen wird beispielsweise die verwaltete Identität aus dem vorherigen Schritt zu einer neuen Gruppe namens myAzureSQLDBAccessGroup hinzugefügt:
groupid=$(az ad group create --display-name myAzureSQLDBAccessGroup --mail-nickname myAzureSQLDBAccessGroup --query objectId --output tsv)
msiobjectid=$(az webapp identity show --resource-group <group-name> --name <app-name> --query principalId --output tsv)
az ad group member add --group $groupid --member-id $msiobjectid
az ad group member list -g $groupid
Informationen zum Gewähren von Datenbankberechtigungen für eine Azure AD-Gruppe finden Sie in der Dokumentation für den jeweiligen Datenbanktyp.
Ich erhalte den Fehler mysql: unknown option '--enable-cleartext-plugin'.
Wenn Sie einen MariaDB-Client verwenden, ist die Option --enable-cleartext-plugin nicht erforderlich.
Ich erhalte den Fehler SSL connection is required. Please specify SSL options and retry.
Das Herstellen einer Verbindung mit der Azure-Datenbank erfordert zusätzliche Einstellungen und geht über den Umfang dieses Tutorials hinaus. Weitere Informationen dazu finden Sie unter den folgenden Links:
Konfigurieren eines Azure AD-Benutzers als Administrator für Ihre Azure-Datenbank.
Herstellen einer Verbindung mit Ihrer Datenbank als Azure AD-Benutzer.
Konfigurieren einer systemseitig oder benutzerseitig zugewiesenen verwalteten Identität für eine App Service-App.
Gewähren von Datenbankzugriff auf die verwaltete Identität.
Herstellen einer Verbindung mit der Azure-Datenbank aus Ihrem Code (.NET Framework 4.8, .NET 6, Node.js, Python, Java) mithilfe einer verwalteten Identität.
Herstellen einer Verbindung mit der Azure-Datenbank aus Ihrer Entwicklungsumgebung mithilfe des Azure AD-Benutzers.