rpc: improve behavior when GSSAPI SASL plugin is missing * If the client cannot enable the GSSAPI plugin, it now proceeds with a connection anyway after logging a single VLOG(1) message. This allows a client to connect to a non-Kerberos-enabled cluster without having to install the GSSAPI plugin.
* If the client fails to negotiate a matching SASL mechanism, it replaces the confusing "No worthy mechs" error message with something that's more usable for the average user, suggesting to install the GSSAPI plugin. Change-Id: I49b991fd7088666a2b8daad18d70844ed8a5451f Reviewed-on: http://gerrit.cloudera.org:8080/4908 Tested-by: Kudu Jenkins Reviewed-by: Dan Burkert <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/e6cb2ef7 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/e6cb2ef7 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/e6cb2ef7 Branch: refs/heads/master Commit: e6cb2ef74c6ea314cbb68e9318b516d1d204aa74 Parents: e46e951 Author: Todd Lipcon <[email protected]> Authored: Tue Nov 1 16:16:52 2016 -0700 Committer: Todd Lipcon <[email protected]> Committed: Wed Nov 2 18:33:48 2016 +0000 ---------------------------------------------------------------------- src/kudu/rpc/connection.cc | 17 ++++++++++++++++- src/kudu/rpc/sasl_client.cc | 11 +++++++++++ src/kudu/rpc/sasl_helper.cc | 3 +-- src/kudu/rpc/sasl_rpc-test.cc | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/e6cb2ef7/src/kudu/rpc/connection.cc ---------------------------------------------------------------------- diff --git a/src/kudu/rpc/connection.cc b/src/kudu/rpc/connection.cc index 8e64e1b..f134d7c 100644 --- a/src/kudu/rpc/connection.cc +++ b/src/kudu/rpc/connection.cc @@ -41,6 +41,7 @@ #include "kudu/rpc/transfer.h" #include "kudu/util/debug-util.h" #include "kudu/util/flag_tags.h" +#include "kudu/util/logging.h" #include "kudu/util/net/sockaddr.h" #include "kudu/util/status.h" #include "kudu/util/trace.h" @@ -634,7 +635,21 @@ Status Connection::InitSaslClient() { // of reversing this address to its canonical hostname to determine // the expected server principal. sasl_client().set_server_fqdn(remote_.host()); - RETURN_NOT_OK(sasl_client().EnableGSSAPI()); + Status gssapi_status = sasl_client().EnableGSSAPI(); + if (!gssapi_status.ok()) { + // If we can't enable GSSAPI, it's likely the client is just missing the + // appropriate SASL plugin. We don't want to require it to be installed + // if the user doesn't care about connecting to servers using Kerberos + // authentication. So, we'll just VLOG this here. If we try to connect + // to a server which requires Kerberos, we'll get a negotiation error + // at that point. + if (VLOG_IS_ON(1)) { + KLOG_FIRST_N(INFO, 1) << "Couldn't enable GSSAPI (Kerberos) SASL plugin: " + << gssapi_status.message().ToString() + << ". This process will be unable to connect to " + << "servers requiring Kerberos authentication."; + } + } // TODO(todd): we dont seem to ever use ANONYMOUS. Should we remove it? RETURN_NOT_OK(sasl_client().EnableAnonymous()); RETURN_NOT_OK(sasl_client().EnablePlain(user_credentials().real_user(), "")); http://git-wip-us.apache.org/repos/asf/kudu/blob/e6cb2ef7/src/kudu/rpc/sasl_client.cc ---------------------------------------------------------------------- diff --git a/src/kudu/rpc/sasl_client.cc b/src/kudu/rpc/sasl_client.cc index 9d04cc2..53c5e4f 100644 --- a/src/kudu/rpc/sasl_client.cc +++ b/src/kudu/rpc/sasl_client.cc @@ -30,6 +30,7 @@ #include "kudu/gutil/map-util.h" #include "kudu/gutil/stringprintf.h" #include "kudu/gutil/strings/substitute.h" +#include "kudu/gutil/strings/util.h" #include "kudu/rpc/blocking_ops.h" #include "kudu/rpc/constants.h" #include "kudu/rpc/rpc_header.pb.h" @@ -376,6 +377,16 @@ Status SaslClient::HandleNegotiateResponse(const SaslMessagePB& response) { if (s.ok()) { nego_ok_ = true; } else if (!s.IsIncomplete()) { + // If we failed to negotiate because we didn't share any mechanisms, + // the most likely case is that the client is missing the GSSAPI SASL + // module, and the server is configured to only allow Kerberos connections. + // Return a more usable error message in this case. + if (MatchPattern(s.ToString(), "*No worthy mechs found") && + ContainsKey(mech_auth_map, kSaslMechGSSAPI) && + !ContainsKey(helper_.LocalMechs(), kSaslMechGSSAPI)) { + return Status::NotAuthorized("server requires GSSAPI (Kerberos) authentication and " + "client was missing the required SASL module"); + } return s; } http://git-wip-us.apache.org/repos/asf/kudu/blob/e6cb2ef7/src/kudu/rpc/sasl_helper.cc ---------------------------------------------------------------------- diff --git a/src/kudu/rpc/sasl_helper.cc b/src/kudu/rpc/sasl_helper.cc index 280f41e..334ae32 100644 --- a/src/kudu/rpc/sasl_helper.cc +++ b/src/kudu/rpc/sasl_helper.cc @@ -153,8 +153,7 @@ Status SaslHelper::EnableGSSAPI() { Status SaslHelper::EnableMechanism(const string& mech) { if (PREDICT_FALSE(!ContainsKey(GlobalMechs(), mech))) { - LOG(DFATAL) << tag_ << ": Unable to find SASL plugin: " << mech; - return Status::InvalidArgument("Unable to find SASL plugin", mech); + return Status::InvalidArgument("unable to find SASL plugin", mech); } AddToLocalMechList(mech); return Status::OK(); http://git-wip-us.apache.org/repos/asf/kudu/blob/e6cb2ef7/src/kudu/rpc/sasl_rpc-test.cc ---------------------------------------------------------------------- diff --git a/src/kudu/rpc/sasl_rpc-test.cc b/src/kudu/rpc/sasl_rpc-test.cc index 7592901..5458345 100644 --- a/src/kudu/rpc/sasl_rpc-test.cc +++ b/src/kudu/rpc/sasl_rpc-test.cc @@ -246,7 +246,7 @@ TEST_F(TestSaslRpc, TestNoMatchingMechanisms) { CHECK_OK(sasl_client.EnablePlain("foo", "bar")); CHECK_OK(sasl_client.Init(kSaslAppName)); Status s = sasl_client.Negotiate(); - ASSERT_STR_CONTAINS(s.ToString(), "no mechanism available: No worthy mechs found"); + ASSERT_STR_CONTAINS(s.ToString(), "client was missing the required SASL module"); }); }
