Java client for Kubernetes and OpenShift providing access to full REST APIs via a fluent DSL
—
This document covers OpenShift authorization review operations, including access reviews, security policy reviews, and permission validation.
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.SubjectAccessReview;
import io.fabric8.openshift.api.model.SubjectAccessReviewResponse;
import io.fabric8.openshift.api.model.ResourceAccessReview;
import io.fabric8.openshift.api.model.ResourceAccessReviewResponse;
import io.fabric8.openshift.api.model.LocalSubjectAccessReview;
import io.fabric8.openshift.api.model.LocalResourceAccessReview;
import io.fabric8.openshift.api.model.SelfSubjectRulesReview;
import io.fabric8.openshift.api.model.SubjectRulesReview;
import io.fabric8.openshift.api.model.PodSecurityPolicyReview;
import io.fabric8.openshift.api.model.PodSecurityPolicySelfSubjectReview;
import io.fabric8.openshift.api.model.PodSecurityPolicySubjectReview;
import io.fabric8.kubernetes.client.dsl.InOutCreateable;
import io.fabric8.kubernetes.client.dsl.NamespacedInOutCreateable;Subject Access Reviews check if a specific user or service account has permission to perform an action.
// Create subject access review to check if user can create pods
SubjectAccessReview review = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("create")
.withGroup("")
.withResource("pods")
.endResourceAttributes()
.withUser("john.doe")
.endSpec()
.build();
SubjectAccessReviewResponse response = client.subjectAccessReviews()
.create(review);
boolean canCreatePods = response.getAllowed();
String reason = response.getReason();
System.out.println("User can create pods: " + canCreatePods);
if (reason != null) {
System.out.println("Reason: " + reason);
}// Check access for user with specific groups
SubjectAccessReview groupReview = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("delete")
.withGroup("apps")
.withResource("deployments")
.withName("my-app")
.endResourceAttributes()
.withUser("jane.smith")
.withGroups("developers", "team-leads")
.endSpec()
.build();
SubjectAccessReviewResponse groupResponse = client.subjectAccessReviews()
.create(groupReview);
System.out.println("Can delete deployment: " + groupResponse.getAllowed());// Check service account permissions
SubjectAccessReview serviceAccountReview = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("get")
.withGroup("")
.withResource("secrets")
.endResourceAttributes()
.withUser("system:serviceaccount:my-project:my-service-account")
.endSpec()
.build();
SubjectAccessReviewResponse saResponse = client.subjectAccessReviews()
.create(serviceAccountReview);
boolean canAccessSecrets = saResponse.getAllowed();// Check access to non-resource URLs
SubjectAccessReview nonResourceReview = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewNonResourceAttributes()
.withPath("/api/v1/nodes")
.withVerb("get")
.endNonResourceAttributes()
.withUser("cluster-reader")
.endSpec()
.build();
SubjectAccessReviewResponse nonResourceResponse = client.subjectAccessReviews()
.create(nonResourceReview);
boolean canAccessNodes = nonResourceResponse.getAllowed();Resource Access Reviews determine which users can perform actions on specific resources.
// Find who can delete pods in a namespace
ResourceAccessReview resourceReview = new ResourceAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("delete")
.withGroup("")
.withResource("pods")
.endResourceAttributes()
.endSpec()
.build();
ResourceAccessReviewResponse resourceResponse = client.resourceAccessReviews()
.create(resourceReview);
List<String> users = resourceResponse.getUsers();
List<String> groups = resourceResponse.getGroups();
System.out.println("Users who can delete pods: " + String.join(", ", users));
System.out.println("Groups who can delete pods: " + String.join(", ", groups));// Check who can update a specific deployment
ResourceAccessReview specificResourceReview = new ResourceAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("update")
.withGroup("apps")
.withResource("deployments")
.withName("my-app")
.endResourceAttributes()
.endSpec()
.build();
ResourceAccessReviewResponse specificResponse = client.resourceAccessReviews()
.create(specificResourceReview);
List<String> authorizedUsers = specificResponse.getUsers();Local Access Reviews are namespace-scoped versions of access reviews.
// Check user access within specific namespace
LocalSubjectAccessReview localReview = new LocalSubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("create")
.withGroup("")
.withResource("configmaps")
.endResourceAttributes()
.withUser("developer-user")
.endSpec()
.build();
SubjectAccessReviewResponse localResponse = client.localSubjectAccessReviews()
.inNamespace("my-project")
.create(localReview);
boolean canCreateConfigMaps = localResponse.getAllowed();// Find who has access to secrets in specific namespace
LocalResourceAccessReview localResourceReview = new LocalResourceAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace("my-project")
.withVerb("get")
.withGroup("")
.withResource("secrets")
.endResourceAttributes()
.endSpec()
.build();
ResourceAccessReviewResponse localResourceResponse = client.localResourceAccessReviews()
.inNamespace("my-project")
.create(localResourceReview);
List<String> secretUsers = localResourceResponse.getUsers();Self Subject Rules Reviews show what actions the current user can perform.
// Get current user's permissions in namespace
SelfSubjectRulesReview selfReview = new SelfSubjectRulesReviewBuilder()
.withNewSpec()
.withNamespace("my-project")
.endSpec()
.build();
SelfSubjectRulesReview selfResponse = client.selfSubjectRulesReviews()
.inNamespace("my-project")
.create(selfReview);
List<PolicyRule> resourceRules = selfResponse.getStatus().getResourceRules();
List<NonResourcePolicyRule> nonResourceRules = selfResponse.getStatus().getNonResourceRules();
System.out.println("Resource permissions:");
for (PolicyRule rule : resourceRules) {
System.out.println(" Resources: " + String.join(", ", rule.getResources()));
System.out.println(" Verbs: " + String.join(", ", rule.getVerbs()));
System.out.println(" API Groups: " + String.join(", ", rule.getApiGroups()));
System.out.println();
}
System.out.println("Non-resource permissions:");
for (NonResourcePolicyRule rule : nonResourceRules) {
System.out.println(" URLs: " + String.join(", ", rule.getNonResourceURLs()));
System.out.println(" Verbs: " + String.join(", ", rule.getVerbs()));
System.out.println();
}// Get specific user's permissions in namespace
SubjectRulesReview subjectRulesReview = new SubjectRulesReviewBuilder()
.withNewSpec()
.withNamespace("my-project")
.withUser("developer-user")
.withGroups("developers")
.endSpec()
.build();
SubjectRulesReview subjectRulesResponse = client.subjectRulesReviews()
.inNamespace("my-project")
.create(subjectRulesReview);
List<PolicyRule> userRules = subjectRulesResponse.getStatus().getResourceRules();
boolean incomplete = subjectRulesResponse.getStatus().getIncomplete();
if (incomplete) {
System.out.println("Warning: Rule list may be incomplete");
}Pod Security Policy Reviews validate pod specifications against security policies.
// Review pod security policy for a pod spec
PodSecurityPolicyReview pspReview = new PodSecurityPolicyReviewBuilder()
.withNewSpec()
.withNewTemplate()
.withNewSpec()
.addNewContainer()
.withName("test-container")
.withImage("nginx")
.withNewSecurityContext()
.withRunAsUser(0L) // Root user
.withPrivileged(true)
.endSecurityContext()
.endContainer()
.endSpec()
.endTemplate()
.withServiceAccountNames("default")
.endSpec()
.build();
PodSecurityPolicyReview pspResponse = client.podSecurityPolicyReviews()
.inNamespace("my-project")
.create(pspReview);
List<PodSecurityPolicySubjectReviewStatus> allowedBy = pspResponse.getStatus().getAllowedBy();
for (PodSecurityPolicySubjectReviewStatus status : allowedBy) {
System.out.println("Allowed by SCC: " + status.getName());
System.out.println(" Template: " + status.getTemplate());
}// Review pod security for current user
PodSecurityPolicySelfSubjectReview selfPspReview = new PodSecurityPolicySelfSubjectReviewBuilder()
.withNewSpec()
.withNewTemplate()
.withNewSpec()
.addNewContainer()
.withName("app-container")
.withImage("my-app:latest")
.withNewSecurityContext()
.withReadOnlyRootFilesystem(true)
.withRunAsNonRoot(true)
.endSecurityContext()
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
PodSecurityPolicySelfSubjectReview selfPspResponse = client.podSecurityPolicySelfSubjectReviews()
.inNamespace("my-project")
.create(selfPspReview);
List<PodSecurityPolicySubjectReviewStatus> selfAllowed = selfPspResponse.getStatus().getAllowedBy();// Review pod security for specific user/group
PodSecurityPolicySubjectReview subjectPspReview = new PodSecurityPolicySubjectReviewBuilder()
.withNewSpec()
.withNewTemplate()
.withNewSpec()
.addNewContainer()
.withName("privileged-container")
.withImage("system-app:latest")
.withNewSecurityContext()
.withPrivileged(true)
.withRunAsUser(0L)
.endSecurityContext()
.endContainer()
.addNewVolume()
.withName("host-volume")
.withNewHostPath()
.withPath("/var/lib/data")
.endHostPath()
.endVolume()
.endSpec()
.endTemplate()
.withUser("system-admin")
.withGroups("system:authenticated")
.endSpec()
.build();
PodSecurityPolicySubjectReview subjectPspResponse = client.podSecurityPolicySubjectReviews()
.inNamespace("my-project")
.create(subjectPspReview);
List<PodSecurityPolicySubjectReviewStatus> subjectAllowed = subjectPspResponse.getStatus().getAllowedBy();public class PermissionChecker {
private final OpenShiftClient client;
public PermissionChecker(OpenShiftClient client) {
this.client = client;
}
public Map<String, Boolean> checkMultiplePermissions(String user, String namespace,
Map<String, String[]> permissions) {
Map<String, Boolean> results = new HashMap<>();
for (Map.Entry<String, String[]> entry : permissions.entrySet()) {
String resource = entry.getKey();
String[] verbs = entry.getValue();
for (String verb : verbs) {
String permissionKey = resource + ":" + verb;
SubjectAccessReview review = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace(namespace)
.withVerb(verb)
.withResource(resource)
.withGroup("")
.endResourceAttributes()
.withUser(user)
.endSpec()
.build();
SubjectAccessReviewResponse response = client.subjectAccessReviews()
.create(review);
results.put(permissionKey, response.getAllowed());
}
}
return results;
}
}public class PermissionAuditor {
private final OpenShiftClient client;
public PermissionAuditor(OpenShiftClient client) {
this.client = client;
}
public void auditNamespacePermissions(String namespace) {
System.out.println("=== Permission Audit for Namespace: " + namespace + " ===\n");
// Audit who can perform critical operations
String[] criticalActions = {"delete", "update", "patch"};
String[] criticalResources = {"pods", "services", "secrets", "configmaps"};
for (String resource : criticalResources) {
System.out.println("Resource: " + resource);
for (String action : criticalActions) {
ResourceAccessReview review = new ResourceAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace(namespace)
.withVerb(action)
.withGroup("")
.withResource(resource)
.endResourceAttributes()
.endSpec()
.build();
ResourceAccessReviewResponse response = client.resourceAccessReviews()
.create(review);
System.out.println(" " + action + ": " +
"users=" + response.getUsers().size() +
", groups=" + response.getGroups().size());
}
System.out.println();
}
}
public void auditUserPermissions(String user, String namespace) {
System.out.println("=== User Permission Audit: " + user + " ===\n");
SelfSubjectRulesReview rulesReview = new SelfSubjectRulesReviewBuilder()
.withNewSpec()
.withNamespace(namespace)
.endSpec()
.build();
// Note: This would need to be done with proper user context
// For demonstration, we'll check specific permissions
String[] commonResources = {"pods", "services", "deployments", "secrets"};
String[] commonVerbs = {"get", "list", "create", "update", "delete"};
for (String resource : commonResources) {
System.out.println("Resource: " + resource);
for (String verb : commonVerbs) {
SubjectAccessReview review = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace(namespace)
.withVerb(verb)
.withGroup("")
.withResource(resource)
.endResourceAttributes()
.withUser(user)
.endSpec()
.build();
SubjectAccessReviewResponse response = client.subjectAccessReviews()
.create(review);
System.out.print(" " + verb + ": " +
(response.getAllowed() ? "✓" : "✗"));
}
System.out.println();
}
}
}import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.*;
public class AuthorizationValidator {
private final OpenShiftClient client;
public AuthorizationValidator(OpenShiftClient client) {
this.client = client;
}
public boolean validateDeploymentPermissions(String user, String namespace,
String deploymentName) {
System.out.println("Validating deployment permissions for user: " + user);
// Required permissions for deployment management
String[][] requiredPermissions = {
{"deployments", "get"},
{"deployments", "update"},
{"deployments", "patch"},
{"replicasets", "get"},
{"replicasets", "list"},
{"pods", "get"},
{"pods", "list"}
};
boolean allPermissionsGranted = true;
for (String[] permission : requiredPermissions) {
String resource = permission[0];
String verb = permission[1];
SubjectAccessReview review = new SubjectAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace(namespace)
.withVerb(verb)
.withGroup("apps")
.withResource(resource)
.withName(deploymentName)
.endResourceAttributes()
.withUser(user)
.endSpec()
.build();
SubjectAccessReviewResponse response = client.subjectAccessReviews()
.create(review);
if (!response.getAllowed()) {
System.out.println(" ✗ Missing permission: " + verb + " " + resource);
allPermissionsGranted = false;
} else {
System.out.println(" ✓ Has permission: " + verb + " " + resource);
}
}
return allPermissionsGranted;
}
public SecurityValidationResult validatePodSecurity(PodSpec podSpec,
String namespace) {
PodSecurityPolicyReview review = new PodSecurityPolicyReviewBuilder()
.withNewSpec()
.withNewTemplate()
.withSpec(podSpec)
.endTemplate()
.withServiceAccountNames("default")
.endSpec()
.build();
PodSecurityPolicyReview response = client.podSecurityPolicyReviews()
.inNamespace(namespace)
.create(review);
SecurityValidationResult result = new SecurityValidationResult();
result.setAllowed(!response.getStatus().getAllowedBy().isEmpty());
if (result.isAllowed()) {
List<String> allowedBySCCs = response.getStatus().getAllowedBy().stream()
.map(PodSecurityPolicySubjectReviewStatus::getName)
.collect(Collectors.toList());
result.setAllowedBySCCs(allowedBySCCs);
}
return result;
}
public List<String> getUsersWithAccess(String namespace, String resource, String verb) {
ResourceAccessReview review = new ResourceAccessReviewBuilder()
.withNewSpec()
.withNewResourceAttributes()
.withNamespace(namespace)
.withVerb(verb)
.withGroup("")
.withResource(resource)
.endResourceAttributes()
.endSpec()
.build();
ResourceAccessReviewResponse response = client.resourceAccessReviews()
.create(review);
return response.getUsers();
}
public static class SecurityValidationResult {
private boolean allowed;
private List<String> allowedBySCCs = new ArrayList<>();
// Getters and setters
public boolean isAllowed() { return allowed; }
public void setAllowed(boolean allowed) { this.allowed = allowed; }
public List<String> getAllowedBySCCs() { return allowedBySCCs; }
public void setAllowedBySCCs(List<String> allowedBySCCs) { this.allowedBySCCs = allowedBySCCs; }
}
}public class SubjectAccessReview implements HasMetadata {
public ObjectMeta getMetadata();
public SubjectAccessReviewSpec getSpec();
}
public class SubjectAccessReviewSpec {
public ResourceAttributes getResourceAttributes();
public NonResourceAttributes getNonResourceAttributes();
public String getUser();
public List<String> getGroups();
public Map<String, List<String>> getExtra();
}
public class SubjectAccessReviewResponse {
public Boolean getAllowed();
public String getDenied();
public String getReason();
public String getEvaluationError();
}
public class ResourceAttributes {
public String getNamespace();
public String getVerb();
public String getGroup();
public String getVersion();
public String getResource();
public String getSubresource();
public String getName();
}
public class NonResourceAttributes {
public String getPath();
public String getVerb();
}public class ResourceAccessReview implements HasMetadata {
public ObjectMeta getMetadata();
public ResourceAccessReviewSpec getSpec();
}
public class ResourceAccessReviewResponse {
public List<String> getUsers();
public List<String> getGroups();
}public class SelfSubjectRulesReview implements HasMetadata {
public ObjectMeta getMetadata();
public SelfSubjectRulesReviewSpec getSpec();
public SubjectRulesReviewStatus getStatus();
}
public class SubjectRulesReviewStatus {
public List<PolicyRule> getResourceRules();
public List<NonResourcePolicyRule> getNonResourceRules();
public Boolean getIncomplete();
public String getEvaluationError();
}
public class PolicyRule {
public List<String> getVerbs();
public List<String> getApiGroups();
public List<String> getResources();
public List<String> getResourceNames();
}
public class NonResourcePolicyRule {
public List<String> getVerbs();
public List<String> getNonResourceURLs();
}public class PodSecurityPolicyReview implements HasMetadata {
public ObjectMeta getMetadata();
public PodSecurityPolicyReviewSpec getSpec();
public PodSecurityPolicyReviewStatus getStatus();
}
public class PodSecurityPolicyReviewSpec {
public PodTemplateSpec getTemplate();
public List<String> getServiceAccountNames();
}
public class PodSecurityPolicyReviewStatus {
public List<PodSecurityPolicySubjectReviewStatus> getAllowedBy();
}
public class PodSecurityPolicySubjectReviewStatus {
public String getName();
public PodTemplateSpec getTemplate();
}Install with Tessl CLI
npx tessl i tessl/maven-io-fabric8--kubernetes-client-project