blob: 87cb6dee12eb30608780bb022cf8ba6991eef712 [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.falcon.security;
import org.apache.falcon.FalconException;
import org.apache.hadoop.conf.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* Helper class for Hadoop credential provider functionality. Reflection to used to avoid
* directly referencing the classes and methods so that version dependency is not introduced
* as the Hadoop credential provider is only introduced in 2.6.0 and later.
*/
public final class CredentialProviderHelper {
private static final Logger LOG = LoggerFactory.getLogger(CredentialProviderHelper.class);
private static Class<?> clsCredProvider;
private static Class<?> clsCredProviderFactory;
private static Method methGetPassword;
private static Method methCreateCredEntry;
private static Method methFlush;
private static Method methGetProviders;
public static final String CREDENTIAL_PROVIDER_PATH = "hadoop.security.credential.provider.path";
static {
try {
LOG.debug("Reflecting credential provider classes and methods");
clsCredProvider = Class.forName("org.apache.hadoop.security.alias.CredentialProvider");
clsCredProviderFactory = Class.forName("org.apache.hadoop.security.alias.CredentialProviderFactory");
methCreateCredEntry = clsCredProvider.getMethod("createCredentialEntry", String.class, char[].class);
methFlush = clsCredProvider.getMethod("flush");
methGetPassword = Configuration.class.getMethod("getPassword", String.class);
methGetProviders = clsCredProviderFactory.getMethod("getProviders", new Class[] { Configuration.class });
LOG.debug("Found CredentialProviderFactory#getProviders");
} catch (ClassNotFoundException | NoSuchMethodException cnfe) {
LOG.debug("Ignoring exception", cnfe);
}
}
private CredentialProviderHelper() {
}
public static boolean isProviderAvailable() {
return !(clsCredProvider == null
|| clsCredProviderFactory == null
|| methCreateCredEntry == null
|| methGetPassword == null
|| methFlush == null);
}
public static String resolveAlias(Configuration conf, String alias) throws FalconException {
try {
char[] cred = (char[]) methGetPassword.invoke(conf, alias);
if (cred == null) {
throw new FalconException("The provided alias cannot be resolved");
}
return new String(cred);
} catch (InvocationTargetException ite) {
throw new FalconException("Error resolving password "
+ " from the credential providers ", ite.getTargetException());
} catch (IllegalAccessException iae) {
throw new FalconException("Error invoking the credential provider method", iae);
}
}
public static void createCredentialEntry(Configuration conf, String alias, String credential)
throws FalconException {
if (!isProviderAvailable()) {
throw new FalconException("CredentialProvider facility not available in the hadoop environment");
}
try {
List<?> result = (List<?>) methGetProviders.invoke(null, new Object[] { conf });
Object provider = result.get(0);
LOG.debug("Using credential provider " + provider);
methCreateCredEntry.invoke(provider, new Object[] { alias, credential.toCharArray() });
methFlush.invoke(provider, new Object[] {});
} catch (InvocationTargetException ite) {
throw new FalconException(
"Error creating credential entry using the credential provider", ite.getTargetException());
} catch (IllegalAccessException iae) {
throw new FalconException("Error accessing the credential create method", iae);
}
}
}