impala-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From he...@apache.org
Subject [2/2] incubator-impala git commit: KUDU-1929: [rpc] Allow using encrypted private keys for TLS
Date Sat, 26 Aug 2017 21:50:59 GMT
KUDU-1929: [rpc] Allow using encrypted private keys for TLS

* This patch adds a new flag for a "password command" for the RPC
  private key.

 * This also makes the webserver move to using the new function
   GetPasswordFromShellCommand().

 * This also consolidates certificates from security-test-util into
   security/tests/test_certs

Testing: Adds 2 tests. One to verify that RPCs work when providing
the right password for password protected private keys, and one to
verify that the Messenger does not startup if the wrong password
is provided when using a password protected private key.

Change-Id: Ifd6369581fa426ceab11e4a10441658c7da47e81
Reviewed-on: http://gerrit.cloudera.org:8080/6635
Tested-by: Kudu Jenkins
Reviewed-by: Sailesh Mukil <sailesh@cloudera.com>
Reviewed-on: http://gerrit.cloudera.org:8080/7741
Reviewed-by: Michael Ho <kwho@cloudera.com>
Tested-by: Impala Public Jenkins


Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/244c1fba
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/244c1fba
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/244c1fba

Branch: refs/heads/master
Commit: 244c1fba66ffcce64b205ee04e69dd6a51087d99
Parents: f20b162
Author: Sailesh Mukil <sailesh@apache.org>
Authored: Tue Apr 4 22:01:25 2017 -0700
Committer: Impala Public Jenkins <impala-public-jenkins@gerrit.cloudera.org>
Committed: Sat Aug 26 08:33:12 2017 +0000

----------------------------------------------------------------------
 be/src/kudu/rpc/messenger.cc               |  23 ++-
 be/src/kudu/rpc/rpc-test.cc                |  58 +++++++
 be/src/kudu/security/crypto.cc             |   5 +-
 be/src/kudu/security/crypto.h              |   6 +-
 be/src/kudu/security/openssl_util.cc       |  20 +++
 be/src/kudu/security/openssl_util.h        |   9 ++
 be/src/kudu/security/openssl_util_bio.h    |  24 ++-
 be/src/kudu/security/security-test-util.cc |  10 +-
 be/src/kudu/security/security-test-util.h  |  71 ---------
 be/src/kudu/security/test/test_certs.cc    | 204 ++++++++++++++++++------
 be/src/kudu/security/test/test_certs.h     |  19 ++-
 be/src/kudu/security/tls_context.cc        |  15 ++
 be/src/kudu/security/tls_context.h         |   7 +
 13 files changed, 328 insertions(+), 143 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/rpc/messenger.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/rpc/messenger.cc b/be/src/kudu/rpc/messenger.cc
index 28fea55..1cec5bf 100644
--- a/be/src/kudu/rpc/messenger.cc
+++ b/be/src/kudu/rpc/messenger.cc
@@ -93,6 +93,12 @@ DEFINE_string(rpc_ca_certificate_file, "",
               "Path to the PEM encoded X509 certificate of the trusted external "
               "certificate authority. The provided certificate should be the root "
               "issuer of the certificate passed in '--rpc_certificate_file'.");
+DEFINE_string(rpc_private_key_password_cmd, "", "A Unix command whose output "
+              "returns the password used to decrypt the RPC server's private key "
+              "file specified in --rpc_private_key_file. If the .PEM key file is "
+              "not password-protected, this flag does not need to be set. "
+              "Trailing whitespace will be trimmed before it is used to decrypt "
+              "the private key.");
 
 // Setting TLS certs and keys via CLI flags is only necessary for external
 // PKI-based security, which is not yet production ready. Instead, see
@@ -268,8 +274,21 @@ Status MessengerBuilder::Build(shared_ptr<Messenger> *msgr) {
       // TODO(KUDU-1920): should we try and enforce that the server
       // is in the subject or alt names of the cert?
       RETURN_NOT_OK(tls_context->LoadCertificateAuthority(FLAGS_rpc_ca_certificate_file));
-      RETURN_NOT_OK(tls_context->LoadCertificateAndKey(FLAGS_rpc_certificate_file,
-                                                       FLAGS_rpc_private_key_file));
+      if (FLAGS_rpc_private_key_password_cmd.empty()) {
+        RETURN_NOT_OK(tls_context->LoadCertificateAndKey(FLAGS_rpc_certificate_file,
+                                                         FLAGS_rpc_private_key_file));
+      } else {
+        RETURN_NOT_OK(tls_context->LoadCertificateAndPasswordProtectedKey(
+            FLAGS_rpc_certificate_file, FLAGS_rpc_private_key_file,
+            [&](){
+              string ret;
+              WARN_NOT_OK(security::GetPasswordFromShellCommand(
+                  FLAGS_rpc_private_key_password_cmd, &ret),
+                  "could not get RPC password from configured command");
+              return ret;
+            }
+        ));
+      }
     } else {
       RETURN_NOT_OK(tls_context->GenerateSelfSignedCertAndKey());
     }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/rpc/rpc-test.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/rpc/rpc-test.cc b/be/src/kudu/rpc/rpc-test.cc
index 63b7b73..47ca528 100644
--- a/be/src/kudu/rpc/rpc-test.cc
+++ b/be/src/kudu/rpc/rpc-test.cc
@@ -30,6 +30,7 @@
 #include "kudu/gutil/strings/substitute.h"
 #include "kudu/rpc/constants.h"
 #include "kudu/rpc/serialization.h"
+#include "kudu/security/test/test_certs.h"
 #include "kudu/util/countdown_latch.h"
 #include "kudu/util/env.h"
 #include "kudu/util/scoped_cleanup.h"
@@ -40,6 +41,10 @@ METRIC_DECLARE_histogram(rpc_incoming_queue_time);
 
 DECLARE_bool(rpc_reopen_outbound_connections);
 DECLARE_int32(rpc_negotiation_inject_delay_ms);
+DECLARE_string(rpc_certificate_file);
+DECLARE_string(rpc_ca_certificate_file);
+DECLARE_string(rpc_private_key_file);
+DECLARE_string(rpc_private_key_password_cmd);
 
 using std::shared_ptr;
 using std::string;
@@ -123,6 +128,59 @@ TEST_P(TestRpc, TestCall) {
   }
 }
 
+// Test making successful RPC calls while using a TLS certificate with a password protected
+// private key.
+TEST_P(TestRpc, TestCallWithPasswordProtectedKey) {
+  bool enable_ssl = GetParam();
+  // We're only interested in running this test with TLS enabled.
+  if (!enable_ssl) return;
+
+  string passwd;
+  CHECK_OK(security::CreateTestSSLCertWithEncryptedKey(GetTestDataDirectory(),
+                                                       &FLAGS_rpc_certificate_file,
+                                                       &FLAGS_rpc_private_key_file,
+                                                       &passwd));
+  FLAGS_rpc_ca_certificate_file = FLAGS_rpc_certificate_file;
+  FLAGS_rpc_private_key_password_cmd = strings::Substitute("echo $0", passwd);
+  // Set up server.
+  Sockaddr server_addr;
+  StartTestServer(&server_addr, enable_ssl);
+
+  // Set up client.
+  LOG(INFO) << "Connecting to " << server_addr.ToString();
+  shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, enable_ssl));
+  Proxy p(client_messenger, server_addr, GenericCalculatorService::static_service_name());
+  ASSERT_STR_CONTAINS(p.ToString(), strings::Substitute("kudu.rpc.GenericCalculatorService@"
+                                                            "{remote=$0, user_credentials=",
+                                                        server_addr.ToString()));
+
+  for (int i = 0; i < 10; i++) {
+    ASSERT_OK(DoTestSyncCall(p, GenericCalculatorService::kAddMethodName));
+  }
+}
+
+// Test that using a TLS certificate with a password protected private key and providing
+// the wrong password for that private key, causes a server startup failure.
+TEST_P(TestRpc, TestCallWithBadPasswordProtectedKey) {
+  bool enable_ssl = GetParam();
+  // We're only interested in running this test with TLS enabled.
+  if (!enable_ssl) return;
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+
+  string passwd;
+  CHECK_OK(security::CreateTestSSLCertWithEncryptedKey(GetTestDataDirectory(),
+                                                       &FLAGS_rpc_certificate_file,
+                                                       &FLAGS_rpc_private_key_file,
+                                                       &passwd));
+  // Overwrite the password with an invalid one.
+  passwd = "badpassword";
+  FLAGS_rpc_ca_certificate_file = FLAGS_rpc_certificate_file;
+  FLAGS_rpc_private_key_password_cmd = strings::Substitute("echo $0", passwd);
+  // Verify that the server fails to start up.
+  Sockaddr server_addr;
+  ASSERT_DEATH(StartTestServer(&server_addr, enable_ssl), "failed to load private key
file");
+}
+
 // Test that connecting to an invalid server properly throws an error.
 TEST_P(TestRpc, TestCallToBadServer) {
   shared_ptr<Messenger> client_messenger(CreateMessenger("Client", 1, GetParam()));

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/crypto.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/crypto.cc b/be/src/kudu/security/crypto.cc
index cf4199e..e7d5db6 100644
--- a/be/src/kudu/security/crypto.cc
+++ b/be/src/kudu/security/crypto.cc
@@ -182,9 +182,10 @@ Status PrivateKey::ToString(std::string* data, DataFormat format) const
{
       data, format, data_.get());
 }
 
-Status PrivateKey::FromFile(const std::string& fpath, DataFormat format) {
+Status PrivateKey::FromFile(const std::string& fpath, DataFormat format,
+                            const PasswordCallback& password_cb) {
   return ::kudu::security::FromFile<RawDataType, RsaPrivateKeyTraits>(
-      fpath, format, &data_);
+      fpath, format, &data_, password_cb);
 }
 
 // The code is modeled after $OPENSSL_ROOT/apps/rsa.c code: there is

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/crypto.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/crypto.h b/be/src/kudu/security/crypto.h
index 619be4d..fe3ecb4 100644
--- a/be/src/kudu/security/crypto.h
+++ b/be/src/kudu/security/crypto.h
@@ -71,7 +71,11 @@ class PrivateKey : public RawDataWrapper<EVP_PKEY> {
 
   Status FromString(const std::string& data, DataFormat format) WARN_UNUSED_RESULT;
   Status ToString(std::string* data, DataFormat format) const WARN_UNUSED_RESULT;
-  Status FromFile(const std::string& fpath, DataFormat format) WARN_UNUSED_RESULT;
+
+  // If 'cb' is set, it will be called to obtain the password necessary to decrypt
+  // the private key file in 'fpath'.
+  Status FromFile(const std::string& fpath, DataFormat format,
+                  const PasswordCallback& password_cb = PasswordCallback()) WARN_UNUSED_RESULT;
 
   // Output the public part of the keypair into the specified placeholder.
   Status GetPublicKey(PublicKey* public_key) const WARN_UNUSED_RESULT;

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/openssl_util.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/openssl_util.cc b/be/src/kudu/security/openssl_util.cc
index f5ce822..dce93fc 100644
--- a/be/src/kudu/security/openssl_util.cc
+++ b/be/src/kudu/security/openssl_util.cc
@@ -22,16 +22,20 @@
 #include <mutex>
 #include <sstream>
 #include <string>
+#include <vector>
 
 #include <glog/logging.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
 
+#include "kudu/gutil/strings/split.h"
+#include "kudu/gutil/strings/strip.h"
 #include "kudu/util/debug/leakcheck_disabler.h"
 #include "kudu/util/errno.h"
 #include "kudu/util/mutex.h"
 #include "kudu/util/status.h"
+#include "kudu/util/subprocess.h"
 #include "kudu/util/thread.h"
 
 using std::ostringstream;
@@ -207,5 +211,21 @@ const string& DataFormatToString(DataFormat fmt) {
   }
 }
 
+Status GetPasswordFromShellCommand(const string& cmd, string* password) {
+  vector<string> argv = strings::Split(cmd, " ", strings::SkipEmpty());
+  if (argv.empty()) {
+    return Status::RuntimeError("invalid empty private key password command");
+  }
+  string stderr, stdout;
+  Status s = Subprocess::Call(argv, "" /* stdin */, &stdout, &stderr);
+  if (!s.ok()) {
+    return Status::RuntimeError(strings::Substitute(
+        "failed to run private key password command: $0", s.ToString()), stderr);
+  }
+  StripTrailingWhitespace(&stdout);
+  *password = stdout;
+  return Status::OK();
+}
+
 } // namespace security
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/openssl_util.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/openssl_util.h b/be/src/kudu/security/openssl_util.h
index 82392c1..f5cd817 100644
--- a/be/src/kudu/security/openssl_util.h
+++ b/be/src/kudu/security/openssl_util.h
@@ -69,6 +69,8 @@ typedef struct x509_st X509;
 namespace kudu {
 namespace security {
 
+using PasswordCallback = std::function<string(void)>;
+
 // Disable initialization of OpenSSL. Must be called before
 // any call to InitializeOpenSSL().
 Status DisableOpenSSLInitialization() WARN_UNUSED_RESULT;
@@ -96,6 +98,13 @@ std::string GetOpenSSLErrors();
 // See man(3) SSL_get_error for more discussion.
 std::string GetSSLErrorDescription(int error_code);
 
+// Runs the shell command 'cmd' which should give a password to a private key file
+// as the output.
+//
+// 'password' is populated with the password string if the command was a success.
+// An error Status object is returned otherwise.
+Status GetPasswordFromShellCommand(const std::string& cmd, std::string* password);
+
 // A generic wrapper for OpenSSL structures.
 template <typename T>
 using c_unique_ptr = std::unique_ptr<T, std::function<void(T*)>>;

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/openssl_util_bio.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/openssl_util_bio.h b/be/src/kudu/security/openssl_util_bio.h
index d4dcc44..c4053a1 100644
--- a/be/src/kudu/security/openssl_util_bio.h
+++ b/be/src/kudu/security/openssl_util_bio.h
@@ -53,15 +53,31 @@ Status ToBIO(BIO* bio, DataFormat format, TYPE* obj) {
   return Status::OK();
 }
 
+// The callback which is called by the OpenSSL library when trying to decrypt
+// a password protected private key.
+inline int TLSPasswordCB(char* buf, int size, int /* rwflag */, void* userdata) {
+  const auto* cb = reinterpret_cast<const PasswordCallback*>(userdata);
+  string pw = (*cb)();
+  if (pw.size() >= size) {
+    LOG(ERROR) << "Provided key password is longer than maximum length "
+               << size;
+    return -1;
+  }
+  strncpy(buf, pw.c_str(), size);
+  return pw.size();
+}
+
 template<typename TYPE, typename Traits = SslTypeTraits<TYPE>>
-Status FromBIO(BIO* bio, DataFormat format, c_unique_ptr<TYPE>* ret) {
+Status FromBIO(BIO* bio, DataFormat format, c_unique_ptr<TYPE>* ret,
+    const PasswordCallback& cb = PasswordCallback()) {
   CHECK(bio);
   switch (format) {
     case DataFormat::DER:
       *ret = ssl_make_unique(Traits::kReadDerFunc(bio, nullptr));
       break;
     case DataFormat::PEM:
-      *ret = ssl_make_unique(Traits::kReadPemFunc(bio, nullptr, nullptr, nullptr));
+      *ret = ssl_make_unique(Traits::kReadPemFunc(bio, nullptr, &TLSPasswordCB,
+          const_cast<PasswordCallback*>(&cb)));
       break;
   }
   if (PREDICT_FALSE(!*ret)) {
@@ -100,11 +116,11 @@ Status ToString(std::string* data, DataFormat format, Type* obj) {
 
 template<typename Type, typename Traits = SslTypeTraits<Type>>
 Status FromFile(const string& fpath, DataFormat format,
-                c_unique_ptr<Type>* ret) {
+                c_unique_ptr<Type>* ret, const PasswordCallback& cb = PasswordCallback())
{
   auto bio = ssl_make_unique(BIO_new(BIO_s_file()));
   OPENSSL_RET_NOT_OK(BIO_read_filename(bio.get(), fpath.c_str()),
       strings::Substitute("could not read data from file '$0'", fpath));
-  RETURN_NOT_OK_PREPEND((FromBIO<Type, Traits>(bio.get(), format, ret)),
+  RETURN_NOT_OK_PREPEND((FromBIO<Type, Traits>(bio.get(), format, ret, cb)),
       strings::Substitute("unable to load data from file '$0'", fpath));
   return Status::OK();
 }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/security-test-util.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/security-test-util.cc b/be/src/kudu/security/security-test-util.cc
index b2c8020..88ef2f8 100644
--- a/be/src/kudu/security/security-test-util.cc
+++ b/be/src/kudu/security/security-test-util.cc
@@ -22,6 +22,7 @@
 #include "kudu/security/ca/cert_management.h"
 #include "kudu/security/cert.h"
 #include "kudu/security/crypto.h"
+#include "kudu/security/test/test_certs.h"
 #include "kudu/security/tls_context.h"
 #include "kudu/util/path_util.h"
 #include "kudu/util/test_util.h"
@@ -77,12 +78,9 @@ Status ConfigureTlsContext(PkiConfig config,
       break;
     };
     case PkiConfig::EXTERNALLY_SIGNED: {
-      // Write certificate to file.
-      std::string cert_path = JoinPathSegments(GetTestDataDirectory(), "kudu-test-cert.pem");
-      RETURN_NOT_OK(CreateSSLServerCert(cert_path));
-      // Write private key to file.
-      std::string key_path = JoinPathSegments(GetTestDataDirectory(), "kudu-test-key.pem");
-      RETURN_NOT_OK(CreateSSLPrivateKey(key_path));
+      std::string cert_path, key_path;
+      // Write certificate and private key to file.
+      RETURN_NOT_OK(CreateTestSSLCertWithPlainKey(GetTestDataDirectory(), &cert_path,
&key_path));
       RETURN_NOT_OK(tls_context->LoadCertificateAndKey(cert_path, key_path));
       RETURN_NOT_OK(tls_context->LoadCertificateAuthority(cert_path));
     };

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/security-test-util.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/security-test-util.h b/be/src/kudu/security/security-test-util.h
index f0b8977..1af3349 100644
--- a/be/src/kudu/security/security-test-util.h
+++ b/be/src/kudu/security/security-test-util.h
@@ -31,77 +31,6 @@ class PrivateKey;
 class PublicKey;
 class TlsContext;
 
-// TODO(todd): consolidate these certs with those in
-// security/test/test_certs.h once we support configuring a password
-// for the RPC cert.
-inline static Status CreateSSLServerCert(const std::string& file_path) {
-  static const char* test_server_cert = R"(
------BEGIN CERTIFICATE-----
-MIIEejCCA2KgAwIBAgIJAKMdvDR5PL82MA0GCSqGSIb3DQEBBQUAMIGEMQswCQYD
-VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j
-aXNjbzERMA8GA1UEChMIQ2xvdWRlcmExEjAQBgNVBAMTCWxvY2FsaG9zdDEhMB8G
-CSqGSIb3DQEJARYSaGVucnlAY2xvdWRlcmEuY29tMB4XDTEzMDkyMjAwMjUxOFoX
-DTQxMDIwNzAwMjUxOFowgYQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y
-bmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMREwDwYDVQQKEwhDbG91ZGVyYTES
-MBAGA1UEAxMJbG9jYWxob3N0MSEwHwYJKoZIhvcNAQkBFhJoZW5yeUBjbG91ZGVy
-YS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCoUj3pMQ2ELkrz
-zq+koixljVFBAEEqwUWSjA+GEKwfFb/UPRjeO/wrKndp2r83jc6KRt66rvAIl8cr
-b54yTOsJ/ZcARrjTwG3IG8Tely/54ZQyH0ImdJyEbCSoI04zX3ovjlppz3g5xanj
-WmpAh6pzPgBOTfisCLMPD70xQ8F//QWZdNatoly54STkTWoJv/Oll/UpXcBY8JOR
-+ytX82eGgG4F8YoQqmbjrrN5JAmqLRiBAkr3WUena6ekqJBalJRzex/Wh8a9XEV7
-9HFVVngBhezsOJgf81hzBzzhULKfxuXl8uaUj3Z9cZg39CDsyz+ULYbsPm8VoMUI
-VCf7MUVTAgMBAAGjgewwgekwHQYDVR0OBBYEFK94kea7jIKQawAIb+0DqsA1rf6n
-MIG5BgNVHSMEgbEwga6AFK94kea7jIKQawAIb+0DqsA1rf6noYGKpIGHMIGEMQsw
-CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
-YW5jaXNjbzERMA8GA1UEChMIQ2xvdWRlcmExEjAQBgNVBAMTCWxvY2FsaG9zdDEh
-MB8GCSqGSIb3DQEJARYSaGVucnlAY2xvdWRlcmEuY29tggkAox28NHk8vzYwDAYD
-VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAEtkPPncCnN2IFVJvz04K+VsX
-b6w3qwPynQKc67+++JkNb3TYKrh/0UVM1NrEOu3TGplqOrKgAlITuaWNqNOSBu1R
-WJtrz85YkonED5awjjuALVEY82+c7pOXkuv5G5421RINfRn2hNzgw8VFb5CEvxHH
-jER80Vx6UGKr/S649qTQ8AzVzTwWS86VsGI2azAD7D67G/IDGf+0P7FsXonKY+vl
-vKzkfaO1+qEOLtDHV9mwlsxl3Re/MNym4ExWHi9txynCNiRZHqWoZUS+KyYqIR2q
-seCrQwgi1Fer9Ekd5XNjWjigC3VC3SjMqWaxeKbZ2/AuABJMz5xSiRkgwphXEQ==
------END CERTIFICATE-----
-  )";
-  RETURN_NOT_OK(WriteStringToFile(Env::Default(), test_server_cert, file_path));
-  return Status::OK();
-}
-
-// Writes the test SSL private key into a temporary file.
-inline static Status CreateSSLPrivateKey(const std::string& file_path) {
-  static const char* test_private_key = R"(
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAqFI96TENhC5K886vpKIsZY1RQQBBKsFFkowPhhCsHxW/1D0Y
-3jv8Kyp3adq/N43Oikbeuq7wCJfHK2+eMkzrCf2XAEa408BtyBvE3pcv+eGUMh9C
-JnSchGwkqCNOM196L45aac94OcWp41pqQIeqcz4ATk34rAizDw+9MUPBf/0FmXTW
-raJcueEk5E1qCb/zpZf1KV3AWPCTkfsrV/NnhoBuBfGKEKpm466zeSQJqi0YgQJK
-91lHp2unpKiQWpSUc3sf1ofGvVxFe/RxVVZ4AYXs7DiYH/NYcwc84VCyn8bl5fLm
-lI92fXGYN/Qg7Ms/lC2G7D5vFaDFCFQn+zFFUwIDAQABAoIBABNTpiIxbLDhs998
-uvQ3XsumR08kXVcwa/GgvWOSZIEJOUaAYWubDaBTNvTjlhMl6DI+YvKihZMnAkp9
-fXefF1nFUWJJvI0ryi8w6RD54RtbCG4c4raRqysVU7wumZsSenAdc0o09UQE6zXc
-uth/+1VSKCzVjRkLwquXDg0rD3vHfQHWQvQlzwUh3OACA3LfLezVqzrEB02YVRxm
-xwg5veeMg6Aod8vsvsajry9eE0hKeFGonRANerL9lwZxzD2ZjU2fSEJYY3xxKVgi
-o+QVTKaAt9pivOs10YVZDcIDH0xmDpxAkaLb5ZAbnjwhf7WGYgEm8VruAHkJxyXX
-yPf3rpkCgYEA0dp/Xv5KBIkD6JJao8hnhtP5x9U7o/pTzRxaO3WUflvTI6DtC0nk
-cTOwFVs4WljT76T937q2x4stuX0woHzvIaZ6wwZ2vv81ikDY6pE8eLWsH/xFAmkx
-HBfkSijFgJV6EpTqUnFD7QKU89tzWrh/kxaMO1WgFaBhxPPs3K1LDTUCgYEAzVW5
-3yjfVHNgjWTeAbnbToGvUihOidvIvS5cVo5q0Dhfabz0tiXFxAoQUGErUGPC8Nu2
-n/HxTI3b0PbCCwjBsDNqX2kzxTSe5aTGIrBUWbped1bxme8jggXuWYbg8vvLpsYf
-wAJPxnGIxW/v/aftHUhbTIuVfZX2+UnilrwiwWcCgYEAg8paz4eXaH277KVtMwq6
-qZwac/tgNz0Qv/GcYVcYaLq2QNvhwoMnakhxvxfIrkS25PuTTJxwCaVIlAMhNMkB
-TPrGghBfJtgUAb1z/Ow1NAG0FWpS1I7HfsMqZcBxOK2nOmA3QItNg11pujQJn+Ha
-jL9OVj0SCkLs48nk6ToTtjkCgYEAh8YCtNwq6IWuN3CWGCAUMpIwIqxCWof48Zch
-OZ7MZEiSVrG6QmMxpRJefTfzUyHUOj2eQZ7SxqMa0c8IuhEdOeyVjudaczD7TLAq
-z68252oDovfbo8Tr/sL7OzmjryfuHqXtQqKEq5xRKvR8hYavlGhO7otx2uv5thcz
-/CYE+UsCgYAsgewfzbcBqJwsAUs98DK99EU8VqKuaYlU5wNvAVb27O6sVeysSokM
-G1TGIXJPphA3dSAe4Pf/j4ff/eGaS20FAFhs4BPpw0fAeCHpmD0BjIba0lxBS/gY
-dc+JVPKL8Fe4a8fmsI6ndcZQ9qpOdZM5WOD0ldKRc+SsrYKkTmOOJQ==
------END RSA PRIVATE KEY-----
-  )";
-  RETURN_NOT_OK(WriteStringToFile(Env::Default(), test_private_key, file_path));
-  return Status::OK();
-}
-
 Status GenerateSelfSignedCAForTests(PrivateKey* ca_key, Cert* ca_cert);
 
 // Describes the options for configuring a TlsContext.

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/test/test_certs.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/test/test_certs.cc b/be/src/kudu/security/test/test_certs.cc
index cdc20b9..8b10cad 100644
--- a/be/src/kudu/security/test/test_certs.cc
+++ b/be/src/kudu/security/test/test_certs.cc
@@ -321,64 +321,168 @@ const char kSignatureLongSHA512[] =
     "bd0L8TcotQHJchZ8THW0rEbuCg79I7Crd1KQYljBpOOhMYZEDEdM9L19JlaMlw+Z"
     "leyLfL8Bw3wCg9cMfNmQfQ==";
 
+Status CreateTestSSLCertWithPlainKey(const string& dir,
+                                     string* cert_file,
+                                     string* key_file) {
+  const char* kCert = R"(
+-----BEGIN CERTIFICATE-----
+MIIEejCCA2KgAwIBAgIJAKMdvDR5PL82MA0GCSqGSIb3DQEBBQUAMIGEMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j
+aXNjbzERMA8GA1UEChMIQ2xvdWRlcmExEjAQBgNVBAMTCWxvY2FsaG9zdDEhMB8G
+CSqGSIb3DQEJARYSaGVucnlAY2xvdWRlcmEuY29tMB4XDTEzMDkyMjAwMjUxOFoX
+DTQxMDIwNzAwMjUxOFowgYQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y
+bmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMREwDwYDVQQKEwhDbG91ZGVyYTES
+MBAGA1UEAxMJbG9jYWxob3N0MSEwHwYJKoZIhvcNAQkBFhJoZW5yeUBjbG91ZGVy
+YS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCoUj3pMQ2ELkrz
+zq+koixljVFBAEEqwUWSjA+GEKwfFb/UPRjeO/wrKndp2r83jc6KRt66rvAIl8cr
+b54yTOsJ/ZcARrjTwG3IG8Tely/54ZQyH0ImdJyEbCSoI04zX3ovjlppz3g5xanj
+WmpAh6pzPgBOTfisCLMPD70xQ8F//QWZdNatoly54STkTWoJv/Oll/UpXcBY8JOR
++ytX82eGgG4F8YoQqmbjrrN5JAmqLRiBAkr3WUena6ekqJBalJRzex/Wh8a9XEV7
+9HFVVngBhezsOJgf81hzBzzhULKfxuXl8uaUj3Z9cZg39CDsyz+ULYbsPm8VoMUI
+VCf7MUVTAgMBAAGjgewwgekwHQYDVR0OBBYEFK94kea7jIKQawAIb+0DqsA1rf6n
+MIG5BgNVHSMEgbEwga6AFK94kea7jIKQawAIb+0DqsA1rf6noYGKpIGHMIGEMQsw
+CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
+YW5jaXNjbzERMA8GA1UEChMIQ2xvdWRlcmExEjAQBgNVBAMTCWxvY2FsaG9zdDEh
+MB8GCSqGSIb3DQEJARYSaGVucnlAY2xvdWRlcmEuY29tggkAox28NHk8vzYwDAYD
+VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAEtkPPncCnN2IFVJvz04K+VsX
+b6w3qwPynQKc67+++JkNb3TYKrh/0UVM1NrEOu3TGplqOrKgAlITuaWNqNOSBu1R
+WJtrz85YkonED5awjjuALVEY82+c7pOXkuv5G5421RINfRn2hNzgw8VFb5CEvxHH
+jER80Vx6UGKr/S649qTQ8AzVzTwWS86VsGI2azAD7D67G/IDGf+0P7FsXonKY+vl
+vKzkfaO1+qEOLtDHV9mwlsxl3Re/MNym4ExWHi9txynCNiRZHqWoZUS+KyYqIR2q
+seCrQwgi1Fer9Ekd5XNjWjigC3VC3SjMqWaxeKbZ2/AuABJMz5xSiRkgwphXEQ==
+-----END CERTIFICATE-----
+  )";
+  const char* kKey = R"(
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAqFI96TENhC5K886vpKIsZY1RQQBBKsFFkowPhhCsHxW/1D0Y
+3jv8Kyp3adq/N43Oikbeuq7wCJfHK2+eMkzrCf2XAEa408BtyBvE3pcv+eGUMh9C
+JnSchGwkqCNOM196L45aac94OcWp41pqQIeqcz4ATk34rAizDw+9MUPBf/0FmXTW
+raJcueEk5E1qCb/zpZf1KV3AWPCTkfsrV/NnhoBuBfGKEKpm466zeSQJqi0YgQJK
+91lHp2unpKiQWpSUc3sf1ofGvVxFe/RxVVZ4AYXs7DiYH/NYcwc84VCyn8bl5fLm
+lI92fXGYN/Qg7Ms/lC2G7D5vFaDFCFQn+zFFUwIDAQABAoIBABNTpiIxbLDhs998
+uvQ3XsumR08kXVcwa/GgvWOSZIEJOUaAYWubDaBTNvTjlhMl6DI+YvKihZMnAkp9
+fXefF1nFUWJJvI0ryi8w6RD54RtbCG4c4raRqysVU7wumZsSenAdc0o09UQE6zXc
+uth/+1VSKCzVjRkLwquXDg0rD3vHfQHWQvQlzwUh3OACA3LfLezVqzrEB02YVRxm
+xwg5veeMg6Aod8vsvsajry9eE0hKeFGonRANerL9lwZxzD2ZjU2fSEJYY3xxKVgi
+o+QVTKaAt9pivOs10YVZDcIDH0xmDpxAkaLb5ZAbnjwhf7WGYgEm8VruAHkJxyXX
+yPf3rpkCgYEA0dp/Xv5KBIkD6JJao8hnhtP5x9U7o/pTzRxaO3WUflvTI6DtC0nk
+cTOwFVs4WljT76T937q2x4stuX0woHzvIaZ6wwZ2vv81ikDY6pE8eLWsH/xFAmkx
+HBfkSijFgJV6EpTqUnFD7QKU89tzWrh/kxaMO1WgFaBhxPPs3K1LDTUCgYEAzVW5
+3yjfVHNgjWTeAbnbToGvUihOidvIvS5cVo5q0Dhfabz0tiXFxAoQUGErUGPC8Nu2
+n/HxTI3b0PbCCwjBsDNqX2kzxTSe5aTGIrBUWbped1bxme8jggXuWYbg8vvLpsYf
+wAJPxnGIxW/v/aftHUhbTIuVfZX2+UnilrwiwWcCgYEAg8paz4eXaH277KVtMwq6
+qZwac/tgNz0Qv/GcYVcYaLq2QNvhwoMnakhxvxfIrkS25PuTTJxwCaVIlAMhNMkB
+TPrGghBfJtgUAb1z/Ow1NAG0FWpS1I7HfsMqZcBxOK2nOmA3QItNg11pujQJn+Ha
+jL9OVj0SCkLs48nk6ToTtjkCgYEAh8YCtNwq6IWuN3CWGCAUMpIwIqxCWof48Zch
+OZ7MZEiSVrG6QmMxpRJefTfzUyHUOj2eQZ7SxqMa0c8IuhEdOeyVjudaczD7TLAq
+z68252oDovfbo8Tr/sL7OzmjryfuHqXtQqKEq5xRKvR8hYavlGhO7otx2uv5thcz
+/CYE+UsCgYAsgewfzbcBqJwsAUs98DK99EU8VqKuaYlU5wNvAVb27O6sVeysSokM
+G1TGIXJPphA3dSAe4Pf/j4ff/eGaS20FAFhs4BPpw0fAeCHpmD0BjIba0lxBS/gY
+dc+JVPKL8Fe4a8fmsI6ndcZQ9qpOdZM5WOD0ldKRc+SsrYKkTmOOJQ==
+-----END RSA PRIVATE KEY-----
+  )";
+
+  *cert_file = JoinPathSegments(dir, "test.cert");
+  *key_file = JoinPathSegments(dir, "test.key");
+
+  RETURN_NOT_OK(WriteStringToFile(Env::Default(), kCert, *cert_file));
+  RETURN_NOT_OK(WriteStringToFile(Env::Default(), kKey, *key_file));
+  return Status::OK();
+}
 
-Status CreateTestSSLCerts(const string& dir,
-                          string* cert_file,
-                          string* key_file,
-                          string* key_password) {
+Status CreateTestSSLCertWithEncryptedKey(const string& dir,
+                                         string* cert_file,
+                                         string* key_file,
+                                         string* key_password) {
   const char* kCert = R"(
 -----BEGIN CERTIFICATE-----
-MIIDXTCCAkWgAwIBAgIJAOOmFHYkBz4rMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+MIIFuTCCA6GgAwIBAgIJAMboiIQH/LDlMA0GCSqGSIb3DQEBCwUAMHMxCzAJBgNV
 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
-aWRnaXRzIFB0eSBMdGQwHhcNMTYxMTAyMjI0OTQ5WhcNMTcwMjEwMjI0OTQ5WjBF
-MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
-ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAppo9GwiDisQVYAF9NXl8ykqo0MIi5rfNwiE9kUWbZ2ejzxs+1Cf7WCn4
-mzbkJx5ZscRjhnNb6dJxtZJeid/qgiNVBcNzh35H8J+ao0tEbHjCs7rKOX0etsFU
-p4GQwYkdfpvVBsU8ciXvkxhvt1XjSU3/YJJRAvCyGVxUQlKiVKGCD4OnFNBwMdNw
-7qI8ryiRv++7I9udfSuM713yMeBtkkV7hWUfxrTgQOLsV/CS+TsSoOJ7JJqHozeZ
-+VYom85UqSfpIFJVzM6S7BTb6SX/vwYIoS70gubT3HbHgDRcMvpCye1npHL9fL7B
-87XZn7wnnUem0eeCqWyUjJ82Uj9mQQIDAQABo1AwTjAdBgNVHQ4EFgQUOY7rpWGo
-ZMrmyRZ9RohPWVwyPBowHwYDVR0jBBgwFoAUOY7rpWGoZMrmyRZ9RohPWVwyPBow
-DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEATKh3io8ruqbhmopY3xQW
-A2pEhs4ZSu3H+AfULMruVsXKEZjWp27nTsFaxLZYUlzeZr0EcWwZ79qkcA8Dyj+m
-VHhrCAPpcjsDACh1ZdUQAgASkVS4VQvkukct3DFa3y0lz5VwQIxjoQR5y6dCvxxX
-T9NpRo/Z7pd4MRhEbz3NT6PScQ9f2MTrR0NOikLdB98JlpKQbEKxzbMhWDw4J3mr
-mK6zdemjdCcRDsBVPswKnyAjkibXaZkpNRzjvDNAgO88MKlArCYoyRZqIfkcSXAw
-wTdGQ+5GQLsY9zS49Rrhk9R7eOmDhaHybdRBDqW1JiCSmzURZAxlnrjox4GmC3JJ
-aA==
+aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMMBk15TmFtZTEbMBkGCSqGSIb3DQEJARYM
+bXlAZW1haWwuY29tMB4XDTE3MDQxNDE3MzEzOVoXDTI3MDQxMjE3MzEzOVowczEL
+MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy
+bmV0IFdpZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAwwGTXlOYW1lMRswGQYJKoZIhvcN
+AQkBFgxteUBlbWFpbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQC+Av808cmgkgtLpH+ERAaJLgpSQ+l2UfUHTB4XeFXcWcxlsRyXqqNTh5NwkjMI
+c6Ei8p12PBol9I2j//l9sCmLXWDXq2EFFkZ+tcszPjQiTmqzPeruAnamYzuQFioZ
+mnNbPypD9qdk/IWY4XWMWOL/qIhnkNQvswSCqu7JA37xaiOqdLBYt/nSN9h5cOwi
+iHQODY15OmrgAB4JO9brHdBp/fzoN3DkHpQ0V5rlEZ+5Ud9qDs3UEQMgo+ZV8wYL
+KVb9/sUyWu+i1NJIAIhNt5oC8AXJJt+C5Bqme3+7mkWnnBo9DwsvnqDOjOY6AvpO
+NHDeRgEBBelj8rGOGQAFgfTlv+w3kDas25oxmoeVXSPF94eU75bu/EE6GGNpe1EB
+ZtfGUSfRLZwBMAeTZ7f1b9xgNygNpBGmwt9bg+qOZ6PYWkGIrP5+Umhjyss26j5r
+PzJSummB93+69QoESLnF68WcFrR7fxN+oVra63kic/wvC3RH+P3lAIaYw9dKGtec
+D3/F2xBp9+Q3nMJQ5MGDdv4wbWQ9lA63uwcWSGIP3R3KKrs4ULtvHIVQz3tgKbwu
+Lw5LM7x3KnV1iMwfJC09I+lv8MxJBS7cxGU7UEyIasIirsZblPTBshjoKPax2RWR
+I/VI9HwdA4cCk+zbvklK3hHgemCagVLIGwT5+tU7tY4UOQIDAQABo1AwTjAdBgNV
+HQ4EFgQU+4nVu5ZsCzs3wxbyS8LNmkL849AwHwYDVR0jBBgwFoAU+4nVu5ZsCzs3
+wxbyS8LNmkL849AwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAWHLA
+OCjmeqf6AWpmoOOx3fUaGzaR0SG1Cn85nDMypdTrZtNUn9mkDDDXH40xP31vUyjx
+i2Z68dvHsJCdqYL1KAwvvWIEt8xzIWI9ALCANl7JD1L224lUdXI/SgOVaba5bxf4
+nVhqeGH5G7WB6g4ZoOkiICluCnjc5FWaZlENJ4oQLLS9mQE7sREouCy+lDnlUW0x
+Mf1A5hiERTmvuy26b/lkjXfdGw0z/lNXNAS2k59cKHZ11FqzSLwzK2betmpJYzcq
+N4kPMbfUDrN5x/pjAl//GATQgCiXCUjwGvKnhhXedLjnLUC7bxrAoDwKj986iKnO
+v9wzukBC6t/Ao1COodDISzTLORTMIWLOjyg9bPVKSjdFxmKhpCUQQ3Jt6k9JOZtR
+hvKVmDZBCB10eCJALsHlDWAy0DgjRrD1dnnXrOIUgq6ZLqtzAKGkQF5Y5sYEXyTm
+fCFgiXHtU2haGzp5x+i/vz/E6bBsxJhUVzaWlP149WhQs4RO1YL3Iqsdcy0AcMA9
+FUNW6C+37fVk6w1OJGcI4uTfgMpSJL7iTCSzuspR4lEPUHLIvB3kZKyjr7/eAiMg
+NU9t8oyYtGfrXWXHEZ+d8vK7KCnvMZ2ezNtMC88tC8NtnJ8yBPxBLS7k1f/IrYVL
+OHUKIgiZvAfTg3GSj/iiNespDd665okkzRb0QNQ=
 -----END CERTIFICATE-----
 )";
   const char* kKey = R"(
 -----BEGIN ENCRYPTED PRIVATE KEY-----
-MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIA3+5nR+Jr18CAggA
-MBQGCCqGSIb3DQMHBAhCwHFGbZEcBgSCBMjT9vVbrYpd1reGwfLhk8703ihlspZi
-cm4Z2MM+lkJs0Pi8O4n+zNSTfgrEr2XGlKIktBWEBxbhYrdYy1bYm4Fu5Z055JFo
-89L/9zT1Zm/agk3CUW+ljirYZF60t/dDWmzLwt9f4dp8m4etL/UwvMJ1NglyxMkj
-c03+aWWh4wHLRGkGDJFsKEQY87LL+nAOZS7P1qY38HnzQTOgLyNpntXX3SryzvQ6
-CpNIyQFhVGXfGn6DzGJB76heyLpCyAvIiP87vBS3zbnSqDM6v6PTW3SMo8R42RfL
-d0CVmO8Z8NQeX29EkMHSRu7gCwXu1pf40QIog2vJZ7dmUgsU9GbBSg8l3nVWS6sm
-AICNwPvHXRMMGX0wBJyK2ihuC7rVd5aZLgmu1sjlLYaB9KkoETcFFT8KbFpnd6aR
-1whXQ4rPm1WyGtqbVGkZthisvGUeeGnbv2HXUVthSGleD+hQuwFXa8wE/8+Ruq9X
-rNv/WMrf2NLIm+wbr19JzVSvLh+j7mIBMZmIwGQvBPo3/Tuq2zeyZdfSOroFcanq
-Lyoc6yF5rAkU5BLVe36e48MarWICWDCxiz1n6tWdCpcXWfBvlWIkkjP1/rhqnOW3
-DKNjTyGJhaVYydkseoGrrpj4gkyyWtpgw+8c7jdtk+7cmIxpXu3UU6fh+Yt3vEhF
-VqHvCd+YuUgpJ+TW574xiau4xbyib5Qv6JAR1Qp3MtzZ1IngyCU4QqqgxBGMBVqc
-2LI7Romw7icfdzJxMeMp9WXh8D0Bxx5kjDcO0eUnkpVkFyozXZkoLCnoJ8u3yJo6
-yV4RQ4mOAWj7uZYg9KEUywNCHuIVPKG0CEfQkxKiPw4uvmdimKZ6Ij7aqrrc68Vi
-oZnNHJEfJhnG78MKHgxXHNrMLFXBgPpLoBQxUBVhI2nq5D2l7gL5bKc9JZNg+mRJ
-CouijXBHS1nZ/7GwVjLvNIGKWEsuiz1P0SYki1S02/3bBF9ySdeNGl1XTNqK4Xqy
-arK4agJc89wg3N6SOIA+q8kA4LScafMtCkVDChw0CcLUrQERpH1tv1cqCt5zXF9n
-5AnnWmEM2knlkHxXzg7k/1YXUz4JMmAhS4gVHuNU1uZR152lD+kgSy2K4sCyCfx2
-iWFpDGj556AUxDRGrqKU7OLC/64AuNz5IJs8doDa29cGGKFw3/foRoOaya84ISGW
-GTl2qDOHZrJbgR6BUpSh2E2mVyO3GwIBst6yIb5VaTpNuIwS6fhjC4fQZEV6hHcx
-qNvHxTTvz6eag4TeUPR48h/kGsI44DB0r4I79WbTwg5dvdlYbchPIwAs888bxpd6
-7ZxSg7EwuyHqJEL0FkWcDgw89+vLDETQiTwfscDxwm893gTymj5JPSDz35kudPlI
-rsNfABLeXSg8Z8/7LsPP6Q48c1jisLVPPndV80cS791dvyXRxZWvX2z5UFuTDy3K
-PV3L60mdejXudzFPfvovhgJDIWsKMmlxYplRWvG3WUXTck1Kb7KEcZmuo4nJMOID
-6caoDNa5L9p5XH54sBCB7uqTNdqijaqq9iBFx/MqL3LHt6/wVF5J9g6PmuDxuYDX
-tBKU0ns67U6wUxvLGBX/7RnWUibc5JwVGPBGw1E5u6MKWxW9Q6Dk1WakAtsqtDkR
-WEc=
+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
+TOQYXv+dMtOkYg==
 -----END ENCRYPTED PRIVATE KEY-----
 )";
   const char* kKeyPassword = "test";

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/test/test_certs.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/test/test_certs.h b/be/src/kudu/security/test/test_certs.h
index ea4e7a6..75e658e 100644
--- a/be/src/kudu/security/test/test_certs.h
+++ b/be/src/kudu/security/test/test_certs.h
@@ -55,13 +55,18 @@ extern const char kSignatureShortSHA512[];
 extern const char kDataLong[];
 extern const char kSignatureLongSHA512[];
 
-// Creates a matching SSL certificate and private key file in 'dir', returning
-// their paths in '*cert_file' and '*key_file'. The password associated with
-// the private key is stored in '*key_password'.
-Status CreateTestSSLCerts(const std::string& dir,
-                          std::string* cert_file,
-                          std::string* key_file,
-                          std::string* key_password);
+// Creates a matching SSL certificate and unencrypted private key file in 'dir',
+// returning their paths in '*cert_file' and '*key_file'.
+Status CreateTestSSLCertWithPlainKey(const std::string& dir,
+                                     std::string* cert_file,
+                                     std::string* key_file);
+
+// Same as the CreateTestSSLCertWithPlainKey() except that the private key is
+// encrypted with a password that is returned in 'key_password'.
+Status CreateTestSSLCertWithEncryptedKey(const std::string& dir,
+                                          std::string* cert_file,
+                                          std::string* key_file,
+                                          std::string* key_password);
 
 } // namespace security
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/tls_context.cc
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/tls_context.cc b/be/src/kudu/security/tls_context.cc
index 23b3d04..353d1ed 100644
--- a/be/src/kudu/security/tls_context.cc
+++ b/be/src/kudu/security/tls_context.cc
@@ -418,6 +418,21 @@ Status TlsContext::LoadCertificateAndKey(const string& certificate_path,
   return UseCertificateAndKey(c, k);
 }
 
+Status TlsContext::LoadCertificateAndPasswordProtectedKey(const string& certificate_path,
+                                                          const string& key_path,
+                                                          const PasswordCallback& password_cb)
{
+  SCOPED_OPENSSL_NO_PENDING_ERRORS;
+  Cert c;
+  RETURN_NOT_OK_PREPEND(c.FromFile(certificate_path, DataFormat::PEM),
+                        "failed to load certificate");
+  PrivateKey k;
+  RETURN_NOT_OK_PREPEND(k.FromFile(key_path, DataFormat::PEM, password_cb),
+                        "failed to load private key file");
+  RETURN_NOT_OK(UseCertificateAndKey(c, k));
+  is_external_cert_ = true;
+  return Status::OK();
+}
+
 Status TlsContext::LoadCertificateAuthority(const string& certificate_path) {
   SCOPED_OPENSSL_NO_PENDING_ERRORS;
   if (has_cert_) DCHECK(is_external_cert_);

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/244c1fba/be/src/kudu/security/tls_context.h
----------------------------------------------------------------------
diff --git a/be/src/kudu/security/tls_context.h b/be/src/kudu/security/tls_context.h
index b278d9c..1785471 100644
--- a/be/src/kudu/security/tls_context.h
+++ b/be/src/kudu/security/tls_context.h
@@ -145,6 +145,13 @@ class TlsContext {
   Status LoadCertificateAndKey(const std::string& certificate_path,
                                const std::string& key_path) WARN_UNUSED_RESULT;
 
+  // Load the server certificate and key (PEM encoded), and use the callback
+  // 'password_cb' to obtain the password that can decrypt the key.
+  Status LoadCertificateAndPasswordProtectedKey(const std::string& certificate_path,
+                                                const std::string& key_path,
+                                                const PasswordCallback& password_cb)
+                                                WARN_UNUSED_RESULT;
+
   // Load the certificate authority (PEM encoded).
   Status LoadCertificateAuthority(const std::string& certificate_path) WARN_UNUSED_RESULT;
 



Mime
View raw message