Gymterview
senior

Как обеспечить безопасность межсервисного взаимодействия?

Безопасность в микросервисной архитектуре — комплексная задача, включающая аутентификацию (OAuth2/JWT), шифрование (mTLS), управление секретами (Vault) и сетевые политики (Network Policies).

Пример
Клиент → API Gateway → Проверка JWT → Микросервис
                            │
                    ┌───────▼───────┐
                    │ Keycloak /    │
                    │ Spring Auth   │
                    │ Server        │
                    └───────────────┘
1. OAuth2/JWT: конфигурация Resource Server
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/health/**").permitAll()
                .requestMatchers("/api/payments/**").hasAuthority("SCOPE_payments")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthConverter()))
            )
            .build();
    }

    private JwtAuthenticationConverter jwtAuthConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(jwt -> {
            Map<String, Object> realmAccess = jwt.getClaim("realm_access");
            List<String> roles = (List<String>) realmAccess.get("roles");
            return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                .collect(Collectors.toList());
        });
        return converter;
    }
}

2. mTLS (Mutual TLS) – взаимная аутентификация сервисов

При mTLS оба участника соединения предъявляют сертификаты. Обычно реализуется через Service Mesh (Istio):

Пример
# Istio PeerAuthentication — требовать mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: banking
spec:
  mtls:
    mode: STRICT

3. Передача контекста пользователя между сервисами

Пример
@Component
public class AuthTokenInterceptor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        String token = SecurityContextHolder.getContext().getAuthentication()
            .getCredentials().toString();
        request.getHeaders().setBearerAuth(token);
        return execution.execute(request, body);
    }
}

4. Защита секретов

  • Хранение в HashiCorp Vault (не в переменных окружения и не в конфигурационных файлах).
  • Ротация секретов (Vault поддерживает автоматическую ротацию паролей БД).
  • Шифрование чувствительных данных в Kafka-сообщениях.

5. Сетевые политики (Network Policies в Kubernetes)

Пример
# Разрешить трафик к payment-service только от api-gateway и order-service
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: payment-service-policy
spec:
  podSelector:
    matchLabels:
      app: payment-service
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-gateway
        - podSelector:
            matchLabels:
              app: order-service
      ports:
        - port: 8080

6. Валидация входных данных

Каждый сервис должен сам валидировать входные данные, не полагаясь на то, что вызывающий сервис уже провёл валидацию.

На собеседовании: покажите многослойную защиту: JWT на Gateway, mTLS между сервисами, Vault для секретов, Network Policies для сетевой изоляции. Частая ошибка — думать, что JWT-валидации на Gateway достаточно и внутренние сервисы не нужно защищать.