HADOOP-14251. Credential provider should handle property key deprecation. Contributed by John Zhuge.
(cherry picked from commit 7e6463d2fb
)
Conflicts:
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestConfiguration.java
This commit is contained in:
parent
245b49332d
commit
6e8c696651
|
@ -299,18 +299,25 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
this.customMessage = customMessage;
|
||||
}
|
||||
|
||||
private final String getWarningMessage(String key) {
|
||||
return getWarningMessage(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to provide the warning message. It gives the custom message if
|
||||
* non-null, and default message otherwise.
|
||||
* @param key the associated deprecated key.
|
||||
* @param source the property source.
|
||||
* @return message that is to be logged when a deprecated key is used.
|
||||
*/
|
||||
private final String getWarningMessage(String key) {
|
||||
private String getWarningMessage(String key, String source) {
|
||||
String warningMessage;
|
||||
if(customMessage == null) {
|
||||
StringBuilder message = new StringBuilder(key);
|
||||
String deprecatedKeySuffix = " is deprecated. Instead, use ";
|
||||
message.append(deprecatedKeySuffix);
|
||||
if (source != null) {
|
||||
message.append(" in " + source);
|
||||
}
|
||||
message.append(" is deprecated. Instead, use ");
|
||||
for (int i = 0; i < newKeys.length; i++) {
|
||||
message.append(newKeys[i]);
|
||||
if(i != newKeys.length-1) {
|
||||
|
@ -586,6 +593,14 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
return deprecationContext.get().getDeprecatedKeyMap().containsKey(key);
|
||||
}
|
||||
|
||||
private static String getDeprecatedKey(String key) {
|
||||
return deprecationContext.get().getReverseDeprecatedKeyMap().get(key);
|
||||
}
|
||||
|
||||
private static DeprecatedKeyInfo getDeprecatedKeyInfo(String key) {
|
||||
return deprecationContext.get().getDeprecatedKeyMap().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all deprecated properties that are not currently set but have a
|
||||
* corresponding new property that is set. Useful for iterating the
|
||||
|
@ -1212,6 +1227,13 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
LOG_DEPRECATION.info(message);
|
||||
}
|
||||
|
||||
void logDeprecationOnce(String name, String source) {
|
||||
DeprecatedKeyInfo keyInfo = getDeprecatedKeyInfo(name);
|
||||
if (keyInfo != null && !keyInfo.getAndSetAccessed()) {
|
||||
LOG_DEPRECATION.info(keyInfo.getWarningMessage(name, source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset a previously set property.
|
||||
*/
|
||||
|
@ -1995,6 +2017,47 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
return pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the credential entry by name from a credential provider.
|
||||
*
|
||||
* Handle key deprecation.
|
||||
*
|
||||
* @param provider a credential provider
|
||||
* @param name alias of the credential
|
||||
* @return the credential entry or null if not found
|
||||
*/
|
||||
private CredentialEntry getCredentialEntry(CredentialProvider provider,
|
||||
String name) throws IOException {
|
||||
CredentialEntry entry = provider.getCredentialEntry(name);
|
||||
if (entry != null) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
// The old name is stored in the credential provider.
|
||||
String oldName = getDeprecatedKey(name);
|
||||
if (oldName != null) {
|
||||
entry = provider.getCredentialEntry(oldName);
|
||||
if (entry != null) {
|
||||
logDeprecationOnce(oldName, provider.toString());
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
// The name is deprecated.
|
||||
DeprecatedKeyInfo keyInfo = getDeprecatedKeyInfo(name);
|
||||
if (keyInfo != null && keyInfo.newKeys != null) {
|
||||
for (String newName : keyInfo.newKeys) {
|
||||
entry = provider.getCredentialEntry(newName);
|
||||
if (entry != null) {
|
||||
logDeprecationOnce(name, null);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try and resolve the provided element name as a credential provider
|
||||
* alias.
|
||||
|
@ -2012,7 +2075,7 @@ public class Configuration implements Iterable<Map.Entry<String,String>>,
|
|||
if (providers != null) {
|
||||
for (CredentialProvider provider : providers) {
|
||||
try {
|
||||
CredentialEntry entry = provider.getCredentialEntry(name);
|
||||
CredentialEntry entry = getCredentialEntry(provider, name);
|
||||
if (entry != null) {
|
||||
pass = entry.getCredential();
|
||||
break;
|
||||
|
|
|
@ -49,13 +49,19 @@ import static org.junit.Assert.assertArrayEquals;
|
|||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.hadoop.conf.Configuration.IntegerRanges;
|
||||
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
|
||||
import org.apache.hadoop.fs.FileUtil;
|
||||
import org.apache.hadoop.fs.Path;
|
||||
import org.apache.hadoop.io.IOUtils;
|
||||
import org.apache.hadoop.net.NetUtils;
|
||||
import org.apache.hadoop.security.alias.CredentialProvider;
|
||||
import org.apache.hadoop.security.alias.CredentialProviderFactory;
|
||||
import org.apache.hadoop.security.alias.LocalJavaKeyStoreProvider;
|
||||
import org.apache.hadoop.test.GenericTestUtils;
|
||||
import org.apache.log4j.AppenderSkeleton;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.spi.LoggingEvent;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Assert;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
|
||||
|
@ -1903,6 +1909,60 @@ public class TestConfiguration extends TestCase {
|
|||
+ classes.length, 0, classes.length);
|
||||
}
|
||||
|
||||
public void testGetPasswordDeprecatedKeyStored() throws Exception {
|
||||
final String oldKey = "test.password.old.key";
|
||||
final String newKey = "test.password.new.key";
|
||||
final String password = "MyPasswordForDeprecatedKey";
|
||||
|
||||
final File tmpDir = GenericTestUtils.getRandomizedTestDir();
|
||||
tmpDir.mkdirs();
|
||||
final String ourUrl = new URI(LocalJavaKeyStoreProvider.SCHEME_NAME,
|
||||
"file", new File(tmpDir, "test.jks").toString(), null).toString();
|
||||
|
||||
conf = new Configuration(false);
|
||||
conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl);
|
||||
CredentialProvider provider =
|
||||
CredentialProviderFactory.getProviders(conf).get(0);
|
||||
provider.createCredentialEntry(oldKey, password.toCharArray());
|
||||
provider.flush();
|
||||
|
||||
Configuration.addDeprecation(oldKey, newKey);
|
||||
|
||||
Assert.assertThat(conf.getPassword(newKey),
|
||||
CoreMatchers.is(password.toCharArray()));
|
||||
Assert.assertThat(conf.getPassword(oldKey),
|
||||
CoreMatchers.is(password.toCharArray()));
|
||||
|
||||
FileUtil.fullyDelete(tmpDir);
|
||||
}
|
||||
|
||||
public void testGetPasswordByDeprecatedKey() throws Exception {
|
||||
final String oldKey = "test.password.old.key";
|
||||
final String newKey = "test.password.new.key";
|
||||
final String password = "MyPasswordForDeprecatedKey";
|
||||
|
||||
final File tmpDir = GenericTestUtils.getRandomizedTestDir();
|
||||
tmpDir.mkdirs();
|
||||
final String ourUrl = new URI(LocalJavaKeyStoreProvider.SCHEME_NAME,
|
||||
"file", new File(tmpDir, "test.jks").toString(), null).toString();
|
||||
|
||||
conf = new Configuration(false);
|
||||
conf.set(CredentialProviderFactory.CREDENTIAL_PROVIDER_PATH, ourUrl);
|
||||
CredentialProvider provider =
|
||||
CredentialProviderFactory.getProviders(conf).get(0);
|
||||
provider.createCredentialEntry(newKey, password.toCharArray());
|
||||
provider.flush();
|
||||
|
||||
Configuration.addDeprecation(oldKey, newKey);
|
||||
|
||||
Assert.assertThat(conf.getPassword(newKey),
|
||||
CoreMatchers.is(password.toCharArray()));
|
||||
Assert.assertThat(conf.getPassword(oldKey),
|
||||
CoreMatchers.is(password.toCharArray()));
|
||||
|
||||
FileUtil.fullyDelete(tmpDir);
|
||||
}
|
||||
|
||||
public static void main(String[] argv) throws Exception {
|
||||
junit.textui.TestRunner.main(new String[]{
|
||||
TestConfiguration.class.getName()
|
||||
|
|
Loading…
Reference in New Issue