/* * Copyright 2016 Red Hat, Inc. * * 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.wildfly.extension.messaging.activemq; import java.util.Set; import java.util.stream.Collectors; import org.apache.activemq.artemis.core.security.CheckType; import org.apache.activemq.artemis.core.security.Role; import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager; import org.wildfly.extension.messaging.activemq.logging.MessagingLogger; import org.wildfly.security.auth.server.RealmUnavailableException; import org.wildfly.security.auth.server.SecurityDomain; import org.wildfly.security.auth.server.SecurityIdentity; import org.wildfly.security.auth.server.ServerAuthenticationContext; import org.wildfly.security.evidence.PasswordGuessEvidence; /** * This class implements an {@link ActiveMQSecurityManager} that uses an Elytron {@link SecurityDomain} to authenticate * users and perform role checking. * * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a> */ public class ElytronSecurityManager implements ActiveMQSecurityManager { private final SecurityDomain securityDomain; private final String defaultUser; private final String defaultPassword; /** * Creates an instance of {@link ElytronSecurityManager} with the specified {@link SecurityDomain}. * * @param securityDomain a reference to the Elytron {@link SecurityDomain} that will be used to authenticate users. */ public ElytronSecurityManager(final SecurityDomain securityDomain) { if (securityDomain == null) throw MessagingLogger.ROOT_LOGGER.invalidNullSecurityDomain(); this.securityDomain = securityDomain; this.defaultUser = DefaultCredentials.getUsername(); this.defaultPassword = DefaultCredentials.getPassword(); } @Override public boolean validateUser(String username, String password) { if (defaultUser.equals(username) && defaultPassword.equals(password)) return true; return this.authenticate(username, password) != null; } @Override public boolean validateUserAndRole(String username, String password, Set<Role> roles, CheckType checkType) { if (defaultUser.equals(username) && defaultPassword.equals(password)) return true; final SecurityIdentity identity = this.authenticate(username, password); final Set<String> filteredRoles = roles.stream().filter(checkType::hasRole).map(Role::getName).collect(Collectors.toSet()); return identity.getRoles().containsAny(filteredRoles); } /** * Attempt to authenticate and authorize an username with the specified password evidence. * * @param username the username being authenticated. * @param password the password to be verified. * @return a reference to the {@link SecurityIdentity} if the user was successfully authenticated and authorized; * {@code null} otherwise. */ private SecurityIdentity authenticate(final String username, final String password) { ServerAuthenticationContext context = this.securityDomain.createNewAuthenticationContext(); PasswordGuessEvidence evidence = null; try { if (password == null) { if (username == null) { if (context.authorizeAnonymous()) { context.succeed(); return context.getAuthorizedIdentity(); } else { context.fail(); return null; } } else { // treat a non-null user name with a null password as a auth failure context.fail(); return null; } } context.setAuthenticationName(username); evidence = new PasswordGuessEvidence(password.toCharArray()); if (context.verifyEvidence(evidence)) { if (context.authorize()) { context.succeed(); return context.getAuthorizedIdentity(); } else { context.fail(); MessagingLogger.ROOT_LOGGER.failedAuthorization(username); } } else { context.fail(); MessagingLogger.ROOT_LOGGER.failedAuthentication(username); } } catch (IllegalArgumentException | IllegalStateException | RealmUnavailableException e) { context.fail(); MessagingLogger.ROOT_LOGGER.failedAuthenticationWithException(e, username, e.getMessage()); } finally { if (evidence != null) { evidence.destroy(); } } return null; } }