Перейти к содержимому
К программе курса
Распределенная трассировка: от основ до production
16 / 1889%

Security & Privacy: PII redaction и авторизация

50 минут

Security & Privacy: PII redaction и авторизация

Проблема: чувствительные данные в traces

Реальный инцидент:

// Trace в Jaeger (публично доступен всей команде)
{
  "trace_id": "a1b2c3d4",
  "spans": [
    {
      "name": "POST /api/users",
      "attributes": {
        "user.email": "alice@company.com",
        "user.phone": "+1-555-0123",
        "user.ssn": "123-45-6789",
        "credit_card": "4111-1111-1111-1111",
        "http.request.header.authorization": "Bearer eyJ..."
      }
    }
  ]
}

Проблемы:

  • ❌ PII (personally identifiable information)
  • ❌ Credentials (токены, пароли)
  • ❌ Business secrets
  • ❌ GDPR/CCPA violation

PII Redaction: OTel Collector

Лучший подход: Удалять PII в Collector (до попадания в storage).

Attributes Processor: удаление атрибутов

processors:
  attributes:
    actions:
      # Удаление PII
      - key: user.email
        action: delete
      - key: user.phone
        action: delete
      - key: user.ssn
        action: delete
 
      # Удаление credentials
      - key: http.request.header.authorization
        action: delete
      - key: http.request.header.cookie
        action: delete
 
      # Удаление business secrets
      - key: api_key
        action: delete

Redaction Processor: маскировка данных

processors:
  redaction:
    # Маскировка email
    allow_all_keys: false
    blocked_values:
      - "email.*"
      - ".*@.*"  # Regex для email
 
    # Маскировка IP addresses
    - "\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b"
 
    # Маскировка credit cards
    - "\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b"

Результат:

// До
{
  "user.email": "alice@company.com",
  "client_ip": "192.168.1.100"
}
 
// После
{
  "user.email": "***REDACTED***",
  "client_ip": "***REDACTED***"
}

SDK-Level Redaction

Зачем: Предотвратить попадание PII в spans вообще.

const { trace } = require("@opentelemetry/api");
 
function redactEmail(email) {
  if (!email) return null;
  const [user, domain] = email.split("@");
  return `${user[0]}***@${domain}`;
}
 
app.post("/users", (req, res) => {
  const span = trace.getActiveSpan();
 
  // ❌ Плохо
  span.setAttribute("user.email", req.body.email);
 
  // ✅ Хорошо
  span.setAttribute("user.email_redacted", redactEmail(req.body.email));
  // Result: "a***@company.com"
});

GDPR Compliance

Right to be Forgotten

Проблема: Пользователь запросил удаление данных, но его email в traces.

Решение 1: Не логировать PII вообще

// Вместо user.email → user.id (хэш)
span.setAttribute("user.id", hashUserId(email)); // SHA-256

Решение 2: TTL для traces

# Tempo config: автоудаление через 7 дней
storage:
  trace:
    backend: local
    local:
      path: /tmp/tempo/traces
    block:
      retention: 168h # 7 days

Encryption in Transit (TLS)

Проблема: Traces передаются по сети незашифрованными.

Решение: TLS для всех connections.

App → Collector (OTLP over TLS)

const {
  OTLPTraceExporter,
} = require("@opentelemetry/exporter-trace-otlp-grpc");
const grpc = require("@grpc/grpc-js");
const fs = require("fs");
 
const exporter = new OTLPTraceExporter({
  url: "https://otel-collector:4317",
  credentials: grpc.credentials.createSsl(
    fs.readFileSync("./ca.crt"), // CA certificate
    fs.readFileSync("./client.key"), // Client key
    fs.readFileSync("./client.crt") // Client cert
  ),
});

Collector → Jaeger (TLS)

exporters:
  jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: false
      ca_file: /etc/ssl/ca.crt
      cert_file: /etc/ssl/client.crt
      key_file: /etc/ssl/client.key

Authorization: Role-Based Access Control

Проблема: Любой сотрудник видит все traces (включая PII).

Решение: Ограничить доступ к traces по ролям.

Jaeger + OAuth2

# Jaeger query service with OAuth
jaeger-query:
  image: jaegertracing/jaeger-query:latest
  environment:
    - QUERY_BASE_PATH=/jaeger
  command:
    - --query.bearer-token-propagation=true
    - --query.ui-config=/etc/jaeger/ui-config.json
 
# OAuth proxy (например, oauth2-proxy)
oauth2-proxy:
  image: quay.io/oauth2-proxy/oauth2-proxy
  command:
    - --upstream=http://jaeger-query:16686
    - --email-domain=company.com
    - --cookie-secret=***
    - --provider=google
  ports:
    - "4180:4180"

Результат: Только авторизованные пользователи видят Jaeger UI.


Audit Logging

Зачем: Знать, кто и когда смотрел traces.

# OTel Collector: audit log processor
processors:
  audit:
    log_file: /var/log/otel-collector-audit.log
    include:
      - span_attributes
      - resource_attributes

Audit log:

{
  "timestamp": "2024-01-15T14:32:15Z",
  "action": "trace_exported",
  "trace_id": "a1b2c3d4",
  "user": "alice@company.com",
  "service": "api-gateway"
}

Multi-tenancy Isolation

Проблема: В shared Jaeger instance видны traces всех tenant'ов.

Решение 1: Отдельный Jaeger на tenant

Tenant A → Collector A → Jaeger A
Tenant B → Collector B → Jaeger B

Решение 2: Tenant ID в traces + фильтрация

// Добавляем tenant_id в каждый span
span.setAttribute("tenant.id", getTenantId(req));
 
// В Jaeger UI фильтруем:
// Tags: tenant.id=tenant-a

Security Best Practices Checklist

✅ Data Protection

  • PII redaction в Collector
  • Credentials не логируются
  • TLS enabled для всех connections
  • Encryption at rest (если требуется)
  • Data retention policy (7-30 days)

✅ Access Control

  • Authentication для Jaeger UI
  • RBAC настроен
  • Audit logging включён
  • Multi-tenancy изолировано

✅ Compliance

  • GDPR Right to be Forgotten
  • CCPA compliance
  • SOC2 audit trail
  • HIPAA (если медицинские данные)

Следующий урок

Финальный урок: Troubleshooting и Best Practices — решение типичных проблем и checklist для production.

Теперь вы можете безопасно использовать трассировку с соблюдением GDPR и защитой PII!

Security & Privacy: PII redaction и авторизация — Распределенная трассировка: от основ до production — Potapov.me