HBASE-14400 Fix HBase RPC protection documentation

Signed-off-by: Andrew Purtell <apurtell@apache.org>
This commit is contained in:
Apekshit(Appy) Sharma 2015-09-10 12:32:24 -07:00 committed by Andrew Purtell
parent 903d876f29
commit fe2c4f630d
5 changed files with 64 additions and 26 deletions

View File

@ -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

View File

@ -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");
} }

View File

@ -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

View File

@ -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");

View File

@ -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>