Autenticar aplicativos Python nos serviços do Azure durante o desenvolvimento local usando entidades de serviço

Ao criar aplicativos em nuvem, os desenvolvedores precisam depurar e testar aplicativos em suas estações de trabalho locais. 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 principais de serviço de aplicativo dedicados a serem usados durante o desenvolvimento local.

Um diagrama mostrando como um aplicativo em execução no desenvolvedor local obtém a entidade de serviço de aplicativo de um arquivo .env e, em seguida, usa essa identidade para se conectar aos recursos do Azure.

Entidades de serviço de aplicativo dedicadas para desenvolvimento local permitem que você siga o princípio de menor privilégio durante o desenvolvimento de aplicativos. Como as permissões têm como escopo exatamente o que é necessário para o aplicativo durante o desenvolvimento, o código do aplicativo é impedido de acessar acidentalmente um recurso do Azure destinado ao uso por um aplicativo diferente. Isso também evita que bugs ocorram quando o aplicativo é movido para produção porque o aplicativo era 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, recomenda-se:

  • Crie 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 registos de aplicações separados por aplicação. 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 do 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 de que ele precisa.

1 - Registar a aplicação no Azure

Os objetos principais do 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.

Os comandos da CLI do Azure podem ser executados 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 ao mesmo tempo.

az ad sp create-for-rbac --name {service-principal-name}

A saída deste comando será semelhante à seguinte. Anote esses valores ou mantenha essa janela aberta, pois você precisará desses valores nas próximas etapas e não poderá visualizar o valor da senha (segredo do cliente) novamente. No entanto, você pode adicionar uma nova senha mais tarde sem invalidar a entidade de serviço ou as senhas existentes, se necessário.

{
  "appId": "00000000-0000-0000-0000-000000000000",
  "displayName": "{service-principal-name}",
  "password": "abcdefghijklmnopqrstuvwxyz",
  "tenant": "33333333-3333-3333-3333-333333333333"
}

2 - Criar um grupo de segurança 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) de que o aplicativo precisa no desenvolvimento local, em vez de atribuir as funções a objetos de entidade de serviço individuais. Isto oferece as seguintes vantagens:

  • Todos os desenvolvedores têm a garantia de ter as mesmas funções atribuídas, uma vez 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 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 Microsoft Entra ID. Os parâmetros --display-name e --main-nickname são necessários. O nome dado ao grupo deve ser baseado no nome do aplicativo. Também é útil incluir uma frase como 'local-dev' no nome do grupo para indicar o propósito do grupo.

az ad group create \
    --display-name MyDisplay \
    --mail-nickname MyDisplay  \
    --description "<group-description>"

Copie o id valor da propriedade na saída do comando. Este é o ID do objeto para o 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ê precisa da ID do objeto da entidade de serviço do aplicativo, que é diferente da ID do aplicativo. Use a lista az ad sp para listar as entidades de serviço disponíveis. O --filter comando parameter aceita filtros de estilo OData e pode ser usado para filtrar a lista conforme mostrado. O --query parâmetro limita as colunas apenas à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>

Nota

Por padrão, a criação de grupos de segurança do Microsoft Entra é limitada a determinadas funções privilegiadas em um diretório. Se não conseguir criar um grupo, contacte um administrador do seu diretório. Se não conseguir adicionar membros a um grupo existente, contacte o proprietário do grupo ou um administrador de diretório. Para saber mais, consulte Gerenciar grupos do Microsoft Entra e associação a grupos.

3 - Atribuir funções à aplicação

Em seguida, você precisa determinar quais funções (permissões) 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 Microsoft Entra criado na etapa 2. As funções podem ser atribuídas em um recurso, grupo de recursos ou escopo de assinatura. Este exemplo mostra como atribuir funções no escopo do grupo de recursos, já que a maioria dos aplicativos agrupa todos os seus recursos do Azure em um único grupo de recursos.

Um usuário, grupo ou entidade de serviço de aplicativo recebe uma função no Azure usando o comando az role assignment create . Você pode especificar um grupo com sua 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 de aplicativo com o appId de leitura, gravação e exclusão acesse contêineres e dados de blob de Armazenamento do Azure em todas as contas de armazenamento no grupo de recursos msdocs-python-sdk-auth-example na assinatura com ID 11111111-1111-1111-1111-111111111111, você atribuiria a entidade de 00000000-0000-0000-0000-000000000000 serviço de aplicativo à função de Colaborador de Dados de Blob de Armazenamento usando o comando a seguir.

az role assignment create --assignee 00000000-0000-0000-0000-000000000000 \
    --scope /subscriptions/11111111-1111-1111-1111-111111111111/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 DefaultAzureCredential objeto procurará as informações da entidade de serviço em um conjunto de variáveis de ambiente em tempo de execução. 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 .env arquivo 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 .env arquivo 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 .env arquivo do check-in.

Para usar o pacote python-dotenv, primeiro instale o pacote em seu aplicativo.

pip install python-dotenv

Em seguida, crie um .env arquivo no diretório raiz do aplicativo. Defina os valores das variáveis 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 de ID do locatário.
  • AZURE_CLIENT_SECRET → A senha/credencial gerada para o aplicativo.
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
AZURE_TENANT_ID=11111111-1111-1111-1111-111111111111
AZURE_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz

Finalmente, no código de inicialização do seu aplicativo, use a python-dotenv biblioteca para ler as variáveis de ambiente do .env arquivo 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 em seu aplicativo

Para autenticar objetos de cliente do SDK do Azure no Azure, seu aplicativo deve usar a DefaultAzureCredentialazure.identity classe do pacote. Nesse cenário, DefaultAzureCredential detetará as variáveis AZURE_CLIENT_IDde ambiente , AZURE_TENANT_IDe AZURE_CLIENT_SECRET serão definidas e lerão essas variáveis para obter as informações da entidade de serviço de 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 de cliente do SDK do Azure em seu aplicativo, você deseja:

  1. Importe a DefaultAzureCredential classe do azure.identity módulo.
  2. Crie um DefaultAzureCredential objeto.
  3. Passe o DefaultAzureCredential objeto para o construtor de objeto de cliente do SDK do Azure.

Um exemplo disso é mostrado no segmento de código 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)