google-site-verification: google61fe8ba583a51912.html
SPIFFE Federation in Java: Secure Service Identity Across Trust Domains

SPIFFE (Secure Production Identity Framework For Everyone) and its companion specification SPIFFA provide a standardized approach to service identity in distributed systems. Federation extends this capability across organizational boundaries, enabling secure service-to-service communication between different trust domains.

What is SPIFFE Federation?

SPIFFE Federation allows SPIFFE identities from one trust domain to be recognized and trusted by another trust domain. For Java applications, this means your services can securely communicate across organizational boundaries, cloud providers, or Kubernetes clusters without managing complex certificate chains or shared secrets.

Key Concepts for Java Developers

  1. SPIFFE ID: A unique identifier for a workload (e.g., spiffe://prod.example.com/order-service)
  2. SVID (SPIFFE Verifiable Identity Document): A cryptographically-verified identity document (X.509 or JWT)
  3. Trust Domain: A security boundary (e.g., prod.example.com)
  4. Federation: Establishing trust between different trust domains

Java SPIFFE Implementation with SPIRE

Maven Dependencies:

<dependencies> <dependency> <groupId>io.spiffe</groupId> <artifactId>spiffe-core</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>io.spiffe</groupId> <artifactId>spiffe-provider</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>io.spiffe</groupId> <artifactId>spiffe-spring-boot-starter</artifactId> <version>1.1.0</version> </dependency> </dependencies>

Federation Configuration

bundle-endpoints.yaml:

federates_with: "acme-corp.com": bundle_endpoint: url: "https://spire.acme-corp.com:8443/bundle-endpoint" authentication: aws_iid: region: "us-west-2" access_key_id: "AKIAIOSFODNN7EXAMPLE" secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" "partner-org.io": bundle_endpoint: url: "https://spire.partner-org.io:8443/bundle-endpoint" authentication: spiffe: endpoint_spiffe_id: "spiffe://partner-org.io/federation-endpoint"

Java Service with SPIFFE Federation

FederatedServiceConfiguration.java:

@Configuration @EnableSpiffe public class FederatedServiceConfiguration { @Value("${spiffe.trust.domain:prod.example.com}") private String trustDomain; @Bean public SpiffeClient spiffeClient() throws Exception { return SpiffeClient.newBuilder() .trustDomain(trustDomain) .federatedTrustDomains("acme-corp.com", "partner-org.io") .spiffeSocketPath("/tmp/spire-agent/public/api.sock") .build(); } @Bean public WorkloadApiClient workloadApiClient() { return new DefaultWorkloadApiClient("/tmp/spire-agent/public/api.sock"); } }

FederatedOrderService.java:

@Service public class FederatedOrderService { private final SpiffeClient spiffeClient; private final RestTemplate restTemplate; public FederatedOrderService(SpiffeClient spiffeClient) { this.spiffeClient = spiffeClient; this.restTemplate = createFederatedRestTemplate(); } private RestTemplate createFederatedRestTemplate() { try { SslContext sslContext = GrpcSslContexts.forClient() .trustManager(spiffeClient.getFederatedBundle()) .keyManager(spiffeClient.getPrivateKey(), spiffeClient.getCertificateChain()) .build(); return RestTemplateBuilder.builder() .sslContext(sslContext) .build(); } catch (Exception e) { throw new RuntimeException("Failed to create federated REST template", e); } } public Order processCrossDomainOrder(OrderRequest request) { // Call service in federated trust domain String acmeInventoryUrl = "https://inventory.acme-corp.com/api/stock"; ResponseEntity<StockInfo> response = restTemplate.exchange( acmeInventoryUrl, HttpMethod.POST, createFederatedRequest(request), StockInfo.class ); return processOrderWithStockInfo(request, response.getBody()); } private HttpEntity<OrderRequest> createFederatedRequest(OrderRequest request) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); try { // Add SPIFFE identity header for JWT authentication String jwtToken = spiffeClient.fetchJwtToken( "spiffe://acme-corp.com/inventory-service", Arrays.asList("inventory-read", "order-write") ); headers.set("Authorization", "Bearer " + jwtToken); } catch (Exception e) { throw new RuntimeException("Failed to create federated authentication", e); } return new HttpEntity<>(request, headers); } }

Spring Security with SPIFFE Federation

SpiffeSecurityConfig.java:

@Configuration @EnableWebSecurity public class SpiffeSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz -> authz .requestMatchers("/api/internal/**").hasAuthority("SPIFFE://prod.example.com/internal-service") .requestMatchers("/api/partner/**").hasAuthority("SPIFFE://acme-corp.com/partner-service") .requestMatchers("/api/public/**").permitAll() .anyRequest().authenticated() ) .x509(x509 -> x509 .subjectPrincipalRegex("CN=(.*?)(?:,|$)") .authenticationUserDetailsService(spiffeUserDetailsService()) ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .decoder(spiffeJwtDecoder()) ) ); return http.build(); } @Bean public UserDetailsService spiffeUserDetailsService() { return new SpiffeUserDetailsService(); } @Bean public JwtDecoder spiffeJwtDecoder() { return new SpiffeFederatedJwtDecoder(); } } @Component class SpiffeUserDetailsService implements UserDetailsService { private final SpiffeClient spiffeClient; public SpiffeUserDetailsService(SpiffeClient spiffeClient) { this.spiffeClient = spiffeClient; } @Override public UserDetails loadUserByUsername(String spiffeId) throws UsernameNotFoundException { try { // Validate the SPIFFE ID is from a federated trust domain if (spiffeClient.isFederatedIdentity(spiffeId)) { return new FederatedServiceUser(spiffeId, getAuthoritiesForSpiffeId(spiffeId)); } throw new UsernameNotFoundException("Not a federated SPIFFE ID: " + spiffeId); } catch (Exception e) { throw new UsernameNotFoundException("Invalid SPIFFE ID: " + spiffeId, e); } } private List<SimpleGrantedAuthority> getAuthoritiesForSpiffeId(String spiffeId) { // Map SPIFFE ID to Spring Security authorities // Example: spiffe://acme-corp.com/inventory-service -> ROLE_ACME_INVENTORY String authority = "ROLE_" + spiffeId.replace("spiffe://", "").replace("/", "_").toUpperCase(); return Arrays.asList(new SimpleGrantedAuthority(authority)); } }

gRPC with SPIFFE Federation

FederatedGrpcConfiguration.java:

@Configuration public class FederatedGrpcConfiguration { @Bean public Server server(SpiffeClient spiffeClient) throws IOException { return ServerBuilder.forPort(8080) .addService(new OrderServiceImpl()) .useTransportSecurity( spiffeClient.getCertificateChain(), spiffeClient.getPrivateKey() ) .build(); } @Bean public ManagedChannel federatedChannel(SpiffeClient spiffeClient) { try { SslContext sslContext = GrpcSslContexts.forClient() .trustManager(spiffeClient.getFederatedBundle()) // Includes federated bundles .keyManager(spiffeClient.getPrivateKey(), spiffeClient.getCertificateChain()) .build(); return Grpc.newChannelBuilder("inventory.acme-corp.com:50051", NettyChannelBuilder.usingNegotiator(sslContext)) .build(); } catch (Exception e) { throw new RuntimeException("Failed to create federated gRPC channel", e); } } }

Kubernetes Deployment with SPIRE

spire-agent-configmap.yaml:

apiVersion: v1 kind: ConfigMap metadata: name: spire-agent-config namespace: spire data: agent.conf: | agent { data_dir = "/run/spire" log_level = "DEBUG" server_address = "spire-server" server_port = "8081" socket_path = "/run/spire/sockets/agent.sock" trust_domain = "prod.example.com" federation { bundle_endpoint { address = "0.0.0.0" port = "8443" } federates_with = "acme-corp.com" federates_with = "partner-org.io" } }

java-service-spiffe.yaml:

apiVersion: apps/v1 kind: Deployment metadata: name: order-service labels: app: order-service spec: replicas: 3 selector: matchLabels: app: order-service template: metadata: labels: app: order-service spec: serviceAccountName: order-service-account containers: - name: order-service image: order-service:latest ports: - containerPort: 8080 env: - name: SPIFFE_ENDPOINT_SOCKET value: "/run/spire/sockets/agent.sock" - name: TRUST_DOMAINS value: "prod.example.com,acme-corp.com,partner-org.io" volumeMounts: - name: spire-agent-socket mountPath: /run/spire/sockets readOnly: true livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 volumes: - name: spire-agent-socket hostPath: path: /run/spire/sockets type: DirectoryOrCreate

Monitoring and Observability

SpiffeMetricsConfiguration.java:

@Component public class SpiffeMetricsConfiguration { private final MeterRegistry meterRegistry; private final SpiffeClient spiffeClient; public SpiffeMetricsConfiguration(MeterRegistry meterRegistry, SpiffeClient spiffeClient) { this.meterRegistry = meterRegistry; this.spiffeClient = spiffeClient; initializeSpiffeMetrics(); } private void initializeSpiffeMetrics() { Gauge.builder("spiffe.federated_trust_domains") .description("Number of federated trust domains") .register(meterRegistry, this, config -> spiffeClient.getFederatedTrustDomains().size()); Counter.builder("spiffe.federated_requests") .description("Federated service requests") .tag("trust_domain", "") .register(meterRegistry); } @EventListener public void handleFederatedRequest(FederatedRequestEvent event) { Counter.builder("spiffe.federated_requests") .tag("trust_domain", event.getTrustDomain()) .tag("success", String.valueOf(event.isSuccess())) .register(meterRegistry) .increment(); } }

Testing Federated Services

TestSpiffeFederation.java:

@SpringBootTest @TestPropertySource(properties = { "spiffe.trust.domain=test.example.com", "spiffe.federation.enabled=true" }) public class TestSpiffeFederation { @Autowired private SpiffeClient spiffeClient; @Test public void testFederatedIdentityValidation() { String federatedSpiffeId = "spiffe://acme-corp.com/inventory-service"; assertTrue(spiffeClient.isFederatedIdentity(federatedSpiffeId)); assertTrue(spiffeClient.validateFederatedSvid(federatedSpiffeId)); } @Test public void testCrossDomainCommunication() { FederatedOrderService orderService = new FederatedOrderService(spiffeClient); OrderRequest request = new OrderRequest("product-123", 5); Order order = orderService.processCrossDomainOrder(request); assertNotNull(order); assertEquals("product-123", order.getProductId()); } } @Configuration static class TestSpiffeConfig { @Bean @Primary public SpiffeClient testSpiffeClient() { return Mockito.mock(SpiffeClient.class); } }

Best Practices for Java SPIFFE Federation

  1. Bundle Refresh Strategy: Implement automatic bundle refresh for federated trust domains
  2. Identity Caching: Cache validated identities with appropriate TTL
  3. Graceful Degradation: Handle federation failures gracefully
  4. Comprehensive Logging: Log federation events for audit and troubleshooting
  5. Security Boundaries: Clearly define which federated services can access which resources

Conclusion

SPIFFE Federation provides a robust foundation for secure service-to-service communication across organizational boundaries in Java applications. By implementing SPIFFE Federation:

  • Eliminate shared secret management across trust domains
  • Establish cryptographically-verified service identities
  • Enable zero-trust networking between federated services
  • Simplify multi-cloud and hybrid cloud security
  • Maintain compliance with strong identity verification

For Java teams operating in complex, multi-organizational environments, SPIFFE Federation offers a standardized, secure approach to service identity that scales with your distributed system architecture.

Java Logistics, Shipping Integration & Enterprise Inventory Automation (Tracking, ERP, RFID & Billing Systems)

https://macronepal.com/blog/aftership-tracking-in-java-enterprise-package-visibility/
Explains how to integrate AfterShip tracking services into Java applications to provide real-time shipment visibility, delivery status updates, and centralized tracking across multiple courier services.

https://macronepal.com/blog/shipping-integration-using-fedex-api-with-java-for-logistics-automation/
Explains how to integrate the FedEx API into Java systems to automate shipping tasks such as creating shipments, calculating delivery costs, generating shipping labels, and tracking packages.

https://macronepal.com/blog/shipping-and-logistics-integrating-ups-apis-with-java-applications/
Explains UPS API integration in Java to enable automated shipping operations including rate calculation, shipment scheduling, tracking, and delivery confirmation management.

https://macronepal.com/blog/generating-and-reading-qr-codes-for-products-in-java/
Explains how Java applications generate and read QR codes for product identification, tracking, and authentication, supporting faster inventory handling and product verification processes.

https://macronepal.com/blog/designing-a-robust-pick-and-pack-workflow-in-java/
Explains how to design an efficient pick-and-pack workflow in Java warehouse systems, covering order processing, item selection, packaging steps, and logistics preparation to improve fulfillment efficiency.

https://macronepal.com/blog/rfid-inventory-management-system-in-java-a-complete-guide/
Explains how RFID technology integrates with Java applications to automate inventory tracking, reduce manual errors, and enable real-time stock monitoring in warehouses and retail environments.

https://macronepal.com/blog/erp-integration-with-odoo-in-java/
Explains how Java applications connect with Odoo ERP systems to synchronize inventory, orders, customer records, and financial data across enterprise systems.

https://macronepal.com/blog/automated-invoice-generation-creating-professional-excel-invoices-with-apache-poi-in-java/
Explains how to automatically generate professional Excel invoices in Java using Apache POI, enabling structured billing documents and automated financial record creation.

https://macronepal.com/blog/enterprise-financial-integration-using-quickbooks-api-in-java-applications/
Explains QuickBooks API integration in Java to automate financial workflows such as invoice management, payment tracking, accounting synchronization, and financial reporting.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper