blob: 52eee250da5733f60510e10e80d4ae929b4f5900 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.accumulo.server.rpc;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
import org.apache.accumulo.core.client.security.tokens.KerberosToken;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.ConfigurationCopy;
import org.apache.accumulo.core.conf.DefaultConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.security.thrift.TCredentials;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.google.common.base.Predicate;
public class TCredentialsUpdatingInvocationHandlerTest {
private static final DefaultConfiguration DEFAULT_CONFIG = DefaultConfiguration.getInstance();
TCredentialsUpdatingInvocationHandler<Object> proxy;
ConfigurationCopy cc;
AccumuloConfiguration conf;
@Before
public void setup() {
cc = new ConfigurationCopy();
conf = new AccumuloConfiguration() {
@Override
public String get(Property property) {
String value = cc.get(property);
if (null == value) {
return DEFAULT_CONFIG.get(property);
}
return value;
}
@Override
public void getProperties(Map<String,String> props, Predicate<String> filter) {
cc.getProperties(props, filter);
}
};
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
}
@After
public void teardown() {
UGIAssumingProcessor.rpcPrincipal.set(null);
}
@Test
public void testNoArgsAreIgnored() throws Exception {
proxy.updateArgs(new Object[] {});
}
@Test
public void testNoTCredsInArgsAreIgnored() throws Exception {
proxy.updateArgs(new Object[] {new Object(), new Object()});
}
@Test
public void testCachedTokenClass() throws Exception {
final String principal = "root";
ConcurrentHashMap<String,Class<? extends AuthenticationToken>> cache = proxy.getTokenCache();
cache.clear();
TCredentials tcreds = new TCredentials(principal, KerberosToken.CLASS_NAME, ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(principal);
proxy.updateArgs(new Object[] {new Object(), tcreds});
Assert.assertEquals(1, cache.size());
Assert.assertEquals(KerberosToken.class, cache.get(KerberosToken.CLASS_NAME));
}
@Test(expected = ThriftSecurityException.class)
public void testMissingPrincipal() throws Exception {
final String principal = "root";
TCredentials tcreds = new TCredentials(principal, KerberosToken.CLASS_NAME, ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(null);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test(expected = ThriftSecurityException.class)
public void testMismatchedPrincipal() throws Exception {
final String principal = "root";
TCredentials tcreds = new TCredentials(principal, KerberosToken.CLASS_NAME, ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(principal + "foobar");
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test(expected = ThriftSecurityException.class)
public void testWrongTokenType() throws Exception {
final String principal = "root";
TCredentials tcreds = new TCredentials(principal, PasswordToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(principal);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test
public void testAllowedAnyImpersonationForAnyUser() throws Exception {
final String proxyServer = "proxy";
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "*");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test
public void testAllowedAnyImpersonationForAnyUserNewConfig() throws Exception {
final String proxyServer = "proxy";
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, proxyServer + ":*");
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test
public void testAllowedImpersonationForSpecificUsers() throws Exception {
final String proxyServer = "proxy";
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", "client1,client2");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
tcreds = new TCredentials("client2", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test
public void testAllowedImpersonationForSpecificUsersNewConfig() throws Exception {
final String proxyServer = "proxy";
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, proxyServer + ":client1,client2");
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
tcreds = new TCredentials("client2", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationForUser() throws Exception {
final String proxyServer = "proxy";
// let "otherproxy" impersonate, but not "proxy"
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".users", "*");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy" + ".hosts", "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationForUserNewConfig() throws Exception {
final String proxyServer = "proxy";
// let "otherproxy" impersonate, but not "proxy"
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, "otherproxy:*");
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationForMultipleUsers() throws Exception {
final String proxyServer = "proxy";
// let "otherproxy" impersonate, but not "proxy"
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".users", "*");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy1" + ".hosts", "*");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".users", "client1,client2");
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + "otherproxy2" + ".hosts", "*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationForMultipleUsersNewConfig() throws Exception {
final String proxyServer = "proxy";
// let "otherproxy" impersonate, but not "proxy"
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, "otherproxy1:*;otherproxy2:client1,client2");
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, "*;*");
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client1", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test
public void testAllowedImpersonationFromSpecificHost() throws Exception {
final String proxyServer = "proxy", client = "client", host = "host.domain.com";
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
TServerUtils.clientAddress.set(host);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test
public void testAllowedImpersonationFromSpecificHostNewConfig() throws Exception {
final String proxyServer = "proxy", client = "client", host = "host.domain.com";
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, proxyServer + ":" + client);
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, host);
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
TServerUtils.clientAddress.set(host);
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@SuppressWarnings("deprecation")
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationFromSpecificHost() throws Exception {
final String proxyServer = "proxy", client = "client", host = "host.domain.com";
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".users", client);
cc.set(Property.INSTANCE_RPC_SASL_PROXYUSERS.getKey() + proxyServer + ".hosts", host);
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
// The RPC came from a different host than is allowed
TServerUtils.clientAddress.set("otherhost.domain.com");
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
@Test(expected = ThriftSecurityException.class)
public void testDisallowedImpersonationFromSpecificHostNewConfig() throws Exception {
final String proxyServer = "proxy", client = "client", host = "host.domain.com";
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_USER_IMPERSONATION, proxyServer + ":" + client);
cc.set(Property.INSTANCE_RPC_SASL_ALLOWED_HOST_IMPERSONATION, host);
proxy = new TCredentialsUpdatingInvocationHandler<>(new Object(), conf);
TCredentials tcreds = new TCredentials("client", KerberosToken.class.getName(), ByteBuffer.allocate(0), UUID.randomUUID().toString());
UGIAssumingProcessor.rpcPrincipal.set(proxyServer);
// The RPC came from a different host than is allowed
TServerUtils.clientAddress.set("otherhost.domain.com");
proxy.updateArgs(new Object[] {new Object(), tcreds});
}
}