So far, the client certificate of a node that is added
to the cluster was created in LUNodeAdd using an RPC
call. This is now simplified by creating the certificate
already in tools/node_daemon_setup.py and only retrieving
its fingerprint by RPC to add it to the configuration.

This simplifies the backend function from only reading
the fingerprint instead of creating the certificate.

Signed-off-by: Helga Velroyen <[email protected]>
---
 lib/backend.py                     | 49 +++-----------------------------------
 lib/bootstrap.py                   |  1 +
 lib/cmdlib/cluster.py              |  9 ++++---
 lib/cmdlib/common.py               |  9 ++++---
 lib/cmdlib/node.py                 |  4 ++--
 lib/tools/common.py                |  2 ++
 lib/tools/node_daemon_setup.py     |  3 +++
 src/Ganeti/Constants.hs            |  6 +----
 test/py/ganeti.backend_unittest.py | 26 --------------------
 9 files changed, 20 insertions(+), 89 deletions(-)

diff --git a/lib/backend.py b/lib/backend.py
index 402aae1..5830f67 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -1211,13 +1211,8 @@ def GetCryptoTokens(token_requests):
   @return: list of tuples of the token type and the public crypto token
 
   """
-  getents = runtime.GetEnts()
-  _VALID_CERT_FILES = [pathutils.NODED_CERT_FILE,
-                       pathutils.NODED_CLIENT_CERT_FILE,
-                       pathutils.NODED_CLIENT_CERT_FILE_TMP]
-  _DEFAULT_CERT_FILE = pathutils.NODED_CLIENT_CERT_FILE
   tokens = []
-  for (token_type, action, options) in token_requests:
+  for (token_type, action, _) in token_requests:
     if token_type not in constants.CRYPTO_TYPES:
       raise errors.ProgrammerError("Token type '%s' not supported." %
                                    token_type)
@@ -1225,46 +1220,8 @@ def GetCryptoTokens(token_requests):
       raise errors.ProgrammerError("Action '%s' is not supported." %
                                    action)
     if token_type == constants.CRYPTO_TYPE_SSL_DIGEST:
-      if action == constants.CRYPTO_ACTION_CREATE:
-
-        # extract file name from options
-        cert_filename = None
-        if options:
-          cert_filename = options.get(constants.CRYPTO_OPTION_CERT_FILE)
-        if not cert_filename:
-          cert_filename = _DEFAULT_CERT_FILE
-        # For security reason, we don't allow arbitrary filenames
-        if not cert_filename in _VALID_CERT_FILES:
-          raise errors.ProgrammerError(
-            "The certificate file name path '%s' is not allowed." %
-            cert_filename)
-
-        # extract serial number from options
-        serial_no = None
-        if options:
-          try:
-            serial_no = int(options[constants.CRYPTO_OPTION_SERIAL_NO])
-          except ValueError:
-            raise errors.ProgrammerError(
-              "The given serial number is not an intenger: %s." %
-              options.get(constants.CRYPTO_OPTION_SERIAL_NO))
-          except KeyError:
-            raise errors.ProgrammerError("No serial number was provided.")
-
-        if not serial_no:
-          raise errors.ProgrammerError(
-            "Cannot create an SSL certificate without a serial no.")
-
-        utils.GenerateNewSslCert(
-          True, cert_filename, serial_no,
-          "Create new client SSL certificate in %s." % cert_filename,
-          uid=getents.masterd_uid, gid=getents.masterd_gid)
-        tokens.append((token_type,
-                       utils.GetCertificateDigest(
-                         cert_filename=cert_filename)))
-      elif action == constants.CRYPTO_ACTION_GET:
-        tokens.append((token_type,
-                       utils.GetCertificateDigest()))
+      tokens.append((token_type,
+                     utils.GetCertificateDigest()))
   return tokens
 
 
diff --git a/lib/bootstrap.py b/lib/bootstrap.py
index a9b1f68..fa6ae19 100644
--- a/lib/bootstrap.py
+++ b/lib/bootstrap.py
@@ -1010,6 +1010,7 @@ def SetupNodeDaemon(opts, cluster_name, node, ssh_port):
       utils.ReadFile(pathutils.NODED_CERT_FILE),
     constants.NDS_SSCONF: ssconf.SimpleStore().ReadAll(),
     constants.NDS_START_NODE_DAEMON: True,
+    constants.NDS_NODE_NAME: node,
     }
 
   RunNodeSetupCmd(cluster_name, node, pathutils.NODE_DAEMON_SETUP,
diff --git a/lib/cmdlib/cluster.py b/lib/cmdlib/cluster.py
index 0251525..5d09202 100644
--- a/lib/cmdlib/cluster.py
+++ b/lib/cmdlib/cluster.py
@@ -65,10 +65,9 @@ from ganeti.cmdlib.common import ShareAll, RunPostHook, \
   CheckOSParams, CheckHVParams, AdjustCandidatePool, CheckNodePVs, \
   ComputeIPolicyInstanceViolation, AnnotateDiskParams, SupportsOob, \
   CheckIpolicyVsDiskTemplates, CheckDiskAccessModeValidity, \
-  CheckDiskAccessModeConsistency, CreateNewClientCert, \
+  CheckDiskAccessModeConsistency, GetClientCertDigest, \
   AddInstanceCommunicationNetworkOp, ConnectInstanceCommunicationNetworkOp, \
-  CheckImageValidity, \
-  CheckDiskAccessModeConsistency, CreateNewClientCert, EnsureKvmdOnNodes
+  CheckImageValidity, CheckDiskAccessModeConsistency, EnsureKvmdOnNodes
 
 import ganeti.masterd.instance
 
@@ -93,7 +92,7 @@ def _UpdateMasterClientCert(
   @return: the digest of the newly created client certificate
 
   """
-  client_digest = CreateNewClientCert(lu, master_uuid, 
filename=client_cert_tmp)
+  client_digest = GetClientCertDigest(lu, master_uuid, 
filename=client_cert_tmp)
   cfg.AddNodeToCandidateCerts(master_uuid, client_digest)
   # This triggers an update of the config and distribution of it with the old
   # SSL certificate
@@ -188,7 +187,7 @@ class LUClusterRenewCrypto(NoHooksLU):
         last_exception = None
         for i in range(self._MAX_NUM_RETRIES):
           try:
-            new_digest = CreateNewClientCert(self, node_uuid)
+            new_digest = GetClientCertDigest(self, node_uuid)
             if node_info.master_candidate:
               self.cfg.AddNodeToCandidateCerts(node_uuid,
                                                new_digest)
diff --git a/lib/cmdlib/common.py b/lib/cmdlib/common.py
index e2eb909..4298e6c 100644
--- a/lib/cmdlib/common.py
+++ b/lib/cmdlib/common.py
@@ -1366,8 +1366,8 @@ def RemoveNodeCertFromCandidateCerts(cfg, node_uuid):
   cfg.RemoveNodeFromCandidateCerts(node_uuid)
 
 
-def CreateNewClientCert(lu, node_uuid, filename=None):
-  """Creates a new client SSL certificate for the node.
+def GetClientCertDigest(lu, node_uuid, filename=None):
+  """Get the client SSL certificate digest for the node.
 
   @type node_uuid: string
   @param node_uuid: the node's UUID
@@ -1380,13 +1380,12 @@ def CreateNewClientCert(lu, node_uuid, filename=None):
   options = {}
   if filename:
     options[constants.CRYPTO_OPTION_CERT_FILE] = filename
-  options[constants.CRYPTO_OPTION_SERIAL_NO] = utils.UuidToInt(node_uuid)
   result = lu.rpc.call_node_crypto_tokens(
              node_uuid,
              [(constants.CRYPTO_TYPE_SSL_DIGEST,
-               constants.CRYPTO_ACTION_CREATE,
+               constants.CRYPTO_ACTION_GET,
                options)])
-  result.Raise("Could not create the node's (uuid %s) SSL client"
+  result.Raise("Could not fetch the node's (uuid %s) SSL client"
                " certificate." % node_uuid)
   ((crypto_type, new_digest), ) = result.payload
   assert crypto_type == constants.CRYPTO_TYPE_SSL_DIGEST
diff --git a/lib/cmdlib/node.py b/lib/cmdlib/node.py
index 1b13aa9..2f83c73 100644
--- a/lib/cmdlib/node.py
+++ b/lib/cmdlib/node.py
@@ -51,7 +51,7 @@ from ganeti.cmdlib.common import CheckParamsNotGlobal, \
   CheckInstanceState, INSTANCE_DOWN, GetUpdatedParams, \
   AdjustCandidatePool, CheckIAllocatorOrNode, LoadNodeEvacResult, \
   GetWantedNodes, MapInstanceLvsToNodes, RunPostHook, \
-  FindFaultyInstanceDisks, CheckStorageTypeEnabled, CreateNewClientCert, \
+  FindFaultyInstanceDisks, CheckStorageTypeEnabled, GetClientCertDigest, \
   AddNodeCertToCandidateCerts, RemoveNodeCertFromCandidateCerts, \
   EnsureKvmdOnNodes
 
@@ -431,7 +431,7 @@ class LUNodeAdd(LogicalUnit):
       RedistributeAncillaryFiles(self)
 
     # We create a new certificate even if the node is readded
-    digest = CreateNewClientCert(self, self.new_node.uuid)
+    digest = GetClientCertDigest(self, self.new_node.uuid)
     if self.new_node.master_candidate:
       self.cfg.AddNodeToCandidateCerts(self.new_node.uuid, digest)
     else:
diff --git a/lib/tools/common.py b/lib/tools/common.py
index 547c072..b48b1ee 100644
--- a/lib/tools/common.py
+++ b/lib/tools/common.py
@@ -165,6 +165,8 @@ def GenerateClientCertificate(
 
   # The hostname of the node is provided with the input data.
   hostname = data.get(constants.NDS_NODE_NAME)
+  if not hostname:
+    raise error_fn("No hostname found.")
 
   utils.GenerateSignedSslCert(client_cert, serial_no, signing_cert,
                               common_name=hostname)
diff --git a/lib/tools/node_daemon_setup.py b/lib/tools/node_daemon_setup.py
index 3eec177..89e8a18 100644
--- a/lib/tools/node_daemon_setup.py
+++ b/lib/tools/node_daemon_setup.py
@@ -48,6 +48,7 @@ from ganeti import serializer
 from ganeti import runtime
 from ganeti import ht
 from ganeti import ssconf
+from ganeti.tools import common
 
 
 _DATA_CHECK = ht.TStrictDict(False, True, {
@@ -55,6 +56,7 @@ _DATA_CHECK = ht.TStrictDict(False, True, {
   constants.NDS_NODE_DAEMON_CERTIFICATE: ht.TNonEmptyString,
   constants.NDS_SSCONF: ht.TDictOf(ht.TNonEmptyString, ht.TString),
   constants.NDS_START_NODE_DAEMON: ht.TBool,
+  constants.NDS_NODE_NAME: ht.TString,
   })
 
 
@@ -227,6 +229,7 @@ def Main():
                     mode=pathutils.NODED_CERT_MODE,
                     uid=getent.masterd_uid, gid=getent.masterd_gid,
                     dry_run=opts.dry_run)
+    common.GenerateClientCertificate(data, SetupError)
 
     if (data.get(constants.NDS_START_NODE_DAEMON) and # pylint: disable=E1103
         not opts.dry_run):
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index 9428780..77b0949 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -4386,12 +4386,8 @@ cryptoTypes = ConstantUtils.mkSet [cryptoTypeSslDigest]
 cryptoActionGet :: String
 cryptoActionGet = "get"
 
--- This is 'create and get'
-cryptoActionCreate :: String
-cryptoActionCreate = "create"
-
 cryptoActions :: FrozenSet String
-cryptoActions = ConstantUtils.mkSet [cryptoActionGet, cryptoActionCreate]
+cryptoActions = ConstantUtils.mkSet [cryptoActionGet]
 
 -- * Options for CryptoActions
 
diff --git a/test/py/ganeti.backend_unittest.py 
b/test/py/ganeti.backend_unittest.py
index 2e33993..6a3346d 100755
--- a/test/py/ganeti.backend_unittest.py
+++ b/test/py/ganeti.backend_unittest.py
@@ -105,32 +105,6 @@ class TestGetCryptoTokens(testutils.GanetiTestCase):
     self.assertTrue((constants.CRYPTO_TYPE_SSL_DIGEST, self._ssl_digest)
                     in result)
 
-  def testCreateSslToken(self):
-    result = backend.GetCryptoTokens(
-      [(constants.CRYPTO_TYPE_SSL_DIGEST, constants.CRYPTO_ACTION_CREATE,
-        {constants.CRYPTO_OPTION_SERIAL_NO: 42})])
-    self.assertTrue((constants.CRYPTO_TYPE_SSL_DIGEST, self._ssl_digest)
-                    in result)
-    self.assertTrue(utils.GenerateNewSslCert.assert_calls().once())
-
-  def testCreateSslTokenDifferentFilename(self):
-    result = backend.GetCryptoTokens(
-      [(constants.CRYPTO_TYPE_SSL_DIGEST, constants.CRYPTO_ACTION_CREATE,
-        {constants.CRYPTO_OPTION_CERT_FILE:
-          pathutils.NODED_CLIENT_CERT_FILE_TMP,
-         constants.CRYPTO_OPTION_SERIAL_NO: 42})])
-    self.assertTrue((constants.CRYPTO_TYPE_SSL_DIGEST, self._ssl_digest)
-                    in result)
-    self.assertTrue(utils.GenerateNewSslCert.assert_calls().once())
-
-  def testCreateSslTokenSerialNo(self):
-    result = backend.GetCryptoTokens(
-      [(constants.CRYPTO_TYPE_SSL_DIGEST, constants.CRYPTO_ACTION_CREATE,
-        {constants.CRYPTO_OPTION_SERIAL_NO: 42})])
-    self.assertTrue((constants.CRYPTO_TYPE_SSL_DIGEST, self._ssl_digest)
-                    in result)
-    self.assertTrue(utils.GenerateNewSslCert.assert_calls().once())
-
   def testUnknownTokenType(self):
     self.assertRaises(errors.ProgrammerError,
                       backend.GetCryptoTokens,
-- 
2.4.3.573.g4eafbef

Reply via email to