Как обезопасить взаимодействие микросервисов при использовании REST или gRPC
golanggRPCRESTбезопасностьмикросервисы
Что проверяют
Понимаете ли вы разницу между защитой канала и проверкой того, кто и что вызывает. Интервьюер ждёт модели «внутренней сети не доверяем» и конкретики на Go. Следом обычно спрашивают, как сервис подтверждает свою личность и как пользователь пробрасывается через цепочку вызовов.
Как отвечать
Разложите ответ по уровням:
- транспорт: TLS везде, включая внутреннюю сеть, а для межсервисных вызовов mTLS, где сертификат предъявляют обе стороны. В Go это
tls.ConfigсClientAuth: tls.RequireAndVerifyClientCertиClientCAs, для gRPCgrpc.Creds(credentials.NewTLS(cfg)),MinVersionне ниже TLS 1.2; - сертификаты: руками их не ротируют. Service mesh (Istio, Linkerd) даёт mTLS прозрачно, SPIFFE/SPIRE выдаёт короткоживущие идентичности, cert-manager обновляет сертификаты в Kubernetes;
- аутентификация: пользовательский JWT или токен OAuth 2.0 client credentials для сервиса. Проверяются подпись,
exp,aud,iss, алгоритм фиксирован на стороне сервера. В gRPC это interceptor, в REST middleware; - авторизация: не «пускать всех с валидным сертификатом», а явный список: сервис A может вызывать только
GetOrderсервиса B. Удобно выносить в OPA или политики mesh; - входные данные: даже от соседнего сервиса. Лимит размера (
http.MaxBytesReader,grpc.MaxRecvMsgSize), валидация, таймауты черезcontextиReadHeaderTimeoutуhttp.Server; - сеть и секреты: NetworkPolicy в Kubernetes, выключенный gRPC reflection в проде, ключи в Vault, а не в образе, логи без токенов.
Где спотыкаются
Говорят «внутри периметра все свои» и оставляют между сервисами голый HTTP. Один скомпрометированный под получает доступ ко всему.
Проверяют JWT без aud или принимают алгоритм из заголовка токена. Токен, выданный для одного сервиса, начинает работать в другом.
Путают TLS и авторизацию: mTLS доказывает, что вызывает сервис A, но не отвечает, можно ли ему это делать.