ACCUMULO-4666 Improve KerberosToken sanity-checks and related doc
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/3d552ea4 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/3d552ea4 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/3d552ea4 Branch: refs/heads/1.8 Commit: 3d552ea41cf70b46370a3a1e05b53ce511a144a6 Parents: efc5a98 Author: Josh Elser <els...@apache.org> Authored: Tue Jun 27 12:47:32 2017 -0400 Committer: Josh Elser <els...@apache.org> Committed: Tue Jun 27 13:23:53 2017 -0400 ---------------------------------------------------------------------- .../client/security/tokens/KerberosToken.java | 18 ++- .../security/tokens/KerberosTokenTest.java | 51 +++++++++ .../security/KerberosTokenEmbeddedKDCTest.java | 112 +++++++++++++++++++ .../test/security/KerberosTokenTest.java | 112 ------------------- 4 files changed, 177 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/3d552ea4/core/src/main/java/org/apache/accumulo/core/client/security/tokens/KerberosToken.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/KerberosToken.java b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/KerberosToken.java index 5bcab1a..9290f71 100644 --- a/core/src/main/java/org/apache/accumulo/core/client/security/tokens/KerberosToken.java +++ b/core/src/main/java/org/apache/accumulo/core/client/security/tokens/KerberosToken.java @@ -48,15 +48,25 @@ public class KerberosToken implements AuthenticationToken { /** * Creates a token using the provided principal and the currently logged-in user via {@link UserGroupInformation}. * + * This method expects the current user (as defined by {@link UserGroupInformation#getCurrentUser()} to be authenticated via Kerberos or as a Proxy (on top of + * another user). An {@link IllegalArgumentException} will be thrown for all other cases. + * * @param principal * The user that is logged in + * @throws IllegalArgumentException + * If the current user is not authentication via Kerberos or Proxy methods. + * @see UserGroupInformation#getCurrentUser() + * @see UserGroupInformation#getAuthenticationMethod() */ public KerberosToken(String principal) throws IOException { this.principal = requireNonNull(principal); - final UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - if (AuthenticationMethod.KERBEROS == ugi.getAuthenticationMethod()) { - checkArgument(ugi.hasKerberosCredentials(), "Subject is not logged in via Kerberos"); - } + validateAuthMethod(UserGroupInformation.getCurrentUser().getAuthenticationMethod()); + } + + static void validateAuthMethod(AuthenticationMethod authMethod) { + // There is also KERBEROS_SSL but that appears to be deprecated/OBE + checkArgument(AuthenticationMethod.KERBEROS == authMethod || AuthenticationMethod.PROXY == authMethod, + "KerberosToken expects KERBEROS or PROXY authentication for the current UserGroupInformation user. Saw " + authMethod); } /** http://git-wip-us.apache.org/repos/asf/accumulo/blob/3d552ea4/core/src/test/java/org/apache/accumulo/core/client/security/tokens/KerberosTokenTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/client/security/tokens/KerberosTokenTest.java b/core/src/test/java/org/apache/accumulo/core/client/security/tokens/KerberosTokenTest.java new file mode 100644 index 0000000..0dbe97d --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/client/security/tokens/KerberosTokenTest.java @@ -0,0 +1,51 @@ +/* + * 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.core.client.security.tokens; + +import static org.junit.Assert.fail; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; +import org.junit.Test; + +/** + * Test class for {@link KerberosToken}. + */ +public class KerberosTokenTest { + + @Test + public void testAuthMethodAcceptance() { + // There is also KERBEROS_SSL but that appears to be deprecated/OBE + Set<AuthenticationMethod> allowedMethods = new HashSet<>(Arrays.asList(AuthenticationMethod.KERBEROS, AuthenticationMethod.PROXY)); + for (AuthenticationMethod authMethod : AuthenticationMethod.values()) { + final boolean allowable = allowedMethods.contains(authMethod); + try { + KerberosToken.validateAuthMethod(authMethod); + if (!allowable) { + fail(authMethod + " should have triggered a thrown exception but it did not"); + } + } catch (IllegalArgumentException e) { + if (allowable) { + fail(authMethod + " should not have triggered a thrown exception"); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/3d552ea4/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenEmbeddedKDCTest.java ---------------------------------------------------------------------- diff --git a/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenEmbeddedKDCTest.java b/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenEmbeddedKDCTest.java new file mode 100644 index 0000000..ae101d0 --- /dev/null +++ b/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenEmbeddedKDCTest.java @@ -0,0 +1,112 @@ +/* + * 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.test.security; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.accumulo.core.client.security.tokens.KerberosToken; +import org.apache.accumulo.harness.TestingKdc; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.CommonConfigurationKeysPublic; +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KerberosTokenEmbeddedKDCTest { + + private static final Logger log = LoggerFactory.getLogger(KerberosTokenEmbeddedKDCTest.class); + + @Rule + public TestName testName = new TestName(); + + private static TestingKdc kdc; + + @BeforeClass + public static void startKdc() throws Exception { + kdc = new TestingKdc(); + kdc.start(); + } + + @AfterClass + public static void stopKdc() throws Exception { + if (null != kdc) { + kdc.stop(); + } + } + + @Before + public void resetUgiForKrb() { + Configuration conf = new Configuration(false); + conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos"); + UserGroupInformation.setConfiguration(conf); + } + + @Test + public void test() throws Exception { + String user = testName.getMethodName(); + File userKeytab = new File(kdc.getKeytabDir(), user + ".keytab"); + if (userKeytab.exists() && !userKeytab.delete()) { + log.warn("Unable to delete {}", userKeytab); + } + + kdc.createPrincipal(userKeytab, user); + + user = kdc.qualifyUser(user); + + UserGroupInformation.loginUserFromKeytab(user, userKeytab.getAbsolutePath()); + KerberosToken token = new KerberosToken(); + + assertEquals(user, token.getPrincipal()); + + // Use the long-hand constructor, should be equivalent to short-hand + KerberosToken tokenWithPrinc = new KerberosToken(user); + assertEquals(token, tokenWithPrinc); + assertEquals(token.hashCode(), tokenWithPrinc.hashCode()); + } + + @Test + public void testDestroy() throws Exception { + String user = testName.getMethodName(); + File userKeytab = new File(kdc.getKeytabDir(), user + ".keytab"); + if (userKeytab.exists() && !userKeytab.delete()) { + log.warn("Unable to delete {}", userKeytab); + } + + kdc.createPrincipal(userKeytab, user); + + user = kdc.qualifyUser(user); + + UserGroupInformation.loginUserFromKeytab(user, userKeytab.getAbsolutePath()); + KerberosToken token = new KerberosToken(); + + assertEquals(user, token.getPrincipal()); + token.destroy(); + assertTrue(token.isDestroyed()); + assertNull(token.getPrincipal()); + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/3d552ea4/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenTest.java ---------------------------------------------------------------------- diff --git a/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenTest.java b/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenTest.java deleted file mode 100644 index ba7c41e..0000000 --- a/test/src/test/java/org/apache/accumulo/test/security/KerberosTokenTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.test.security; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; - -import org.apache.accumulo.core.client.security.tokens.KerberosToken; -import org.apache.accumulo.harness.TestingKdc; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.CommonConfigurationKeysPublic; -import org.apache.hadoop.security.UserGroupInformation; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class KerberosTokenTest { - - private static final Logger log = LoggerFactory.getLogger(KerberosTokenTest.class); - - @Rule - public TestName testName = new TestName(); - - private static TestingKdc kdc; - - @BeforeClass - public static void startKdc() throws Exception { - kdc = new TestingKdc(); - kdc.start(); - } - - @AfterClass - public static void stopKdc() throws Exception { - if (null != kdc) { - kdc.stop(); - } - } - - @Before - public void resetUgiForKrb() { - Configuration conf = new Configuration(false); - conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos"); - UserGroupInformation.setConfiguration(conf); - } - - @Test - public void test() throws Exception { - String user = testName.getMethodName(); - File userKeytab = new File(kdc.getKeytabDir(), user + ".keytab"); - if (userKeytab.exists() && !userKeytab.delete()) { - log.warn("Unable to delete {}", userKeytab); - } - - kdc.createPrincipal(userKeytab, user); - - user = kdc.qualifyUser(user); - - UserGroupInformation.loginUserFromKeytab(user, userKeytab.getAbsolutePath()); - KerberosToken token = new KerberosToken(); - - assertEquals(user, token.getPrincipal()); - - // Use the long-hand constructor, should be equivalent to short-hand - KerberosToken tokenWithPrinc = new KerberosToken(user); - assertEquals(token, tokenWithPrinc); - assertEquals(token.hashCode(), tokenWithPrinc.hashCode()); - } - - @Test - public void testDestroy() throws Exception { - String user = testName.getMethodName(); - File userKeytab = new File(kdc.getKeytabDir(), user + ".keytab"); - if (userKeytab.exists() && !userKeytab.delete()) { - log.warn("Unable to delete {}", userKeytab); - } - - kdc.createPrincipal(userKeytab, user); - - user = kdc.qualifyUser(user); - - UserGroupInformation.loginUserFromKeytab(user, userKeytab.getAbsolutePath()); - KerberosToken token = new KerberosToken(); - - assertEquals(user, token.getPrincipal()); - token.destroy(); - assertTrue(token.isDestroyed()); - assertNull(token.getPrincipal()); - } - -}