/* * 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 com.addthis.hydra.job.auth; import javax.annotation.Nonnull; import java.io.IOException; import com.google.common.collect.ImmutableList; import com.google.common.io.Closer; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * In the nested authentication manager the inner manager * has precedence over the outer manager. * * If the user is authenticated using the inner manager * then the outer manager is used as a decorator to augment * the profile of the user. If the user is authenticated using * the inner manager then authentication is ignored by the outer manager. * * If the user is not authenticated using the inner manager * then authentication is performed using the outer manager. */ class AuthenticationManagerNested extends AuthenticationManager { private static final Logger log = LoggerFactory.getLogger(AuthenticationManagerNested.class); @Nonnull final AuthenticationManager inner; @Nonnull final AuthenticationManager outer; @Nonnull final Closer closer; @JsonCreator public AuthenticationManagerNested(@JsonProperty("inner") AuthenticationManager inner, @JsonProperty("outer") AuthenticationManager outer) { this.inner = inner; this.outer = outer; this.closer = Closer.create(); closer.register(outer); closer.register(inner); log.info("Registering nested authentication"); } @Override String login(String username, String password, boolean ssl) { if ((username == null) || (password == null)) { return null; } String token = inner.login(username, password, ssl); if (token == null) { token = outer.login(username, password, ssl); } return token; } @Override public boolean verify(String username, String password, boolean ssl) { if ((username == null) || (password == null)) { return false; } return inner.verify(username, password, ssl) || outer.verify(username, password, ssl); } @Override User authenticate(String username, String secret) { if ((username == null) || (secret == null)) { return null; } User innerMatch = inner.authenticate(username, secret); User outerMatch; if (innerMatch != null) { outerMatch = outer.getUser(username); } else { outerMatch = outer.authenticate(username, secret); } return DefaultUser.join(innerMatch, outerMatch); } @Override User getUser(String username) { if (username == null) { return null; } User innerUser = inner.getUser(username); User outerUser = outer.getUser(username); return DefaultUser.join(innerUser, outerUser); } @Override String sudoToken(String username) { if (username == null) { return null; } String innerToken = inner.sudoToken(username); if (innerToken != null) { return innerToken; } else { return outer.sudoToken(username); } } @Override public void evict(String username) { inner.evict(username); outer.evict(username); } @Override void logout(String username, String secret) { inner.logout(username, secret); outer.logout(username, secret); } @Override public void close() throws IOException { closer.close(); } @Override ImmutableList<String> adminGroups() { return ImmutableList.<String>builder().addAll(inner.adminGroups()).addAll(outer.adminGroups()).build(); } @Override ImmutableList<String> adminUsers() { return ImmutableList.<String>builder().addAll(inner.adminUsers()).addAll(outer.adminGroups()).build(); } }