Udostępnij przez


Scenariusz: podpisane żądania HTTP (SHR)

Użyj podpisanych żądań HTTP (SHR) w połączeniu z Microsoft Entra SDK dla AgentID, aby zaimplementować zabezpieczenia tokenu proof-of-possession (PoP). Tokeny PoP kryptograficznie łączą się z kluczem publicznym, zapobiegając kradzieży tokenów i atakom odtworzeniowym podczas wywoływania interfejsów API niższych warstw.

Wymagania wstępne

  • Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
  • Zestaw Microsoft Entra SDK dla AgentID wdrożony i uruchomiony z włączoną obsługą dowodu posiadania. Aby uzyskać instrukcje dotyczące instalacji, zobacz Przewodnik instalacji.
  • Para kluczy RSA — generuj parę kluczy publicznych/prywatnych na potrzeby podpisywania kryptograficznego. Klucz publiczny jest skonfigurowany w zestawie SDK, a klucz prywatny pozostaje bezpieczny w aplikacji.
  • Interfejs API podrzędny obsługujący tokeny poP — docelowy interfejs API musi weryfikować tokeny dowodu posiadania i weryfikować podpisy przy użyciu klucza publicznego.
  • Odpowiednie uprawnienia w usłudze Microsoft Entra ID — Twoje konto musi mieć uprawnienia do rejestrowania aplikacji i konfigurowania ustawień poP.

Generowanie pary kluczy

Przed zaimplementowaniem tokenów PoP wygeneruj parę kluczy RSA. Klucz prywatny pozostaje w aplikacji do podpisywania żądań, podczas gdy klucz publiczny jest skonfigurowany w Microsoft Entra SDK dla identyfikatora 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

Konfiguracja

Skonfiguruj zestaw Microsoft Entra SDK dla identyfikatora AgentID przy użyciu klucza publicznego RSA i ustawień podrzędnego interfejsu API. Przechowywanie poufnych kluczy w bezpiecznych magazynach konfiguracji:

Konfiguracja zestawu 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>"

Przykłady użycia

Aby użyć tokenów poP w aplikacji, zażądaj tokenu PoP z zestawu Microsoft Entra SDK for AgentID, określając klucz publiczny, a następnie uwzględnij go w żądaniach interfejsu 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 na żądanie

Ustawienia poP można zastąpić dla poszczególnych żądań, określając różne klucze publiczne dla różnych interfejsów API lub zakresów:

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

Zarządzanie kluczami

Zaimplementuj bezpieczne rozwiązania w zakresie zarządzania kluczami, aby chronić klucze RSA i włączać rotację kluczy w razie potrzeby:

Bezpieczny magazyn kluczy

Bezpieczne przechowywanie kluczy RSA przy użyciu Sekretów 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

Rotacja kluczy

Okresowo obracaj klucze podpisywania przy użyciu biblioteki OpenSSL i aktualizuj konfiguracje:

#!/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

Weryfikowanie tokenów poP

Interfejs API podrzędny musi zweryfikować token poP, aby upewnić się, że jest on poprawnie podpisany i powiązany z żądaniem:

  1. Weryfikowanie podpisu JWT przy użyciu klucza publicznego wyodrębnionego z tokenu
  2. Weryfikowanie standardowych oświadczeń JWT (wystawca, odbiorcy, wygaśnięcie)
  3. Sprawdź, cnf czy oświadczenie zawiera oczekiwany klucz publiczny
  4. Sprawdź, czy podpis żądania HTTP jest zgodny z kluczem cnf z oświadczenia

Korzyści

Implementowanie podpisanych żądań HTTP przy użyciu tokenów dowodowych posiadania zapewnia kilka zalet zabezpieczeń:

  • Powiązanie tokenu: każdy token jest kryptograficznie powiązany z określonym kluczem publicznym, uniemożliwiając nieautoryzowane użycie nawet w przypadku przechwycenia.
  • Zapobieganie odtwarzaniu: osoba atakująca nie może odtworzyć przechwyconego tokenu bez posiadania odpowiedniego klucza prywatnego.
  • Zwiększone zabezpieczenia: zapewnia ochronę przed kradzieżą tokenów, szczególnie ważną dla poufnych operacji i środowisk o wysokim poziomie zabezpieczeń.
  • Dowód posiadania: Kryptograficznie potwierdza, że klient przechowuje klucz prywatny odpowiadający tokenowi.

Najlepsze rozwiązania

Podczas implementowania podpisanych żądań HTTP postępuj zgodnie z tymi rozwiązaniami, aby zachować niezawodność zabezpieczeń i działania:

  • Bezpieczne klucze prywatne: nigdy nie ujawniaj kluczy prywatnych w dziennikach, plikach konfiguracji lub repozytoriach kodu. Przechowuj je bezpiecznie przy użyciu magazynów kluczy lub systemów zarządzania konfiguracją.
  • Regularnie rotuj klucze: wdroż harmonogram rotacji kluczy, aby zminimalizować wpływ potencjalnego naruszenia klucza. Zaktualizuj zarówno zestaw SDK, jak i podrzędne interfejsy API podczas rotacji.
  • Użyj kluczy Per-API: użyj różnych par kluczy dla różnych interfejsów API lub stref zabezpieczeń, aby ograniczyć wpływ, jeśli jeden klucz zostanie naruszony.
  • Monitorowanie użycia: przeprowadzaj audyt i monitorowanie użycia tokenów PoP w celu wykrycia podejrzanych wzorców lub nieautoryzowanych prób dostępu.
  • Dokładnie przetestuj: Zweryfikuj, czy weryfikacja tokenu PoP działa prawidłowo przed wdrożeniem do środowiska produkcyjnego, upewniając się, że zarówno weryfikacja podpisu, jak i kontrola powiązania żądań przechodzą pomyślnie.

Dalsze kroki

Po zaimplementowaniu tokenów PoP