Autenticar aplicativos Python para serviços do Azure durante o desenvolvimento local usando entidades de serviço
Ao criar aplicativos de nuvem, os desenvolvedores precisam depurar e testar aplicativos em sua estação de trabalho local. Quando um aplicativo é executado na estação de trabalho de um desenvolvedor durante o desenvolvimento local, ele ainda deve se autenticar em todos os serviços do Azure usados pelo aplicativo. Este artigo aborda como configurar objetos de entidade de serviço de aplicativo dedicados a serem usados durante o desenvolvimento local.
As entidades de serviço de aplicativo dedicadas para desenvolvimento local permitem que você siga o princípio do privilégio mínimo durante o desenvolvimento de aplicativos. Como as permissões têm o escopo exatamente do que é necessário para o aplicativo durante o desenvolvimento, o código do aplicativo é impedido de acessar acidentalmente um recurso do Azure destinado a ser usado por um aplicativo diferente. Isso também impede que bugs ocorram quando o aplicativo é movido para produção porque o aplicativo foi superprivilegiado no ambiente de desenvolvimento.
Uma entidade de serviço de aplicativo é configurada para o aplicativo quando o aplicativo é registrado no Azure. Ao registrar aplicativos para desenvolvimento local, é recomendável:
- Criar registros de aplicativo separados para cada desenvolvedor que trabalha no aplicativo. Isso criará entidades de serviço de aplicativo separadas para cada desenvolvedor usar durante o desenvolvimento local e evitará a necessidade de os desenvolvedores compartilharem credenciais para uma única entidade de serviço de aplicativo.
- Crie registros de aplicativo separados por aplicativo. Isso define o escopo das permissões do aplicativo apenas para o que é necessário para o aplicativo.
Durante o desenvolvimento local, as variáveis de ambiente são definidas com a identidade da entidade de serviço de aplicativo. O SDK do Azure para Python lê essas variáveis de ambiente e usa essas informações para autenticar o aplicativo nos recursos do Azure necessários.
1 – Registrar o aplicativo no Azure
Os objetos da entidade de serviço de aplicativo são criados com um registro de aplicativo no Azure. Isso pode ser feito usando o portal do Azure ou a CLI do Azure.
É possível executar os comandos da CLI do Azure no Azure Cloud Shell ou em uma estação de trabalho com a CLI do Azure instalada.
Primeiro, use o comando az ad sp create-for-rbac para criar uma nova entidade de serviço para o aplicativo. O comando também cria o registro do aplicativo para o aplicativo ao mesmo tempo.
az ad sp create-for-rbac --name <service-principal-name>
A saída deste comando terá a aparência a seguir. Anote esses valores ou mantenha essa janela aberta, já que você precisará desses valores nas próximas etapas e não poderá exibir o valor da senha (segredo do cliente) novamente. Mas você pode adicionar uma nova senha mais tarde, sem invalidar a entidade de serviço ou os segredos existentes, se necessário.
{
"appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"displayName": "<service-principal-name>",
"password": "Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6",
"tenant": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
}
2 – Criar um grupo de segurança do Microsoft Entra para desenvolvimento local
Como normalmente há vários desenvolvedores que trabalham em um aplicativo, é recomendável criar um grupo de segurança do Microsoft Entra para encapsular as funções (permissões) que o aplicativo precisa no desenvolvimento local, em vez de atribuir as funções a objetos de entidade de serviço individuais. As vantagens oferecidas são:
- Cada desenvolvedor deve ter as mesmas funções atribuídas, já que as funções são atribuídas no nível do grupo.
- Se uma nova função for necessária para o aplicativo, ela só precisará ser adicionada ao grupo do Microsoft Entra para o aplicativo.
- Se um novo desenvolvedor ingressar na equipe, uma nova entidade de serviço de aplicativo será criada para o desenvolvedor e adicionada ao grupo, garantindo que o desenvolvedor tenha as permissões certas para trabalhar no aplicativo.
O comando az ad group create é usado para criar grupos de segurança no ID do Microsoft Entra. Os parâmetros --display-name
e --main-nickname
são obrigatórios. O nome fornecido ao grupo deve ter como base o nome do aplicativo. Também é interessante incluir uma frase como “desenvolvimento local” no nome do grupo para indicar a finalidade do grupo.
az ad group create \
--display-name MyDisplay \
--mail-nickname MyDisplay \
--description "<group-description>"
Copie o valor da propriedade id
na saída do comando. Esse é o ID do objeto do grupo. Você precisa dele em etapas posteriores. Você também pode usar o comando az ad group show para recuperar essa propriedade.
Para adicionar membros ao grupo, você precisará da ID do objeto da entidade de serviço do aplicativo, que é diferente da ID do aplicativo. Use az ad sp list para listar as entidades de serviço disponíveis. O comando de parâmetro --filter
aceita filtros de estilo OData e pode ser usado para filtrar a lista, conforme mostrado. O parâmetro --query
limita as colunas somente às de interesse.
az ad sp list \
--filter "startswith(displayName, 'msdocs')" \
--query "[].{objectId:id, displayName:displayName}" \
--output table
O comando az ad group member add pode ser usado para adicionar membros a grupos.
az ad group member add \
--group <group-name> \
--member-id <object-id>
Observação
Por padrão, a criação de grupos de segurança do Microsoft Entra é limitada a determinadas funções com privilégio em um diretório. Se não for possível criar um grupo, entre em contato com um administrador do seu diretório. Se você não puder adicionar membros a um grupo existente, entre em contato com o proprietário do grupo ou com um administrador de diretório. Para saber mais, consulte Gerenciar grupos do Microsoft Entra e associação de grupo.
3 – Atribuir funções ao aplicativo
Em seguida, você precisa determinar as funções (permissões) de que seu aplicativo precisa em quais recursos e atribuir essas funções ao seu aplicativo. Neste exemplo, as funções são atribuídas ao grupo do Microsoft Entra criado na etapa 2. As funções podem ser atribuídas a um recurso, grupo de recursos ou escopo de assinatura. Este exemplo mostra como atribuir funções no escopo do grupo de recursos, uma vez que a maioria dos aplicativos agrupa todos os seus recursos do Azure em um único grupo de recursos.
Uma entidade de serviço de usuário, grupo ou aplicativo recebe uma função no Azure usando o comando az role assignment create. Você pode especificar um grupo com o ID de objeto. Você pode especificar uma entidade de serviço de aplicativo com seu appId.
az role assignment create --assignee <appId or objectId> \
--scope /subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName> \
--role "<roleName>"
Para obter os nomes de função que podem ser atribuídos, use o comando az role definition list.
az role definition list \
--query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
--output table
Por exemplo, para permitir que a entidade de serviço do aplicativo com o appId de 00001111-aaaa-2222-bbbb-3333cccc4444
leitura, gravação e exclusão acesse os contêineres do Azure Storage Blob e os dados em todas as contas de armazenamento no grupo de recursos msdocs-python-sdk-auth-example na assinatura com ID aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
, você deve atribuir a entidade de serviço do aplicativo à função de Colaborador de dados de blob de armazenamento usando o seguinte comando.
az role assignment create --assignee 00001111-aaaa-2222-bbbb-3333cccc4444 \
--scope /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-python-sdk-auth-example \
--role "Storage Blob Data Contributor"
Para obter informações sobre como atribuir permissões no nível de recurso ou assinatura usando a CLI do Azure, consulte o artigo Atribuir funções do Azure usando a CLI do Azure.
4 - Definir variáveis de ambiente de desenvolvimento local
O objeto DefaultAzureCredential
procurará as informações da entidade de serviço em um conjunto de variáveis de ambiente no runtime. Como a maioria dos desenvolvedores trabalha em vários aplicativos, é recomendável usar um pacote como python-dotenv para acessar o ambiente a partir de um arquivo .env
armazenado no diretório do aplicativo durante o desenvolvimento. Isso define o escopo das variáveis de ambiente usadas para autenticar o aplicativo no Azure, de modo que elas só possam ser usadas por esse aplicativo.
O arquivo .env
nunca é verificado no controle do código-fonte, pois contém a chave secreta do aplicativo para o Azure. O arquivo .gitignore padrão para Python exclui automaticamente o arquivo .env
do check-in.
Para usar o pacote python-dotenv, primeiro instale o pacote em seu aplicativo.
pip install python-dotenv
Em seguida, crie um arquivo .env
no diretório raiz do aplicativo. Defina os valores da variável de ambiente com os valores obtidos do processo de registro do aplicativo da seguinte maneira:
AZURE_CLIENT_ID
→ O valor da ID do aplicativo.AZURE_TENANT_ID
→ O valor da ID do locatário.AZURE_CLIENT_SECRET
→ A senha/credencial gerada para o aplicativo.
AZURE_CLIENT_ID=00001111-aaaa-2222-bbbb-3333cccc4444
AZURE_TENANT_ID=aaaabbbb-0000-cccc-1111-dddd2222eeee
AZURE_CLIENT_SECRET=Ee5Ff~6Gg7.-Hh8Ii9Jj0Kk1Ll2Mm3_Nn4Oo5Pp6
Por fim, no código de inicialização do aplicativo, use a biblioteca python-dotenv
para ler as variáveis de ambiente do arquivo .env
na inicialização.
from dotenv import load_dotenv
if ( os.environ['ENVIRONMENT'] == 'development'):
print("Loading environment variables from .env file")
load_dotenv(".env")
5 – Implementar DefaultAzureCredential no seu aplicativo
Para autenticar objetos clientes do SDK do Azure no Azure, seu aplicativo deve usar a classe DefaultAzureCredential
do pacote azure.identity
. Nesse cenário, DefaultAzureCredential
detectará as variáveis de ambiente AZURE_CLIENT_ID
, AZURE_TENANT_ID
e AZURE_CLIENT_SECRET
será definido e lerá essas variáveis para obter as informações da entidade de serviço do aplicativo com as quais se conectar ao Azure.
Comece adicionando o pacote azure.identity ao seu aplicativo.
pip install azure-identity
Em seguida, para qualquer código Python que crie um objeto cliente do SDK do Azure em seu aplicativo, você deverá:
- Importar a classe
DefaultAzureCredential
do móduloazure.identity
. - Crie um objeto
DefaultAzureCredential
. - Passar o objeto
DefaultAzureCredential
para o construtor do objeto do cliente do SDK do Azure.
Um exemplo disso é mostrado na ilustração a seguir.
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
# Acquire a credential object
token_credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url="https://<my_account_name>.blob.core.windows.net",
credential=token_credential)