This is an automated email from the ASF dual-hosted git repository.
laiyingchun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git
The following commit(s) were added to refs/heads/master by this push:
new 3aeb91399 KUDU-3448 Add support for encrypting TSKs
3aeb91399 is described below
commit 3aeb9139992eab62160b85bb1e51d44301549569
Author: Attila Bukor <[email protected]>
AuthorDate: Mon Mar 13 18:51:04 2023 +0100
KUDU-3448 Add support for encrypting TSKs
In a previous patch, support for encrypting IPKI root CA private keys
has been added. This is a follow up patch, to add encryption support for
token signing keys as well. It is controlled by a new flag:
--tsk_private_key_password_cmd.
If this flag is set, the token signing keys will be stored in the
syscatalog table in encrypted form (AES-256-CBC with PKCS#8 encoding).
Token signing keys rotate automatically in Kudu, but for now, at least,
encryption of TSKs can't be turned on or off on an existing master, so
if this flag is set on the first startup of a master, it must be set to
a command that outputs the same password as on initialization, and vice
versa, it must not be provided on later master startups if it wasn't
provided on initialization.
Change-Id: Id8d770de7ed824cfc725003bbe77f1e42629029b
Reviewed-on: http://gerrit.cloudera.org:8080/19617
Tested-by: Attila Bukor <[email protected]>
Reviewed-by: Alexey Serbin <[email protected]>
---
.../integration-tests/catalog_manager_tsk-itest.cc | 2 ++
src/kudu/master/master-test.cc | 4 ++-
src/kudu/security/token_signing_key.cc | 33 ++++++++++++++++++++--
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/src/kudu/integration-tests/catalog_manager_tsk-itest.cc
b/src/kudu/integration-tests/catalog_manager_tsk-itest.cc
index 04453422d..cceb1aa07 100644
--- a/src/kudu/integration-tests/catalog_manager_tsk-itest.cc
+++ b/src/kudu/integration-tests/catalog_manager_tsk-itest.cc
@@ -24,6 +24,7 @@
#include <ostream>
#include <string>
#include <thread>
+#include <type_traits>
#include <vector>
#include <glog/logging.h>
@@ -91,6 +92,7 @@ class CatalogManagerTskITest : public KuduTest {
"--raft_enable_pre_election=false",
"--master_non_leader_masters_propagate_tsk",
"--tsk_rotation_seconds=2",
+ "--tsk_private_key_password_cmd=echo test",
};
copy(master_flags.begin(), master_flags.end(),
back_inserter(cluster_opts_.extra_master_flags));
diff --git a/src/kudu/master/master-test.cc b/src/kudu/master/master-test.cc
index ae290a3f7..4652f1817 100644
--- a/src/kudu/master/master-test.cc
+++ b/src/kudu/master/master-test.cc
@@ -149,6 +149,7 @@ DECLARE_int64(on_disk_size_for_testing);
DECLARE_string(ipki_private_key_password_cmd);
DECLARE_string(location_mapping_cmd);
DECLARE_string(log_filename);
+DECLARE_string(tsk_private_key_password_cmd);
DECLARE_string(webserver_doc_root);
METRIC_DECLARE_histogram(handler_latency_kudu_master_MasterService_GetTableSchema);
@@ -3039,6 +3040,7 @@ class MasterWithEncryptedKeysTest : public MasterTest,
void SetUp() override {
if (GetParam()) {
FLAGS_ipki_private_key_password_cmd = "echo test";
+ FLAGS_tsk_private_key_password_cmd = "echo foo";
}
MasterTest::SetUp();
}
@@ -3141,7 +3143,7 @@ TEST_F(MasterTest, TestConnectToMasterAndAssignLocation) {
// Test that the master signs its own server certificate when it becomes the
leader,
// and also that it loads TSKs into the messenger's verifier.
-TEST_F(MasterTest, TestSignOwnCertAndLoadTSKs) {
+TEST_P(MasterWithEncryptedKeysTest, TestSignOwnCertAndLoadTSKs) {
ASSERT_EVENTUALLY([&]() {
ASSERT_TRUE(master_->tls_context().has_signed_cert());
ASSERT_GT(master_->messenger()->token_verifier().GetMaxKnownKeySequenceNumber(),
-1);
diff --git a/src/kudu/security/token_signing_key.cc
b/src/kudu/security/token_signing_key.cc
index f9f8d3f8f..733cdf832 100644
--- a/src/kudu/security/token_signing_key.cc
+++ b/src/kudu/security/token_signing_key.cc
@@ -17,10 +17,12 @@
#include "kudu/security/token_signing_key.h"
+#include <functional>
#include <memory>
#include <string>
#include <utility>
+#include <gflags/gflags.h>
#include <glog/logging.h>
#include "kudu/security/crypto.h"
@@ -28,6 +30,11 @@
#include "kudu/util/openssl_util.h"
#include "kudu/util/status.h"
+DEFINE_string(tsk_private_key_password_cmd, "",
+ "A Unix command whose output returns the password to encrypt "
+ "and decrypt the token signing key");
+
+using kudu::security::PasswordCallback;
using std::unique_ptr;
using std::string;
@@ -59,7 +66,18 @@ bool TokenSigningPublicKey::VerifySignature(const
SignedTokenPB& token) const {
TokenSigningPrivateKey::TokenSigningPrivateKey(
const TokenSigningPrivateKeyPB& pb)
: key_(new PrivateKey) {
- CHECK_OK(key_->FromString(pb.rsa_key_der(), DataFormat::DER));
+ if (FLAGS_tsk_private_key_password_cmd.empty()) {
+ CHECK_OK(key_->FromString(pb.rsa_key_der(), DataFormat::DER));
+ } else {
+ CHECK_OK(key_->FromEncryptedString(pb.rsa_key_der(), DataFormat::DER,
+ [&](string* password) {
+ RETURN_NOT_OK_PREPEND(GetPasswordFromShellCommand(
+ FLAGS_tsk_private_key_password_cmd, password),
+ "could not get TSK private key password from configured
command");
+ return Status::OK();
+ }
+ ));
+ }
private_key_der_ = pb.rsa_key_der();
key_seq_num_ = pb.key_seq_num();
expire_time_ = pb.expire_unix_epoch_seconds();
@@ -74,7 +92,18 @@ TokenSigningPrivateKey::TokenSigningPrivateKey(
: key_(std::move(key)),
key_seq_num_(key_seq_num),
expire_time_(expire_time) {
- CHECK_OK(key_->ToString(&private_key_der_, DataFormat::DER));
+ if (FLAGS_tsk_private_key_password_cmd.empty()) {
+ CHECK_OK(key_->ToString(&private_key_der_, DataFormat::DER));
+ } else {
+ CHECK_OK(key_->ToEncryptedString(&private_key_der_, DataFormat::DER,
+ [&](string* password){
+ RETURN_NOT_OK_PREPEND(GetPasswordFromShellCommand(
+ FLAGS_tsk_private_key_password_cmd, password),
+ "could not get TSK private key password from configured
command");
+ return Status::OK();
+ }
+ ));
+ }
PublicKey public_key;
CHECK_OK(key_->GetPublicKey(&public_key));
CHECK_OK(public_key.ToString(&public_key_der_, DataFormat::DER));