blob: da0c7b17d9aa2d2ea1a585dea17d38357d6e1fda [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.core.clientImpl;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.function.Predicate;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.ClientProperty;
import org.apache.accumulo.core.conf.DefaultConfiguration;
import org.apache.accumulo.core.conf.HadoopCredentialProvider;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.rpc.SaslConnectionParams;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ClientConfConverter {
private static final Logger log = LoggerFactory.getLogger(ClientConfConverter.class);
private static Map<String,String> confProps = new HashMap<>();
private static Map<String,String> propsConf = new HashMap<>();
@SuppressWarnings("deprecation")
private static void init() {
propsConf.put(ClientProperty.INSTANCE_ZOOKEEPERS.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_ZK_HOST
.getKey());
propsConf.put(ClientProperty.INSTANCE_ZOOKEEPERS_TIMEOUT.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_ZK_TIMEOUT
.getKey());
propsConf.put(ClientProperty.SSL_ENABLED.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_RPC_SSL_ENABLED
.getKey());
propsConf.put(ClientProperty.SSL_KEYSTORE_PATH.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_KEYSTORE_PATH
.getKey());
propsConf.put(ClientProperty.SSL_KEYSTORE_TYPE.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_KEYSTORE_TYPE
.getKey());
propsConf.put(ClientProperty.SSL_KEYSTORE_PASSWORD.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_KEYSTORE_PASSWORD
.getKey());
propsConf.put(ClientProperty.SSL_TRUSTSTORE_PATH.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_TRUSTSTORE_PATH
.getKey());
propsConf.put(ClientProperty.SSL_TRUSTSTORE_TYPE.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_TRUSTSTORE_TYPE
.getKey());
propsConf.put(ClientProperty.SSL_TRUSTSTORE_PASSWORD.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SSL_TRUSTSTORE_PASSWORD
.getKey());
propsConf.put(ClientProperty.SSL_USE_JSSE.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_USE_JSSE.getKey());
propsConf.put(ClientProperty.SASL_ENABLED.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_RPC_SASL_ENABLED
.getKey());
propsConf.put(ClientProperty.SASL_QOP.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.RPC_SASL_QOP.getKey());
propsConf.put(ClientProperty.SASL_KERBEROS_SERVER_PRIMARY.getKey(),
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY
.getKey());
for (Map.Entry<String,String> entry : propsConf.entrySet()) {
confProps.put(entry.getValue(), entry.getKey());
}
}
static {
init();
}
@SuppressWarnings("deprecation")
public static org.apache.accumulo.core.client.ClientConfiguration
toClientConf(Properties properties) {
org.apache.accumulo.core.client.ClientConfiguration config =
org.apache.accumulo.core.client.ClientConfiguration.create();
for (Object keyObj : properties.keySet()) {
String propKey = (String) keyObj;
String val = properties.getProperty(propKey);
String confKey = propsConf.get(propKey);
if (confKey == null) {
config.setProperty(propKey, val);
} else {
config.setProperty(confKey, val);
}
if (propKey.equals(ClientProperty.SSL_KEYSTORE_PATH.getKey())) {
config.setProperty(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_RPC_SSL_CLIENT_AUTH,
"true");
}
}
return config;
}
@SuppressWarnings("deprecation")
public static Properties
toProperties(org.apache.accumulo.core.client.ClientConfiguration clientConf) {
Properties props = new Properties();
Iterator<String> clientConfIter = clientConf.getKeys();
while (clientConfIter.hasNext()) {
String confKey = clientConfIter.next();
String val = clientConf.getString(confKey);
String propKey = confProps.get(confKey);
if (propKey == null) {
if (!confKey.equals(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.INSTANCE_RPC_SSL_CLIENT_AUTH
.getKey())) {
props.setProperty(confKey, val);
}
} else {
props.setProperty(propKey, val);
}
}
return props;
}
public static Properties toProperties(AccumuloConfiguration config) {
return toProperties(toClientConf(config));
}
public static AccumuloConfiguration toAccumuloConf(Properties properties) {
return toAccumuloConf(toClientConf(properties));
}
/**
* A utility method for converting client configuration to a standard configuration object for use
* internally.
*
* @param config
* the original config
* @return the client configuration presented in the form of an {@link AccumuloConfiguration}
*/
@SuppressWarnings("deprecation")
public static AccumuloConfiguration
toAccumuloConf(final org.apache.accumulo.core.client.ClientConfiguration config) {
final AccumuloConfiguration defaults = DefaultConfiguration.getInstance();
return new AccumuloConfiguration() {
@Override
public String get(Property property) {
final String key = property.getKey();
// Attempt to load sensitive properties from a CredentialProvider, if configured
if (property.isSensitive()) {
org.apache.hadoop.conf.Configuration hadoopConf = getHadoopConfiguration();
if (hadoopConf != null) {
char[] value = HadoopCredentialProvider.getValue(hadoopConf, key);
if (value != null) {
log.trace("Loaded sensitive value for {} from CredentialProvider", key);
return new String(value);
} else {
log.trace("Tried to load sensitive value for {} from CredentialProvider, "
+ "but none was found", key);
}
}
}
if (config.containsKey(key)) {
return config.getString(key);
} else {
// Reconstitute the server kerberos property from the client config
if (property == Property.GENERAL_KERBEROS_PRINCIPAL) {
if (config.containsKey(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY
.getKey())) {
// Avoid providing a realm since we don't know what it is...
return config.getString(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY
.getKey())
+ "/_HOST@" + SaslConnectionParams.getDefaultRealm();
}
}
return defaults.get(property);
}
}
@Override
public void getProperties(Map<String,String> props, Predicate<String> filter) {
defaults.getProperties(props, filter);
Iterator<String> keyIter = config.getKeys();
while (keyIter.hasNext()) {
String key = keyIter.next();
if (filter.test(key)) {
props.put(key, config.getString(key));
}
}
// Two client props that don't exist on the server config. Client doesn't need to know about
// the Kerberos instance from the principle, but servers do
// Automatically reconstruct the server property when converting a client config.
if (props.containsKey(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY
.getKey())) {
final String serverPrimary = props.remove(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY
.getKey());
if (filter.test(Property.GENERAL_KERBEROS_PRINCIPAL.getKey())) {
// Use the _HOST expansion. It should be unnecessary in "client land".
props.put(Property.GENERAL_KERBEROS_PRINCIPAL.getKey(),
serverPrimary + "/_HOST@" + SaslConnectionParams.getDefaultRealm());
}
}
// Attempt to load sensitive properties from a CredentialProvider, if configured
org.apache.hadoop.conf.Configuration hadoopConf = getHadoopConfiguration();
if (hadoopConf != null) {
for (String key : HadoopCredentialProvider.getKeys(hadoopConf)) {
if (!Property.isValidPropertyKey(key) || !Property.isSensitive(key)) {
continue;
}
if (filter.test(key)) {
char[] value = HadoopCredentialProvider.getValue(hadoopConf, key);
if (value != null) {
props.put(key, new String(value));
}
}
}
}
}
private org.apache.hadoop.conf.Configuration getHadoopConfiguration() {
String credProviderPaths =
config.getString(Property.GENERAL_SECURITY_CREDENTIAL_PROVIDER_PATHS.getKey());
if (credProviderPaths != null && !credProviderPaths.isEmpty()) {
org.apache.hadoop.conf.Configuration hConf = new org.apache.hadoop.conf.Configuration();
HadoopCredentialProvider.setPath(hConf, credProviderPaths);
return hConf;
}
log.trace("Did not find credential provider configuration in ClientConfiguration");
return null;
}
};
}
@SuppressWarnings("deprecation")
public static org.apache.accumulo.core.client.ClientConfiguration
toClientConf(AccumuloConfiguration conf) {
org.apache.accumulo.core.client.ClientConfiguration clientConf =
org.apache.accumulo.core.client.ClientConfiguration.create();
// Servers will only have the full principal in their configuration -- parse the
// primary and realm from it.
final String serverPrincipal = conf.get(Property.GENERAL_KERBEROS_PRINCIPAL);
final KerberosName krbName;
if (serverPrincipal != null && !serverPrincipal.isEmpty()) {
krbName = new KerberosName(serverPrincipal);
clientConf.setProperty(
org.apache.accumulo.core.client.ClientConfiguration.ClientProperty.KERBEROS_SERVER_PRIMARY,
krbName.getServiceName());
}
HashSet<String> clientKeys = new HashSet<>();
for (org.apache.accumulo.core.client.ClientConfiguration.ClientProperty prop : org.apache.accumulo.core.client.ClientConfiguration.ClientProperty
.values()) {
clientKeys.add(prop.getKey());
}
String key;
for (Map.Entry<String,String> entry : conf) {
key = entry.getKey();
if (clientKeys.contains(key)) {
clientConf.setProperty(key, entry.getValue());
}
}
return clientConf;
}
}