Gerir API Credentials do Sophos Fusion com segurança
O Sophos Fusion (anteriormente Sophos Central) pode ser automatizado através de APIs e ligado a plataformas de SIEM, RMM, reporting ou seguros. Para esse efeito, não se utilizam contas pessoais de administrador, mas API Credentials próprias, compostas por Client ID e Client Secret.
Estas credenciais são identidades de máquinas. Quem possuir um secret pode executar todas as ações de API permitidas pela função Service Principal atribuída. Por isso, um secret deve ser tratado como uma palavra-passe privilegiada e nunca pode ficar guardado em scripts, tickets, e-mails ou repositórios Git.
Distinguir API Credentials do Integration Credential Manager
Em Global Settings > Access Control existem duas áreas com nomes semelhantes:
| Área | Função |
|---|---|
| API Credentials | Identidade técnica com a qual uma aplicação acede às APIs do Sophos Fusion |
| Integration Credential Manager | Credenciais de produtos de terceiros que a Sophos utiliza para integrações como Data Ingestion ou Response Actions |
Para um script próprio, uma consulta SIEM ou um cliente de API, criam-se API Credentials. As credenciais de um produto de terceiros que o próprio Sophos Fusion deve utilizar pertencem, pelo contrário, ao Integration Credential Manager.
Nem todas as automatizações necessitam de API Credentials gerais: os utilizadores e grupos são sincronizados através de um serviço de diretório e o software pode ser distribuído por um script de instalação executado localmente em cada dispositivo. Só se cria uma identidade de API para o AD Sync quando o processo de sincronização previsto a exigir, atribuindo-lhe exclusivamente a função Service Principal Directory Sync.
Pré-requisitos e responsabilidade
Apenas um Super Admin pode criar e gerir API Credentials. A aplicação autentica-se com o seu próprio Client ID e Client Secret, e não com a conta pessoal do administrador.
Antes da criação, documentam-se a finalidade, o responsável, o sistema de destino, a função necessária, a data de expiração e o contacto de emergência. Utiliza-se uma Credential própria para cada aplicação e ambiente. Um secret comum para um script de backup, o SIEM e prestadores externos impede um bloqueio seletivo e dificulta a análise da causa.
Escolher a função Service Principal adequada
A Sophos disponibiliza várias funções:
- Service Principal Read-Only lê dados do tenant, mas não os pode alterar nem executar consultas Live Discover.
- Service Principal Management pode consultar, criar, alterar e eliminar utilizadores e grupos de utilizadores, consultar e processar Alerts, consultar Endpoints e iniciar ações como um scan, bem como consultar e alterar definições globais de Endpoint Protection. Além disso, a função gere administradores, funções e Security Policies, mas não tem acesso a consultas Live Discover.
- Service Principal Forensics cria, consulta, executa e elimina consultas Live Discover.
- Service Principal Directory Sync destina-se exclusivamente à sincronização do Active Directory e não pode executar outras tarefas de API.
- Service Principal Firewall limita a identidade à gestão de Firewalls e não permite tarefas de API do Central fora desse âmbito.
- Service Principal Audit Log permite que aplicações externas, ferramentas SIEM e scripts de integração obtenham eventos do Audit Log com acesso de consulta só de leitura.
- Service Principal Super Admin possui direitos abrangentes de leitura, escrita e eliminação, bem como acesso a consultas.
A seleção começa sempre pela função mais limitada. Uma integração de reporting ou de seguros cibernéticos recebe Read-Only. O AD Sync recebe a função prevista especificamente para esse efeito. Super Admin só é utilizado quando os endpoints de API documentados exigem efetivamente direitos de escrita abrangentes e nenhuma função mais limitada funciona.
Criar a Credential
Inicie sessão em fusion.sophos.com e abra Global Settings > Access Control > API Credentials. No primeiro acesso, é necessário aceitar os termos de utilização.
- Abrir Add Credential.
- Introduzir um nome inequívoco e uma descrição com a aplicação, o ambiente e o responsável.
- Selecionar a função Service Principal mínima necessária.
- Criar a Credential e copiar imediatamente o Client ID e o Client Secret.
- Guardar o secret num Secret Store empresarial e limpar a área de transferência temporária.
O Client Secret só é apresentado uma vez. Não pode voltar a ser mostrado posteriormente. Se for perdido, não se recupera o secret existente; cria-se uma nova Credential e elimina-se a antiga depois de a transição ter sido concluída com êxito.
Contrato da API, autenticação e região
O processo seguinte descreve as API REST de produto regionais do Sophos Central: o host Identity global emite o token OAuth; o host global whoami identifica a credencial. Para contratos REST com encaminhamento regional, os pedidos de produto do tenant usam depois o host devolvido para esse tenant. Para isso, os seguintes destinos HTTPS têm de estar acessíveis a partir da estação de administração ou do sistema de integração:
POST https://id.sophos.com/api/v2/oauth2/tokenpara OAuth2;GET https://api.central.sophos.com/whoami/v1para identidade e descoberta do host;GET https://api.central.sophos.com/partner/v1/tenantspara credenciais de parceiro;GET https://api.central.sophos.com/organization/v1/tenantspara credenciais Enterprise;- o host HTTPS devolvido em
apiHosts.dataRegionou no campo do tenantapiHostpara a API de produto.
Não adivinhar um URL regional nem copiá-lo de uma tabela estática. Para este processo REST, aceitar apenas o host HTTPS completo devolvido e só depois acrescentar os caminhos de produto. A verificação do host no script abaixo aplica-se a este contrato, não universalmente a todas as API Sophos.
A Search GraphQL API tem um contrato de destino próprio: POST JSON para https://api.taegis.sophos.com/graphql com token Bearer, X-Tenant-ID e X-GraphQL-Schema: default. Não se utiliza o host REST regional nem se substitui globalmente apiHosts.dataRegion. A obtenção do token e a associação ao tenant continuam necessárias; esclarecer separadamente permissões e direitos de acesso para a operação concreta. As descrições gerais de funções acima não comprovam uma função mínima Search GraphQL. O runbook de consultas Search-QL históricas descreve o processo completo. O nome de host, por si só, não garante a residência dos dados.
Pedir um token de acesso com segurança
Ler o segredo sem o mostrar e enviar os dados do formulário pela entrada padrão. Assim, não fica no histórico da shell nem como argumento expandido na lista de processos:
read -r -p "Client ID: " SOPHOS_CLIENT_ID
read -r -s -p "Client Secret: " SOPHOS_CLIENT_SECRET; printf '\n'
TOKEN_RESPONSE=$(printf 'grant_type=client_credentials&client_id=%s&client_secret=%s&scope=token' \
"$(printf '%s' "$SOPHOS_CLIENT_ID" | jq -sRr '@uri')" \
"$(printf '%s' "$SOPHOS_CLIENT_SECRET" | jq -sRr '@uri')" |
curl --fail-with-body --silent --show-error --request POST \
--header 'Content-Type: application/x-www-form-urlencoded' --data-binary @- \
https://id.sophos.com/api/v2/oauth2/token)
unset SOPHOS_CLIENT_SECRET
SOPHOS_ACCESS_TOKEN=$(jq -er '
select(.token_type == "bearer") |
select((.expires_in | type) == "number" and .expires_in > 0) |
.access_token | select(type == "string" and length > 0)
' <<<"$TOKEN_RESPONSE")
unset TOKEN_RESPONSE
WHOAMI=$(printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" |
curl --fail-with-body --silent --show-error --config - https://api.central.sophos.com/whoami/v1
)
Uma resposta bem-sucedida contém pelo menos access_token, token_type: "bearer" e expires_in; também podem aparecer refresh_token, errorCode, message e trackingId. expires_in é a validade em segundos. No fluxo Client Credentials, pedir um novo token de acesso após expirar, em vez de depender do refresh_token opcional. Nunca registar a resposta: ambos os campos de token são segredos.
Avaliar whoami
Passar o cabeçalho Bearer ao curl pela entrada padrão e guardar apenas os campos de descoberta não secretos. Os valores do exemplo de resposta de tenant são marcadores, não valores de produção.
{
"id": "<tenant-uuid>",
"idType": "tenant",
"apiHosts": {
"global": "https://api.central.sophos.com",
"dataRegion": "https://api-us03.central.sophos.com"
}
}
Com idType: "tenant", verificar rigorosamente UUID e host antes de os adotar. Com idType: "partner" ou "organization", whoami normalmente só contém apiHosts.global; SOPHOS_ID não é então um ID de tenant. O ciclo limitado utiliza o cabeçalho de contexto necessário e segue pages.total. Cada objeto tenant fornece o seu próprio id e apiHost. Escolher o destino por um UUID de uma correspondência interna fiável, nunca apenas por um nome apresentado semelhante.
SOPHOS_ID=$(jq -er '.id|select(type=="string" and length>0)' <<<"$WHOAMI")
SOPHOS_ID_TYPE=$(jq -er '.idType|select(.=="tenant" or .=="partner" or .=="organization")' <<<"$WHOAMI")
UUID_RE='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$'
if [[ "$SOPHOS_ID_TYPE" == tenant ]]; then
SOPHOS_TENANT_ID=$(jq -er --arg re "$UUID_RE" '.id|select(type=="string" and test($re))' <<<"$WHOAMI")
SOPHOS_API_HOST=$(jq -er '.apiHosts.dataRegion|select(type=="string" and test("^https://api-[a-z0-9-]+\\.central\\.sophos\\.com$"))' <<<"$WHOAMI")
else
case "$SOPHOS_ID_TYPE" in
partner) TENANTS_URL='https://api.central.sophos.com/partner/v1/tenants'; CONTEXT_HEADER="X-Partner-ID: ${SOPHOS_ID}" ;;
organization) TENANTS_URL='https://api.central.sophos.com/organization/v1/tenants'; CONTEXT_HEADER="X-Organization-ID: ${SOPHOS_ID}" ;;
*) exit 1 ;;
esac
TENANTS_FILE=$(mktemp); printf '[]\n' >"$TENANTS_FILE"; page=1; max_pages=1000; expected_pages=
while (( page <= max_pages )); do
PAGE_RESPONSE=$(printf 'header = "Authorization: Bearer %s"\n' "$SOPHOS_ACCESS_TOKEN" | curl --fail-with-body --silent --show-error --get --config - --header "$CONTEXT_HEADER" --data-urlencode "page=${page}" --data-urlencode 'pageSize=100' --data-urlencode 'pageTotal=true' "$TENANTS_URL")
page_total=$(jq -er 'select((.items|type)=="array")|.pages.total|select(type=="number" and floor==. and .>=1 and .<=1000)' <<<"$PAGE_RESPONSE")
if [[ -z "$expected_pages" ]]; then expected_pages=$page_total; fi; [[ "$page_total" == "$expected_pages" ]] || exit 1
jq -e --argjson page "$PAGE_RESPONSE" '.+$page.items' "$TENANTS_FILE" >"${TENANTS_FILE}.new"; mv "${TENANTS_FILE}.new" "$TENANTS_FILE"
(( page >= expected_pages )) && break; ((page++))
done
(( page == expected_pages )) || exit 1
read -r -p 'UUID do tenant de destino do mapeamento aprovado: ' TARGET_TENANT_ID
TARGET_TENANT=$(jq -cer --arg id "$TARGET_TENANT_ID" --arg re "$UUID_RE" '[.[]|select((.id|type)=="string" and (.id|test($re)) and (.id|ascii_downcase)==($id|ascii_downcase))|select((.apiHost|type)=="string" and (.apiHost|test("^https://api-[a-z0-9-]+\\.central\\.sophos\\.com$")))]|select(length==1)|.[0]' "$TENANTS_FILE")
SOPHOS_TENANT_ID=$(jq -r .id <<<"$TARGET_TENANT"); SOPHOS_API_HOST=$(jq -r .apiHost <<<"$TARGET_TENANT"); rm -f "$TENANTS_FILE"
fi
export SOPHOS_TENANT_ID SOPHOS_API_HOST
Cada pedido de produto do tenant neste processo REST regional associa então três valores: o token Bearer, X-Tenant-ID: <Tenant-UUID> e o apiHost regional desse tenant. Não utilizar o host global como substituto de uma API REST de produto regional. Um host GraphQL específico de API é distinto. scope=token não autoriza operações funcionais; função, acesso ao tenant, licença e endpoint concreto também determinam a autorização.
Validação e recuperação controlada
Antes de escrever, chamar um endpoint de leitura inofensivo da API de destino e verificar idType esperado, UUID correto do tenant, formato de host permitido, JSON válido, paginação completa e objetos esperados. Depois confirmar um caso de teste expressamente proibido com 403, sem provocar uma alteração em produção. No fim da sessão, remover token de acesso, ID do tenant e host:
unset SOPHOS_ACCESS_TOKEN SOPHOS_CLIENT_ID SOPHOS_ID SOPHOS_ID_TYPE
unset SOPHOS_TENANT_ID SOPHOS_API_HOST WHOAMI
Com tenant ou host incorreto, parar imediatamente a execução, não enviar escritas e isolar os resultados guardados como dados potencialmente de outro tenant, ou eliminá-los conforme as regras. Reverter uma alteração funcional já efetuada com o rollback específico do produto documentado previamente; eliminar a credencial apenas revoga chamadas futuras e não desfaz alterações.
Resolver problemas do acesso comum à API
400: verificar codificação do formulário, campos obrigatórios e exatamentegrant_type=client_credentialsescope=token.401: verificar existência e expiração da credencial, conjunto de segredos mais recente, token e sintaxe Bearer; depois autenticar novamente uma vez.403: a identidade está autenticada, mas falta função, acesso ao tenant ou permissão específica da operação. Não atribuir Super Admin indiscriminadamente.404: verificar host global ou regional, versão da API e caminho; não procurar uma região por tentativas.429: respeitarRetry-Aftere repetir de forma limitada com backoff e jitter.5xx: guardar ID do pedido outrackingId, hora, método e caminho expurgado e repetir dentro de um limite; nunca copiar segredo ou token para um ticket de suporte.idTypeinesperado ouapiHostausente: não construir cabeçalhos de tenant. Verificar o tipo de credencial e a lista Partner/Enterprise de tenants integralmente paginada.
Testar a autenticação de forma controlada
O primeiro teste não é uma escrita em produção. Para o teste REST regional aqui apresentado, obter primeiro um token de acesso OAuth no endpoint Sophos Identity. Depois, whoami devolve identidade, tipo de conta e, nas credenciais de tenant, o host API regional; credenciais de parceiro e organização exigem a lista de tenants. Só depois efetuar uma leitura inofensiva no host API REST devolvido para esse tenant.
Não copiar um host API REST regional de um exemplo. Para este contrato, utilizar o URL fornecido por whoami ou pela lista de tenants; Search GraphQL utiliza o host distinto descrito acima. O ID do tenant e o ID da organização também não são intercambiáveis.
Para o teste, documentam-se pelo menos os seguintes casos:
- A autenticação com a nova identidade funciona.
- É devolvido o tenant esperado.
- As operações de leitura autorizadas funcionam.
- Uma operação não autorizada é rejeitada com
403 Forbidden. - O sistema de destino regista o teste de forma rastreável sem guardar o Client Secret.
Gerir a expiração e a rotação
A Sophos não envia qualquer aviso quando uma API Credential expira. Depois de expirar, já não pode ser utilizada para autenticação e é removida automaticamente do Sophos Fusion. Por isso, a monitorização tem de ser feita fora do Sophos Fusion.
Um processo de rotação correto utiliza uma sobreposição curta:
- Criar uma nova Credential com uma função idêntica ou mais limitada.
- Alterar a aplicação para o Client ID e o secret da nova Credential.
- Testar a autenticação e a função operacional.
- Eliminar a Credential antiga.
- Verificar a alteração no registo de secrets e na documentação operacional.
A Credential antiga não permanece ativa durante meses por precaução. Se uma aplicação suportar apenas um conjunto de secrets, planeia-se uma janela de manutenção.
Substituir antigos SIEM API Tokens
API Token Management é o método de autenticação anterior para a SIEM Integration API. A Sophos já não emite novos tokens nessa área nem prolonga a validade dos existentes. Os tokens existentes só funcionam até à respetiva expiração.
Uma integração que ainda os utilize não deve ser mantida até ao último dia. Inventariam-se o token, o sistema de destino, a data de expiração e os endpoints utilizados, cria-se uma API Credential adequada, altera-se a aplicação e verifica-se o fluxo de dados completo. O token antigo só é removido depois de uma verificação paralela bem-sucedida.
A mudança de um Legacy Token para API Credentials não é uma simples alteração de nome. A integração tem de suportar a autenticação OAuth, whoami, o Regional Host e o modelo de funções. Por isso, um SIEM Connector é configurado com base nas instruções atuais do fabricante e não através de um exemplo antigo de token.
Prestadores externos e acesso de terceiros
Para uma entidade externa, cria-se uma identidade Service Principal Read-Only própria, desde que bastem direitos de leitura. O Client ID e o secret são transmitidos através de um canal separado e cifrado. Define-se uma data final para o acesso, que é eliminado no fim do projeto.
Através da API, este acesso de terceiros pode ler, em particular, Alerts e Events, resultados do Account Health Check, detalhes de dispositivos e configurações de Policy. Read-Only impede a adição, alteração e eliminação no Sophos Fusion, mas não limita automaticamente os dados legíveis que a plataforma de terceiros consulta ou armazena efetivamente. Antes da autorização, clarificam-se contratualmente o âmbito dos dados, a finalidade da utilização, o local de armazenamento, a retenção e a eliminação.
A criação segue o caminho normal Global Settings > Access Control > API Credentials > Add Credential. No primeiro acesso, confirmam-se os termos de utilização e de proteção de dados, seleciona-se a função Service Principal Read-Only e copiam-se imediatamente e de forma segura o Client ID e o Client Secret, que só é apresentado uma vez. A transmissão é feita através de um canal cifrado aprovado, por exemplo o portal HTTPS do fornecedor, e não por e-mail ou no texto de um ticket.
O API Host não é copiado de uma tabela regional estática. A aplicação utiliza whoami para determinar o API Host válido para esse tenant específico. Desta forma, a integração continua corretamente documentada mesmo que a Sophos altere regiões ou endpoints. Assim que o fornecedor deixar de necessitar do acesso, a Credential é eliminada, revogando imediatamente a autorização de API.
Não é aceitável exportar a conta pessoal de Super Admin, utilizar uma identidade de API comum para vários clientes ou colocar um secret num ticket de suporte. O prestador também tem de indicar onde o secret é guardado, como é protegido e quando é eliminado.
Isolar erros de forma direcionada
401 Unauthorized
Na maioria dos casos, o Client ID, o secret, o Token Endpoint ou o OAuth Request estão incorretos. Uma Credential expirada e já removida também provoca este erro. Primeiro, verifica-se se a Credential ainda existe no Sophos Fusion e se a aplicação utiliza realmente o conjunto de secrets mais recente.
403 Forbidden
A autenticação foi bem-sucedida, mas a função não permite a ação. Em vez de atribuir imediatamente Super Admin, associa-se o endpoint de API necessário à função Service Principal adequada.
Token correto, região de dados errada
O token de acesso, por si só, não determina o host API de produto. Para uma API REST de produto com encaminhamento regional, a aplicação tem de utilizar o host regional fornecido por whoami ou pela lista de tenants; Search GraphQL tem o seu próprio contrato de destino. Um host fixo de outra região provoca erros ou consultas no limite errado da plataforma.
A integração falha sem aviso
Se o Sophos Fusion não mostrar um Alert aberto, verificam-se a data de expiração, a última chamada de API bem-sucedida e a versão do secret no sistema de destino. A monitorização da expiração pertence à monitorização externa.
Revisão regular
Pelo menos trimestralmente, verificam-se o nome, o responsável, a função, a última utilização, a expiração e o sistema de destino de cada Credential. As identidades não atribuíveis ou não utilizadas são eliminadas. Se houver suspeita de fuga de um secret, a Credential afetada é imediatamente eliminada e substituída por uma nova. Em seguida, analisam-se os registos do sistema de destino e da integração à procura de chamadas de API anómalas.
Os direitos pessoais de administrador são verificados separadamente de acordo com Atribuir corretamente funções administrativas no Sophos Fusion. As API Credentials não substituem o MFA nem um acesso pessoal e rastreável de administrador.