Cenário: Solicitações HTTP assinadas (SHR)

Use solicitações HTTP assinadas (SHR) com o SDK Microsoft Entra para ID do Agente para implementar a segurança do token PoP (prova de posse). Os tokens PoP associam tokens criptograficamente a uma chave pública, impedindo o roubo de tokens e os ataques de reprodução ao chamar APIs downstream.

Pré-requisitos

  • Uma conta Azure com uma assinatura ativa. Crie uma conta gratuitamente.
  • Microsoft Entra SDK para AgentID implantado e em execução com suporte de prova de posse habilitado. Consulte o Guia de Instalação para obter instruções de instalação.
  • Par de chaves RSA – Gerar um par de chaves pública/privada para assinatura criptográfica. A chave pública é configurada no SDK, enquanto a chave privada permanece segura em seu aplicativo.
  • API downstream com suporte a tokens PoP – a API de destino deve validar tokens de prova de posse e verificar assinaturas usando a chave pública.
  • Permissões apropriadas no Microsoft Entra ID - sua conta deve ter permissões para registrar aplicativos e definir configurações de PoP.

Gerar par de chaves

Antes de implementar tokens PoP, gere um par de chaves RSA. A chave privada permanece em seu aplicativo para solicitações de assinatura, enquanto a chave pública está configurada no SDK Microsoft Entra para AgentID:

# Generate RSA private key
openssl genrsa -out private.pem 2048

# Extract public key
openssl rsa -in private.pem -pubout -out public.pem

# Base64 encode public key for configuration
base64 -w 0 public.pem > public.pem.b64

# View base64-encoded key
cat public.pem.b64

Configuração

Configure o SDK do Microsoft Entra para a identificação do agente com sua chave pública RSA e as configurações da API downstream. Armazene chaves confidenciais em repositórios de configuração seguros:

Configuração do SDK

apiVersion: v1
kind: Secret
metadata:
  name: shr-keys
type: Opaque
data:
  public-key: <base64-encoded-public-key>

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: sidecar-config
data:
  # ... other configuration ...
  DownstreamApis__SecureApi__BaseUrl: "https://api.contoso.com"
  DownstreamApis__SecureApi__Scopes: "api://secureapi/.default"
  DownstreamApis__SecureApi__AcquireTokenOptions__PopPublicKey: "<base64-public-key>"

Exemplos de uso

Para usar tokens PoP em seu aplicativo, solicite um token PoP do SDK do Microsoft Entra para ID do Agente especificando sua chave pública e, em seguida, inclua-o em solicitações de API:

TypeScript

// Request PoP token
async function getPopToken(incomingToken: string, publicKey: string): Promise<string> {
  const sidecarUrl = process.env.SIDECAR_URL!;
  
  const response = await fetch(
    `${sidecarUrl}/AuthorizationHeader/SecureApi?` +
    `optionsOverride.AcquireTokenOptions.PopPublicKey=${encodeURIComponent(publicKey)}`,
    {
      headers: {
        'Authorization': incomingToken
      }
    }
  );
  
  const data = await response.json();
  return data.authorizationHeader; // Returns "PoP <pop-token>"
}

// Use PoP token with signed request
async function callSecureApi(incomingToken: string, publicKey: string, privateKey: string) {
  // Get PoP token from the SDK
  const popToken = await getPopToken(incomingToken, publicKey);
  
  // Make request to API with PoP token
  const response = await fetch('https://api.contoso.com/secure/data', {
    headers: {
      'Authorization': popToken
    }
  });
  
  return await response.json();
}

Python

import base64
import requests
import os

def get_pop_token(incoming_token: str, public_key: str) -> str:
    """Get a PoP token from the SDK."""
    sidecar_url = os.getenv('SIDECAR_URL', 'http://localhost:5000')
    
    response = requests.get(
        f"{sidecar_url}/AuthorizationHeader/SecureApi",
        params={
            'optionsOverride.AcquireTokenOptions.PopPublicKey': public_key
        },
        headers={'Authorization': incoming_token}
    )
    
    response.raise_for_status()
    data = response.json()
    return data['authorizationHeader']

def call_secure_api(incoming_token: str, public_key_b64: str):
    """Call API with PoP token."""
    pop_token = get_pop_token(incoming_token, public_key_b64)
    
    response = requests.get(
        'https://api.contoso.com/secure/data',
        headers={'Authorization': pop_token}
    )
    
    return response.json()

SHR por solicitação

Você pode substituir as configurações de PoP por solicitação especificando chaves públicas diferentes para diferentes APIs ou escopos:

// Enable SHR for specific request
const response = await fetch(
  `${sidecarUrl}/AuthorizationHeader/Graph?` +
  `optionsOverride.AcquireTokenOptions.PopPublicKey=${encodeURIComponent(publicKey)}`,
  {
    headers: { 'Authorization': incomingToken }
  }
);

Gerenciamento de chaves criptográficas

Implemente práticas de gerenciamento de chaves seguras para proteger suas chaves RSA e habilite a rotação de chaves quando necessário:

Armazenamento seguro de chaves

Armazene chaves RSA com segurança usando segredos do Kubernetes:

# Store keys in Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: shr-keys
type: Opaque
data:
  public-key: <base64-encoded-public-key>
  private-key: <base64-encoded-private-key>

---
# Mount keys in application
volumes:
- name: shr-keys
  secret:
    secretName: shr-keys
    defaultMode: 0400

containers:
- name: app
  volumeMounts:
  - name: shr-keys
    mountPath: /keys
    readOnly: true

Alteração de chaves

Gire as chaves de assinatura periodicamente usando o OpenSSL e as configurações de atualização:

#!/bin/bash
# Script to rotate SHR keys

# Generate new key pair
openssl genrsa -out private-new.pem 2048
openssl rsa -in private-new.pem -pubout -out public-new.pem
base64 -w 0 public-new.pem > public-new.pem.b64

# Update Kubernetes secret
kubectl create secret generic shr-keys-new \
  --from-file=public-key=public-new.pem.b64 \
  --from-file=private-key=private-new.pem \
  --dry-run=client -o yaml | kubectl apply -f -

# Update deployment to use new keys
kubectl rollout restart deployment myapp

Validando tokens PoP

A API downstream deve validar o token PoP para garantir que ele esteja assinado corretamente e associado à solicitação:

  1. Verificar a assinatura JWT usando a chave pública extraída do token
  2. Validar declarações JWT padrão (emissor, público, expiração)
  3. Verifique se a cnf declaração contém a chave pública esperada
  4. Valide se a assinatura da solicitação HTTP corresponde usando a chave da declaração cnf

Benefícios

Implementar solicitações HTTP assinadas com tokens de prova de posse fornece várias vantagens de segurança:

  • Associação de token: cada token está vinculado criptograficamente a uma chave pública específica, impedindo o uso não autorizado mesmo se interceptado.
  • Prevenção de reprodução: um invasor não pode reproduzir um token capturado sem possuir a chave privada correspondente.
  • Segurança aprimorada: fornece proteção contra roubo de token, especialmente importante para operações confidenciais e ambientes de alta segurança.
  • Prova de posse: prova criptograficamente que o cliente contém a chave privada correspondente ao token.

Práticas recomendadas

Ao implementar solicitações HTTP assinadas, siga estas práticas para manter a segurança e a confiabilidade operacional:

  • Chaves Privadas Seguras: nunca exponha chaves privadas em logs, arquivos de configuração ou repositórios de código. Armazene-os com segurança usando cofres de chaves ou sistemas de gerenciamento de configuração.
  • Rotacione chaves regularmente: Implemente um cronograma de rotação de chaves para minimizar o impacto de um possível comprometimento de chave. Atualize o SDK e as APIs downstream durante a rotação.
  • Use Per-API Chaves: use pares de chaves diferentes para APIs ou zonas de segurança diferentes para limitar o impacto se uma chave estiver comprometida.
  • Monitorar o uso: audite e monitore o uso de token PoP para detectar padrões suspeitos ou tentativas de acesso não autorizado.
  • Teste minuciosamente: verifique se a validação do token PoP funciona corretamente antes de implantar na produção, garantindo que as verificações de validação de assinatura e de associação de solicitação sejam aprovadas.