Java client for Kubernetes and OpenShift providing access to full REST APIs via a fluent DSL
—
This document covers OpenShift user management, security operations, roles, role bindings, and security context constraints.
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.User;
import io.fabric8.openshift.api.model.UserList;
import io.fabric8.openshift.api.model.Group;
import io.fabric8.openshift.api.model.GroupList;
import io.fabric8.openshift.api.model.Identity;
import io.fabric8.openshift.api.model.IdentityList;
import io.fabric8.openshift.api.model.UserIdentityMapping;
import io.fabric8.openshift.api.model.Role;
import io.fabric8.openshift.api.model.RoleList;
import io.fabric8.openshift.api.model.RoleBinding;
import io.fabric8.openshift.api.model.RoleBindingList;
import io.fabric8.openshift.api.model.ClusterRole;
import io.fabric8.openshift.api.model.ClusterRoleList;
import io.fabric8.openshift.api.model.ClusterRoleBinding;
import io.fabric8.openshift.api.model.ClusterRoleBindingList;
import io.fabric8.openshift.api.model.RoleBindingRestriction;
import io.fabric8.openshift.api.model.RoleBindingRestrictionList;
import io.fabric8.openshift.api.model.SecurityContextConstraints;
import io.fabric8.openshift.api.model.SecurityContextConstraintsList;
import io.fabric8.openshift.api.model.RangeAllocation;
import io.fabric8.openshift.api.model.RangeAllocationList;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.InOutCreateable;// List all users in the cluster
UserList users = client.users().list();
// Get a specific user
User user = client.users()
.withName("john.doe")
.get();
// Get current user (equivalent to 'oc whoami')
User currentUser = client.currentUser();
String currentUsername = currentUser.getMetadata().getName();
// Check user details
String fullName = user.getFullName();
List<String> identities = user.getIdentities();
List<String> groups = user.getGroups();// Get user identities and providers
User user = client.users()
.withName("jane.smith")
.get();
if (user.getIdentities() != null) {
for (String identityName : user.getIdentities()) {
Identity identity = client.identities()
.withName(identityName)
.get();
System.out.println("Identity: " + identity.getProviderName() +
":" + identity.getProviderUserName());
}
}// List all groups
GroupList groups = client.groups().list();
// Get a specific group
Group group = client.groups()
.withName("developers")
.get();
// Create a new group
Group newGroup = new GroupBuilder()
.withNewMetadata()
.withName("backend-developers")
.endMetadata()
.addToUsers("alice", "bob", "charlie")
.build();
Group created = client.groups().create(newGroup);// Add user to group
Group updatedGroup = client.groups()
.withName("developers")
.edit(group -> new GroupBuilder(group)
.addToUsers("new-developer")
.build());
// Remove user from group
Group reducedGroup = client.groups()
.withName("developers")
.edit(group -> new GroupBuilder(group)
.removeFromUsers("former-developer")
.build());
// Get group members
Group group = client.groups()
.withName("developers")
.get();
List<String> members = group.getUsers();
System.out.println("Group members: " + String.join(", ", members));// List all identities
IdentityList identities = client.identities().list();
// Get identity by name (format: provider:providerUserName)
Identity identity = client.identities()
.withName("github:johndoe")
.get();
// Find identities by provider
IdentityList githubIdentities = client.identities()
.withLabel("provider", "github")
.list();
// Get identity details
String providerName = identity.getProviderName();
String providerUserName = identity.getProviderUserName();
String userName = identity.getUser().getName();// Create user identity mapping (links identity to user)
UserIdentityMapping mapping = new UserIdentityMappingBuilder()
.withNewIdentity()
.withName("github:newuser")
.endIdentity()
.withNewUser()
.withName("new.user")
.endUser()
.build();
UserIdentityMapping created = client.userIdentityMappings()
.create(mapping);// List roles in a namespace
RoleList roles = client.roles()
.inNamespace("my-project")
.list();
// Get a specific role
Role role = client.roles()
.inNamespace("my-project")
.withName("developer-role")
.get();
// Create a custom role
Role customRole = new RoleBuilder()
.withNewMetadata()
.withName("custom-developer")
.withNamespace("my-project")
.endMetadata()
.addNewRule()
.withApiGroups("", "apps", "extensions")
.withResources("pods", "services", "deployments", "replicasets")
.withVerbs("get", "list", "watch", "create", "update", "patch", "delete")
.endRule()
.addNewRule()
.withApiGroups("build.openshift.io")
.withResources("builds", "buildconfigs")
.withVerbs("get", "list", "watch", "create")
.endRule()
.build();
Role created = client.roles()
.inNamespace("my-project")
.create(customRole);// List cluster roles (cluster-wide)
ClusterRoleList clusterRoles = client.clusterRoles().list();
// Get specific cluster role
ClusterRole clusterRole = client.clusterRoles()
.withName("cluster-admin")
.get();
// Create custom cluster role
ClusterRole customClusterRole = new ClusterRoleBuilder()
.withNewMetadata()
.withName("custom-cluster-viewer")
.endMetadata()
.addNewRule()
.withApiGroups("*")
.withResources("*")
.withVerbs("get", "list", "watch")
.endRule()
.addNewRule()
.withNonResourceURLs("/metrics", "/healthz")
.withVerbs("get")
.endRule()
.build();
ClusterRole created = client.clusterRoles().create(customClusterRole);// List role bindings in a namespace
RoleBindingList roleBindings = client.roleBindings()
.inNamespace("my-project")
.list();
// Get specific role binding
RoleBinding roleBinding = client.roleBindings()
.inNamespace("my-project")
.withName("developers-binding")
.get();
// Create role binding for user
RoleBinding userBinding = new RoleBindingBuilder()
.withNewMetadata()
.withName("developer-john")
.withNamespace("my-project")
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("Role")
.withName("developer-role")
.endRoleRef()
.addNewSubject()
.withKind("User")
.withName("john.doe")
.withApiGroup("rbac.authorization.k8s.io")
.endSubject()
.build();
RoleBinding created = client.roleBindings()
.inNamespace("my-project")
.create(userBinding);// Create role binding for group
RoleBinding groupBinding = new RoleBindingBuilder()
.withNewMetadata()
.withName("developers-group-binding")
.withNamespace("my-project")
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("edit")
.endRoleRef()
.addNewSubject()
.withKind("Group")
.withName("developers")
.withApiGroup("rbac.authorization.k8s.io")
.endSubject()
.build();
RoleBinding created = client.roleBindings()
.inNamespace("my-project")
.create(groupBinding);// List cluster role bindings
ClusterRoleBindingList clusterRoleBindings = client.clusterRoleBindings().list();
// Create cluster role binding
ClusterRoleBinding clusterBinding = new ClusterRoleBindingBuilder()
.withNewMetadata()
.withName("cluster-admins")
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName("cluster-admin")
.endRoleRef()
.addNewSubject()
.withKind("User")
.withName("admin-user")
.withApiGroup("rbac.authorization.k8s.io")
.endSubject()
.addNewSubject()
.withKind("Group")
.withName("cluster-admins")
.withApiGroup("rbac.authorization.k8s.io")
.endSubject()
.build();
ClusterRoleBinding created = client.clusterRoleBindings().create(clusterBinding);// List role binding restrictions
RoleBindingRestrictionList restrictions = client.roleBindingRestrictions()
.inNamespace("my-project")
.list();
// Create role binding restriction
RoleBindingRestriction restriction = new RoleBindingRestrictionBuilder()
.withNewMetadata()
.withName("no-admin-bindings")
.withNamespace("my-project")
.endMetadata()
.withNewSpec()
.addNewRoleBindingRestriction()
.addToRoles("admin", "cluster-admin")
.endRoleBindingRestriction()
.addNewUserRestriction()
.addToUsers("restricted-user")
.endUserRestriction()
.endSpec()
.build();
RoleBindingRestriction created = client.roleBindingRestrictions()
.inNamespace("my-project")
.create(restriction);// List all security context constraints
SecurityContextConstraintsList sccs = client.securityContextConstraints().list();
// Get specific SCC
SecurityContextConstraints scc = client.securityContextConstraints()
.withName("restricted")
.get();
// Get SCC details
Boolean allowHostDirVolumePlugin = scc.getAllowHostDirVolumePlugin();
Boolean allowHostNetwork = scc.getAllowHostNetwork();
Boolean allowHostPorts = scc.getAllowHostPorts();
Boolean allowPrivilegedContainer = scc.getAllowPrivilegedContainer();
Boolean readOnlyRootFilesystem = scc.getReadOnlyRootFilesystem();// Create custom security context constraint
SecurityContextConstraints customSCC = new SecurityContextConstraintsBuilder()
.withNewMetadata()
.withName("custom-scc")
.endMetadata()
.withAllowHostDirVolumePlugin(false)
.withAllowHostIPC(false)
.withAllowHostNetwork(false)
.withAllowHostPID(false)
.withAllowHostPorts(false)
.withAllowPrivilegedContainer(false)
.withAllowedCapabilities() // No additional capabilities
.withDefaultAddCapabilities() // No default capabilities
.withRequiredDropCapabilities("ALL")
.withAllowedFlexVolumes() // No flex volumes
.withReadOnlyRootFilesystem(true)
.withNewRunAsUser()
.withType("MustRunAsRange")
.endRunAsUser()
.withNewSeLinuxContext()
.withType("MustRunAs")
.endSeLinuxContext()
.withNewFsGroup()
.withType("MustRunAs")
.endFsGroup()
.withUsers("system:serviceaccount:my-project:restricted-sa")
.build();
SecurityContextConstraints created = client.securityContextConstraints()
.create(customSCC);// Add user to SCC
SecurityContextConstraints updated = client.securityContextConstraints()
.withName("anyuid")
.edit(scc -> new SecurityContextConstraintsBuilder(scc)
.addToUsers("system:serviceaccount:my-project:privileged-sa")
.build());
// Add group to SCC
SecurityContextConstraints groupUpdated = client.securityContextConstraints()
.withName("privileged")
.edit(scc -> new SecurityContextConstraintsBuilder(scc)
.addToGroups("system:authenticated")
.build());// List range allocations (UID/GID ranges)
RangeAllocationList rangeAllocations = client.rangeAllocations().list();
// Get specific range allocation
RangeAllocation uidRange = client.rangeAllocations()
.withName("uid-range")
.get();
// Range allocation details
String range = uidRange.getRange(); // e.g., "1000000000-1000999999/10000"
byte[] data = uidRange.getData(); // Allocation bitmap// Monitor role binding changes
client.roleBindings()
.inAnyNamespace()
.watch(new Watcher<RoleBinding>() {
@Override
public void eventReceived(Action action, RoleBinding roleBinding) {
System.out.println("RoleBinding " + action + ": " +
roleBinding.getMetadata().getName() +
" in namespace " + roleBinding.getMetadata().getNamespace());
// Log subjects
roleBinding.getSubjects().forEach(subject ->
System.out.println(" Subject: " + subject.getKind() +
"/" + subject.getName()));
}
@Override
public void onClose(WatcherException cause) {
System.out.println("RoleBinding watch closed: " + cause.getMessage());
}
});
// Monitor user changes
client.users().watch(new Watcher<User>() {
@Override
public void eventReceived(Action action, User user) {
System.out.println("User " + action + ": " + user.getMetadata().getName());
if (user.getGroups() != null) {
System.out.println(" Groups: " + String.join(", ", user.getGroups()));
}
}
@Override
public void onClose(WatcherException cause) {
System.out.println("User watch closed: " + cause.getMessage());
}
});import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.api.model.*;
import io.fabric8.kubernetes.api.model.rbac.*;
public class UserSecurityManager {
private final OpenShiftClient client;
public UserSecurityManager(OpenShiftClient client) {
this.client = client;
}
public void setupUserAccess(String username, String namespace,
String role, List<String> groups) {
// 1. Verify user exists
User user = client.users().withName(username).get();
if (user == null) {
System.out.println("Warning: User " + username + " not found in system");
return;
}
// 2. Add user to groups if specified
if (groups != null && !groups.isEmpty()) {
addUserToGroups(username, groups);
}
// 3. Create role binding for user in namespace
createUserRoleBinding(username, namespace, role);
// 4. Verify access
verifyUserAccess(username, namespace);
System.out.println("User access setup completed for: " + username);
}
private void addUserToGroups(String username, List<String> groups) {
for (String groupName : groups) {
Group group = client.groups().withName(groupName).get();
if (group == null) {
// Create group if it doesn't exist
group = client.groups().create(new GroupBuilder()
.withNewMetadata()
.withName(groupName)
.endMetadata()
.addToUsers(username)
.build());
System.out.println("Created group: " + groupName);
} else {
// Add user to existing group
if (!group.getUsers().contains(username)) {
client.groups().withName(groupName)
.edit(g -> new GroupBuilder(g)
.addToUsers(username)
.build());
System.out.println("Added " + username + " to group: " + groupName);
}
}
}
}
private void createUserRoleBinding(String username, String namespace, String role) {
String bindingName = username + "-" + role + "-binding";
RoleBinding binding = new RoleBindingBuilder()
.withNewMetadata()
.withName(bindingName)
.withNamespace(namespace)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole") // Assume cluster role
.withName(role)
.endRoleRef()
.addNewSubject()
.withKind("User")
.withName(username)
.withApiGroup("rbac.authorization.k8s.io")
.endSubject()
.build();
client.roleBindings()
.inNamespace(namespace)
.createOrReplace(binding);
System.out.println("Created role binding: " + bindingName);
}
private void verifyUserAccess(String username, String namespace) {
// Get all role bindings that include this user
RoleBindingList roleBindings = client.roleBindings()
.inNamespace(namespace)
.list();
List<String> userRoles = new ArrayList<>();
for (RoleBinding binding : roleBindings.getItems()) {
boolean hasUser = binding.getSubjects().stream()
.anyMatch(subject ->
"User".equals(subject.getKind()) &&
username.equals(subject.getName()));
if (hasUser) {
userRoles.add(binding.getRoleRef().getName());
}
}
System.out.println("User " + username + " has roles in " + namespace +
": " + String.join(", ", userRoles));
}
public void auditSecurityPolicies(String namespace) {
System.out.println("Security audit for namespace: " + namespace);
// Audit role bindings
RoleBindingList roleBindings = client.roleBindings()
.inNamespace(namespace)
.list();
System.out.println("\nRole Bindings:");
for (RoleBinding binding : roleBindings.getItems()) {
System.out.println(" " + binding.getMetadata().getName() +
" -> " + binding.getRoleRef().getName());
binding.getSubjects().forEach(subject ->
System.out.println(" " + subject.getKind() + ": " + subject.getName()));
}
// Audit security context constraints usage
SecurityContextConstraintsList sccs = client.securityContextConstraints().list();
System.out.println("\nSecurity Context Constraints with namespace access:");
for (SecurityContextConstraints scc : sccs.getItems()) {
boolean hasNamespaceAccess = false;
if (scc.getUsers() != null) {
hasNamespaceAccess = scc.getUsers().stream()
.anyMatch(user -> user.contains(namespace));
}
if (hasNamespaceAccess) {
System.out.println(" " + scc.getMetadata().getName() +
" (privileged: " + scc.getAllowPrivilegedContainer() + ")");
}
}
}
}public class ServiceAccountSecurity {
private final OpenShiftClient client;
public ServiceAccountSecurity(OpenShiftClient client) {
this.client = client;
}
public void setupServiceAccountSecurity(String namespace, String saName,
String sccName, List<String> roles) {
// 1. Create service account
ServiceAccount sa = new ServiceAccountBuilder()
.withNewMetadata()
.withName(saName)
.withNamespace(namespace)
.endMetadata()
.build();
client.serviceAccounts()
.inNamespace(namespace)
.createOrReplace(sa);
// 2. Add service account to SCC
String saFullName = "system:serviceaccount:" + namespace + ":" + saName;
client.securityContextConstraints()
.withName(sccName)
.edit(scc -> new SecurityContextConstraintsBuilder(scc)
.addToUsers(saFullName)
.build());
// 3. Create role bindings for service account
for (String role : roles) {
RoleBinding saBinding = new RoleBindingBuilder()
.withNewMetadata()
.withName(saName + "-" + role + "-binding")
.withNamespace(namespace)
.endMetadata()
.withNewRoleRef()
.withApiGroup("rbac.authorization.k8s.io")
.withKind("ClusterRole")
.withName(role)
.endRoleRef()
.addNewSubject()
.withKind("ServiceAccount")
.withName(saName)
.withNamespace(namespace)
.endSubject()
.build();
client.roleBindings()
.inNamespace(namespace)
.createOrReplace(saBinding);
}
System.out.println("Service account security setup completed: " + saName);
}
}public class User implements HasMetadata {
public ObjectMeta getMetadata();
public String getFullName();
public List<String> getIdentities();
public List<String> getGroups();
}public class Group implements HasMetadata {
public ObjectMeta getMetadata();
public List<String> getUsers();
}public class Identity implements HasMetadata {
public ObjectMeta getMetadata();
public String getProviderName();
public String getProviderUserName();
public ObjectReference getUser();
public Object getExtra();
}public class Role implements HasMetadata {
public ObjectMeta getMetadata();
public List<PolicyRule> getRules();
}
public class ClusterRole implements HasMetadata {
public ObjectMeta getMetadata();
public List<PolicyRule> getRules();
public AggregationRule getAggregationRule();
}
public class PolicyRule {
public List<String> getApiGroups();
public List<String> getResources();
public List<String> getResourceNames();
public List<String> getVerbs();
public List<String> getNonResourceURLs();
}public class RoleBinding implements HasMetadata {
public ObjectMeta getMetadata();
public RoleRef getRoleRef();
public List<Subject> getSubjects();
}
public class ClusterRoleBinding implements HasMetadata {
public ObjectMeta getMetadata();
public RoleRef getRoleRef();
public List<Subject> getSubjects();
}
public class RoleRef {
public String getApiGroup();
public String getKind();
public String getName();
}
public class Subject {
public String getApiGroup();
public String getKind(); // User, Group, ServiceAccount
public String getName();
public String getNamespace();
}public class SecurityContextConstraints implements HasMetadata {
public ObjectMeta getMetadata();
public Boolean getAllowHostDirVolumePlugin();
public Boolean getAllowHostIPC();
public Boolean getAllowHostNetwork();
public Boolean getAllowHostPID();
public Boolean getAllowHostPorts();
public Boolean getAllowPrivilegedContainer();
public List<String> getAllowedCapabilities();
public List<String> getDefaultAddCapabilities();
public List<String> getRequiredDropCapabilities();
public List<AllowedFlexVolume> getAllowedFlexVolumes();
public Boolean getReadOnlyRootFilesystem();
public RunAsUserStrategyOptions getRunAsUser();
public SELinuxContextStrategyOptions getSeLinuxContext();
public FSGroupStrategyOptions getFsGroup();
public List<String> getUsers();
public List<String> getGroups();
public Integer getPriority();
}Install with Tessl CLI
npx tessl i tessl/maven-io-fabric8--kubernetes-client-project