/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.uberfire.ext.security.management.keycloak; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.jboss.errai.security.shared.api.Group; import org.jboss.errai.security.shared.api.Role; import org.jboss.errai.security.shared.api.identity.User; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.client.ClientResponseFailure; import org.jboss.resteasy.spi.NotFoundException; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.uberfire.ext.security.management.api.AbstractEntityManager; import org.uberfire.ext.security.management.api.UserManager; import org.uberfire.ext.security.management.api.exception.GroupNotFoundException; import org.uberfire.ext.security.management.api.exception.OperationFailedException; import org.uberfire.ext.security.management.api.exception.SecurityManagementException; import org.uberfire.ext.security.management.api.exception.UserNotFoundException; import org.uberfire.ext.security.management.impl.SearchRequestImpl; import org.uberfire.ext.security.management.impl.UserAttributeImpl; import org.uberfire.ext.security.management.keycloak.client.ClientFactory; import org.uberfire.ext.security.management.keycloak.client.Keycloak; import org.uberfire.ext.security.management.keycloak.client.resource.RealmResource; import org.uberfire.ext.security.management.keycloak.client.resource.RoleMappingResource; import org.uberfire.ext.security.management.keycloak.client.resource.RoleResource; import org.uberfire.ext.security.management.keycloak.client.resource.UserResource; import org.uberfire.ext.security.management.keycloak.client.resource.UsersResource; import org.uberfire.ext.security.management.util.SecurityManagementUtils; public abstract class BaseKeyCloakManager { protected static final String ATTRIBUTE_USER_ID = "user.id"; protected static final String ATTRIBUTE_USER_FIRST_NAME = "user.firstName"; protected static final String ATTRIBUTE_USER_LAST_NAME = "user.lastName"; protected static final String ATTRIBUTE_USER_ENABLED = "user.enabled"; protected static final String ATTRIBUTE_USER_EMAIL = "user.email"; protected static final String ATTRIBUTE_USER_EMAIL_VERIFIED = "user.isEmailVerified"; protected static final UserManager.UserAttribute USER_ID = new UserAttributeImpl(ATTRIBUTE_USER_ID, true, false, null); protected static final UserManager.UserAttribute USER_FIST_NAME = new UserAttributeImpl(ATTRIBUTE_USER_FIRST_NAME, true, true, "First name"); protected static final UserManager.UserAttribute USER_LAST_NAME = new UserAttributeImpl(ATTRIBUTE_USER_LAST_NAME, true, true, "Last name"); protected static final UserManager.UserAttribute USER_ENABLED = new UserAttributeImpl(ATTRIBUTE_USER_ENABLED, true, true, "true"); protected static final UserManager.UserAttribute USER_EMAIL = new UserAttributeImpl(ATTRIBUTE_USER_EMAIL, false, true, ""); protected static final UserManager.UserAttribute USER_EMAIL_VERIFIED = new UserAttributeImpl(ATTRIBUTE_USER_EMAIL_VERIFIED, false, true, "false"); protected static final Collection<UserManager.UserAttribute> USER_ATTRIBUTES = Arrays.asList(USER_ID, USER_FIST_NAME, USER_LAST_NAME, USER_ENABLED, USER_EMAIL, USER_EMAIL_VERIFIED); private static final Logger LOG = LoggerFactory.getLogger(BaseKeyCloakManager.class); protected ClientFactory factory; protected void init(ClientFactory factory) { this.factory = factory; } protected synchronized Keycloak getKeyCloakInstance() { return factory.get(); } protected RealmResource getRealmResource() { return getKeyCloakInstance().realm(); } protected AbstractEntityManager.SearchRequest getSearchRequest(final AbstractEntityManager.SearchRequest request) { return request != null ? request : new SearchRequestImpl(); } protected User createUser(UserRepresentation userRepresentation) { return createUser(userRepresentation, null, null); } protected User createUser(UserRepresentation userRepresentation, Set<Group> groups, Set<Role> roles) { if (userRepresentation != null) { String username = userRepresentation.getUsername(); final User user = SecurityManagementUtils.createUser(username, groups, roles); fillUserAttributes(user, userRepresentation); return user; } return null; } protected Group createGroup(RoleRepresentation roleRepresentation) { if (roleRepresentation != null) { String name = roleRepresentation.getName(); ; final Group group = createGroup(name); return group; } return null; } protected Group createGroup(String name) { if (name != null) { final Group group = SecurityManagementUtils.createGroup(name); return group; } return null; } protected Set[] getUserGroupsAndRoles(final RoleMappingResource roleMappingResource) { if (roleMappingResource != null) { List<RoleRepresentation> roles = roleMappingResource.realmLevel().listEffective(); if (roles != null && !roles.isEmpty()) { final Set<Group> _groups = new HashSet<Group>(); final Set<Role> _roles = new HashSet<Role>(); final Set<String> registeredRoles = SecurityManagementUtils.getRegisteredRoleNames(); for (RoleRepresentation roleRepresentation : roles) { if (roleRepresentation != null) { String name = roleRepresentation.getName(); SecurityManagementUtils.populateGroupOrRoles(name, registeredRoles, _groups, _roles); } } return new Set[]{_groups, _roles}; } } return null; } protected void fillUserAttributes(final User user, final UserRepresentation userRepresentation) { final String userId = userRepresentation.getId(); final String firstName = userRepresentation.getFirstName(); final String lastName = userRepresentation.getLastName(); final String email = userRepresentation.getEmail(); final boolean isEmailVerified = userRepresentation.isEmailVerified(); final boolean isEnabled = userRepresentation.isEnabled(); user.setProperty(ATTRIBUTE_USER_ID, userId); user.setProperty(ATTRIBUTE_USER_FIRST_NAME, firstName); user.setProperty(ATTRIBUTE_USER_LAST_NAME, lastName); user.setProperty(ATTRIBUTE_USER_EMAIL, email); user.setProperty(ATTRIBUTE_USER_EMAIL_VERIFIED, Boolean.toString(isEmailVerified)); user.setProperty(ATTRIBUTE_USER_ENABLED, Boolean.toString(isEnabled)); final Map<String, Object> attrs = userRepresentation.getAttributes(); if (attrs != null && !attrs.isEmpty()) { for (final Map.Entry<String, Object> entry : attrs.entrySet()) { final String v = entry.getValue() != null ? entry.getValue().toString() : null; user.setProperty(entry.getKey(), v); } } } protected void fillUserRepresentationAttributes(final User user, final UserRepresentation userRepresentation) { String username = user.getIdentifier(); userRepresentation.setUsername(username); Map<String, String> props = user.getProperties(); if (props != null && !props.isEmpty()) { for (Map.Entry<String, String> entry : props.entrySet()) { final String key = entry.getKey(); final String value = entry.getValue(); if (ATTRIBUTE_USER_ID.equals(key)) { userRepresentation.setId(value); } else if (ATTRIBUTE_USER_FIRST_NAME.equals(key)) { userRepresentation.setFirstName(value); } else if (ATTRIBUTE_USER_LAST_NAME.equals(key)) { userRepresentation.setLastName(value); } else if (ATTRIBUTE_USER_EMAIL.equals(key)) { userRepresentation.setEmail(value); } else if (ATTRIBUTE_USER_EMAIL_VERIFIED.equals(key)) { userRepresentation.setEmailVerified(Boolean.valueOf(value)); } else if (ATTRIBUTE_USER_ENABLED.equals(key)) { userRepresentation.setEnabled(Boolean.valueOf(value)); } else { userRepresentation.singleAttribute(key, value); } } } } protected UserResource getUserResource(UsersResource usersResource, String username) { List<UserRepresentation> userRepresentations = usersResource.search(username, null, null, null, 0, 1); if (userRepresentations == null || userRepresentations.isEmpty()) { throw new UserNotFoundException(username); } String id = userRepresentations.get(0).getId(); return usersResource.get(id); } protected RoleRepresentation getRoleRepresentation(String name, RoleResource roleResource) { if (roleResource != null) { try { return roleResource.toRepresentation(); } catch (NotFoundException e) { throw new GroupNotFoundException(name); } catch (ClientResponseFailure clientResponseFailure) { int status = clientResponseFailure.getResponse().getResponseStatus().getStatusCode(); if (404 == status) { throw new GroupNotFoundException(name); } } catch (Exception e) { throw new SecurityManagementException(e); } } throw new GroupNotFoundException(name); } protected void handleResponse(ClientResponse response) { if (response != null) { int status = response.getStatus(); response.releaseConnection(); if (status >= 400) { throw new OperationFailedException(status, "Operation failed. See server log messages."); } } } }