Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
As auditorias de bases de dados são um componente importante dos requisitos de conformidade da sua organização. Ao monitorizar as atividades direcionadas, pode atingir a sua linha de base de segurança. No Base de Dados do Azure para PostgreSQL flexible server, pode configurar auditorias usando a extensão pgaudit PG, conforme descrito em Audit logging no Base de Dados do Azure para PostgreSQL.
Um dos desafios é usar a funcionalidade de auditoria juntamente com a autenticação do Microsoft Entra ID quando se utilizam grupos Microsoft Entra ID e se pretende auditar as ações dos membros individuais do grupo. Este desafio existe porque os membros do grupo iniciam sessão usando os seus tokens de acesso pessoais, mas usam o nome do grupo como nome de utilizador.
Kusto Query Language (KQL) é uma poderosa linguagem de consulta apenas de leitura, baseada em pipelines, que permite consultar os registos de serviço do Azure. O KQL suporta consultar logs do Azure para analisar rapidamente um grande volume de dados. Para este artigo, use o KQL para consultar os registos do Azure Postgres e extrair informações de utilizador do Microsoft Entra ID a partir dos registos de auditoria.
Pré-requisitos
- Ativar registo de auditoria - Registo de auditoria na Azure Database para PostgreSQL
- Permitir o envio dos logs do Azure Postgres para o Azure Log Analytics - Configurar e aceder aos logs
- Ajuste o parâmetro
log_line_prefix: No painel Parâmetros, defina olog_line_prefixde modo a incluir os caracteres de escapeuser=%u,db=%d,session=%c,sess_time=%sna mesma sequência para obter os resultados pretendidos.- Antes:
log_line_prefix=%t-%c- - Depois:
log_line_prefix=%t-%c-user=%u,db=%d,session=%c,sess_time=%s
- Antes:
Consulta Kusto
A seguinte consulta Kusto consulta o AzureDiagnostics duas vezes.
A primeira subconsulta encontra todas as linhas que contêm a cadeia Microsoft Entra ID connection authorized e extrai o PrincipalName dessas linhas logarítmicas, juntamente com o SessionId.
A segunda subconsulta encontra todos os registos de auditoria.
Finalmente, estas duas subconsultas são unidas no SessionId.
let lookbackTime = ago(3d);
let opindex = 3;
let startIndex = toscalar(range thirdIndex from opindex to opindex step 1
| project thirdIndex);
AzureDiagnostics
| where ResourceProvider == 'MICROSOFT.DBFORPOSTGRESQL'
| where TimeGenerated >= lookbackTime
| where Message contains 'Microsoft Entra ID connection authorized'
| extend SessionId = tostring(split(tostring(split(Message, 'session=')[-1]), ',sess_time')[-2])
| extend UPN = iff(Message contains 'UPN',tostring(split(tostring(split(Message, 'UPN=')[-1]), 'oid=')[-2]), '')
| extend appId = iff(Message contains 'appid', tostring(split(tostring(split(Message, 'appid=')[-1]), 'oid=')[-2]), '')
| extend PrincipalName = strcat(UPN, appId)
| project SessionId, PrincipalName
| join kind=leftouter
(
AzureDiagnostics
| where ResourceProvider == 'MICROSOFT.DBFORPOSTGRESQL'
| where TimeGenerated >= lookbackTime
| where Message contains 'AUDIT: SESSION'
| extend RoleName = tostring(split(tostring(split(Message, 'user=')[-1]), ',db')[-2])
| where RoleName !in ('azuresu', '[unknown]', 'postgres', '')
| extend SessionId = tostring(split(tostring(split(Message, 'session=')[-1]), ',sess_time')[-2])
| extend SubMessage = tostring(split(Message, 'SESSION,')[-1])
| extend splitArray = split(SubMessage, ',')
| extend SqlQueryP1 = tostring(split(tostring(split(Message, ',,,')[-1]), ',<')[-2])
| extend SqlQueryP2 = replace_string(tostring(split(SqlQueryP1, ',\"')[-1]), '"', '')
| extend SqlQueryP3 = tostring(split(Message, ',,,')[1])
| extend OperationType = tostring(splitArray[startIndex])
| extend SqlQuery = trim('"', case(OperationType == 'EXECUTE', SqlQueryP2, SqlQueryP1 == '', SqlQueryP3, SqlQueryP1))
)
on $left.SessionId == $right.SessionId
| project TimeGenerated, PrincipalName, RoleName, OperationType, SqlQuery
Resultados de exemplo
A tabela resultante é a seguinte:
| TimeGenerated | Nome Principal | Nome da Função | TipoDeOperação | SqlQuery |
|---|---|---|---|---|
| 2025-12-12T16:25:05.104Z | user@example.com | ExemploNome do Grupo | SELECT | selecionar * de pg_seclabels; |
| 2025-12-12T16:25:04.000Z | user@example.com | user@example.com | SELECT | selecionar * de pg_seclabels; |
Se o utilizador iniciar sessão como um papel de grupo, as PrincipalName colunas e RoleName mostram valores diferentes, como na primeira linha do exemplo.
O PrincipalName valor identifica o utilizador que iniciou sessão. O RoleName valor identifica o papel no PostgreSQL ao qual o utilizador acede após iniciar sessão.
PrincipalName é o Nome do Principal do Utilizador (UPN) ou o AppId, dependendo se o principal de utilizador ou o principal de serviço inicia sessão.