Istio Authorization Policies provide service-level access control in Kubernetes environments. This guide covers how to implement, test, and manage Istio Authorization Policies with Java applications.
Overview and Concepts
Istio Authorization Policy Components:
- Workload Selectors: Target specific services/pods
- Rules: Define access control rules
- Sources: Specify who can access (principals, namespaces, IP blocks)
- Operations: Define what actions are allowed (HTTP methods, paths)
- Conditions: Additional constraints (headers, JWT claims)
Key Benefits:
- Service Mesh Security: Enforce security at the network layer
- Zero-Trust Networking: Default deny, explicit allow
- Flexible Policies: Rich condition matching
- Kubernetes Native: CRD-based configuration
Dependencies and Setup
Maven Dependencies
<properties> <spring-boot.version>3.1.0</spring-boot.version> <kubernetes-client.version>6.7.2</kubernetes-client.version> <istio-client.version>1.18.0</istio-client.version> </properties> <dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>${spring-boot.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- Kubernetes Client --> <dependency> <groupId>io.fabric8</groupId> <artifactId>kubernetes-client</artifactId> <version>${kubernetes-client.version}</version> </dependency> <!-- Istio Client --> <dependency> <groupId>io.fabric8</groupId> <artifactId>istio-client</artifactId> <version>${istio-client.version}</version> </dependency> <!-- YAML Processing --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId> <version>2.15.2</version> </dependency> <!-- Validation --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>${spring-boot.version}</version> </dependency> </dependencies> Application Configuration
# application.yml istio: authorization: enabled: true namespace: ${NAMESPACE:default} service-account: ${SERVICE_ACCOUNT:my-service} auto-create-policies: true spring: application: name: user-service management: endpoints: web: exposure: include: health,info,metrics,istio-policies endpoint: health: show-details: always logging: level: com.example.istio: DEBUG Configuration Properties
@Configuration @ConfigurationProperties(prefix = "istio.authorization") @Data public class IstioAuthorizationProperties { private boolean enabled = true; private String namespace = "default"; private String serviceAccount; private boolean autoCreatePolicies = true; private PolicyDefaults defaults = new PolicyDefaults(); @Data public static class PolicyDefaults { private String action = "ALLOW"; private int priority = 1000; private boolean auditEnabled = false; } } Core Authorization Policy Models
1. Istio Authorization Policy Models
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class IstioAuthorizationPolicy { private String name; private String namespace; private String serviceAccount; private PolicySpec spec; @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class PolicySpec { private Selector selector; private List<Rule> rules; private String action; private List<Rule> denyRules; @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class Selector { private Map<String, String> matchLabels; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class Rule { private List<Source> from; private List<To> to; private List<When> when; @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class Source { private List<Principal> principals; private List<Namespace> namespaces; private List<IPBlock> ipBlocks; private List<RequestPrincipal> requestPrincipals; private List<NotSource> notSources; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class To { private List<Operation> operations; private List<NotOperation> notOperations; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class When { private String key; private List<String> values; private List<String> notValues; } } } } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Principal { private String name; private String namespace; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Namespace { private String name; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class IPBlock { private String cidr; private List<String> except; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class RequestPrincipal { private String value; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Operation { private List<String> methods; private List<String> paths; private List<String> hosts; private List<String> ports; } // NotSource, NotOperation are similar to their positive counterparts 2. Policy Request/Response Models
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class PolicyRequest { private String policyName; private String serviceName; private List<AccessRule> allowRules; private List<AccessRule> denyRules; private String action; private Integer priority; @Data @Builder @NoArgsConstructor @AllArgsConstructor public static class AccessRule { private List<String> sources; private List<String> methods; private List<String> paths; private Map<String, String> conditions; } } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class PolicyResponse { private String policyName; private String status; private String message; private Instant createdAt; private String yamlDefinition; } @Data @Builder @NoArgsConstructor @AllArgsConstructor public class PolicyValidationResult { private boolean valid; private List<String> errors; private List<String> warnings; public static PolicyValidationResult valid() { return PolicyValidationResult.builder().valid(true).errors(new ArrayList<>()).warnings(new ArrayList<>()).build(); } public static PolicyValidationResult invalid(String error) { return PolicyValidationResult.builder().valid(false).errors(List.of(error)).warnings(new ArrayList<>()).build(); } } Istio Policy Service
1. Core Policy Management Service
@Service @Slf4j public class IstioAuthorizationPolicyService { private final IstioAuthorizationProperties properties; private final KubernetesClient kubernetesClient; private final ObjectMapper yamlMapper; public IstioAuthorizationPolicyService(IstioAuthorizationProperties properties, KubernetesClient kubernetesClient) { this.properties = properties; this.kubernetesClient = kubernetesClient; this.yamlMapper = new ObjectMapper(new YAMLFactory()); } public PolicyResponse createPolicy(PolicyRequest request) { log.info("Creating Istio Authorization Policy: {}", request.getPolicyName()); try { // Validate policy request PolicyValidationResult validation = validatePolicyRequest(request); if (!validation.isValid()) { return PolicyResponse.builder() .policyName(request.getPolicyName()) .status("FAILED") .message("Validation failed: " + String.join(", ", validation.getErrors())) .createdAt(Instant.now()) .build(); } // Convert to Istio Authorization Policy IstioAuthorizationPolicy policy = convertToIstioPolicy(request); // Create Kubernetes resource createKubernetesResource(policy); log.info("Successfully created Istio Authorization Policy: {}", request.getPolicyName()); return PolicyResponse.builder() .policyName(request.getPolicyName()) .status("SUCCESS") .message("Policy created successfully") .createdAt(Instant.now()) .yamlDefinition(generateYamlDefinition(policy)) .build(); } catch (Exception e) { log.error("Failed to create Istio Authorization Policy: {}", request.getPolicyName(), e); return PolicyResponse.builder() .policyName(request.getPolicyName()) .status("FAILED") .message("Creation failed: " + e.getMessage()) .createdAt(Instant.now()) .build(); } } public PolicyResponse updatePolicy(PolicyRequest request) { log.info("Updating Istio Authorization Policy: {}", request.getPolicyName()); try { // Check if policy exists if (!policyExists(request.getPolicyName())) { return PolicyResponse.builder() .policyName(request.getPolicyName()) .status("FAILED") .message("Policy not found") .createdAt(Instant.now()) .build(); } // Delete existing policy deletePolicy(request.getPolicyName()); // Create new policy return createPolicy(request); } catch (Exception e) { log.error("Failed to update Istio Authorization Policy: {}", request.getPolicyName(), e); return PolicyResponse.builder() .policyName(request.getPolicyName()) .status("FAILED") .message("Update failed: " + e.getMessage()) .createdAt(Instant.now()) .build(); } } public boolean deletePolicy(String policyName) { log.info("Deleting Istio Authorization Policy: {}", policyName); try { return kubernetesClient.resources(io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy.class) .inNamespace(properties.getNamespace()) .withName(policyName) .delete(); } catch (Exception e) { log.error("Failed to delete Istio Authorization Policy: {}", policyName, e); return false; } } public List<String> listPolicies() { log.debug("Listing Istio Authorization Policies in namespace: {}", properties.getNamespace()); try { return kubernetesClient.resources(io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy.class) .inNamespace(properties.getNamespace()) .list() .getItems() .stream() .map(policy -> policy.getMetadata().getName()) .collect(Collectors.toList()); } catch (Exception e) { log.error("Failed to list Istio Authorization Policies", e); return Collections.emptyList(); } } public Optional<IstioAuthorizationPolicy> getPolicy(String policyName) { log.debug("Getting Istio Authorization Policy: {}", policyName); try { io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy policy = kubernetesClient.resources(io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy.class) .inNamespace(properties.getNamespace()) .withName(policyName) .get(); return policy != null ? Optional.of(convertFromKubernetesResource(policy)) : Optional.empty(); } catch (Exception e) { log.error("Failed to get Istio Authorization Policy: {}", policyName, e); return Optional.empty(); } } public PolicyValidationResult validatePolicy(PolicyRequest request) { List<String> errors = new ArrayList<>(); List<String> warnings = new ArrayList<>(); // Validate policy name if (request.getPolicyName() == null || request.getPolicyName().trim().isEmpty()) { errors.add("Policy name is required"); } else if (!request.getPolicyName().matches("^[a-z0-9-]+$")) { errors.add("Policy name must contain only lowercase letters, numbers, and hyphens"); } // Validate service name if (request.getServiceName() == null || request.getServiceName().trim().isEmpty()) { errors.add("Service name is required"); } // Validate action if (request.getAction() != null && !List.of("ALLOW", "DENY", "AUDIT", "CUSTOM").contains(request.getAction().toUpperCase())) { errors.add("Invalid action. Must be one of: ALLOW, DENY, AUDIT, CUSTOM"); } // Validate rules if ((request.getAllowRules() == null || request.getAllowRules().isEmpty()) && (request.getDenyRules() == null || request.getDenyRules().isEmpty())) { warnings.add("Policy has no rules defined - this may not have the intended effect"); } // Validate priority if (request.getPriority() != null && (request.getPriority() < 0 || request.getPriority() > 1000000)) { errors.add("Priority must be between 0 and 1000000"); } return PolicyValidationResult.builder() .valid(errors.isEmpty()) .errors(errors) .warnings(warnings) .build(); } private PolicyValidationResult validatePolicyRequest(PolicyRequest request) { // Basic validation PolicyValidationResult basicValidation = validatePolicy(request); if (!basicValidation.isValid()) { return basicValidation; } // Check for policy name conflicts if (policyExists(request.getPolicyName())) { return PolicyValidationResult.invalid("Policy with name '" + request.getPolicyName() + "' already exists"); } return PolicyValidationResult.valid(); } private boolean policyExists(String policyName) { return getPolicy(policyName).isPresent(); } private IstioAuthorizationPolicy convertToIstioPolicy(PolicyRequest request) { return IstioAuthorizationPolicy.builder() .name(request.getPolicyName()) .namespace(properties.getNamespace()) .serviceAccount(properties.getServiceAccount()) .spec(buildPolicySpec(request)) .build(); } private IstioAuthorizationPolicy.PolicySpec buildPolicySpec(PolicyRequest request) { IstioAuthorizationPolicy.PolicySpec.PolicySpecBuilder specBuilder = IstioAuthorizationPolicy.PolicySpec.builder(); // Set selector specBuilder.selector(buildSelector(request.getServiceName())); // Set action specBuilder.action(request.getAction() != null ? request.getAction() : properties.getDefaults().getAction()); // Build allow rules if (request.getAllowRules() != null && !request.getAllowRules().isEmpty()) { specBuilder.rules(buildRules(request.getAllowRules())); } // Build deny rules if (request.getDenyRules() != null && !request.getDenyRules().isEmpty()) { specBuilder.denyRules(buildRules(request.getDenyRules())); } return specBuilder.build(); } private IstioAuthorizationPolicy.PolicySpec.Selector buildSelector(String serviceName) { return IstioAuthorizationPolicy.PolicySpec.Selector.builder() .matchLabels(Map.of( "app", serviceName, "version", "v1" )) .build(); } private List<IstioAuthorizationPolicy.PolicySpec.Rule> buildRules(List<PolicyRequest.AccessRule> accessRules) { return accessRules.stream() .map(this::buildRule) .collect(Collectors.toList()); } private IstioAuthorizationPolicy.PolicySpec.Rule buildRule(PolicyRequest.AccessRule accessRule) { IstioAuthorizationPolicy.PolicySpec.Rule.RuleBuilder ruleBuilder = IstioAuthorizationPolicy.PolicySpec.Rule.builder(); // Build sources if (accessRule.getSources() != null && !accessRule.getSources().isEmpty()) { ruleBuilder.from(buildSources(accessRule.getSources())); } // Build operations if (accessRule.getMethods() != null || accessRule.getPaths() != null) { ruleBuilder.to(buildOperations(accessRule.getMethods(), accessRule.getPaths())); } // Build conditions if (accessRule.getConditions() != null && !accessRule.getConditions().isEmpty()) { ruleBuilder.when(buildConditions(accessRule.getConditions())); } return ruleBuilder.build(); } private List<IstioAuthorizationPolicy.PolicySpec.Rule.Source> buildSources(List<String> sources) { return sources.stream() .map(this::parseSource) .collect(Collectors.toList()); } private IstioAuthorizationPolicy.PolicySpec.Rule.Source parseSource(String source) { // Parse source string format: "principal:cluster.local/ns/default/sa/service-account" // or "namespace:default" or "ip:192.168.1.0/24" if (source.startsWith("principal:")) { return IstioAuthorizationPolicy.PolicySpec.Rule.Source.builder() .principals(List.of(Principal.builder().name(source.substring(10)).build())) .build(); } else if (source.startsWith("namespace:")) { return IstioAuthorizationPolicy.PolicySpec.Rule.Source.builder() .namespaces(List.of(Namespace.builder().name(source.substring(10)).build())) .build(); } else if (source.startsWith("ip:")) { return IstioAuthorizationPolicy.PolicySpec.Rule.Source.builder() .ipBlocks(List.of(IPBlock.builder().cidr(source.substring(3)).build())) .build(); } else { // Default to principal return IstioAuthorizationPolicy.PolicySpec.Rule.Source.builder() .principals(List.of(Principal.builder().name(source).build())) .build(); } } private List<IstioAuthorizationPolicy.PolicySpec.Rule.To> buildOperations(List<String> methods, List<String> paths) { Operation operation = Operation.builder() .methods(methods != null ? methods : List.of("*")) .paths(paths != null ? paths : List.of("*")) .build(); return List.of( IstioAuthorizationPolicy.PolicySpec.Rule.To.builder() .operations(List.of(operation)) .build() ); } private List<IstioAuthorizationPolicy.PolicySpec.Rule.When> buildConditions(Map<String, String> conditions) { return conditions.entrySet().stream() .map(entry -> IstioAuthorizationPolicy.PolicySpec.Rule.When.builder() .key(entry.getKey()) .values(List.of(entry.getValue())) .build()) .collect(Collectors.toList()); } private void createKubernetesResource(IstioAuthorizationPolicy policy) { io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy k8sPolicy = convertToKubernetesResource(policy); kubernetesClient.resources(io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy.class) .inNamespace(policy.getNamespace()) .resource(k8sPolicy) .create(); } private io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy convertToKubernetesResource( IstioAuthorizationPolicy policy) { io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy k8sPolicy = new io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy(); // Set metadata ObjectMeta metadata = new ObjectMeta(); metadata.setName(policy.getName()); metadata.setNamespace(policy.getNamespace()); k8sPolicy.setMetadata(metadata); // Set spec io.fabric8.istio.api.security.v1beta1.AuthorizationPolicySpec spec = new io.fabric8.istio.api.security.v1beta1.AuthorizationPolicySpec(); // Convert selector if (policy.getSpec().getSelector() != null) { Map<String, String> matchLabels = policy.getSpec().getSelector().getMatchLabels(); if (matchLabels != null) { spec.setSelector(new io.fabric8.istio.api.security.v1beta1.WorkloadSelector(matchLabels)); } } // Convert rules if (policy.getSpec().getRules() != null) { spec.setRules(convertRules(policy.getSpec().getRules())); } // Convert action if (policy.getSpec().getAction() != null) { spec.setAction(io.fabric8.istio.api.security.v1beta1.AuthorizationPolicyAction.valueOf( policy.getSpec().getAction())); } k8sPolicy.setSpec(spec); return k8sPolicy; } private List<io.fabric8.istio.api.security.v1beta1.Rule> convertRules( List<IstioAuthorizationPolicy.PolicySpec.Rule> rules) { return rules.stream() .map(this::convertRule) .collect(Collectors.toList()); } private io.fabric8.istio.api.security.v1beta1.Rule convertRule( IstioAuthorizationPolicy.PolicySpec.Rule rule) { io.fabric8.istio.api.security.v1beta1.Rule k8sRule = new io.fabric8.istio.api.security.v1beta1.Rule(); // Convert from if (rule.getFrom() != null) { k8sRule.setFrom(convertFrom(rule.getFrom())); } // Convert to if (rule.getTo() != null) { k8sRule.setTo(convertTo(rule.getTo())); } // Convert when if (rule.getWhen() != null) { k8sRule.setWhen(convertWhen(rule.getWhen())); } return k8sRule; } private List<io.fabric8.istio.api.security.v1beta1.RuleFrom> convertFrom( List<IstioAuthorizationPolicy.PolicySpec.Rule.Source> from) { return from.stream() .map(this::convertFromSource) .collect(Collectors.toList()); } private io.fabric8.istio.api.security.v1beta1.RuleFrom convertFromSource( IstioAuthorizationPolicy.PolicySpec.Rule.Source source) { io.fabric8.istio.api.security.v1beta1.RuleFrom ruleFrom = new io.fabric8.istio.api.security.v1beta1.RuleFrom(); if (source.getPrincipals() != null) { ruleFrom.setSource(new io.fabric8.istio.api.security.v1beta1.Source() .setPrincipals(source.getPrincipals().stream() .map(Principal::getName) .collect(Collectors.toList()))); } // Similar conversion for namespaces, ipBlocks, etc. return ruleFrom; } // Similar conversion methods for To and When... private IstioAuthorizationPolicy convertFromKubernetesResource( io.fabric8.istio.api.security.v1beta1.AuthorizationPolicy k8sPolicy) { // Reverse conversion logic return IstioAuthorizationPolicy.builder() .name(k8sPolicy.getMetadata().getName()) .namespace(k8sPolicy.getMetadata().getNamespace()) .build(); // Complete the conversion based on your needs } private String generateYamlDefinition(IstioAuthorizationPolicy policy) { try { return yamlMapper.writeValueAsString(convertToKubernetesResource(policy)); } catch (Exception e) { log.error("Failed to generate YAML definition for policy: {}", policy.getName(), e); return "Error generating YAML definition"; } } } 2. Policy Template Service
@Service @Slf4j public class IstioPolicyTemplateService { private final IstioAuthorizationPolicyService policyService; public IstioPolicyTemplateService(IstioAuthorizationPolicyService policyService) { this.policyService = policyService; } public PolicyResponse createNamespaceIsolationPolicy(String serviceName, String namespace) { PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-namespace-isolation") .serviceName(serviceName) .action("ALLOW") .priority(1000) .allowRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of("namespace:" + namespace)) .methods(List.of("GET", "POST", "PUT", "DELETE")) .paths(List.of("/*")) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createServiceToServicePolicy(String sourceService, String targetService) { PolicyRequest request = PolicyRequest.builder() .policyName(targetService + "-allow-" + sourceService) .serviceName(targetService) .action("ALLOW") .priority(900) .allowRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of("principal:cluster.local/ns/default/sa/" + sourceService)) .methods(List.of("*")) .paths(List.of("/*")) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createPublicApiPolicy(String serviceName, List<String> publicPaths) { PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-public-api") .serviceName(serviceName) .action("ALLOW") .priority(800) .allowRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of("*")) // Allow from anywhere .methods(List.of("GET")) .paths(publicPaths) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createAdminApiPolicy(String serviceName, List<String> adminPaths) { PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-admin-api") .serviceName(serviceName) .action("ALLOW") .priority(1100) // Higher priority than public API .allowRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of( "principal:cluster.local/ns/kube-system/sa/admin", "principal:cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account" )) .methods(List.of("*")) .paths(adminPaths) .conditions(Map.of( "request.headers[x-admin-token]", "present" )) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createDenyAllPolicy(String serviceName) { PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-deny-all") .serviceName(serviceName) .action("DENY") .priority(1) // Lowest priority - acts as default deny .denyRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of("*")) .methods(List.of("*")) .paths(List.of("/*")) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createJwtAuthPolicy(String serviceName, String issuer, List<String> protectedPaths) { PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-jwt-auth") .serviceName(serviceName) .action("DENY") .priority(500) .denyRules(List.of( PolicyRequest.AccessRule.builder() .sources(List.of("*")) .methods(List.of("*")) .paths(protectedPaths) .conditions(Map.of( "request.auth.claims[iss]", "!" + issuer, "request.auth.principal", "not-present" )) .build() )) .build(); return policyService.createPolicy(request); } public PolicyResponse createIpWhitelistPolicy(String serviceName, List<String> allowedIps) { List<PolicyRequest.AccessRule> allowRules = allowedIps.stream() .map(ip -> PolicyRequest.AccessRule.builder() .sources(List.of("ip:" + ip)) .methods(List.of("*")) .paths(List.of("/*")) .build()) .collect(Collectors.toList()); PolicyRequest request = PolicyRequest.builder() .policyName(serviceName + "-ip-whitelist") .serviceName(serviceName) .action("ALLOW") .priority(700) .allowRules(allowRules) .build(); return policyService.createPolicy(request); } } REST Controllers
1. Policy Management Controller
@RestController @RequestMapping("/api/istio/policies") @Validated @Slf4j public class IstioPolicyController { private final IstioAuthorizationPolicyService policyService; private final IstioPolicyTemplateService templateService; public IstioPolicyController(IstioAuthorizationPolicyService policyService, IstioPolicyTemplateService templateService) { this.policyService = policyService; this.templateService = templateService; } @PostMapping public ResponseEntity<PolicyResponse> createPolicy(@Valid @RequestBody PolicyRequest request) { log.info("Creating Istio Authorization Policy: {}", request.getPolicyName()); PolicyResponse response = policyService.createPolicy(request); HttpStatus status = "SUCCESS".equals(response.getStatus()) ? HttpStatus.CREATED : HttpStatus.BAD_REQUEST; return ResponseEntity.status(status).body(response); } @PutMapping("/{policyName}") public ResponseEntity<PolicyResponse> updatePolicy(@PathVariable String policyName, @Valid @RequestBody PolicyRequest request) { log.info("Updating Istio Authorization Policy: {}", policyName); // Ensure policy name matches path request.setPolicyName(policyName); PolicyResponse response = policyService.updatePolicy(request); HttpStatus status = "SUCCESS".equals(response.getStatus()) ? HttpStatus.OK : HttpStatus.BAD_REQUEST; return ResponseEntity.status(status).body(response); } @DeleteMapping("/{policyName}") public ResponseEntity<BaseResponse> deletePolicy(@PathVariable String policyName) { log.info("Deleting Istio Authorization Policy: {}", policyName); boolean success = policyService.deletePolicy(policyName); BaseResponse response = BaseResponse.builder() .success(success) .message(success ? "Policy deleted successfully" : "Failed to delete policy") .build(); HttpStatus status = success ? HttpStatus.OK : HttpStatus.NOT_FOUND; return ResponseEntity.status(status).body(response); } @GetMapping public ResponseEntity<List<String>> listPolicies() { log.debug("Listing all Istio Authorization Policies"); List<String> policies = policyService.listPolicies(); return ResponseEntity.ok(policies); } @GetMapping("/{policyName}") public ResponseEntity<IstioAuthorizationPolicy> getPolicy(@PathVariable String policyName) { log.debug("Getting Istio Authorization Policy: {}", policyName); Optional<IstioAuthorizationPolicy> policy = policyService.getPolicy(policyName); return policy.map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } @PostMapping("/{policyName}/validate") public ResponseEntity<PolicyValidationResult> validatePolicy(@PathVariable String policyName, @Valid @RequestBody PolicyRequest request) { log.debug("Validating Istio Authorization Policy: {}", policyName); PolicyValidationResult result = policyService.validatePolicy(request); return ResponseEntity.ok(result); } // Template endpoints @PostMapping("/templates/namespace-isolation") public ResponseEntity<PolicyResponse> createNamespaceIsolation( @RequestParam String serviceName, @RequestParam String namespace) { PolicyResponse response = templateService.createNamespaceIsolationPolicy(serviceName, namespace); return ResponseEntity.status(HttpStatus.CREATED).body(response); } @PostMapping("/templates/service-to-service") public ResponseEntity<PolicyResponse> createServiceToServicePolicy( @RequestParam String sourceService, @RequestParam String targetService) { PolicyResponse response = templateService.createServiceToServicePolicy(sourceService, targetService); return ResponseEntity.status(HttpStatus.CREATED).body(response); } @PostMapping("/templates/public-api") public ResponseEntity<PolicyResponse> createPublicApiPolicy( @RequestParam String serviceName, @RequestBody List<String> publicPaths) { PolicyResponse response = templateService.createPublicApiPolicy(serviceName, publicPaths); return ResponseEntity.status(HttpStatus.CREATED).body(response); } @PostMapping("/templates/deny-all") public ResponseEntity<PolicyResponse> createDenyAllPolicy(@RequestParam String serviceName) { PolicyResponse response = templateService.createDenyAllPolicy(serviceName); return ResponseEntity.status(HttpStatus.CREATED).body(response); } } @Data class BaseResponse { private boolean success; private String message; private Instant timestamp; public BaseResponse(boolean success, String message) { this.success = success; this.message = message; this.timestamp = Instant.now(); } public static BaseResponse success(String message) { return new BaseResponse(true, message); } public static BaseResponse error(String message) { return new BaseResponse(false, message); } } 2. Policy Monitoring Controller
```java
@RestController
@RequestMapping("/api/istio/monitoring")
@Slf4j
public class IstioPolicyMonitoringController {
private final IstioAuthorizationPolicyService policyService; private final KubernetesClient kubernetesClient; public IstioPolicyMonitoringController(IstioAuthorizationPolicyService policyService, KubernetesClient kubernetesClient) { this.policyService = policyService; this.kubernetesClient = kubernetesClient; } @GetMapping("/health") public ResponseEntity<HealthResponse> healthCheck() { try { // Check Kubernetes connectivity kubernetesClient.pods().list(); // Check policy access policyService.listPolicies(); return ResponseEntity.ok(HealthResponse.healthy()); } catch (Exception e) { log.error("Health check failed", e); return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE) .body(HealthResponse.unhealthy(e.getMessage())); } } @GetMapping("/metrics") public ResponseEntity<PolicyMetrics> getPolicyMetrics() { List<String> policies = policyService.listPolicies(); PolicyMetrics metrics = PolicyMetrics.builder() .totalPolicies(policies.size()) .policiesByNamespace(getPoliciesByNamespace()) .recentlyCreated(getRecentlyCreatedPolicies()) .build(); return ResponseEntity.ok(metrics); } @GetMapping("/audit") public ResponseEntity<List<PolicyAuditEntry>> getPolicyAudit( @RequestParam(defaultValue = "7") int days) { // This would typically query an audit log List<PolicyAuditEntry> auditEntries = simulatePolicyAudit(days); return ResponseEntity.ok(auditEntries); } private Map<String, Integer> getPoliciesByNamespace() { // Implementation to group policies by namespace return Map.of("default", policyService.listPolicies().size()); } private List<String> getRecentlyCreatedPolicies() { // Implementation to get recently created policies return policyService.listPolicies().stream() .limit(10) .collect(Collectors.toList()); } private List<PolicyAuditEntry> simulatePolicyAudit(int days) { // Simulate audit entries - in real implementation, query from audit log return List.of( PolicyAuditEntry.builder() .policyName("example-policy") .action("CREATE") .user("system:serviceaccount:default:istio-policy-manager") .timestamp(Instant.now().minus(Duration.ofDays(1))) .success(true) .