Configurar conexões sem senha entre vários aplicativos e serviços do Azure
Artigo
Os aplicativos geralmente exigem conexões seguras entre vários serviços do Azure simultaneamente. Por exemplo, uma instância corporativa do Serviço de Aplicativo do Azure pode se conectar a várias contas de armazenamento diferentes, uma instância do banco de dados SQL do Azure, um barramento de serviço e muito mais.
As identidades gerenciadas são a opção de autenticação recomendada para conexões seguras e sem senha entre os recursos do Azure. Os desenvolvedores não precisam rastrear e gerenciar manualmente muitos segredos diferentes para identidades gerenciadas, já que a maioria dessas tarefas é tratada internamente pelo Azure. Este tutorial explora como gerenciar conexões entre vários serviços usando identidades gerenciadas e a biblioteca de cliente do Azure Identity.
Comparar os tipos de identidades gerenciadas
O Azure fornece os seguintes tipos de identidades gerenciadas:
As identidades gerenciadas atribuídas ao sistema estão diretamente ligadas a um único recurso do Azure. Quando você habilita uma identidade gerenciada atribuída ao sistema em um serviço, o Azure cria uma identidade vinculada e manipula tarefas administrativas para essa identidade internamente. Quando o recurso do Azure é excluído, a identidade também é excluída.
As identidades gerenciadas atribuídas pelo usuário são identidades independentes criadas por um administrador e podem ser associadas a um ou mais recursos do Azure. O ciclo de vida da identidade é independente desses recursos.
Você pode ler mais sobre as práticas recomendadas e quando usar identidades atribuídas pelo sistema versus identidades atribuídas pelo usuário nas recomendações de práticas recomendadas de identidades.
Explore DefaultAzureCredential
As identidades gerenciadas geralmente são implementadas no código do aplicativo por meio de uma classe chamada DefaultAzureCredential da Azure.Identity biblioteca do cliente. DefaultAzureCredential suporta vários métodos de autenticação e determina automaticamente quais devem ser usados em tempo de execução. Você pode ler mais sobre essa abordagem na visão geral de DefaultAzureCredential.
Conectar um aplicativo hospedado do Azure a vários serviços do Azure
Você foi encarregado de conectar um aplicativo existente a vários serviços e bancos de dados do Azure usando conexões sem senha. O aplicativo é uma API Web ASP.NET Core hospedada no Serviço de Aplicativo do Azure, embora as etapas abaixo também se apliquem a outros ambientes de hospedagem do Azure, como Azure Spring Apps, Máquinas Virtuais, Aplicativos de Contêiner e AKS.
Este tutorial aplica-se às arquiteturas a seguir, embora possa ser adaptado a muitos outros cenários, bem como através de alterações mínimas de configuração.
As etapas a seguir demonstram como configurar um aplicativo para usar uma identidade gerenciada atribuída ao sistema e sua conta de desenvolvimento local para se conectar a vários Serviços do Azure.
Criar uma identidade gerenciada atribuída ao sistema
No portal do Azure, navegue até o aplicativo hospedado que você gostaria de conectar a outros serviços.
Na página de visão geral do serviço, selecione Identidade.
Alterne a configuração Status para Ativado para habilitar uma identidade gerenciada atribuída ao sistema para o serviço.
Atribuir funções à identidade gerenciada para cada serviço conectado
Navegue até a página de visão geral da conta de armazenamento à qual você gostaria de conceder acesso à sua identidade.
Selecione Controle de acesso (IAM) na navegação da conta de armazenamento.
Escolha + Adicionar e, em seguida, Adicionar atribuição de função.
Na caixa Pesquisa de função, procure por Colaborador de Dados de Blob de Armazenamento, que concede permissões para executar operações de leitura e gravação em dados de blob. Você pode atribuir qualquer função apropriada para seu caso de uso. Selecione o Colaborador de Dados de Blob de Armazenamento na lista e escolha Avançar.
Na tela Adicionar atribuição de função, para a opção Atribuir acesso a, selecione Identidade gerenciada. Em seguida, escolha +Selecionar membros.
No submenu, procure a identidade gerenciada que você criou inserindo o nome do seu serviço de aplicativo. Selecione a identidade atribuída ao sistema e, em seguida, escolha Selecionar para fechar o menu suspenso.
Selecione Avançar algumas vezes até conseguir selecionar Revisar + atribuir para concluir a atribuição de função.
Repita esse processo para os outros serviços aos quais você gostaria de se conectar.
Considerações sobre o desenvolvimento local
Também pode ativar o acesso aos recursos do Azure para desenvolvimento local atribuindo funções a uma conta de utilizador da mesma forma que atribuiu funções à sua identidade gerida.
Depois de atribuir a função de Colaborador de Dados de Blob de Armazenamento à sua identidade gerenciada, em Atribuir acesso a, desta vez selecione Usuário, grupo ou entidade de serviço. Escolha + Selecionar membros para abrir o menu suspenso novamente.
Procure a conta user@domain ou o grupo de segurança do Microsoft Entra ao qual você gostaria de conceder acesso por endereço de email ou nome e selecione-o. Essa deve ser a mesma conta que você usa para entrar em suas ferramentas de desenvolvimento local, como o Visual Studio ou a CLI do Azure.
Nota
Você também pode atribuir essas funções a um grupo de segurança do Microsoft Entra se estiver trabalhando em uma equipe com vários desenvolvedores. Em seguida, você pode colocar qualquer desenvolvedor dentro desse grupo que precise de acesso para desenvolver o aplicativo localmente.
Dentro do seu projeto, adicione uma referência ao Azure.Identity pacote NuGet. Esta biblioteca contém todas as entidades necessárias para implementar DefaultAzureCredentialo . Também pode adicionar quaisquer outras bibliotecas do Azure que sejam relevantes para a sua aplicação. Neste exemplo, os Azure.Storage.Blobs pacotes e são adicionados para se conectar ao Armazenamento de Blobs e Azure.KeyVault.Keys ao Cofre de Chaves.
Na parte superior do arquivo Program.cs , adicione as seguintes instruções using:
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Security.KeyVault.Keys;
Program.cs No arquivo do código do projeto, crie instâncias dos serviços necessários aos quais seu aplicativo se conectará. Os exemplos a seguir se conectam ao Armazenamento de Blob e ao barramento de serviço usando as classes SDK correspondentes.
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");
Dentro do seu projeto, adicione a azure-identity dependência ao seu arquivo pom.xml . Esta biblioteca contém todas as entidades necessárias para implementar DefaultAzureCredentialo . Você também pode adicionar quaisquer outras dependências do Azure que sejam relevantes para seu aplicativo. Neste exemplo, as azure-storage-blob dependências e são adicionadas para se conectar ao Armazenamento de Blobs e azure-messaging-servicebus ao Cofre de Chaves.
No código do projeto, crie instâncias dos serviços necessários aos quais seu aplicativo se conectará. Os exemplos a seguir se conectam ao Armazenamento de Blob e ao barramento de serviço usando as classes SDK correspondentes.
class Demo {
public static void main(String[] args) {
DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint("https://<your-storage-account>.blob.core.windows.net")
.credential(defaultAzureCredential)
.buildClient();
ServiceBusClientBuilder clientBuilder = new ServiceBusClientBuilder().credential(defaultAzureCredential);
ServiceBusSenderClient serviceBusSenderClient = clientBuilder.sender()
.queueName("producttracking")
.buildClient();
}
}
Dentro do seu projeto, só precisa adicionar dependências de serviço que você usa. Neste exemplo, as spring-cloud-azure-starter-storage-blob dependências e são adicionadas para se conectar ao Armazenamento de Blobs e spring-cloud-azure-starter-servicebus ao Cofre de Chaves.
No código do projeto, crie instâncias dos serviços necessários aos quais seu aplicativo se conectará. Os exemplos a seguir se conectam ao Armazenamento de Blob e ao barramento de serviço usando as classes SDK correspondentes.
@Service
public class ExampleService {
@Autowired
private BlobServiceClient blobServiceClient;
@Autowired
private ServiceBusSenderClient serviceBusSenderClient;
}
Dentro do seu projeto, use npm para adicionar uma referência ao @azure/identity pacote. Esta biblioteca contém todas as entidades necessárias para implementar DefaultAzureCredentialo . Instale quaisquer outras bibliotecas do SDK do Azure que sejam relevantes para o seu aplicativo.
Na parte superior do arquivo, adicione as seguintes import instruções para importar as classes de index.js cliente necessárias para os serviços aos quais seu aplicativo se conectará:
import { DefaultAzureCredential } from "@azure/identity";
import { BlobServiceClient } from "@azure/storage-blob";
import { KeyClient } from "@azure/keyvault-keys";
Dentro do index.js arquivo, crie objetos de cliente para os serviços do Azure aos quais seu aplicativo se conectará. Os exemplos a seguir se conectam ao Armazenamento de Blobs e ao Cofre de Chaves usando as classes SDK correspondentes.
// 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");
Quando esse código de aplicativo é executado localmente, DefaultAzureCredential procurará as primeiras credenciais disponíveis em uma cadeia de credenciais. Se o Managed_Identity_Client_ID for nulo localmente, ele usará automaticamente as credenciais da CLI do Azure local ou do logon do Visual Studio. Você pode ler mais sobre esse processo na visão geral da biblioteca de Identidades do Azure.
Quando o aplicativo é implantado no Azure, DefaultAzureCredential recuperará automaticamente a Managed_Identity_Client_ID variável do ambiente do serviço de aplicativo. Esse valor fica disponível quando uma identidade gerenciada é associada ao seu aplicativo.
Esse processo geral garante que seu aplicativo possa ser executado com segurança localmente e no Azure sem a necessidade de alterações de código.
Conecte vários aplicativos usando várias identidades gerenciadas
Embora todos os aplicativos no exemplo anterior compartilhassem os mesmos requisitos de acesso ao serviço, os ambientes reais geralmente são mais matizados. Considere um cenário em que vários aplicativos se conectam às mesmas contas de armazenamento, mas dois dos aplicativos também acessam serviços ou bancos de dados diferentes.
Para configurar essa configuração em seu código, certifique-se de que seu aplicativo registre serviços separados para se conectar a cada conta de armazenamento ou banco de dados. Certifique-se de obter os IDs de cliente de identidade gerenciados corretos para cada serviço ao configurar DefaultAzureCredentialo . O exemplo de código a seguir configura as seguintes conexões de serviço:
Duas conexões para contas de armazenamento separadas usando uma identidade gerenciada atribuída pelo usuário compartilhada
Uma conexão com o Azure Cosmos DB e os serviços SQL do Azure usando uma segunda identidade gerenciada compartilhada atribuída pelo usuário
// 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();
}
}
}
O Spring Cloud Azure não oferece suporte à configuração de vários clientes do mesmo serviço, os códigos a seguir criam vários beans para essa situação.
@Configuration
public class AzureStorageConfiguration {
@Bean("secondBlobServiceClient")
public BlobServiceClient secondBlobServiceClient(BlobServiceClientBuilder builder) {
return builder.endpoint("https://<receipt-storage-account>.blob.core.windows.net").buildClient();
}
@Bean("firstBlobServiceClient")
public BlobServiceClient firstBlobServiceClient(BlobServiceClientBuilder builder) {
return builder.buildClient();
}
}
Dentro do seu projeto, use npm para adicionar uma referência ao @azure/identity pacote. Esta biblioteca contém todas as entidades necessárias para implementar DefaultAzureCredentialo . Instale quaisquer outras bibliotecas do SDK do Azure que sejam relevantes para o seu aplicativo.
Na parte superior do arquivo, adicione as seguintes import instruções para importar as classes de index.js cliente necessárias para os serviços aos quais seu aplicativo se conectará:
import { DefaultAzureCredential } from "@azure/identity";
import { BlobServiceClient } from "@azure/storage-blob";
import { KeyClient } from "@azure/keyvault-keys";
Dentro do index.js arquivo, crie objetos de cliente para os serviços do Azure aos quais seu aplicativo se conectará. Os exemplos a seguir se conectam ao Armazenamento de Blob, ao Cosmos DB e ao SQL do Azure usando as classes SDK correspondentes.
// 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);
Você também pode associar uma identidade gerenciada atribuída pelo usuário, bem como uma identidade gerenciada atribuída pelo sistema a um recurso simultaneamente. Isso pode ser útil em cenários em que todos os aplicativos exigem acesso aos mesmos serviços compartilhados, mas um dos aplicativos também tem uma dependência muito específica de um serviço adicional. O uso de uma identidade atribuída pelo sistema também garante que a identidade vinculada a esse aplicativo específico seja excluída quando o aplicativo for excluído, o que pode ajudar a manter seu ambiente limpo.
Esses tipos de cenários são explorados com mais profundidade nas recomendações de práticas recomendadas de identidades.
Próximos passos
Neste tutorial, você aprendeu como migrar um aplicativo para conexões sem senha. Você pode ler os seguintes recursos para explorar os conceitos discutidos neste artigo com mais profundidade: