HDFS-13682. Cannot create encryption zone after KMS auth token expires.

(cherry picked from commit 32f867a6a9)
This commit is contained in:
Xiao Chen 2018-06-20 15:58:01 -07:00
parent a31a966a20
commit e8655b8c72
3 changed files with 41 additions and 6 deletions

View File

@ -32,7 +32,9 @@ import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.ProviderUtils; import org.apache.hadoop.security.ProviderUtils;
import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
import org.apache.hadoop.security.authentication.client.ConnectionConfigurator; import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
import org.apache.hadoop.security.ssl.SSLFactory; import org.apache.hadoop.security.ssl.SSLFactory;
import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.TokenIdentifier;
@ -543,7 +545,9 @@ public class KMSClientProvider extends KeyProvider implements CryptoExtension,
String requestMethod = conn.getRequestMethod(); String requestMethod = conn.getRequestMethod();
URL url = conn.getURL(); URL url = conn.getURL();
conn = createConnection(url, requestMethod); conn = createConnection(url, requestMethod);
conn.setRequestProperty(CONTENT_TYPE, contentType); if (contentType != null && !contentType.isEmpty()) {
conn.setRequestProperty(CONTENT_TYPE, contentType);
}
return call(conn, jsonOutput, expectedResponse, klass, return call(conn, jsonOutput, expectedResponse, klass,
authRetryCount - 1); authRetryCount - 1);
} }
@ -1087,8 +1091,7 @@ public class KMSClientProvider extends KeyProvider implements CryptoExtension,
actualUgi = currentUgi.getRealUser(); actualUgi = currentUgi.getRealUser();
} }
if (UserGroupInformation.isSecurityEnabled() && if (UserGroupInformation.isSecurityEnabled() &&
!containsKmsDt(actualUgi) && !containsKmsDt(actualUgi) && !actualUgi.shouldRelogin()) {
!actualUgi.hasKerberosCredentials()) {
// Use login user is only necessary when Kerberos is enabled // Use login user is only necessary when Kerberos is enabled
// but the actual user does not have either // but the actual user does not have either
// Kerberos credential or KMS delegation token for KMS operations // Kerberos credential or KMS delegation token for KMS operations

View File

@ -830,7 +830,9 @@ public class UserGroupInformation {
return start + (long) ((end - start) * TICKET_RENEW_WINDOW); return start + (long) ((end - start) * TICKET_RENEW_WINDOW);
} }
private boolean shouldRelogin() { @InterfaceAudience.Private
@InterfaceStability.Unstable
public boolean shouldRelogin() {
return hasKerberosCredentials() && isHadoopLogin(); return hasKerberosCredentials() && isHadoopLogin();
} }

View File

@ -107,6 +107,8 @@ public class TestSecureEncryptionZoneWithKMS {
// MiniKMS // MiniKMS
private static MiniKMS miniKMS; private static MiniKMS miniKMS;
private final String testKey = "test_key"; private final String testKey = "test_key";
private static boolean testKeyCreated = false;
private static final long AUTH_TOKEN_VALIDITY = 1;
// MiniDFS // MiniDFS
private MiniDFSCluster cluster; private MiniDFSCluster cluster;
@ -128,7 +130,7 @@ public class TestSecureEncryptionZoneWithKMS {
} }
@Rule @Rule
public Timeout timeout = new Timeout(30000); public Timeout timeout = new Timeout(120000);
@BeforeClass @BeforeClass
public static void init() throws Exception { public static void init() throws Exception {
@ -215,6 +217,9 @@ public class TestSecureEncryptionZoneWithKMS {
"HTTP/localhost"); "HTTP/localhost");
kmsConf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT"); kmsConf.set("hadoop.kms.authentication.kerberos.name.rules", "DEFAULT");
kmsConf.set("hadoop.kms.acl.GENERATE_EEK", "hdfs"); kmsConf.set("hadoop.kms.acl.GENERATE_EEK", "hdfs");
// set kms auth token expiration low for testCreateZoneAfterAuthTokenExpiry
kmsConf.setLong("hadoop.kms.authentication.token.validity",
AUTH_TOKEN_VALIDITY);
Writer writer = new FileWriter(kmsFile); Writer writer = new FileWriter(kmsFile);
kmsConf.writeXml(writer); kmsConf.writeXml(writer);
@ -260,7 +265,10 @@ public class TestSecureEncryptionZoneWithKMS {
cluster.waitActive(); cluster.waitActive();
// Create a test key // Create a test key
DFSTestUtil.createKey(testKey, cluster, conf); if (!testKeyCreated) {
DFSTestUtil.createKey(testKey, cluster, conf);
testKeyCreated = true;
}
} }
@After @After
@ -307,4 +315,26 @@ public class TestSecureEncryptionZoneWithKMS {
} }
}); });
} }
@Test
public void testCreateZoneAfterAuthTokenExpiry() throws Exception {
final UserGroupInformation ugi = UserGroupInformation
.loginUserFromKeytabAndReturnUGI(hdfsPrincipal, keytab);
LOG.info("Created ugi: {} ", ugi);
ugi.doAs((PrivilegedExceptionAction<Object>) () -> {
final Path zone = new Path("/expire1");
fsWrapper.mkdir(zone, FsPermission.getDirDefault(), true);
dfsAdmin.createEncryptionZone(zone, testKey, NO_TRASH);
final Path zone1 = new Path("/expire2");
fsWrapper.mkdir(zone1, FsPermission.getDirDefault(), true);
final long sleepInterval = (AUTH_TOKEN_VALIDITY + 1) * 1000;
LOG.info("Sleeping {} seconds to wait for kms auth token expiration",
sleepInterval);
Thread.sleep(sleepInterval);
dfsAdmin.createEncryptionZone(zone1, testKey, NO_TRASH);
return null;
});
}
} }