Autenticação Microsoft Entra com mssql-python

O Microsoft Entra ID fornece autenticação baseada em identidade para Base de Dados SQL do Azure, Azure SQL Managed Instance e base de dados SQL no Microsoft Fabric através do driver mssql-python. A autenticação Microsoft Entra oferece estas capacidades em relação à autenticação SQL:

  • Gestão centralizada de identidades através do Microsoft Entra ID.
  • Autenticação baseada em token que elimina a necessidade de palavras-passe.
  • Suporte a políticas de acesso condicional.
  • Identidades geridas para aplicações alojadas no Azure.

O controlador mssql-python suporta sete modos de autenticação do Microsoft Entra, todos configurados pela palavra-chave Authentication da cadeia de ligação.

Modos de autenticação

Defina a Authentication palavra-chave na sua cadeia de ligação para um dos seguintes valores:

Valor de autenticação Descrição
ActiveDirectoryDefault Usa DefaultAzureCredential, que tenta múltiplos métodos automaticamente.
ActiveDirectoryInteractive Login interativo baseado no navegador.
ActiveDirectoryDeviceCode Entrada de código em https://microsoft.com/devicelogin.
ActiveDirectoryPassword Nome de utilizador e palavra-passe com Microsoft Entra ID. Preterido.
ActiveDirectoryMSI Identidade gerida (atribuída pelo sistema ou pelo utilizador).
ActiveDirectoryServicePrincipal Principal de serviço com ID de cliente e segredo.
ActiveDirectoryIntegrated Windows integrado com Microsoft Entra ID (Kerberos).

Note

Os modos ActiveDirectoryDefault, ActiveDirectoryInteractive e ActiveDirectoryDeviceCode exigem o pacote azure-identity. Instale-o com pip install azure-identity.

DefaultAzureCredential

O ActiveDirectoryDefault modo utiliza DefaultAzureCredential do Azure Identity SDK, que tenta estes métodos de autenticação por ordem:

  1. Variáveis de ambiente.
  2. Identidade da carga de trabalho para Kubernetes.
  3. Identidade gerenciada.
  4. Credenciais da CLI do Azure.
  5. Credenciais do Azure PowerShell.
  6. Credenciais da CLI de Desenvolvimento do Azure.
  7. Navegador interativo, se ativado.

Exemplo: Autenticação por defeito

O exemplo seguinte liga-se a ActiveDirectoryDefault, que usa a DefaultAzureCredential cadeia para encontrar automaticamente uma credencial válida:

import mssql_python

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDefault;"
    "Encrypt=yes;"
)

cursor = conn.cursor()
cursor.execute("SELECT USER_NAME()")
print(f"Connected as: {cursor.fetchval()}")

Use este modo para desenvolvimento local porque ele capta automaticamente as credenciais do CLI do Azure. Para produção, use um modo de autenticação específico (ActiveDirectoryMSI, ActiveDirectoryServicePrincipal) em vez disso. DefaultAzureCredential Percorre vários fornecedores de credenciais em cada primeira ligação, o que adiciona uma latência que as cargas de trabalho de produção não precisam.

Autenticação interativa

Para aplicações interativas, utilize autenticação baseada em navegador. O utilizador deve ter uma conta de base de dados criada com CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER. Para todos os pré-requisitos, consulte Configurar autenticação Microsoft Entra.

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryInteractive;"
    "Encrypt=yes;"
)

No Windows, este modo delega ao fluxo interativo nativo do driver ODBC. Noutras plataformas, utiliza autenticação baseada em navegador do Azure Identity SDK.

Autenticação de código de dispositivo

Use autenticação por código de dispositivo para ambientes sem navegador, como sessões SSH ou contentores. O utilizador deve ter uma conta de base de dados criada com CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER. Para pré-requisitos, consulte Configurar autenticação Microsoft Entra.

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryDeviceCode;"
    "Encrypt=yes;"
)
# Output: To sign in, use a web browser to open https://microsoft.com/devicelogin
# and enter the code XXXXXXX to authenticate.

Siga o aviso para autenticar num navegador noutro dispositivo.

Autenticação do serviço principal

Use autenticação por principal de serviço para aplicações automatizadas que não requerem interação do utilizador:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryServicePrincipal;"
    "UID=<client-id>;"       # Application (client) ID
    "PWD=<client-secret>;"   # Client secret
    "Encrypt=yes;"
)

Criar um service principal

  1. Registe uma candidatura no Microsoft Entra ID.
  2. Criar um segredo de cliente.
  3. Conceda ao principal de serviço acesso à sua base de dados:
-- In Azure SQL
CREATE USER [app-name] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [app-name];
ALTER ROLE db_datawriter ADD MEMBER [app-name];

Sugestão

Se CREATE USER falhar com o erro 33131 (nome de exibição duplicado), use WITH OBJECT_ID para especificar o ID de Objeto do principal de serviço a partir da página de aplicações empresariais no portal Azure (não na página de registo de aplicações):

CREATE USER [app-name] FROM EXTERNAL PROVIDER
    WITH OBJECT_ID = '<enterprise-app-object-id>';

Para mais detalhes, consulte os logins da Microsoft Entra e utilizadores com nomes de exibição não únicos.

Identidade gerenciada

Use autenticação de identidade gerida para aplicações alojadas no Azure, como App Service, Funções do Azure e VMs:

Identidade gerenciada atribuída ao sistema

Ligue-se usando a identidade atribuída diretamente ao recurso Azure:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryMSI;"
    "Encrypt=yes;"
)

Identidade gerenciada atribuída pelo usuário

Especifique o ID do cliente de uma identidade gerida atribuída pelo utilizador no campo UID:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryMSI;"
    "UID=<managed-identity-client-id>;"
    "Encrypt=yes;"
)

Configurar o acesso à base de dados

Conceda à identidade gerida acesso na sua base de dados. Um administrador Microsoft Entra deve estar configurado no servidor antes de poder criar utilizadores externos. Para ativar a identidade gerida no seu recurso Azure, veja Identidades geridas para recursos Azure.

-- Replace 'my-app-service' with your Azure resource name
CREATE USER [my-app-service] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [my-app-service];
ALTER ROLE db_datawriter ADD MEMBER [my-app-service];

Autenticação por palavra-passe (obsoleta)

Importante

A opção de autenticação ActiveDirectoryPassword (autenticação por palavra-passe do Microsoft Entra ID) está obsoleta nos drivers SQL da Microsoft. Este fluxo de autenticação de alto risco é incompatível com a autenticação multifator (MFA) obrigatória da Microsoft Entra e pode não funcionar em inquilinos onde a MFA é aplicada. Planeio migrar para um método de autenticação Microsoft Entra diferente.

A autenticação por palavra-passe do Microsoft Entra ID baseia-se na concessão OAuth 2.0 Resource Owner Password Credentials (ROPC), que permite a uma aplicação iniciar a sessão do utilizador processando diretamente a respetiva palavra-passe.

A Microsoft recomenda que não uses o fluxo ROPC porque é incompatível com o MFA. Na maioria dos cenários, alternativas mais seguras estão disponíveis e são recomendadas. Este fluxo exige um elevado grau de confiança na aplicação e acarreta riscos que não existem noutros fluxos. Use este fluxo apenas quando fluxos mais seguros não forem viáveis. A Microsoft está a afastar-se deste fluxo de autenticação de alto risco para proteger os utilizadores de ataques maliciosos. Para mais informações, consulte Planeamento para autenticação multifator obrigatória para Azure.

Quando um utilizador estiver presente no início de sessão, utilize a autenticação ActiveDirectoryInteractive ou ActiveDirectoryIntegrated para que o registo de auditoria seja atribuído ao utilizador com sessão iniciada e as políticas de Acesso Condicional se apliquem.

Para cenários de serviço para serviço não supervisionados, siga as orientações sobre contas de serviço do Microsoft Entra:

  • Se a sua aplicação correr na infraestrutura Azure, use o ActiveDirectoryMSI (ou o ActiveDirectoryManagedIdentity em alguns drivers). As identidades geridas eliminam a sobrecarga de manter e rotacionar segredos e certificados.
  • Se a identidade gerida não estiver disponível (por exemplo, se a aplicação estiver a ser executada fora do Azure), use o ActiveDirectoryServicePrincipal. Quando o driver o permite, prefira um certificado de cliente em vez de um segredo de cliente. Com um certificado, a chave privada permanece no cliente e apenas uma asserção assinada é enviada à Microsoft Entra para autenticar o cliente. Se a chave estiver armazenada em hardware (como um TPM ou HSM) ou marcada como não exportável, não pode ser extraída sob a forma de uma cadeia de caracteres, da mesma forma que um segredo do cliente pode.
  • Não use uma conta de utilizador Microsoft Entra como conta de serviço.

Use autenticação por palavra-passe quando precisar de um nome de utilizador e uma palavra-passe com uma conta Microsoft Entra. O utilizador deve ter uma conta de base de dados criada com CREATE USER [user@domain.com] FROM EXTERNAL PROVIDER:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryPassword;"
    "UID=<login@domain.com>;"
    "PWD=<password>;"
    "Encrypt=yes;"
)

Autenticação integrada do Windows

Utilize a autenticação integrada do Windows para ambientes Windows associados a um domínio com Kerberos. Este modo requer que o seu Active Directory no local esteja federado com o Microsoft Entra ID e um administrador Microsoft Entra configurado no servidor:

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Authentication=ActiveDirectoryIntegrated;"
    "Encrypt=yes;"
)

Este modo utiliza as credenciais Kerberos do utilizador atual do Windows. No Linux e macOS, deve configurar o Kerberos manualmente (krb5.conf e um keytab ou ticket válido). Veja a autenticação do Active Directory para o SQL Server no Linux para a configuração do Kerberos no lado do cliente.

Objetos de credenciais com token_provider

Passe um objeto de credenciais diretamente com o parâmetro token_provider. O driver chama o método get_token() do objeto quando precisa de um token, pelo que o utilizador não precisa de incluir o token num atributo de ligação.

Qualquer objeto com um get_token(scope) método que devolve um objeto com um .token atributo satisfaz o contrato. Todas as credenciais do pacote azure-identity são válidas, incluindo DefaultAzureCredential, AzureCliCredential, ManagedIdentityCredential e ClientSecretCredential.

import mssql_python
from azure.identity import DefaultAzureCredential

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;"
    "Encrypt=yes",
    token_provider=DefaultAzureCredential(),
)

O condutor pede o https://database.windows.net/.default telescópio. Este parâmetro suporta apenas o escopo comercial de cloud do Azure. Para nuvens soberanas, utilize a autenticação por token de acesso e solicite o âmbito exigido pela sua nuvem.

As operações de cópia em massa adquirem um token novo do fornecedor para cada operação, porque abrem a sua própria ligação.

Também pode fornecer o seu próprio objeto, o que é útil quando o token é proveniente de outra origem que não azure-identity, como um ambiente de notebook que expõe o seu próprio auxiliar de token:

from types import SimpleNamespace

class NotebookTokenProvider:
    def get_token(self, scope):
        # Return any object with a .token attribute holding the raw JWT string.
        return SimpleNamespace(token=get_platform_token(scope))

conn = mssql_python.connect(connection_string, token_provider=NotebookTokenProvider())

O driver exporta um TokenProvider tipo de protocolo para verificação de tipos estáticos:

from mssql_python import TokenProvider

def open_connection(credential: TokenProvider):
    return mssql_python.connect(connection_string, token_provider=credential)

O token_provider parâmetro é a única fonte de token para uma ligação que o utiliza. O driver gera InterfaceError se for utilizado em conjunto com qualquer um dos seguintes:

  • A palavra-chave Authentication na cadeia de ligação.

  • Um token transmitido através de attrs_before com SQL_COPT_SS_ACCESS_TOKEN.

A passagem de um objeto sem um método get_token() também gera InterfaceError.

Se a cadeia de ligação contiver UID ou PWD, o controlador ignora-os e emite um UserWarning que indica as palavras-chave ignoradas. Remova-os da cadeia de ligação para silenciar o aviso.

Note

As ligações que autenticam com um objeto credencial são agrupadas por identidade. Para mais informações, consulte agrupamento de ligações.

Autenticação de token de acesso

Pode adquirir tokens externamente, por exemplo, através de uma cache partilhada de tokens ou de um endpoint de nuvem soberana. Nestes casos, use SQL_COPT_SS_ACCESS_TOKEN com o attrs_before parâmetro para passar diretamente o token. Esta abordagem ignora o fluxo de aquisição de tokens integrado no controlador.

Prefira o token_provider parâmetro descrito na secção anterior quando a sua credencial provém de azure-identity. Trata da codificação de tokens por si e atualiza os tokens para ligações agrupadas.

import mssql_python
from azure.identity import DefaultAzureCredential
import struct

def get_token():
    credential = DefaultAzureCredential(
        exclude_interactive_browser_credential=False
    )
    token_bytes = credential.get_token(
        "https://database.windows.net/.default"
    ).token.encode("utf-16le")
    token_struct = struct.pack(
        f'<I{len(token_bytes)}s', len(token_bytes), token_bytes
    )
    return token_struct

SQL_COPT_SS_ACCESS_TOKEN = 1256

conn = mssql_python.connect(
    "Server=<server>.database.windows.net;"
    "Database=<database>;",
    attrs_before={SQL_COPT_SS_ACCESS_TOKEN: get_token()}
)

Importante

Ao usar SQL_COPT_SS_ACCESS_TOKEN, a cadeia de ligação não deve incluir UID, PWD, Authentication, ou Trusted_Connection. O próprio token trata da autenticação.

Escolher um modo de autenticação

Scenario Modo recomendado
Computador de desenvolvimento ActiveDirectoryDefault (utiliza a CLI do Azure)
Serviço de Aplicações do Azure / Functions ActiveDirectoryMSI (mais rápido que o padrão)
Azure Kubernetes Service ActiveDirectoryDefault (identidade da carga de trabalho)
Scripts automatizados no local ActiveDirectoryServicePrincipal
Aplicação interativa de ambiente de trabalho ActiveDirectoryInteractive
SSH/container sem navegador ActiveDirectoryDeviceCode

Troubleshoot

Falha de início de sessão do utilizador 'NT AUTHORITY\ANONYMOUS LOGON'

Verifique se o utilizador ou identidade gerida existe na base de dados:

CREATE USER [identity-name] FROM EXTERNAL PROVIDER;

AADSTS700016: Aplicação não encontrada

O principal de serviço ou o ID da aplicação está incorreto. Verifique o ID do cliente e se a aplicação está registada no seu tenant Microsoft Entra.

O endpoint da Identidade Gerida não está acessível

  • Verifique se a identidade gerida está ativada no recurso Azure.
  • Para a identidade atribuída pelo utilizador, verifique se o ID do cliente está correto.
  • Verifique se o recurso tem acesso de rede ao endpoint de identidade.

Tempo limite para aquisição de tokens

ActiveDirectoryDefault utiliza DefaultAzureCredential, que percorre uma cadeia de fornecedores de credenciais em sequência até que um deles seja bem-sucedido. Este percurso pela cadeia acrescenta segundos de latência na ligação inicial, especialmente quando os provedores anteriores na cadeia (variáveis de ambiente, identidade da carga de trabalho) falham antes de se chegar ao que funciona. Em produção, especifique diretamente o tipo de credencial para saltar a cadeia:

# Slow: DefaultAzureCredential tries multiple providers
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryDefault")

# Fast: Skip directly to managed identity
conn = mssql_python.connect(connection_string, authentication="ActiveDirectoryMSI")