マネージド ID は、Azure リソース間の安全なパスワードレス接続に推奨されている認証オプションです。 マネージド ID では、開発者がさまざまなシークレットを手動で追跡して管理する必要はありません。これらのタスクのほとんどは Azure によって内部で処理されるためです。 このチュートリアルでは、マネージド ID と Azure ID クライアント ライブラリを使用して複数のサービス間の接続を管理する方法について説明します。
マネージド ID の種類を比較する
Azure には、次の種類のマネージド ID が用意されています。
システム割り当てマネージド ID は、1 つの Azure リソースに直接関連付けられます。 サービスでシステム割り当てマネージド ID を有効にすると、Azure によってリンクされた ID が作成され、その ID の管理タスクが内部で処理されます。 Azure リソースが削除されると、ID も削除されます。
ユーザー割り当てマネージド ID は、管理者によって作成され、1 つ以上の Azure リソースに関連付けることができる独立した ID です。 ID のライフサイクルは、それらのリソースから独立しています。
ベスト プラクティス、およびシステム割り当て ID とユーザー割り当て ID をそれぞれどのようなときに使用するかについての詳細は、ID のベスト プラクティスの推奨事項に関するページを参照してください。
パスワードレス接続を使用して、既存のアプリを複数の Azure サービスとデータベースに接続する作業をしているとします。 このアプリケーションは Azure App Service でホストされている ASP.NET Core Web API ですが、以下の手順は、Azure Spring Apps、Virtual Machines、Container Apps、AKS などの他の Azure ホスティング環境にも適用されます。
ポップアップに App Service の名前を入力し、作成したマネージド ID を検索します。 システム割り当て ID を選択し、[選択] を選択してポップアップ メニューを閉じます。
[次へ] を何度か選択して [レビューと割り当て] を選択すれば、ロールの割り当ては完了です。
接続する他のサービスでこのプロセスを繰り返します。
ローカル開発の考慮事項
また、マネージド ID にロールを割り当てたときと同じ方法でユーザー アカウントにロールを割り当て、ローカル開発用の Azure リソースにアクセスできるようにすることもできます。
マネージド ID に [ストレージ BLOB データ共同作成者] ロールを割り当てたら、[アクセスの割り当て先] で、今度は [User, group or service principal] (ユーザー、グループ、またはサービス プリンシパル) を選択します。 [+ メンバーを選択する] を選択してポップアップ メニューをもう一度開きます。
メール アドレスまたは名前でアクセス権を付与する user@domain アカウントまたは Microsoft Entra セキュリティ グループを検索し、それを選択します。 これは、Visual Studio や Azure CLI などの、ローカル開発ツールへのサインインに使用するアカウントと同じであることが必要です。
Note
複数の開発者がいるチームで作業している場合は、これらのロールを Microsoft Entra セキュリティ グループに割り当てることもできます。 そのうえで、アプリをローカルで開発するアクセス権が必要な開発者を、そのグループに入れることができます。
var blobServiceClient = new BlobServiceClient(
new Uri("https://<your-storage-account>.blob.core.windows.net"),
new DefaultAzureCredential(credOptions));
var serviceBusClient = new ServiceBusClient("<your-namespace>", new DefaultAzureCredential());
var sender = serviceBusClient.CreateSender("producttracking");
// Azure resource names
const storageAccount = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const keyVaultName = process.env.AZURE_KEYVAULT_NAME;
// Create client for Blob Storage using managed identity
const blobServiceClient = new BlobServiceClient(
`https://${storageAccount}.blob.core.windows.net`,
new DefaultAzureCredential()
);
// Create client for Key Vault using managed identity
const keyClient = new KeyClient(`https://${keyVaultName}.vault.azure.net`, new DefaultAzureCredential());
// Create a new key in Key Vault
const result = await keyClient.createKey(keyVaultName, "RSA");
このアプリケーション コードをローカルで実行すると、DefaultAzureCredential では資格情報チェーンを検索して最初に使用可能な資格情報を見つけます。 ローカルで Managed_Identity_Client_ID が null の場合、ローカルの Azure CLI または Visual Studio サインインの資格情報が自動的に使用されます。 このプロセスの詳細については、Azure ID ライブラリの概要に関するページを参照してください。
アプリケーションが Azure にデプロイされると、DefaultAzureCredential によって App Service Environment から自動的に Managed_Identity_Client_ID 変数が取得されます。 この値は、マネージド ID がアプリに関連付けられると使用できるようになります。
コードでこのセットアップを構成するには、アプリケーションで、それぞれのストレージ アカウントまたはデータベースに接続するために個別のサービスを登録する必要があります。 DefaultAzureCredential を構成するときは、必ず、各サービスの正しいマネージド ID クライアント ID を取り込みます。 次のコード例では、次のようなサービス接続を構成しています。
共有ユーザー割り当てマネージド ID を使用した個別のストレージ アカウントへの 2 つの接続
2 つ目の共有ユーザー割り当てマネージド ID を使用した Azure Cosmos DB と Azure SQL サービスへの接続
// Get the first user-assigned managed identity ID to connect to shared storage
const clientIdStorage = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID_Storage");
// First blob storage client that using a managed identity
BlobServiceClient blobServiceClient = new BlobServiceClient(
new Uri("https://<receipt-storage-account>.blob.core.windows.net"),
new DefaultAzureCredential()
{
ManagedIdentityClientId = clientIDstorage
});
// Second blob storage client that using a managed identity
BlobServiceClient blobServiceClient2 = new BlobServiceClient(
new Uri("https://<contract-storage-account>.blob.core.windows.net"),
new DefaultAzureCredential()
{
ManagedIdentityClientId = clientIDstorage
});
// Get the second user-assigned managed identity ID to connect to shared databases
var clientIDdatabases = Environment.GetEnvironmentVariable("Managed_Identity_Client_ID_Databases");
// Create an Azure Cosmos DB client
CosmosClient client = new CosmosClient(
accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT", EnvironmentVariableTarget.Process),
new DefaultAzureCredential()
{
ManagedIdentityClientId = clientIDdatabases
});
// Open a connection to Azure SQL using a managed identity
string ConnectionString1 = @"Server=<azure-sql-hostname>.database.windows.net; User Id=ClientIDOfTheManagedIdentity; Authentication=Active Directory Default; Database=<database-name>";
using (SqlConnection conn = new SqlConnection(ConnectionString1))
{
conn.Open();
}
class Demo {
public static void main(String[] args) {
// Get the first user-assigned managed identity ID to connect to shared storage
String clientIdStorage = System.getenv("Managed_Identity_Client_ID_Storage");
// Get the DefaultAzureCredential from clientIdStorage
DefaultAzureCredential storageCredential =
new DefaultAzureCredentialBuilder().managedIdentityClientId(clientIdStorage).build();
// First blob storage client that using a managed identity
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint("https://<receipt-storage-account>.blob.core.windows.net")
.credential(storageCredential)
.buildClient();
// Second blob storage client that using a managed identity
BlobServiceClient blobServiceClient2 = new BlobServiceClientBuilder()
.endpoint("https://<contract-storage-account>.blob.core.windows.net")
.credential(storageCredential)
.buildClient();
// Get the second user-assigned managed identity ID to connect to shared databases
String clientIdDatabase = System.getenv("Managed_Identity_Client_ID_Databases");
// Create an Azure Cosmos DB client
CosmosClient cosmosClient = new CosmosClientBuilder()
.endpoint("https://<cosmos-db-account>.documents.azure.com:443/")
.credential(new DefaultAzureCredentialBuilder().managedIdentityClientId(clientIdDatabase).build())
.buildClient();
// Open a connection to Azure SQL using a managed identity
String connectionUrl = "jdbc:sqlserver://<azure-sql-hostname>.database.windows.net:1433;"
+ "database=<database-name>;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database"
+ ".windows.net;loginTimeout=30;Authentication=ActiveDirectoryMSI;";
try {
Connection connection = DriverManager.getConnection(connectionUrl);
Statement statement = connection.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// Get the first user-assigned managed identity ID to connect to shared storage
const clientIdStorage = process.env.MANAGED_IDENTITY_CLIENT_ID_STORAGE;
// Storage account names
const storageAccountName1 = process.env.AZURE_STORAGE_ACCOUNT_NAME_1;
const storageAccountName2 = process.env.AZURE_STORAGE_ACCOUNT_NAME_2;
// First blob storage client that using a managed identity
const blobServiceClient = new BlobServiceClient(
`https://${storageAccountName1}.blob.core.windows.net`,
new DefaultAzureCredential({
managedIdentityClientId: clientIdStorage
})
);
// Second blob storage client that using a managed identity
const blobServiceClient2 = new BlobServiceClient(
`https://${storageAccountName2}.blob.core.windows.net`,
new DefaultAzureCredential({
managedIdentityClientId: clientIdStorage
})
);
// Get the second user-assigned managed identity ID to connect to shared databases
const clientIdDatabases = process.env.MANAGED_IDENTITY_CLIENT_ID_DATABASES;
// Cosmos DB Account endpoint
const cosmosDbAccountEndpoint = process.env.COSMOS_ENDPOINT;
// Create an Azure Cosmos DB client
const client = new CosmosClient({
endpoint: cosmosDbAccountEndpoint,
credential: new DefaultAzureCredential({
managedIdentityClientId: clientIdDatabases
})
});
// Open a connection to Azure SQL using a managed identity with mssql package
// mssql reads the environment variables to get the managed identity
const server = process.env.AZURE_SQL_SERVER;
const database = process.env.AZURE_SQL_DATABASE;
const port = parseInt(process.env.AZURE_SQL_PORT);
const type = process.env.AZURE_SQL_AUTHENTICATIONTYPE;
const config = {
server,
port,
database,
authentication: {
type // <---- Passwordless connection
},
options: {
encrypt: true
}
};
await sql.connect(sqlConfig);
ユーザー割り当てマネージド ID とシステム割り当てマネージド ID を同時にリソースに関連付けることもできます。 これは、すべてのアプリで同じ共有サービスにアクセスする必要がありますが、アプリの 1 つが追加のサービスへの固有の依存関係を持っているというシナリオで役立ちます。 システム割り当て ID を使用すると、アプリが削除されたときに、その特定のアプリに関連付けられている ID も削除されます。これによって環境がクリーンに保たれます。