diff --git a/hbase-native-client/Dockerfile b/hbase-native-client/Dockerfile deleted file mode 100644 index 8b56590..0000000 --- a/hbase-native-client/Dockerfile +++ /dev/null @@ -1,58 +0,0 @@ -## -# 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. - -FROM pjameson/buck-folly-watchman:20160511 - -ARG CC=/usr/bin/gcc-5 -ARG CXX=/usr/bin/g++-5 -ARG CFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 -fPIC -g -fno-omit-frame-pointer -O2 -pthread" -ARG CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 -fPIC -g -fno-omit-frame-pointer -O2 -pthread" - -ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" - -RUN apt-get install -y vim maven inetutils-ping python-pip doxygen graphviz clang-format && \ - pip install yapf && \ - apt-get -qq clean && \ - apt-get -y -qq autoremove && \ - rm -rf /var/lib/{apt,dpkg,cache,log}/ && \ - rm -rf /tmp/* - -RUN git clone https://github.com/google/protobuf.git /usr/src/protobuf && \ - cd /usr/src/protobuf/ && \ - git checkout 2.7.0 && \ - mkdir gmock && \ - ldconfig && \ - ./autogen.sh && \ - ./configure && \ - make && \ - make install && \ - make clean && \ - rm -rf .git && \ - cd /usr/src && \ - wget http://www-us.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz && \ - tar zxf zookeeper-3.4.8.tar.gz && \ - rm -rf zookeeper-3.4.8.tar.gz && \ - cd zookeeper-3.4.8 && \ - cd src/c && \ - ldconfig && \ - ./configure && \ - make && \ - make install && \ - make clean && \ - ldconfig - -WORKDIR /usr/src/hbase/hbase-native-client diff --git a/hbase-native-client/bin/start-docker.sh b/hbase-native-client/bin/start-docker.sh index 8b017a0..d9d5dc7 100755 --- a/hbase-native-client/bin/start-docker.sh +++ b/hbase-native-client/bin/start-docker.sh @@ -52,11 +52,11 @@ fi; # Build the image # # This shouldn't be needed after the development environment is a little more stable. -docker build -t hbase_native . +docker build -t hbase_native -f docker-files/Dockerfile . # After the image is built run the thing -docker run -p 16050:16050/tcp \ +docker run -h="securecluster" -p 16050:16050/tcp \ -v ${BASE_DIR}/..:/usr/src/hbase \ -v ~/.m2:/root/.m2 \ - -it hbase_native /bin/bash + -it hbase_native /bin/bash -c "/usr/sbin/krb5kdc -P /var/run/krb5kdc.pid; /bin/bash" popd diff --git a/hbase-native-client/connection/BUCK b/hbase-native-client/connection/BUCK index 36111f8..c3119eb 100644 --- a/hbase-native-client/connection/BUCK +++ b/hbase-native-client/connection/BUCK @@ -22,6 +22,7 @@ cxx_library( exported_headers=[ "client-dispatcher.h", "client-handler.h", + "sasl-handler.h", "connection-factory.h", "connection-pool.h", "connection-id.h", @@ -31,6 +32,7 @@ cxx_library( "response.h", "service.h", "rpc-client.h", + "sasl-util.h", ], srcs=[ "client-dispatcher.cc", @@ -40,6 +42,8 @@ cxx_library( "pipeline.cc", "request.cc", "rpc-client.cc", + "sasl-handler.cc", + "sasl-util.cc", ], deps=[ "//if:if", @@ -51,8 +55,16 @@ cxx_library( "//exceptions:exceptions", ], compiler_flags=['-Weffc++'], - visibility=['//core/...',],) + linker_flags=['-L/usr/local/lib', '-lsasl2', '-lkrb5'], + exported_linker_flags=['-L/usr/local/lib', '-lsasl2', '-lkrb5'], + visibility=[ + '//core/...', + ],) cxx_test( name="connection-pool-test", - srcs=["connection-pool-test.cc",], - deps=[":connection",],) + srcs=[ + "connection-pool-test.cc", + ], + deps=[ + ":connection", + ],) diff --git a/hbase-native-client/connection/client-handler.cc b/hbase-native-client/connection/client-handler.cc index 113ebd0..e60382d 100644 --- a/hbase-native-client/connection/client-handler.cc +++ b/hbase-native-client/connection/client-handler.cc @@ -128,11 +128,9 @@ Future ClientHandler::write(Context *ctx, std::unique_ptr r) { // We need to send the header once. // So use call_once to make sure that only one thread wins this. std::call_once((*once_flag_), [ctx, this]() { - VLOG(3) << "Writing RPC connection Preamble and Header to server: " << server_; - auto pre = serde_.Preamble(); + VLOG(3) << "Writing RPC Header to server: " << server_; auto header = serde_.Header(user_name_); - pre->appendChain(std::move(header)); - ctx->fireWrite(std::move(pre)); + ctx->fireWrite(std::move(header)); }); VLOG(3) << "Writing RPC Request with call_id:" diff --git a/hbase-native-client/connection/connection-factory.cc b/hbase-native-client/connection/connection-factory.cc index afa227d..9b06c84 100644 --- a/hbase-native-client/connection/connection-factory.cc +++ b/hbase-native-client/connection/connection-factory.cc @@ -18,9 +18,12 @@ */ #include "connection/connection-factory.h" +#include "connection/sasl-handler.h" #include +#include +#include #include "connection/client-dispatcher.h" #include "connection/pipeline.h" #include "connection/service.h" @@ -31,10 +34,13 @@ using std::chrono::milliseconds; using std::chrono::nanoseconds; ConnectionFactory::ConnectionFactory(std::shared_ptr io_pool, - std::shared_ptr codec, nanoseconds connect_timeout) + std::shared_ptr codec, + std::shared_ptr conf, + nanoseconds connect_timeout) : connect_timeout_(connect_timeout), io_pool_(io_pool), - pipeline_factory_(std::make_shared(codec)) {} + conf_(conf), + pipeline_factory_(std::make_shared(codec, conf)) {} std::shared_ptr> ConnectionFactory::MakeBootstrap() { auto client = std::make_shared>(); diff --git a/hbase-native-client/connection/connection-factory.h b/hbase-native-client/connection/connection-factory.h index 1e75571..e1d7f6c 100644 --- a/hbase-native-client/connection/connection-factory.h +++ b/hbase-native-client/connection/connection-factory.h @@ -28,6 +28,7 @@ #include "connection/request.h" #include "connection/response.h" #include "connection/service.h" +#include "security/user.h" using std::chrono::nanoseconds; @@ -44,7 +45,8 @@ class ConnectionFactory { * There should only be one ConnectionFactory per client. */ ConnectionFactory(std::shared_ptr io_pool, - std::shared_ptr codec, nanoseconds connect_timeout = nanoseconds(0)); + std::shared_ptr codec, std::shared_ptr conf, + nanoseconds connect_timeout = nanoseconds(0)); /** Default Destructor */ virtual ~ConnectionFactory() = default; @@ -65,6 +67,7 @@ class ConnectionFactory { private: nanoseconds connect_timeout_; + std::shared_ptr conf_; std::shared_ptr io_pool_; std::shared_ptr pipeline_factory_; }; diff --git a/hbase-native-client/connection/connection-pool-test.cc b/hbase-native-client/connection/connection-pool-test.cc index 8ecdf29..04ec7f1 100644 --- a/hbase-native-client/connection/connection-pool-test.cc +++ b/hbase-native-client/connection/connection-pool-test.cc @@ -36,7 +36,7 @@ using hbase::ConnectionId; class MockConnectionFactory : public ConnectionFactory { public: - MockConnectionFactory() : ConnectionFactory(nullptr, nullptr) {} + MockConnectionFactory() : ConnectionFactory(nullptr, nullptr, nullptr) {} MOCK_METHOD0(MakeBootstrap, std::shared_ptr>()); MOCK_METHOD3(Connect, std::shared_ptr( std::shared_ptr>, diff --git a/hbase-native-client/connection/connection-pool.cc b/hbase-native-client/connection/connection-pool.cc index 3121294..d3ac3c2 100644 --- a/hbase-native-client/connection/connection-pool.cc +++ b/hbase-native-client/connection/connection-pool.cc @@ -36,11 +36,13 @@ using folly::SharedMutexWritePriority; using folly::SocketAddress; ConnectionPool::ConnectionPool(std::shared_ptr io_executor, - std::shared_ptr codec, nanoseconds connect_timeout) - : cf_(std::make_shared(io_executor, codec, connect_timeout)), + std::shared_ptr codec, std::shared_ptr conf, + nanoseconds connect_timeout) + : cf_(std::make_shared(io_executor, codec, conf, connect_timeout)), clients_(), connections_(), - map_mutex_() {} + map_mutex_(), + conf_(conf) {} ConnectionPool::ConnectionPool(std::shared_ptr cf) : cf_(cf), clients_(), connections_(), map_mutex_() {} diff --git a/hbase-native-client/connection/connection-pool.h b/hbase-native-client/connection/connection-pool.h index 2a8f195..0582d9b 100644 --- a/hbase-native-client/connection/connection-pool.h +++ b/hbase-native-client/connection/connection-pool.h @@ -50,7 +50,8 @@ class ConnectionPool { public: /** Create connection pool wit default connection factory */ ConnectionPool(std::shared_ptr io_executor, - std::shared_ptr codec, nanoseconds connect_timeout = nanoseconds(0)); + std::shared_ptr codec, std::shared_ptr conf, + nanoseconds connect_timeout = nanoseconds(0)); /** * Constructor that allows specifiying the connetion factory. @@ -93,6 +94,7 @@ class ConnectionPool { clients_; folly::SharedMutexWritePriority map_mutex_; std::shared_ptr cf_; + std::shared_ptr conf_; }; } // namespace hbase diff --git a/hbase-native-client/connection/pipeline.cc b/hbase-native-client/connection/pipeline.cc index edada52..d27c849 100644 --- a/hbase-native-client/connection/pipeline.cc +++ b/hbase-native-client/connection/pipeline.cc @@ -25,13 +25,15 @@ #include #include "connection/client-handler.h" +#include "connection/sasl-handler.h" using namespace folly; using namespace hbase; using namespace wangle; -RpcPipelineFactory::RpcPipelineFactory(std::shared_ptr codec) - : user_util_(), codec_(codec) {} +RpcPipelineFactory::RpcPipelineFactory(std::shared_ptr codec, + std::shared_ptr conf) + : user_util_(), codec_(codec), conf_(conf) {} SerializePipeline::Ptr RpcPipelineFactory::newPipeline( std::shared_ptr sock) { @@ -41,8 +43,10 @@ SerializePipeline::Ptr RpcPipelineFactory::newPipeline( auto pipeline = SerializePipeline::create(); pipeline->addBack(AsyncSocketHandler{sock}); pipeline->addBack(EventBaseHandler{}); + auto secure = security::User::IsSecurityEnabled(*conf_); + pipeline->addBack(SaslHandler{user_util_.user_name(secure), conf_}); pipeline->addBack(LengthFieldBasedFrameDecoder{}); - pipeline->addBack(ClientHandler{user_util_.user_name(), codec_, addr.describe()}); + pipeline->addBack(ClientHandler{user_util_.user_name(secure), codec_, addr.describe()}); pipeline->finalize(); return pipeline; } diff --git a/hbase-native-client/connection/pipeline.h b/hbase-native-client/connection/pipeline.h index ea40cfd..add7fe5 100644 --- a/hbase-native-client/connection/pipeline.h +++ b/hbase-native-client/connection/pipeline.h @@ -25,6 +25,7 @@ #include "connection/request.h" #include "connection/response.h" +#include "core/configuration.h" #include "serde/codec.h" #include "utils/user-util.h" @@ -41,7 +42,7 @@ class RpcPipelineFactory : public wangle::PipelineFactory { /** * Constructor. This will create user util. */ - explicit RpcPipelineFactory(std::shared_ptr codec); + explicit RpcPipelineFactory(std::shared_ptr codec, std::shared_ptr conf); /** * Create a new pipeline. @@ -57,5 +58,6 @@ class RpcPipelineFactory : public wangle::PipelineFactory { private: UserUtil user_util_; std::shared_ptr codec_; + std::shared_ptr conf_; }; } // namespace hbase diff --git a/hbase-native-client/connection/rpc-client.cc b/hbase-native-client/connection/rpc-client.cc index 5fa1138..57df66d 100644 --- a/hbase-native-client/connection/rpc-client.cc +++ b/hbase-native-client/connection/rpc-client.cc @@ -30,9 +30,10 @@ using hbase::RpcClient; namespace hbase { RpcClient::RpcClient(std::shared_ptr io_executor, - std::shared_ptr codec, nanoseconds connect_timeout) - : io_executor_(io_executor) { - cp_ = std::make_shared(io_executor_, codec, connect_timeout); + std::shared_ptr codec, std::shared_ptr conf, + nanoseconds connect_timeout) + : io_executor_(io_executor), conf_(conf) { + cp_ = std::make_shared(io_executor_, codec, conf, connect_timeout); } void RpcClient::Close() { io_executor_->stop(); } diff --git a/hbase-native-client/connection/rpc-client.h b/hbase-native-client/connection/rpc-client.h index d416ceb..fbb773a 100644 --- a/hbase-native-client/connection/rpc-client.h +++ b/hbase-native-client/connection/rpc-client.h @@ -46,7 +46,7 @@ namespace hbase { class RpcClient { public: RpcClient(std::shared_ptr io_executor, std::shared_ptr codec, - nanoseconds connect_timeout = nanoseconds(0)); + std::shared_ptr conf, nanoseconds connect_timeout = nanoseconds(0)); virtual ~RpcClient() { Close(); } @@ -78,5 +78,6 @@ class RpcClient { private: std::shared_ptr cp_; std::shared_ptr io_executor_; + std::shared_ptr conf_; }; } // namespace hbase diff --git a/hbase-native-client/core/BUCK b/hbase-native-client/core/BUCK index e9fc716..9cea1f6 100644 --- a/hbase-native-client/core/BUCK +++ b/hbase-native-client/core/BUCK @@ -92,7 +92,9 @@ cxx_library( "//third-party:zookeeper_mt", ], compiler_flags=['-Weffc++', '-ggdb'], - visibility=['PUBLIC',],) + visibility=[ + 'PUBLIC', + ],) cxx_library( name="conf", exported_headers=[ @@ -105,10 +107,14 @@ cxx_library( ], deps=["//third-party:folly"], compiler_flags=['-Weffc++', '-ggdb'], - visibility=['PUBLIC',],) + visibility=[ + 'PUBLIC', + ],) cxx_test( name="location-cache-test", - srcs=["location-cache-test.cc",], + srcs=[ + "location-cache-test.cc", + ], deps=[ ":core", "//test-util:test-util", @@ -116,12 +122,18 @@ cxx_test( run_test_separately=True,) cxx_test( name="cell-test", - srcs=["cell-test.cc",], - deps=[":core",], + srcs=[ + "cell-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="filter-test", - srcs=["filter-test.cc",], + srcs=[ + "filter-test.cc", + ], deps=[ ":core", "//if:if", @@ -131,17 +143,27 @@ cxx_test( run_test_separately=True,) cxx_test( name="get-test", - srcs=["get-test.cc",], - deps=[":core",], + srcs=[ + "get-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="put-test", - srcs=["put-test.cc",], - deps=[":core",], + srcs=[ + "put-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="retry-test", - srcs=["async-rpc-retrying-test.cc",], + srcs=[ + "async-rpc-retrying-test.cc", + ], deps=[ ":core", "//test-util:test-util", @@ -150,32 +172,54 @@ cxx_test( run_test_separately=True,) cxx_test( name="time-range-test", - srcs=["time-range-test.cc",], - deps=[":core",], + srcs=[ + "time-range-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="configuration-test", - srcs=["configuration-test.cc",], - deps=[":core",], + srcs=[ + "configuration-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="hbase-configuration-test", - srcs=["hbase-configuration-test.cc",], - deps=[":core",], + srcs=[ + "hbase-configuration-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="scan-test", - srcs=["scan-test.cc",], - deps=[":core",], + srcs=[ + "scan-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="result-test", - srcs=["result-test.cc",], - deps=[":core",], + srcs=[ + "result-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_test( name="request-converter-test", - srcs=["request-converter-test.cc",], + srcs=[ + "request-converter-test.cc", + ], deps=[ ":core", "//connection:connection", @@ -184,7 +228,9 @@ cxx_test( run_test_separately=True,) cxx_test( name="client-test", - srcs=["client-test.cc",], + srcs=[ + "client-test.cc", + ], deps=[ ":core", "//if:if", @@ -194,10 +240,16 @@ cxx_test( run_test_separately=True,) cxx_test( name="zk-util-test", - srcs=["zk-util-test.cc",], - deps=[":core",], + srcs=[ + "zk-util-test.cc", + ], + deps=[ + ":core", + ], run_test_separately=True,) cxx_binary( name="simple-client", - srcs=["simple-client.cc",], + srcs=[ + "simple-client.cc", + ], deps=[":core", "//connection:connection"],) diff --git a/hbase-native-client/core/async-connection.cc b/hbase-native-client/core/async-connection.cc index 4642c61..ef945fb 100644 --- a/hbase-native-client/core/async-connection.cc +++ b/hbase-native-client/core/async-connection.cc @@ -44,8 +44,8 @@ void AsyncConnectionImpl::Init() { } else { LOG(WARNING) << "Not using RPC Cell Codec"; } - rpc_client_ = - std::make_shared(io_executor_, codec, connection_conf_->connect_timeout()); + rpc_client_ = std::make_shared(io_executor_, codec, conf_, + connection_conf_->connect_timeout()); location_cache_ = std::make_shared(conf_, cpu_executor_, rpc_client_->connection_pool()); caller_factory_ = diff --git a/hbase-native-client/core/async-rpc-retrying-test.cc b/hbase-native-client/core/async-rpc-retrying-test.cc index 487c34c..11750eb 100644 --- a/hbase-native-client/core/async-rpc-retrying-test.cc +++ b/hbase-native-client/core/async-rpc-retrying-test.cc @@ -317,7 +317,8 @@ void runTest(std::shared_ptr region_locator, std::string auto io_executor_ = client.async_connection()->io_executor(); auto retry_executor_ = std::make_shared(1); auto codec = std::make_shared(); - auto rpc_client = std::make_shared(io_executor_, codec); + auto rpc_client = + std::make_shared(io_executor_, codec, AsyncRpcRetryTest::test_util->conf()); // auto retry_event_base_ = std::make_shared(true); std::shared_ptr retry_timer = folly::HHWheelTimer::newTimer(retry_executor_->getEventBase()); diff --git a/hbase-native-client/core/location-cache-test.cc b/hbase-native-client/core/location-cache-test.cc index 8d1ac5f..3253c56 100644 --- a/hbase-native-client/core/location-cache-test.cc +++ b/hbase-native-client/core/location-cache-test.cc @@ -52,7 +52,7 @@ TEST_F(LocationCacheTest, TestGetMetaNodeContents) { auto cpu = std::make_shared(4); auto io = std::make_shared(4); auto codec = std::make_shared(); - auto cp = std::make_shared(io, codec); + auto cp = std::make_shared(io, codec, LocationCacheTest::test_util_->conf()); LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp}; auto f = cache.LocateMeta(); auto result = f.get(); @@ -68,7 +68,7 @@ TEST_F(LocationCacheTest, TestGetRegionLocation) { auto cpu = std::make_shared(4); auto io = std::make_shared(4); auto codec = std::make_shared(); - auto cp = std::make_shared(io, codec); + auto cp = std::make_shared(io, codec, LocationCacheTest::test_util_->conf()); LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp}; // If there is no table this should throw an exception @@ -87,7 +87,7 @@ TEST_F(LocationCacheTest, TestCaching) { auto cpu = std::make_shared(4); auto io = std::make_shared(4); auto codec = std::make_shared(); - auto cp = std::make_shared(io, codec); + auto cp = std::make_shared(io, codec, LocationCacheTest::test_util_->conf()); LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp}; auto tn_1 = folly::to("t1"); diff --git a/hbase-native-client/security/BUCK b/hbase-native-client/security/BUCK index 7383028..f8a5695 100644 --- a/hbase-native-client/security/BUCK +++ b/hbase-native-client/security/BUCK @@ -19,8 +19,12 @@ # to a single server. cxx_library( name="security", - exported_headers=["user.h",], + exported_headers=[ + "user.h", + ], srcs=[], deps=["//core:conf"], compiler_flags=['-Weffc++'], - visibility=['//core/...', '//connection/...'],) + visibility=[ + 'PUBLIC', + ],) diff --git a/hbase-native-client/security/user.h b/hbase-native-client/security/user.h index 035af31..307fc61 100644 --- a/hbase-native-client/security/user.h +++ b/hbase-native-client/security/user.h @@ -18,6 +18,7 @@ */ #pragma once +#include #include #include #include "core/configuration.h" diff --git a/hbase-native-client/serde/BUCK b/hbase-native-client/serde/BUCK index 38e7b4d..18e949c 100644 --- a/hbase-native-client/serde/BUCK +++ b/hbase-native-client/serde/BUCK @@ -31,7 +31,9 @@ cxx_library( "rpc.cc", "zk.cc", ], - deps=["//if:if", "//third-party:folly", "//utils:utils"], + deps=[ + "//if:if", "//third-party:folly", "//utils:utils", "//security:security" + ], tests=[ ":client-deserializer-test", ":client-serializer-test", @@ -41,28 +43,54 @@ cxx_library( ":region-info-deserializer-test", ], compiler_flags=['-Weffc++'], - visibility=['PUBLIC',],) + visibility=[ + 'PUBLIC', + ],) cxx_test( name="table-name-test", - srcs=["table-name-test.cc",], - deps=[":serde",],) + srcs=[ + "table-name-test.cc", + ], + deps=[ + ":serde", + ],) cxx_test( name="server-name-test", - srcs=["server-name-test.cc",], - deps=[":serde",],) + srcs=[ + "server-name-test.cc", + ], + deps=[ + ":serde", + ],) cxx_test( name="client-serializer-test", - srcs=["client-serializer-test.cc",], - deps=[":serde",],) + srcs=[ + "client-serializer-test.cc", + ], + deps=[ + ":serde", + ],) cxx_test( name="client-deserializer-test", - srcs=["client-deserializer-test.cc",], - deps=[":serde",],) + srcs=[ + "client-deserializer-test.cc", + ], + deps=[ + ":serde", + ],) cxx_test( name="zk-deserializer-test", - srcs=["zk-deserializer-test.cc",], - deps=[":serde",],) + srcs=[ + "zk-deserializer-test.cc", + ], + deps=[ + ":serde", + ],) cxx_test( name="region-info-deserializer-test", - srcs=["region-info-deserializer-test.cc",], - deps=[":serde",],) + srcs=[ + "region-info-deserializer-test.cc", + ], + deps=[ + ":serde", + ],) diff --git a/hbase-native-client/serde/client-serializer-test.cc b/hbase-native-client/serde/client-serializer-test.cc index 33c48f3..7d8b29c 100644 --- a/hbase-native-client/serde/client-serializer-test.cc +++ b/hbase-native-client/serde/client-serializer-test.cc @@ -33,7 +33,7 @@ using namespace folly::io; TEST(RpcSerdeTest, PreambleIncludesHBas) { RpcSerde ser{nullptr}; - auto buf = ser.Preamble(); + auto buf = ser.Preamble(false); const char *p = reinterpret_cast(buf->data()); // Take the first for chars and make sure they are the // magic string @@ -44,7 +44,7 @@ TEST(RpcSerdeTest, PreambleIncludesHBas) { TEST(RpcSerdeTest, PreambleIncludesVersion) { RpcSerde ser{nullptr}; - auto buf = ser.Preamble(); + auto buf = ser.Preamble(false); EXPECT_EQ(0, static_cast(buf->data())[4]); EXPECT_EQ(80, static_cast(buf->data())[5]); } diff --git a/hbase-native-client/serde/rpc.cc b/hbase-native-client/serde/rpc.cc index e657a64..968cd5b 100644 --- a/hbase-native-client/serde/rpc.cc +++ b/hbase-native-client/serde/rpc.cc @@ -50,6 +50,7 @@ static const std::string PREAMBLE = "HBas"; static const std::string INTERFACE = "ClientService"; static const uint8_t RPC_VERSION = 0; static const uint8_t DEFAULT_AUTH_TYPE = 80; +static const uint8_t KERBEROS_AUTH_TYPE = 81; int RpcSerde::ParseDelimited(const IOBuf *buf, Message *msg) { if (buf == nullptr || msg == nullptr) { @@ -85,17 +86,21 @@ int RpcSerde::ParseDelimited(const IOBuf *buf, Message *msg) { return coded_stream.CurrentPosition(); } -RpcSerde::RpcSerde(std::shared_ptr codec) : auth_type_(DEFAULT_AUTH_TYPE), codec_(codec) {} +RpcSerde::RpcSerde(std::shared_ptr codec) : codec_(codec) {} -unique_ptr RpcSerde::Preamble() { +std::unique_ptr RpcSerde::Preamble(bool secure) { auto magic = IOBuf::copyBuffer(PREAMBLE, 0, 2); magic->append(2); RWPrivateCursor c(magic.get()); c.skip(4); // Version c.write(RPC_VERSION); - // Standard security aka Please don't lie to me. - c.write(auth_type_); + if (secure) { + // for now support only KERBEROS (DIGEST is not supported) + c.write(KERBEROS_AUTH_TYPE); + } else { + c.write(DEFAULT_AUTH_TYPE); + } return magic; } diff --git a/hbase-native-client/serde/rpc.h b/hbase-native-client/serde/rpc.h index abebe94..15aa1ee 100644 --- a/hbase-native-client/serde/rpc.h +++ b/hbase-native-client/serde/rpc.h @@ -68,7 +68,7 @@ class RpcSerde { /** * Create a new connection preamble in a new IOBuf. */ - std::unique_ptr Preamble(); + static std::unique_ptr Preamble(bool secure); /** * Create the header protobuf object and serialize it to a new IOBuf. @@ -119,7 +119,6 @@ class RpcSerde { private: /* data */ - uint8_t auth_type_; std::shared_ptr codec_; std::unique_ptr CreateVersionInfo(); }; diff --git a/hbase-native-client/third-party/BUCK b/hbase-native-client/third-party/BUCK index f37eb4e..418323b 100644 --- a/hbase-native-client/third-party/BUCK +++ b/hbase-native-client/third-party/BUCK @@ -91,7 +91,8 @@ wangle = add_system_libs( genrule( name="gen_zk", out="gen_zk", - bash="mkdir -p $OUT && wget http://www-us.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz && tar zxf zookeeper-3.4.8.tar.gz && rm -rf zookeeper-3.4.8.tar.gz && cd zookeeper-3.4.8 && cd src/c && ./configure --prefix=$OUT && make && make install && cd $OUT && rm -rf zookeeper-3.4.8*" + bash= + "mkdir -p $OUT && wget http://www-us.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz && tar zxf zookeeper-3.4.8.tar.gz && rm -rf zookeeper-3.4.8.tar.gz && cd zookeeper-3.4.8 && cd src/c && ./configure --prefix=$OUT && make && make install && cd $OUT && rm -rf zookeeper-3.4.8*" ) cxx_library( name='google-test', @@ -112,4 +113,6 @@ cxx_library( ('googletest/googlemock', 'src/*.cc'), ]), exported_deps=dynamic_rules, - visibility=['PUBLIC',],) + visibility=[ + 'PUBLIC', + ],) diff --git a/hbase-native-client/utils/BUCK b/hbase-native-client/utils/BUCK index 04e2b67..ed8e114 100644 --- a/hbase-native-client/utils/BUCK +++ b/hbase-native-client/utils/BUCK @@ -26,15 +26,29 @@ cxx_library( "version.h", ], srcs=["bytes-util.cc", "connection-util.cc", "user-util.cc"], - deps=['//third-party:folly',], + deps=[ + '//third-party:folly', + ], tests=[":user-util-test"], - visibility=['PUBLIC',], + linker_flags=['-L/usr/local/lib', '-lkrb5'], + exported_linker_flags=['-L/usr/local/lib', '-lkrb5'], + visibility=[ + 'PUBLIC', + ], compiler_flags=['-Weffc++'],) cxx_test( name="user-util-test", - srcs=["user-util-test.cc",], - deps=[":utils",],) + srcs=[ + "user-util-test.cc", + ], + deps=[ + ":utils", + ],) cxx_test( name="bytes-util-test", - srcs=["bytes-util-test.cc",], - deps=[":utils",],) + srcs=[ + "bytes-util-test.cc", + ], + deps=[ + ":utils", + ],) diff --git a/hbase-native-client/utils/user-util-test.cc b/hbase-native-client/utils/user-util-test.cc index 7c11d8c..aa3fa45 100644 --- a/hbase-native-client/utils/user-util-test.cc +++ b/hbase-native-client/utils/user-util-test.cc @@ -28,7 +28,7 @@ using namespace hbase; TEST(TestUserUtil, TestGetSomething) { UserUtil u_util; - string name = u_util.user_name(); + string name = u_util.user_name(false); // TODO shell out to whoami to check this. ASSERT_GT(name.length(), 0); diff --git a/hbase-native-client/utils/user-util.cc b/hbase-native-client/utils/user-util.cc index 9e170e0..71f0012 100644 --- a/hbase-native-client/utils/user-util.cc +++ b/hbase-native-client/utils/user-util.cc @@ -20,6 +20,7 @@ #include "utils/user-util.h" #include +#include #include #include #include @@ -27,14 +28,14 @@ using namespace hbase; using namespace std; -UserUtil::UserUtil() : once_flag_{}, user_name_{"drwho"} {} +UserUtil::UserUtil() : once_flag_{} {} -string UserUtil::user_name() { - std::call_once(once_flag_, [this]() { compute_user_name(); }); +string UserUtil::user_name(bool secure) { + std::call_once(once_flag_, [this, secure]() { compute_user_name(secure); }); return user_name_; } -void UserUtil::compute_user_name() { +void UserUtil::compute_user_name(bool secure) { // According to the man page of getpwuid // this should never be free'd // @@ -45,4 +46,32 @@ void UserUtil::compute_user_name() { if (passwd && passwd->pw_name) { user_name_ = string{passwd->pw_name}; } + if (!secure) return; + krb5_context ctx; + krb5_error_code ret = krb5_init_context(&ctx); + if (ret != 0) { + throw std::runtime_error("cannot init krb ctx " + std::to_string(ret)); + } + krb5_ccache ccache; + ret = krb5_cc_default(ctx, &ccache); + if (ret != 0) { + throw std::runtime_error("cannot get default cache " + std::to_string(ret)); + } + // Here is sample principal: hbase/23a03935850c@EXAMPLE.COM + // There may be one (user) or two (user/host) components before the @ sign + krb5_principal princ; + ret = krb5_cc_get_principal(ctx, ccache, &princ); + if (ret != 0) { + throw std::runtime_error("cannot get default principal " + std::to_string(ret)); + } + user_name_ = princ->data->data; + if (krb5_princ_size(ctx, princ) >= 2) { + user_name_ += "/"; + user_name_ += static_cast(princ->data[1].data); + } + user_name_ += "@"; + user_name_ += princ->realm.data; + VLOG(1) << "user " << user_name_; + krb5_free_principal(ctx, princ); + krb5_free_context(ctx); } diff --git a/hbase-native-client/utils/user-util.h b/hbase-native-client/utils/user-util.h index 6f8fce1..6258c85 100644 --- a/hbase-native-client/utils/user-util.h +++ b/hbase-native-client/utils/user-util.h @@ -41,13 +41,13 @@ class UserUtil { * Get the username of the user owning this process. This is thread safe and * lockless for every invocation other than the first one. */ - std::string user_name(); + std::string user_name(bool secure = false); private: /** * Compute the username. This will block. */ - void compute_user_name(); + void compute_user_name(bool secure); std::once_flag once_flag_; std::string user_name_; }; diff --git a/hbase-native-client/connection/sasl-handler.h b/hbase-native-client/connection/sasl-handler.h new file mode 100644 index 0000000..5e8cceb --- /dev/null +++ b/hbase-native-client/connection/sasl-handler.h @@ -0,0 +1,78 @@ +/* + * 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. + * + */ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include "connection/sasl-util.h" +#include "connection/service.h" +#include "security/user.h" +#include "serde/rpc.h" + +namespace hbase { + +/** + * Class to perform SASL handshake with server (currently works with regionserver principals only) + * It is inserted between EventBaseHandler and LengthFieldBasedFrameDecoder in the pipeline + * SaslHandler would intercept writes to server by buffering the IOBuf's and start the handshake + * process + * (via sasl_client_XX calls provided by Cyrus) + * After handshake is complete, SaslHandler would send the buffered IOBuf's to server and + * act as pass-thru from then on + */ +class SaslHandler + : public wangle::HandlerAdapter> { + public: + explicit SaslHandler(std::string user_name, std::shared_ptr conf); + SaslHandler(const SaslHandler& hdlr); + ~SaslHandler(); + + // from HandlerAdapter + void read(Context* ctx, folly::IOBufQueue& buf) override; + folly::Future write(Context* ctx, std::unique_ptr buf) override; + void transportActive(Context* ctx) override; + + private: + // used by Cyrus + sasl_conn_t* sconn_ = nullptr; + std::string user_name_; + std::string service_name_; + std::string host_name_; + bool secure_; + std::atomic_flag sasl_connection_setup_started_; + std::atomic sasl_connection_setup_in_progress_{true}; + // vector of folly::IOBuf which buffers client writes before handshake is complete + std::vector> iobuf_; + SaslUtil sasl_util_; + + // writes the output returned by sasl_client_XX to server + folly::Future WriteSaslOutput(Context* ctx, const char* out, unsigned int outlen); + folly::Future SaslInit(Context* ctx); + void FinishAuth(Context* ctx, folly::IOBufQueue& bufQueue); + void ContinueSaslNegotiation(Context* ctx, folly::IOBufQueue& buf); + std::string ParseServiceName(std::shared_ptr conf, bool secure); +}; +} // namespace hbase diff --git a/hbase-native-client/connection/sasl-handler.cc b/hbase-native-client/connection/sasl-handler.cc new file mode 100644 index 0000000..8c4179a --- /dev/null +++ b/hbase-native-client/connection/sasl-handler.cc @@ -0,0 +1,224 @@ +/* + * 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. + * + */ +#include "connection/sasl-handler.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "connection/service.h" +#include "security/user.h" +using hbase::security::User; + +using std::chrono::nanoseconds; +using namespace folly; +using namespace wangle; +using namespace hbase; + +SaslHandler::SaslHandler(std::string user_name, std::shared_ptr conf) + : user_name_(user_name) { + host_name_.clear(); + secure_ = User::IsSecurityEnabled(*conf); + service_name_ = SaslUtil::ParseServiceName(conf, secure_); + sasl_connection_setup_started_.clear(); + sasl_connection_setup_in_progress_.store(true); +} + +SaslHandler::SaslHandler(const SaslHandler &hdlr) { + user_name_ = hdlr.user_name_; + service_name_ = hdlr.service_name_; + secure_ = hdlr.secure_; + host_name_ = hdlr.host_name_; + // copy-constructor sets the flags below to their initial state as opposed to getting them + // from the object this class is constructed from. That way, this instance is ready to do + // sasl stuff without issues, right from the SaslInit. Sharing a sasl session is not useful + // between two handler instances. + sasl_connection_setup_started_.clear(); + sasl_connection_setup_in_progress_.store(true); + sconn_ = nullptr; +} + +SaslHandler::~SaslHandler() { + if (nullptr != sconn_) { + sasl_dispose(&sconn_); + } + sconn_ = nullptr; +} + +void SaslHandler::transportActive(Context *ctx) { + // assign hostname; needed for the sasl handshake if secure + folly::SocketAddress address; + ctx->getTransport()->getPeerAddress(&address); + host_name_ = address.getHostStr(); + + // now init the sasl library; this is once per process + if (secure_) { + sasl_util_.InitializeSaslLib(); + } + // write the preamble to kick off the RPC handshake + VLOG(3) << "Writing RPC connection Preamble to server: " << host_name_; + auto preamble = RpcSerde::Preamble(secure_); + ctx->fireWrite(std::move(preamble)); +} + +void SaslHandler::read(Context *ctx, folly::IOBufQueue &buf) { + // if security is not on, or in case of security-on, if secure connection setup not in progress, + // pass it up without touching + if (!secure_ || !sasl_connection_setup_in_progress_.load()) { + ctx->fireRead(buf); + } else { + // message is for this handler; process it appropriately + ContinueSaslNegotiation(ctx, buf); + } +} + +folly::Future SaslHandler::write(Context *ctx, std::unique_ptr buf) { + // if security is on, and if secure connection setup in progress, + // this message is for this handler to process and respond + if (secure_ && sasl_connection_setup_in_progress_.load()) { + // store IOBuf which is to be sent to server after SASL handshake + iobuf_.push_back(std::move(buf)); + if (!sasl_connection_setup_started_.test_and_set()) { + // for the first incoming RPC from the higher layer, trigger sasl initialization + return SaslInit(ctx); + } else { + // for the subsequent incoming RPCs from the higher layer, just return empty future + folly::Promise p_; + return p_.getFuture(); + } + } + // pass the bytes recieved down without touching it + return ctx->fireWrite(std::move(buf)); +} + +folly::Future SaslHandler::WriteSaslOutput(Context *ctx, const char *out, + unsigned int outlen) { + int buffer_size = outlen + 4; + auto iob = IOBuf::create(buffer_size); + iob->append(buffer_size); + // Create the array output stream. + google::protobuf::io::ArrayOutputStream aos{iob->writableData(), buffer_size}; + std::unique_ptr coded_output = + std::make_unique(&aos); + uint32_t total_size = outlen; + total_size = ntohl(total_size); + coded_output->WriteRaw(&total_size, 4); + coded_output->WriteRaw(out, outlen); + return ctx->fireWrite(std::move(iob)); +} + +void SaslHandler::FinishAuth(Context *ctx, folly::IOBufQueue &bufQueue) { + std::unique_ptr iob; + if (!bufQueue.empty()) { + iob = bufQueue.pop_front(); + throw std::runtime_error("Error in the final step of handshake " + + std::string(reinterpret_cast(iob->data()))); + } else { + sasl_connection_setup_in_progress_.store(false); + // write what we buffered + for (size_t i = 0; i < iobuf_.size(); i++) { + iob = std::move(iobuf_.at(i)); + ctx->fireWrite(std::move(iob)); + } + } +} + +folly::Future SaslHandler::SaslInit(Context *ctx) { + int rc; + const char *mechusing, *mechlist = "GSSAPI"; + const char *out; + unsigned int outlen; + + rc = sasl_client_new(service_name_.c_str(), /* The service we are using*/ + host_name_.c_str(), NULL, + NULL, /* Local and remote IP address strings + (NULL disables mechanisms which require this info)*/ + NULL, /*connection-specific callbacks*/ + 0 /*security flags*/, &sconn_); + if (rc != SASL_OK) { + LOG(FATAL) << "Cannot create client (" << rc << ") "; + throw std::runtime_error("Cannot create client"); + } + int curr_rc; + do { + curr_rc = sasl_client_start(sconn_, /* the same context from above */ + mechlist, /* the list of mechanisms from the server */ + NULL, /* filled in if an interaction is needed */ + &out, /* filled in on success */ + &outlen, /* filled in on success */ + &mechusing); + } while (curr_rc == SASL_INTERACT); /* the mechanism may ask us to fill + in things many times. result is SASL_CONTINUE on success */ + if (curr_rc != SASL_CONTINUE) { + throw std::runtime_error("Cannot start client (" + std::to_string(curr_rc) + ")"); + } + folly::Future fut = WriteSaslOutput(ctx, out, outlen); + return fut; +} + +void SaslHandler::ContinueSaslNegotiation(Context *ctx, folly::IOBufQueue &bufQueue) { + const char *out; + unsigned int outlen; + + int bytes_sent = 0; + int bytes_received = 0; + + std::unique_ptr iob = bufQueue.pop_front(); + bytes_received = iob->length(); + if (bytes_received == 0) { + throw std::runtime_error("Error in sasl handshake"); + } + folly::io::RWPrivateCursor c(iob.get()); + std::uint32_t status = c.readBE(); + std::uint32_t sz = c.readBE(); + + if (status != 0 /*Status 0 is success*/) { + // Assumption here is that the response from server is not more than 8 * 1024 + throw std::runtime_error("Error in sasl handshake " + + std::string(reinterpret_cast(c.writableData()))); + } + out = nullptr; + outlen = 0; + + int curr_rc = + sasl_client_step(sconn_, /* our context */ + reinterpret_cast(c.writableData()), /* the data from the server */ + sz, /* its length */ + NULL, /* this should be unallocated and NULL */ + &out, /* filled in on success */ + &outlen); /* filled in on success */ + + if (curr_rc == SASL_OK || curr_rc == SASL_CONTINUE) { + WriteSaslOutput(ctx, out, outlen); + } + if (curr_rc == SASL_OK) { + FinishAuth(ctx, bufQueue); + } +} diff --git a/hbase-native-client/connection/sasl-util.h b/hbase-native-client/connection/sasl-util.h new file mode 100644 index 0000000..4d58d9ee --- /dev/null +++ b/hbase-native-client/connection/sasl-util.h @@ -0,0 +1,46 @@ +/* + * 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. + * + */ +#pragma once + +#include +#include +#include + +#include "core/configuration.h" + +class SaslUtil { + public: + void InitializeSaslLib(void); + static std::string ParseServiceName(std::shared_ptr conf, bool secure); + + private: + static constexpr const char *kDefaultPluginDir = "/usr/lib/sasl2"; + // for now the sasl handler is hardcoded to work against the regionservers only. In the future, if + // we + // need the master rpc to work, we could have a map of service names to principals to use (similar + // to the Java implementation) + static constexpr const char *kServerPrincipalConfKey = "hbase.regionserver.kerberos.principal"; + + static int GetPluginPath(void *context, const char **path); + static void *MutexNew(void); + static int MutexLock(void *m); + static int MutexUnlock(void *m); + static void MutexDispose(void *m); + static std::once_flag library_inited_; +}; diff --git a/hbase-native-client/connection/sasl-util.cc b/hbase-native-client/connection/sasl-util.cc new file mode 100644 index 0000000..a000a27 --- /dev/null +++ b/hbase-native-client/connection/sasl-util.cc @@ -0,0 +1,96 @@ +/* + * 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. + * + */ +#include "connection/sasl-util.h" + +#include +#include +#include +#include + +#include + +// constexpr const char *SaslUtil::kDefaultPluginDir = "/usr/lib/sasl2"; +// constexpr const char *SaslUtil::kServerPrincipalConfKey = +// "hbase.regionserver.kerberos.principal"; + +int SaslUtil::GetPluginPath(void *context __attribute__((unused)), const char **path) { + *path = getenv("SASL_PATH"); + + if (*path == NULL) { + *path = kDefaultPluginDir; + } + return SASL_OK; +} + +void *SaslUtil::MutexNew(void) { + auto m = new std::mutex(); + return m; +} + +int SaslUtil::MutexLock(void *m) { + (reinterpret_cast(m))->lock(); + return SASL_OK; +} + +int SaslUtil::MutexUnlock(void *m) { + (reinterpret_cast(m))->unlock(); + return SASL_OK; +} + +void SaslUtil::MutexDispose(void *m) { + std::mutex *mutex = reinterpret_cast(m); + delete mutex; +} + +std::once_flag SaslUtil::library_inited_; + +void SaslUtil::InitializeSaslLib() { + std::call_once(library_inited_, []() { + sasl_set_mutex(reinterpret_cast(&SaslUtil::MutexNew), + reinterpret_cast(&SaslUtil::MutexLock), + reinterpret_cast(&SaslUtil::MutexUnlock), + reinterpret_cast(&SaslUtil::MutexDispose)); + static sasl_callback_t callbacks[] = { + {SASL_CB_GETPATH, (sasl_callback_ft)&SaslUtil::GetPluginPath, NULL}, + {SASL_CB_LIST_END, NULL, NULL}}; + int rc = sasl_client_init(callbacks); + if (rc != SASL_OK) { + throw std::runtime_error("Cannot initialize client " + std::to_string(rc)); + } + }); +} + +std::string SaslUtil::ParseServiceName(std::shared_ptr conf, bool secure) { + if (!secure) { + return std::string(); + } + std::string svrPrincipal = conf->Get(kServerPrincipalConfKey, ""); + // principal is of this form: hbase/23a03935850c@EXAMPLE.COM + // where 23a03935850c is the host (optional) + std::size_t pos = svrPrincipal.find("/"); + if (pos == std::string::npos && svrPrincipal.find("@") != std::string::npos) { + pos = svrPrincipal.find("@"); + } + if (pos == std::string::npos) { + throw std::runtime_error("Couldn't retrieve service principal from conf"); + } + VLOG(1) << "pos " << pos << " " << svrPrincipal; + std::string service_name = svrPrincipal.substr(0, pos); + return service_name; +} diff --git a/hbase-native-client/docker-files/Dockerfile b/hbase-native-client/docker-files/Dockerfile new file mode 100644 index 0000000..36997dd --- /dev/null +++ b/hbase-native-client/docker-files/Dockerfile @@ -0,0 +1,86 @@ +## +# 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. + +FROM pjameson/buck-folly-watchman:20160511 + +ARG CC=/usr/bin/gcc-5 +ARG CXX=/usr/bin/g++-5 +ARG CFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 -fPIC -g -fno-omit-frame-pointer -O2 -pthread" +ARG CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0 -fPIC -g -fno-omit-frame-pointer -O2 -pthread" + +ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" + +RUN wget ftp://ftp.cyrusimap.org/cyrus-sasl/cyrus-sasl-2.1.26.tar.gz ; \ + tar zxf cyrus-sasl-2.1.26.tar.gz ; \ + cd cyrus-sasl-2.1.26 ; \ + ./configure ; \ + make ; \ + make install ;\ + cp /usr/local/lib/sasl2/* /usr/lib/sasl2/ + +RUN apt-get install -y vim maven inetutils-ping python-pip doxygen graphviz clang-format && \ + pip install yapf && \ + apt-get -qq clean && \ + apt-get -y -qq autoremove && \ + rm -rf /var/lib/{apt,dpkg,cache,log}/ && \ + rm -rf /tmp/* + +RUN apt-get update && \ + apt-get install -y debconf-utils debconf-set-selections && \ + echo "krb5-config krb5-config/kerberos_servers string localhost" | debconf-set-selections ; \ + echo "krb5-config krb5-config/admin_server string localhost" | debconf-set-selections ; \ + echo "krb5-config krb5-config/add_servers_realm string EXAMPLE.COM" | debconf-set-selections ; \ + echo "krb5-config krb5-config/default_realm string EXAMPLE.COM" | debconf-set-selections ; \ + apt-get install -y krb5-kdc krb5-admin-server ; \ + echo "admin" > /tmp/krb-realm.pass ; \ + echo "admin" >> /tmp/krb-realm.pass ; \ + krb5_newrealm < /tmp/krb-realm.pass ; \ + echo "addprinc hbase" > /tmp/krb-princ.pass ; \ + echo "admin" >> /tmp/krb-princ.pass ; \ + echo "admin" >> /tmp/krb-princ.pass ; \ + kadmin.local < /tmp/krb-princ.pass ; \ + echo 'addprinc hbase/securecluster' > /tmp/krb-princ.pass; echo 'admin' >> /tmp/krb-princ.pass ; \ + rm hbase-host.keytab ; echo 'admin' >> /tmp/krb-princ.pass ; \ + echo 'xst -k hbase-host.keytab hbase/securecluster@EXAMPLE.COM' >> /tmp/krb-princ.pass ; \ + kadmin.local < /tmp/krb-princ.pass ; +COPY docker-files/krb5.conf /etc + +RUN git clone https://github.com/google/protobuf.git /usr/src/protobuf && \ + cd /usr/src/protobuf/ && \ + git checkout 2.7.0 && \ + mkdir gmock && \ + ldconfig && \ + ./autogen.sh && \ + ./configure && \ + make && \ + make install && \ + make clean && \ + rm -rf .git && \ + cd /usr/src && \ + wget http://www-us.apache.org/dist/zookeeper/zookeeper-3.4.8/zookeeper-3.4.8.tar.gz && \ + tar zxf zookeeper-3.4.8.tar.gz && \ + rm -rf zookeeper-3.4.8.tar.gz && \ + cd zookeeper-3.4.8 && \ + cd src/c && \ + ldconfig && \ + ./configure && \ + make && \ + make install && \ + make clean && \ + ldconfig + +WORKDIR /usr/src/hbase/hbase-native-client diff --git a/hbase-native-client/docker-files/krb5.conf b/hbase-native-client/docker-files/krb5.conf new file mode 100644 index 0000000..d449928 --- /dev/null +++ b/hbase-native-client/docker-files/krb5.conf @@ -0,0 +1,20 @@ +[logging] + default = FILE:/var/log/krb5libs.log + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmind.log + +[libdefaults] + default_realm = EXAMPLE.COM + dns_lookup_realm = false + dns_lookup_kdc = false + ticket_lifetime = 24h + renew_lifetime = 7d + forwardable = true + rdns = false + +[realms] +EXAMPLE.COM = { +kdc = localhost +admin_server = localhost +} +[domain_realm]