You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by to...@apache.org on 2017/02/01 21:25:44 UTC

[3/3] kudu git commit: Extract a static function to generate a self-signed CA

Extract a static function to generate a self-signed CA

We had some similar code in a test case and in MasterCertAuthority. This
extracts a function to create a self-signed CA, as well as a test
utility function which creates both a self-signed CA and private key.

Currently the test utility is only used from one test case, but I have
plans to use it elsewhere.

Change-Id: Ib40add99ed96e4753a3810709c66d07c96ab70bd
Reviewed-on: http://gerrit.cloudera.org:8080/5844
Tested-by: Kudu Jenkins
Reviewed-by: Alexey Serbin <as...@cloudera.com>
Reviewed-by: Dan Burkert <da...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/86714152
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/86714152
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/86714152

Branch: refs/heads/master
Commit: 86714152d3122580984a28ad0fc46ed942d5020c
Parents: 431aee5
Author: Todd Lipcon <to...@apache.org>
Authored: Tue Jan 31 14:52:37 2017 -0800
Committer: Todd Lipcon <to...@apache.org>
Committed: Wed Feb 1 21:24:31 2017 +0000

----------------------------------------------------------------------
 src/kudu/master/master_cert_authority.cc     | 21 ++-------
 src/kudu/security/CMakeLists.txt             |  1 +
 src/kudu/security/ca/cert_management-test.cc | 27 +++---------
 src/kudu/security/ca/cert_management.cc      | 20 +++++++++
 src/kudu/security/ca/cert_management.h       | 34 +++++++++------
 src/kudu/security/security-test-util.cc      | 52 +++++++++++++++++++++++
 src/kudu/security/security-test-util.h       | 11 ++++-
 7 files changed, 112 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/master/master_cert_authority.cc
----------------------------------------------------------------------
diff --git a/src/kudu/master/master_cert_authority.cc b/src/kudu/master/master_cert_authority.cc
index 8b33991..45190a1 100644
--- a/src/kudu/master/master_cert_authority.cc
+++ b/src/kudu/master/master_cert_authority.cc
@@ -75,26 +75,13 @@ MasterCertAuthority::~MasterCertAuthority() {
 Status MasterCertAuthority::Init() {
   CHECK(!ca_private_key_);
 
-  // Create a key for the self-signed CA.
-  shared_ptr<PrivateKey> key(make_shared<PrivateKey>());
+  // Create a key and cert for the self-signed CA.
+  auto key = make_shared<PrivateKey>();
+  auto ca_cert = make_shared<Cert>();
   RETURN_NOT_OK(GeneratePrivateKey(FLAGS_master_ca_rsa_key_length_bits,
                                    key.get()));
 
-  // Generate a CSR for the CA.
-  CertSignRequest ca_csr;
-  {
-    CaCertRequestGenerator gen(PrepareCaConfig(server_uuid_));
-    RETURN_NOT_OK(gen.Init());
-    RETURN_NOT_OK(gen.GenerateRequest(*key, &ca_csr));
-  }
-
-  // Self-sign the CA's CSR.
-  auto ca_cert = make_shared<Cert>();
-  {
-    CertSigner ca_signer;
-    RETURN_NOT_OK(ca_signer.InitForSelfSigning(key));
-    RETURN_NOT_OK(ca_signer.Sign(ca_csr, ca_cert.get()));
-  }
+  RETURN_NOT_OK(CertSigner::SelfSignCA(key, PrepareCaConfig(server_uuid_), ca_cert.get()));
 
   // Initialize our signer with the new CA.
   auto signer = make_shared<CertSigner>();

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/kudu/security/CMakeLists.txt b/src/kudu/security/CMakeLists.txt
index 2627b77..4a4501f 100644
--- a/src/kudu/security/CMakeLists.txt
+++ b/src/kudu/security/CMakeLists.txt
@@ -90,6 +90,7 @@ ADD_EXPORTABLE_LIBRARY(security
 
 if (NOT NO_TESTS)
   set(SECURITY_TEST_SRCS
+    security-test-util.cc
     test/mini_kdc.cc
     test/test_certs.cc)
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/ca/cert_management-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/security/ca/cert_management-test.cc b/src/kudu/security/ca/cert_management-test.cc
index c4d9084..39dfec8 100644
--- a/src/kudu/security/ca/cert_management-test.cc
+++ b/src/kudu/security/ca/cert_management-test.cc
@@ -17,6 +17,7 @@
 
 #include "kudu/security/ca/cert_management.h"
 
+#include <memory>
 #include <thread>
 #include <utility>
 #include <vector>
@@ -26,6 +27,7 @@
 #include "kudu/gutil/strings/util.h"
 #include "kudu/security/cert.h"
 #include "kudu/security/openssl_util.h"
+#include "kudu/security/security-test-util.h"
 #include "kudu/security/test/test_certs.h"
 #include "kudu/util/env.h"
 #include "kudu/util/path_util.h"
@@ -33,6 +35,7 @@
 #include "kudu/util/test_macros.h"
 #include "kudu/util/test_util.h"
 
+using std::shared_ptr;
 using std::string;
 using std::vector;
 using std::thread;
@@ -372,27 +375,9 @@ TEST_F(CertManagementTest, SignCaCert) {
 // Test the creation and use of a CA which uses a self-signed CA cert
 // generated on the fly.
 TEST_F(CertManagementTest, TestSelfSignedCA) {
-  // Create a key for the self-signed CA.
-  auto ca_key = std::make_shared<PrivateKey>();
-  ASSERT_OK(GeneratePrivateKey(2048, ca_key.get()));
-
-  // Generate a CSR for the CA.
-  CertSignRequest ca_csr;
-  {
-    const CertRequestGenerator::Config gen_config(
-        PrepareConfig("8C084CF6-A30B-4F5B-9673-A73E62E29A9D"));
-    CaCertRequestGenerator gen(gen_config);
-    ASSERT_OK(gen.Init());
-    ASSERT_OK(gen.GenerateRequest(*ca_key, &ca_csr));
-  }
-
-  // Self-sign the CA's CSR.
-  auto ca_cert = std::make_shared<Cert>();
-  {
-    CertSigner ca_signer;
-    ASSERT_OK(ca_signer.InitForSelfSigning(ca_key));
-    ASSERT_OK(ca_signer.Sign(ca_csr, ca_cert.get()));
-  }
+  shared_ptr<PrivateKey> ca_key;
+  shared_ptr<Cert> ca_cert;
+  ASSERT_OK(GenerateSelfSignedCAForTests(&ca_key, &ca_cert));
 
   // Create a key for the tablet server.
   auto ts_key = std::make_shared<PrivateKey>();

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/ca/cert_management.cc
----------------------------------------------------------------------
diff --git a/src/kudu/security/ca/cert_management.cc b/src/kudu/security/ca/cert_management.cc
index 8de37dd..710b23e 100644
--- a/src/kudu/security/ca/cert_management.cc
+++ b/src/kudu/security/ca/cert_management.cc
@@ -281,6 +281,26 @@ Status CaCertRequestGenerator::SetExtensions(X509_REQ* req) const {
   return Status::OK();
 }
 
+Status CertSigner::SelfSignCA(const shared_ptr<PrivateKey>& key,
+                              CaCertRequestGenerator::Config config,
+                              Cert* cert) {
+  // Generate a CSR for the CA.
+  CertSignRequest ca_csr;
+  {
+    CaCertRequestGenerator gen(std::move(config));
+    RETURN_NOT_OK(gen.Init());
+    RETURN_NOT_OK(gen.GenerateRequest(*key, &ca_csr));
+  }
+
+  // Self-sign the CA's CSR.
+  {
+    CertSigner ca_signer;
+    RETURN_NOT_OK(ca_signer.InitForSelfSigning(key));
+    RETURN_NOT_OK(ca_signer.Sign(ca_csr, cert));
+  }
+  return Status::OK();
+}
+
 CertSigner::CertSigner()
     : is_initialized_(false) {
 }

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/ca/cert_management.h
----------------------------------------------------------------------
diff --git a/src/kudu/security/ca/cert_management.h b/src/kudu/security/ca/cert_management.h
index 4974983..7a2887a 100644
--- a/src/kudu/security/ca/cert_management.h
+++ b/src/kudu/security/ca/cert_management.h
@@ -54,15 +54,15 @@ class CertRequestGeneratorBase {
   // Properties for the generated X509 CSR.  Using server UUID for the common
   // name field.
   struct Config {
-    const std::string country;  // subject field: C
-    const std::string state;    // subject field: ST
-    const std::string locality; // subject field: L
-    const std::string org;      // subject field: O
-    const std::string unit;     // subject field: OU
-    const std::string uuid;     // subject field: CN
-    const std::string comment;  // custom extension: Netscape Comment
-    const std::vector<std::string> hostnames; // subjectAltName extension (DNS:)
-    const std::vector<std::string> ips;       // subjectAltName extension (IP:)
+    std::string country;  // subject field: C
+    std::string state;    // subject field: ST
+    std::string locality; // subject field: L
+    std::string org;      // subject field: O
+    std::string unit;     // subject field: OU
+    std::string uuid;     // subject field: CN
+    std::string comment;  // custom extension: Netscape Comment
+    std::vector<std::string> hostnames; // subjectAltName extension (DNS:)
+    std::vector<std::string> ips;       // subjectAltName extension (IP:)
   };
 
   explicit CertRequestGeneratorBase(Config config);
@@ -134,6 +134,11 @@ class CaCertRequestGenerator : public CertRequestGeneratorBase {
 // An utility class for issuing and signing certificates.
 class CertSigner {
  public:
+  // Generate a self-signed certificate authority using the given key
+  // and CSR configuration.
+  static Status SelfSignCA(const std::shared_ptr<PrivateKey>& key,
+                           CaCertRequestGenerator::Config config,
+                           Cert* cert);
   // Create a CertSigner.
   // Exactly one of the following Init*() methods must be called
   // exactly once before the instance may be used.
@@ -149,11 +154,6 @@ class CertSigner {
   // on disk.
   Status InitFromFiles(const std::string& ca_cert_path,
                        const std::string& ca_private_key_path);
-  // Initialize the signer for self-signing using the given private key.
-  //
-  // Any certificates signed by this CertSigner will have the 'issuer' equal
-  // to the signed cert's subject.
-  Status InitForSelfSigning(std::shared_ptr<PrivateKey> private_key);
 
   // Set the expiration interval for certs signed by this signer.
   // This may be changed at any point.
@@ -175,6 +175,12 @@ class CertSigner {
   static Status DigestSign(const EVP_MD* md, EVP_PKEY* pkey, X509* x);
   static Status GenerateSerial(c_unique_ptr<ASN1_INTEGER>* ret);
 
+  // Initialize the signer for self-signing using the given private key.
+  //
+  // Any certificates signed by this CertSigner will have the 'issuer' equal
+  // to the signed cert's subject.
+  Status InitForSelfSigning(std::shared_ptr<PrivateKey> private_key);
+
   Status DoSign(const EVP_MD* digest, int32_t exp_seconds, X509 *ret) const;
 
   mutable simple_spinlock lock_;

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/security-test-util.cc
----------------------------------------------------------------------
diff --git a/src/kudu/security/security-test-util.cc b/src/kudu/security/security-test-util.cc
new file mode 100644
index 0000000..2fa8b1f
--- /dev/null
+++ b/src/kudu/security/security-test-util.cc
@@ -0,0 +1,52 @@
+// 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 "kudu/security/security-test-util.h"
+
+#include <memory>
+
+#include <glog/logging.h>
+
+#include "kudu/security/ca/cert_management.h"
+#include "kudu/security/cert.h"
+#include "kudu/security/crypto.h"
+
+namespace kudu {
+namespace security {
+
+using ca::CaCertRequestGenerator;
+using ca::CertSigner;
+
+Status GenerateSelfSignedCAForTests(std::shared_ptr<PrivateKey>* ca_key,
+                                    std::shared_ptr<Cert>* ca_cert) {
+  // Create a key for the self-signed CA.
+  auto ret_ca_key = std::make_shared<PrivateKey>();
+  auto ret_ca_cert = std::make_shared<Cert>();
+  RETURN_NOT_OK(GeneratePrivateKey(512, ret_ca_key.get()));
+
+  CaCertRequestGenerator::Config config;
+  config.uuid = "test-ca-uuid";
+  RETURN_NOT_OK(CertSigner::SelfSignCA(ret_ca_key, config, ret_ca_cert.get()));
+
+  *ca_key = std::move(ret_ca_key);
+  *ca_cert = std::move(ret_ca_cert);
+  return Status::OK();
+}
+
+
+} // namespace security
+} // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/86714152/src/kudu/security/security-test-util.h
----------------------------------------------------------------------
diff --git a/src/kudu/security/security-test-util.h b/src/kudu/security/security-test-util.h
index 76853d4..17c5375 100644
--- a/src/kudu/security/security-test-util.h
+++ b/src/kudu/security/security-test-util.h
@@ -25,10 +25,13 @@
 namespace kudu {
 namespace security {
 
+class Cert;
+class PrivateKey;
+
 // TODO(todd): consolidate these certs with those in
 // security/test/test_certs.h once we support configuring a password
 // for the RPC cert.
-static Status CreateSSLServerCert(const std::string& file_path) {
+inline static Status CreateSSLServerCert(const std::string& file_path) {
   static const char* test_server_cert = R"(
 -----BEGIN CERTIFICATE-----
 MIIEejCCA2KgAwIBAgIJAKMdvDR5PL82MA0GCSqGSIb3DQEBBQUAMIGEMQswCQYD
@@ -62,7 +65,7 @@ seCrQwgi1Fer9Ekd5XNjWjigC3VC3SjMqWaxeKbZ2/AuABJMz5xSiRkgwphXEQ==
 }
 
 // Writes the test SSL private key into a temporary file.
-static Status CreateSSLPrivateKey(const std::string& file_path) {
+inline static Status CreateSSLPrivateKey(const std::string& file_path) {
   static const char* test_private_key = R"(
 -----BEGIN RSA PRIVATE KEY-----
 MIIEpAIBAAKCAQEAqFI96TENhC5K886vpKIsZY1RQQBBKsFFkowPhhCsHxW/1D0Y
@@ -96,5 +99,9 @@ dc+JVPKL8Fe4a8fmsI6ndcZQ9qpOdZM5WOD0ldKRc+SsrYKkTmOOJQ==
   return Status::OK();
 }
 
+// TODO(todd): change these from shared_ptrs to unique_ptrs
+Status GenerateSelfSignedCAForTests(std::shared_ptr<PrivateKey>* ca_key,
+                                    std::shared_ptr<Cert>* ca_cert);
+
 } // namespace security
 } // namespace kudu