Entra App Management Policies: Restringir Secrets e Certificados
As credenciais de aplicações — secrets, certificados, symmetric keys — estão entre os artefactos mais explorados em ataques a tenants Microsoft: um secret vazado num script é acesso silencioso ao Graph, muitas vezes com permissões de aplicação (sem utilizador ao balcão). O consent phishing típico não precisaria disto, mas a realidade de uma PME costuma ser mais banal: apps registadas há anos, secrets com dois anos de validade e ninguém a saber ao certo quem as criou.
App Management Policies do Microsoft Entra ID dão ao tenant uma camada de controlo sobre como apps e service principals podem ser configurados: que credenciais podem ser criadas, com que validade máxima, que identifier URIs são aceites e que audiences são permitidas. É a política que impede o próximo secret “nunca expira” de nascer num tenant que já viveu um incidente.
O que as políticas cobrem
Um bloco applicationRestrictions controla aplicações, um bloco servicePrincipalRestrictions controla service principals. As restrições disponíveis:
| Restrição | O que faz | No admin center |
|---|---|---|
passwordAddition + symmetricKeyAddition |
Bloqueia a criação de novos secrets (passwords) e symmetric keys | Block password addition |
passwordLifetime + symmetricKeyLifetime |
Impõe uma vida útil máxima a secrets | Restrict max password lifetime |
asymmetricKeyLifetime |
Impõe uma vida útil máxima a certificados | Restrict max certificate lifetime |
customPasswordAddition |
Bloqueia secrets criados por clientes (ex.: módulos PowerShell antigos que geram a password localmente) — não bloqueia secrets gerados pelo Entra | Block custom passwords |
nonDefaultUriAddition |
Só aceita identifier URIs por defeito: api://{appId} ou api://{tenantId}/{appId} |
Block custom identifier URIs |
uriAdditionWithoutUniqueTenantIdentifier |
Bloqueia URIs sem identificador único do tenant | Block identifier URIs without unique tenant identifier |
audiences |
Restringe por signInAudience — bloqueia apps multitenant ou de contas consumer |
Block multitenant applications / Block consumer account applications |
trustedCertificateAuthority |
Só aceita certificados emitidos pelas CAs confiáveis do tenant | Só API |
Cada restrição tem um state (enabled/disabled) e, nas de lifetime, um maxLifetime em formato ISO-8601 — por exemplo P180D para 180 dias. A Microsoft exige paridade nos blocos de lifetime (documentado no guia de configuração do Entra): passwordAddition e passwordLifetime esperam os QUATRO blocos em igual estado — a restrição e a correspondente symmetricKeyAddition/symmetricKeyLifetime, nas colecções applicationRestrictions e servicePrincipalRestrictions — ou nenhum deles presente. O certificado (asymmetricKeyLifetime) segue a mesma régua nos DOIS blocos de keyCredentials. O agrupamento do portal é diferente: Block password addition e Restrict max password lifetime juntam password+symmetric key, e o Restrict max certificate lifetime fica isolado.
Âmbito temporal: os exemplos desta secção usam state, formato visível na API beta. Os exemplos oficiais em /v1.0/ usam antes restrictForAppsCreatedAfterDateTime — a data a partir da qual a restrição se aplica a apps novas, e que a Microsoft documenta poder aplicar-se retroactivamente a apps existentes (apps criadas antes da data ficam de fora, salvo outra política que as cubra). As duas propriedades coexistem no mesmo objecto de restrição — ao partir de exemplos v1.0 vem a data, não o estado.
Política por omissão do tenant
No topo está a tenant-wide application authentication settings policy, o objeto defaultAppManagementPolicy — existe sempre, não se cria nem apaga, e aplica-se a todas as apps e service principals do tenant. Vem desactivada de origem (isEnabled: false): os PATCHes abaixo enviam isEnabled: true — sem essa linha, as restrições gravam mas não chegam a aplicar-se.
⚠️ Atenção: o que uma política custom define tem prioridade sobre o default — nos dois sentidos. Pode apertar regras para uma app específica, mas também desligar uma restrição que o default impõe (é assim que nascem as excepções): uma restrição marcada disabled na política da app não se aplica, independentemente do default do tenant. Só o que a política custom NÃO define herda do default.
Quando o default não chega, criam-se custom app management policies: uma política custom permite regras diferentes para uma app específica — e cada application ou service principal só pode ter uma política custom atribuída. Os dois usos típicos: dar excepções (a política custom desliga a restrição para essa app) ou apertar (uma app crítica com validade de secret de 30 dias enquanto o resto do tenant fica em 180).
Aplicar no Microsoft Graph
Bloquear a criação de secrets em todo o tenant
O PATCH a seguir activa passwordAddition e symmetricKeyAddition nas duas colecções — aplicações e service principals:
Connect-MgGraph -Scopes "Policy.ReadWrite.ApplicationConfiguration"
$body = @{
isEnabled = $true
applicationRestrictions = @{
passwordCredentials = @(
@{ restrictionType = "passwordAddition"; state = "enabled" }
@{ restrictionType = "symmetricKeyAddition"; state = "enabled" }
)
}
servicePrincipalRestrictions = @{
passwordCredentials = @(
@{ restrictionType = "passwordAddition"; state = "enabled" }
@{ restrictionType = "symmetricKeyAddition"; state = "enabled" }
)
}
} | ConvertTo-Json -Depth 6
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/beta/policies/defaultAppManagementPolicy" `
-Body $body -ContentType "application/json"
O admin center faz o mesmo sem Graph: Entra ID > Enterprise apps > Application policies > Block password addition, estado On, Applies to = All applications, Save.
Limitar a vida de certificados a 180 dias
$body = @{
isEnabled = $true
applicationRestrictions = @{
keyCredentials = @(
@{ restrictionType = "asymmetricKeyLifetime"; state = "enabled"; maxLifetime = "P180D" }
)
}
servicePrincipalRestrictions = @{
keyCredentials = @(
@{ restrictionType = "asymmetricKeyLifetime"; state = "enabled"; maxLifetime = "P180D" }
)
}
} | ConvertTo-Json -Depth 6
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/beta/policies/defaultAppManagementPolicy" `
-Body $body -ContentType "application/json"
Para secrets, a mecânica é igual com passwordLifetime/symmetricKeyLifetime (os quatro blocos no mesmo estado, como visto acima).
Excepção para uma app específica
Uma política custom com a restrição desligada — por exemplo, uma app que precisa de identifier URIs fora dos formatos padrão:
$body = @{
displayName = "Excepcao identifier URIs"
description = "Policy granting an exemption to the nonDefaultUriAddition restriction"
isEnabled = $true
restrictions = @{
applicationRestrictions = @{
identifierUris = @{
nonDefaultUriAddition = @{ state = "disabled" }
}
}
}
} | ConvertTo-Json -Depth 6
$p = Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/beta/policies/appManagementPolicies" `
-Body $body -ContentType "application/json"
# Atribuir a app concreta ao objecto policies
Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/beta/applications/{objectId-da-app}/appManagementPolicies/`$ref" `
-Body (@{ "@odata.id" = "https://graph.microsoft.com/v1.0/policies/appManagementPolicies/$($p.id)" } | ConvertTo-Json) `
-ContentType "application/json"
Se a app já tiver política própria, a excepção entra nessa política — e convém confirmar que a política não está atribuída a mais apps, ou a excepção espalha-se.
Excepção para um processo (caller exception)
Quando quem viola a política não é a app mas o processo que a cria — um runner que regista apps e cria secrets em lote —, a excepção dá-se ao actor via custom security attributes, na secção Excluded callers da restrição. Este tipo de excepção usa custom security attributes e requer as roles Attribute Definition Administrator (definir o atributo) e Attribute Assignment Administrator (atribuir ao actor), para além das roles de configuração das políticas. A Attribute Assignment Reader só é necessária para quem usa o Entra admin center ou o portal Azure — via Graph ou PowerShell não é exigida.
Os exemplos usam o endpoint /beta/, como na documentação da feature — o resource appManagementPolicy também existe em /v1.0/.
Papéis necessários
Para configurar app management policies: Security Administrator e mais Cloud Application Administrator ou Application Administrator — ou um Global Administrator sozinho. Leitura e atribuição têm papéis próprios na API. A aplicação prática do dia-a-dia é esta dupla.
O que as políticas NÃO fazem
- Não revogam nem apagam credenciais já existentes — as restrições são sobre a criação e a configuração a partir daí. Os secrets antigos, se existirem, mantêm-se até expirar ou serem apagados à mão — um inventário prévio de apps cobre essa parte.
- A restrição
customPasswordAdditionnão bloqueia secrets gerados pelo próprio Entra no portal/Graph — bloqueia só os criados pelo cliente (SDKs antigos, módulos PowerShell legacy). trustedCertificateAuthoritysó está disponível via API — sem toggle no admin center.
Erros comuns
- O admin center recusa editar restrições manipuladas na API — aparece “The restriction have been modified outside of this interface. To prevent data loss, editing is disabled until restrictions are synchronized.” As restrições de lifetime têm a regra de paridade: os 4 blocos de password/symmetric key (e os 2 de certificado) têm de estar no mesmo estado — ou ausentes por inteiro. A correcção faz-se no Graph.
- A excepção fica atribuída a mais apps do que pretendido — as políticas custom partilham-se por atribuição — ver sempre
appliesToantes de gravar. - Apps multitenant de terceiros — as restrições a service principals de outros tenants aplicam-se no objeto SP — sem isso, apps SaaS com secrets continuam nas regras do tenant de origem.
Artigos Relacionados
- Defender SaaS contra Abuso de OAuth: ShinyHunters e Consent Phishing no Microsoft 365
- Backup e Recuperação do Entra ID: Proteger Configurações Cloud do Microsoft 365