HBASE-14400 Fix HBase RPC protection documentation
Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
parent
903d876f29
commit
fe2c4f630d
|
@ -74,7 +74,8 @@ public class SaslClientHandler extends ChannelDuplexHandler {
|
||||||
* @param token for Sasl
|
* @param token for Sasl
|
||||||
* @param serverPrincipal Server's Kerberos principal name
|
* @param serverPrincipal Server's Kerberos principal name
|
||||||
* @param fallbackAllowed True if server may also fall back to less secure connection
|
* @param fallbackAllowed True if server may also fall back to less secure connection
|
||||||
* @param rpcProtection Quality of protection. Integrity or privacy
|
* @param rpcProtection Quality of protection. Can be 'authentication', 'integrity' or
|
||||||
|
* 'privacy'.
|
||||||
* @param exceptionHandler handler for exceptions
|
* @param exceptionHandler handler for exceptions
|
||||||
* @param successfulConnectHandler handler for succesful connects
|
* @param successfulConnectHandler handler for succesful connects
|
||||||
* @throws java.io.IOException if handler could not be created
|
* @throws java.io.IOException if handler could not be created
|
||||||
|
|
|
@ -24,10 +24,13 @@ import java.util.TreeMap;
|
||||||
import javax.security.sasl.Sasl;
|
import javax.security.sasl.Sasl;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
import org.apache.hadoop.hbase.classification.InterfaceAudience;
|
||||||
|
|
||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
public class SaslUtil {
|
public class SaslUtil {
|
||||||
|
private static final Log log = LogFactory.getLog(SaslUtil.class);
|
||||||
public static final String SASL_DEFAULT_REALM = "default";
|
public static final String SASL_DEFAULT_REALM = "default";
|
||||||
public static final Map<String, String> SASL_PROPS =
|
public static final Map<String, String> SASL_PROPS =
|
||||||
new TreeMap<String, String>();
|
new TreeMap<String, String>();
|
||||||
|
@ -66,16 +69,41 @@ public class SaslUtil {
|
||||||
return new String(Base64.encodeBase64(password)).toCharArray();
|
return new String(Base64.encodeBase64(password)).toCharArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initSaslProperties(String rpcProtection) {
|
/**
|
||||||
QualityOfProtection saslQOP = QualityOfProtection.AUTHENTICATION;
|
* Returns {@link org.apache.hadoop.hbase.security.SaslUtil.QualityOfProtection}
|
||||||
if (QualityOfProtection.INTEGRITY.name().toLowerCase()
|
* corresponding to the given {@code stringQop} value. Returns null if value is
|
||||||
.equals(rpcProtection)) {
|
* invalid.
|
||||||
saslQOP = QualityOfProtection.INTEGRITY;
|
*/
|
||||||
} else if (QualityOfProtection.PRIVACY.name().toLowerCase().equals(
|
public static QualityOfProtection getQop(String stringQop) {
|
||||||
rpcProtection)) {
|
QualityOfProtection qop = null;
|
||||||
saslQOP = QualityOfProtection.PRIVACY;
|
if (QualityOfProtection.AUTHENTICATION.name().toLowerCase().equals(stringQop)
|
||||||
|
|| QualityOfProtection.AUTHENTICATION.saslQop.equals(stringQop)) {
|
||||||
|
qop = QualityOfProtection.AUTHENTICATION;
|
||||||
|
} else if (QualityOfProtection.INTEGRITY.name().toLowerCase().equals(stringQop)
|
||||||
|
|| QualityOfProtection.INTEGRITY.saslQop.equals(stringQop)) {
|
||||||
|
qop = QualityOfProtection.INTEGRITY;
|
||||||
|
} else if (QualityOfProtection.PRIVACY.name().toLowerCase().equals(stringQop)
|
||||||
|
|| QualityOfProtection.PRIVACY.saslQop.equals(stringQop)) {
|
||||||
|
qop = QualityOfProtection.PRIVACY;
|
||||||
}
|
}
|
||||||
|
if (qop == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid qop: " + stringQop
|
||||||
|
+ ". It must be one of 'authentication', 'integrity', 'privacy'.");
|
||||||
|
}
|
||||||
|
if (QualityOfProtection.AUTHENTICATION.saslQop.equals(stringQop)
|
||||||
|
|| QualityOfProtection.INTEGRITY.saslQop.equals(stringQop)
|
||||||
|
|| QualityOfProtection.PRIVACY.saslQop.equals(stringQop)) {
|
||||||
|
log.warn("Use authentication/integrity/privacy as value for rpc protection "
|
||||||
|
+ "configurations instead of auth/auth-int/auth-conf.");
|
||||||
|
}
|
||||||
|
return qop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initSaslProperties(String rpcProtection) {
|
||||||
|
QualityOfProtection saslQOP = getQop(rpcProtection);
|
||||||
|
if (saslQOP == null) {
|
||||||
|
saslQOP = QualityOfProtection.AUTHENTICATION;
|
||||||
|
}
|
||||||
SaslUtil.SASL_PROPS.put(Sasl.QOP, saslQOP.getSaslQop());
|
SaslUtil.SASL_PROPS.put(Sasl.QOP, saslQOP.getSaslQop());
|
||||||
SaslUtil.SASL_PROPS.put(Sasl.SERVER_AUTH, "true");
|
SaslUtil.SASL_PROPS.put(Sasl.SERVER_AUTH, "true");
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,10 @@ import org.apache.hadoop.security.token.TokenIdentifier;
|
||||||
import org.apache.log4j.Level;
|
import org.apache.log4j.Level;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
@ -72,6 +74,10 @@ public class TestHBaseSaslRpcClient {
|
||||||
|
|
||||||
private static final Logger LOG = Logger.getLogger(TestHBaseSaslRpcClient.class);
|
private static final Logger LOG = Logger.getLogger(TestHBaseSaslRpcClient.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void before() {
|
public static void before() {
|
||||||
Logger.getRootLogger().setLevel(Level.DEBUG);
|
Logger.getRootLogger().setLevel(Level.DEBUG);
|
||||||
|
@ -101,6 +107,10 @@ public class TestHBaseSaslRpcClient {
|
||||||
"integrity");
|
"integrity");
|
||||||
assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.
|
assertTrue(SaslUtil.SASL_PROPS.get(Sasl.QOP).equals(SaslUtil.QualityOfProtection.
|
||||||
INTEGRITY.getSaslQop()));
|
INTEGRITY.getSaslQop()));
|
||||||
|
|
||||||
|
exception.expect(IllegalArgumentException.class);
|
||||||
|
new HBaseSaslRpcClient(AuthMethod.DIGEST, token, "principal/host@DOMAIN.COM", false,
|
||||||
|
"wrongvalue");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -54,6 +54,7 @@ import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
|
||||||
import org.apache.hadoop.hbase.filter.ParseFilter;
|
import org.apache.hadoop.hbase.filter.ParseFilter;
|
||||||
import org.apache.hadoop.hbase.http.InfoServer;
|
import org.apache.hadoop.hbase.http.InfoServer;
|
||||||
|
import org.apache.hadoop.hbase.security.SaslUtil;
|
||||||
import org.apache.hadoop.hbase.security.SecurityUtil;
|
import org.apache.hadoop.hbase.security.SecurityUtil;
|
||||||
import org.apache.hadoop.hbase.security.UserProvider;
|
import org.apache.hadoop.hbase.security.UserProvider;
|
||||||
import org.apache.hadoop.hbase.thrift.CallQueue;
|
import org.apache.hadoop.hbase.thrift.CallQueue;
|
||||||
|
@ -98,9 +99,9 @@ public class ThriftServer extends Configured implements Tool {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrift quality of protection configuration key. Valid values can be:
|
* Thrift quality of protection configuration key. Valid values can be:
|
||||||
* auth-conf: authentication, integrity and confidentiality checking
|
* privacy: authentication, integrity and confidentiality checking
|
||||||
* auth-int: authentication and integrity checking
|
* integrity: authentication and integrity checking
|
||||||
* auth: authentication only
|
* authentication: authentication only
|
||||||
*
|
*
|
||||||
* This is used to authenticate the callers and support impersonation.
|
* This is used to authenticate the callers and support impersonation.
|
||||||
* The thrift server and the HBase cluster must run in secure mode.
|
* The thrift server and the HBase cluster must run in secure mode.
|
||||||
|
@ -161,7 +162,8 @@ public class ThriftServer extends Configured implements Tool {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TTransportFactory getTTransportFactory(
|
private static TTransportFactory getTTransportFactory(
|
||||||
String qop, String name, String host, boolean framed, int frameSize) {
|
SaslUtil.QualityOfProtection qop, String name, String host,
|
||||||
|
boolean framed, int frameSize) {
|
||||||
if (framed) {
|
if (framed) {
|
||||||
if (qop != null) {
|
if (qop != null) {
|
||||||
throw new RuntimeException("Thrift server authentication"
|
throw new RuntimeException("Thrift server authentication"
|
||||||
|
@ -173,7 +175,7 @@ public class ThriftServer extends Configured implements Tool {
|
||||||
return new TTransportFactory();
|
return new TTransportFactory();
|
||||||
} else {
|
} else {
|
||||||
Map<String, String> saslProperties = new HashMap<String, String>();
|
Map<String, String> saslProperties = new HashMap<String, String>();
|
||||||
saslProperties.put(Sasl.QOP, qop);
|
saslProperties.put(Sasl.QOP, qop.getSaslQop());
|
||||||
TSaslServerTransport.Factory saslFactory = new TSaslServerTransport.Factory();
|
TSaslServerTransport.Factory saslFactory = new TSaslServerTransport.Factory();
|
||||||
saslFactory.addServerDefinition("GSSAPI", name, host, saslProperties,
|
saslFactory.addServerDefinition("GSSAPI", name, host, saslProperties,
|
||||||
new SaslGssCallbackHandler() {
|
new SaslGssCallbackHandler() {
|
||||||
|
@ -377,13 +379,10 @@ public class ThriftServer extends Configured implements Tool {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserGroupInformation realUser = userProvider.getCurrent().getUGI();
|
UserGroupInformation realUser = userProvider.getCurrent().getUGI();
|
||||||
String qop = conf.get(THRIFT_QOP_KEY);
|
String stringQop = conf.get(THRIFT_QOP_KEY);
|
||||||
if (qop != null) {
|
SaslUtil.QualityOfProtection qop = null;
|
||||||
if (!qop.equals("auth") && !qop.equals("auth-int")
|
if (stringQop != null) {
|
||||||
&& !qop.equals("auth-conf")) {
|
qop = SaslUtil.getQop(stringQop);
|
||||||
throw new IOException("Invalid " + THRIFT_QOP_KEY + ": " + qop
|
|
||||||
+ ", it must be 'auth', 'auth-int', or 'auth-conf'");
|
|
||||||
}
|
|
||||||
if (!securityEnabled) {
|
if (!securityEnabled) {
|
||||||
throw new IOException("Thrift server must"
|
throw new IOException("Thrift server must"
|
||||||
+ " run in secure mode to support authentication");
|
+ " run in secure mode to support authentication");
|
||||||
|
|
|
@ -222,9 +222,9 @@ To enable it, do the following.
|
||||||
. Be sure that HBase is configured to allow proxy users, as described in <<security.rest.gateway>>.
|
. Be sure that HBase is configured to allow proxy users, as described in <<security.rest.gateway>>.
|
||||||
. In _hbase-site.xml_ for each cluster node running a Thrift gateway, set the property `hbase.thrift.security.qop` to one of the following three values:
|
. In _hbase-site.xml_ for each cluster node running a Thrift gateway, set the property `hbase.thrift.security.qop` to one of the following three values:
|
||||||
+
|
+
|
||||||
* `auth-conf` - authentication, integrity, and confidentiality checking
|
* `privacy` - authentication, integrity, and confidentiality checking.
|
||||||
* `auth-int` - authentication and integrity checking
|
* `integrity` - authentication and integrity checking
|
||||||
* `auth` - authentication checking only
|
* `authentication` - authentication checking only
|
||||||
|
|
||||||
. Restart the Thrift gateway processes for the changes to take effect.
|
. Restart the Thrift gateway processes for the changes to take effect.
|
||||||
If a node is running Thrift, the output of the `jps` command will list a `ThriftServer` process.
|
If a node is running Thrift, the output of the `jps` command will list a `ThriftServer` process.
|
||||||
|
@ -765,7 +765,7 @@ For an example of using both together, see <<security.example.config>>.
|
||||||
</property>
|
</property>
|
||||||
----
|
----
|
||||||
+
|
+
|
||||||
Optionally, you can enable transport security, by setting `hbase.rpc.protection` to `auth-conf`.
|
Optionally, you can enable transport security, by setting `hbase.rpc.protection` to `privacy`.
|
||||||
This requires HBase 0.98.4 or newer.
|
This requires HBase 0.98.4 or newer.
|
||||||
|
|
||||||
. Set up the Hadoop group mapper in the Hadoop namenode's _core-site.xml_.
|
. Set up the Hadoop group mapper in the Hadoop namenode's _core-site.xml_.
|
||||||
|
@ -1668,7 +1668,7 @@ All options have been discussed separately in the sections above.
|
||||||
<!-- Secure RPC Transport -->
|
<!-- Secure RPC Transport -->
|
||||||
<property>
|
<property>
|
||||||
<name>hbase.rpc.protection</name>
|
<name>hbase.rpc.protection</name>
|
||||||
<value>auth-conf</value>
|
<value>privacy</value>
|
||||||
</property>
|
</property>
|
||||||
<!-- Transparent Encryption -->
|
<!-- Transparent Encryption -->
|
||||||
<property>
|
<property>
|
||||||
|
|
Loading…
Reference in New Issue