Securing Microservices with SPIFFE and Spring Security
Microservices architectures introduce new security challenges, particularly in workload authentication and identity management. SPIFFE (Secure Production Identity Framework for Everyone) provides a standardized way to issue and verify identities in dynamic environments. Combined with Spring Security, we can build a robust authentication mechanism for microservices.
This article explores how to integrate SPIFFE with Spring Security to secure microservice communications.
1. What is SPIFFE?
SPIFFE is an open-source framework that provides:
- Secure identities for workloads (services, containers, VMs).
- SPIFFE Verifiable Identity Document (SVID) as a cryptographically verifiable identity.
- SPIRE (SPIFFE Runtime Environment) for issuing and managing identities.
1.1 Key Components:
- SPIFFE ID – A unique identifier (e.g.,
spiffe://example.org/myservice). - SVID – A signed identity document (X.509 or JWT).
- SPIRE – The reference implementation for managing identities.
2. Why Use SPIFFE with Spring Security?
- Zero Trust Security: No implicit trust between services; every request must be authenticated.
- Dynamic Environments: Works seamlessly in Kubernetes, VMs, and cloud-native setups.
- Standardized Identity: Replaces ad-hoc solutions like API keys or static certificates.
3. Integrating SPIFFE with Spring Security
Step 1: Set Up SPIRE Server and Agents
Before integrating with Spring, deploy SPIRE to issue SVIDs:
# Example SPIRE server in Kubernetes kubectl apply -f https://raw.githubusercontent.com/spiffe/spire/main/examples/k8s/server.yaml # SPIRE agent kubectl apply -f https://raw.githubusercontent.com/spiffe/spire/main/examples/k8s/agent.yaml
Step 2: Configure Spring Security for SPIFFE
Spring Security can validate X.509 SVIDs from SPIFFE.
Add Dependencies (pom.xml):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
Configure application.yml:
server:
ssl:
enabled: true
key-store: /path/to/keystore.p12
key-store-password: changeit
trust-store: /path/to/truststore.jks
trust-store-password: changeit
client-auth: need # Enforces mTLS
Custom Security Configuration:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)")
.userDetailsService(userDetailsService());
}
@Bean
public UserDetailsService userDetailsService() {
return username -> {
if (username.equals("spiffe://example.org/myservice")) {
return new User(username, "", AuthorityUtils.createAuthorityList("ROLE_SERVICE"));
}
throw new UsernameNotFoundException("Service not authorized");
};
}
}
Step 3: Validate SPIFFE IDs in Requests
Use Spring AOP or Filters to verify SPIFFE IDs in headers or mTLS certificates.
@Component
public class SpiffeAuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
if (certs != null && certs.length > 0) {
String spiffeId = extractSpiffeId(certs[0]);
if (!spiffeId.startsWith("spiffe://trusted-domain/")) {
response.sendError(403, "Unauthorized SPIFFE ID");
return;
}
}
filterChain.doFilter(request, response);
}
private String extractSpiffeId(X509Certificate cert) {
// Parse SPIFFE ID from SAN (Subject Alternative Name)
return cert.getSubjectAlternativeNames()
.stream()
.filter(san -> san.get(0).equals(6)) // URI type in SAN
.map(san -> (String) san.get(1))
.findFirst()
.orElseThrow(() -> new RuntimeException("No SPIFFE ID found"));
}
}
4. Example: Securing a Spring Boot Microservice
A full example is available in:
5. Best Practices
- Rotate SVIDs Frequently: Use SPIRE’s automatic rotation.
- Limit Trust Domains: Only accept SPIFFE IDs from trusted issuers.
- Audit Logging: Log all authentication attempts.
6. Conclusion
By combining SPIFFE for workload identity and Spring Security for authentication, we can enforce Zero Trust principles in microservices. This approach eliminates static credentials and ensures secure, verifiable communication.




