With this interdiff, the patch is complete, including maintaining
functionality of the upgrade:

diff --git a/tools/post-upgrade b/tools/post-upgrade
index 6aec3ff..74ade3c 100644
--- a/tools/post-upgrade
+++ b/tools/post-upgrade
@@ -43,11 +43,9 @@ def main():
   version = utils.version.ParseVersion(versionstring)

   if utils.version.IsBefore(version, 2, 11, 0):
-    result = utils.RunCmd(["gnt-cluster", "renew-crypto",
-                           "--new-node-certificates", "-f"])
-    if result.failed:
-      cli.ToStderr("Failed to create node certificates: %s; Output %s" %
-                   (result.fail_reason, result.output))
+    # FIXME: Add client certificate handling here when resolving issue 692.
+    pass
+
   return 0

 if __name__ == "__main__":


Cheers,
Helga


On Fri, Jan 24, 2014 at 1:36 PM, Helga Velroyen <[email protected]> wrote:

> As discussed offline, I will resend this patch with an addition about the
> upgrades, so disregard this for now.
>
>
> On Thu, Jan 23, 2014 at 5:33 PM, Helga Velroyen <[email protected]> wrote:
>
>> This patch temporarily disables the usage of the client
>> SSL certificates. The handling of RPC connections had a
>> conceptional flaw, because the certificates lack a proper
>> signature. For this, Ganeti needs to implement a CA,
>> which is already designed (see design-x509-ca.rst) but
>> not implemented yet. This patch keeps most of the
>> client certificate infrastructure intact which was already
>> created and and can be reused, but just disables the
>> actual usage of the certificates in RPC calls till the CA
>> is in place.
>>
>> Signed-off-by: Helga Velroyen <[email protected]>
>> ---
>> My apologies for identifying this problem only now. For some
>> reason, it worked perfectly on debian machines and was only
>> discovered on fedora machines. I will investigate this
>> further to find out why the debian machines completely
>> ignored the signatures so far.
>>
>>  lib/cmdlib/cluster.py              |   1 -
>>  lib/http/__init__.py               |   2 +-
>>  lib/rpc/node.py                    |  12 +---
>>  man/gnt-cluster.rst                |   7 +-
>>  src/Ganeti/Rpc.hs                  |  12 +---
>>  test/py/cmdlib/cluster_unittest.py | 134
>> -------------------------------------
>>  6 files changed, 6 insertions(+), 162 deletions(-)
>>
>> diff --git a/lib/cmdlib/cluster.py b/lib/cmdlib/cluster.py
>> index d04bd69..5f18205 100644
>> --- a/lib/cmdlib/cluster.py
>> +++ b/lib/cmdlib/cluster.py
>> @@ -3182,7 +3182,6 @@ class LUClusterVerifyGroup(LogicalUnit,
>> _VerifyErrors):
>>
>>      feedback_fn("* Verifying configuration file consistency")
>>
>> -    self._VerifyClientCertificates(self.my_node_info.values(),
>> all_nvinfo)
>>      # If not all nodes are being checked, we need to make sure the
>> master node
>>      # and a non-checked vm_capable node are in the list.
>>      absent_node_uuids =
>> set(self.all_node_info).difference(self.my_node_info)
>> diff --git a/lib/http/__init__.py b/lib/http/__init__.py
>> index 614d6ba..5ae981f 100644
>> --- a/lib/http/__init__.py
>> +++ b/lib/http/__init__.py
>> @@ -610,7 +610,7 @@ class HttpBase(object):
>>      if ssl_verify_peer:
>>        ctx.set_verify(OpenSSL.SSL.VERIFY_PEER |
>>                       OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
>> -                     ssl_verify_callback)
>> +                     self._SSLVerifyCallback)
>>
>>        # Also add our certificate as a trusted CA to be sent to the
>> client.
>>        # This is required at least for GnuTLS clients to work.
>> diff --git a/lib/rpc/node.py b/lib/rpc/node.py
>> index 8c0f822..e3944aa 100644
>> --- a/lib/rpc/node.py
>> +++ b/lib/rpc/node.py
>> @@ -98,23 +98,15 @@ def Shutdown():
>>
>>  def _ConfigRpcCurl(curl):
>>    noded_cert = str(pathutils.NODED_CERT_FILE)
>> -  noded_client_cert = str(pathutils.NODED_CLIENT_CERT_FILE)
>> -
>> -  # FIXME: The next two lines are necessary to ensure upgradability from
>> -  # 2.10 to 2.11. Remove in 2.12, because this slows down RPC calls.
>> -  if not os.path.exists(noded_client_cert):
>> -    logging.info("Using server certificate as client certificate for
>> RPC"
>> -                 "call.")
>> -    noded_client_cert = noded_cert
>>
>>    curl.setopt(pycurl.FOLLOWLOCATION, False)
>>    curl.setopt(pycurl.CAINFO, noded_cert)
>>    curl.setopt(pycurl.SSL_VERIFYHOST, 0)
>>    curl.setopt(pycurl.SSL_VERIFYPEER, True)
>>    curl.setopt(pycurl.SSLCERTTYPE, "PEM")
>> -  curl.setopt(pycurl.SSLCERT, noded_client_cert)
>> +  curl.setopt(pycurl.SSLCERT, noded_cert)
>>    curl.setopt(pycurl.SSLKEYTYPE, "PEM")
>> -  curl.setopt(pycurl.SSLKEY, noded_client_cert)
>> +  curl.setopt(pycurl.SSLKEY, noded_cert)
>>    curl.setopt(pycurl.CONNECTTIMEOUT, constants.RPC_CONNECT_TIMEOUT)
>>
>>
>> diff --git a/man/gnt-cluster.rst b/man/gnt-cluster.rst
>> index 72756c2..eeb1b5a 100644
>> --- a/man/gnt-cluster.rst
>> +++ b/man/gnt-cluster.rst
>> @@ -766,7 +766,7 @@ RENEW-CRYPTO
>>  ~~~~~~~~~~~~
>>
>>  | **renew-crypto** [-f]
>> -| [\--new-cluster-certificate] | [\--new-node-certificates]
>> +| [\--new-cluster-certificate]
>>  | [\--new-confd-hmac-key]
>>  | [\--new-rapi-certificate] [\--rapi-certificate *rapi-cert*]
>>  | [\--new-spice-certificate | \--spice-certificate *spice-cert*
>> @@ -779,11 +779,6 @@ options ``--new-cluster-certificate`` and
>> ``--new-confd-hmac-key``
>>  can be used to regenerate respectively the cluster-internal SSL
>>  certificate and the HMAC key used by **ganeti-confd**\(8).
>>
>> -The option ``--new-node-certificates`` will generate new node SSL
>> -certificates for all nodes. Note that the regeneration of the node
>> -certificates takes place after the other certificates are created
>> -and distributed and the ganeti daemons are restarted again.
>> -
>>  To generate a new self-signed RAPI certificate (used by
>>  **ganeti-rapi**\(8)) specify ``--new-rapi-certificate``. If you want to
>>  use your own certificate, e.g. one signed by a certificate
>> diff --git a/src/Ganeti/Rpc.hs b/src/Ganeti/Rpc.hs
>> index 598b76f..2526d2e 100644
>> --- a/src/Ganeti/Rpc.hs
>> +++ b/src/Ganeti/Rpc.hs
>> @@ -90,7 +90,6 @@ import Data.Maybe (fromMaybe)
>>  import qualified Text.JSON as J
>>  import Text.JSON.Pretty (pp_value)
>>  import qualified Data.ByteString.Base64.Lazy as Base64
>> -import System.Directory
>>
>>  import Network.Curl hiding (content)
>>  import qualified Ganeti.Path as P
>> @@ -229,15 +228,8 @@ getOptionsForCall cert_path client_cert_path call =
>>  executeRpcCalls :: (Rpc a b) => [(Node, a)] -> IO [(Node, ERpcError b)]
>>  executeRpcCalls nodeCalls = do
>>    cert_file <- P.nodedCertFile
>> -  client_cert_file_name <- P.nodedClientCertFile
>> -  client_file_exists <- doesFileExist client_cert_file_name
>> -  -- FIXME: This is needed to ensure upgradability to 2.11
>> -  -- Remove in 2.12.
>> -  let client_cert_file = if client_file_exists
>> -                         then client_cert_file_name
>> -                         else cert_file
>> -      (nodes, calls) = unzip nodeCalls
>> -      opts = map (getOptionsForCall cert_file client_cert_file) calls
>> +  let (nodes, calls) = unzip nodeCalls
>> +      opts = map (getOptionsForCall cert_file cert_file) calls
>>        opts_urls = zipWith3 (\n c o ->
>>                           case prepareHttpRequest o n c of
>>                             Left v -> Left v
>> diff --git a/test/py/cmdlib/cluster_unittest.py
>> b/test/py/cmdlib/cluster_unittest.py
>> index 51aa3e0..fad9276 100644
>> --- a/test/py/cmdlib/cluster_unittest.py
>> +++ b/test/py/cmdlib/cluster_unittest.py
>> @@ -1085,140 +1085,6 @@ class TestLUClusterVerifyGroup(CmdlibTestCase):
>>      self.ExecOpCode(op)
>>
>>
>> -class TestLUClusterVerifyClientCerts(CmdlibTestCase):
>> -
>> -  def _AddNormalNode(self):
>> -    self.normalnode = copy.deepcopy(self.master)
>> -    self.normalnode.master_candidate = False
>> -    self.normalnode.uuid = "normal-node-uuid"
>> -    self.cfg.AddNode(self.normalnode, None)
>> -
>> -  def testVerifyMasterCandidate(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {self.master.uuid: client_cert}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -
>> -  def testVerifyMasterCandidateInvalid(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {self.master.uuid: client_cert}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (666, "Invalid Certificate")}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("Client certificate")
>> -    self.mcpu.assertLogContainsRegex("failed validation")
>> -
>> -  def testVerifyNoMasterCandidateMap(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex(
>> -      "list of master candidate certificates is empty")
>> -
>> -  def testVerifyNoSharingMasterCandidates(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {
>> -      self.master.uuid: client_cert,
>> -      "some-other-master-candidate-uuid": client_cert}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex(
>> -      "two master candidates configured to use the same")
>> -
>> -  def testVerifyMasterCandidateCertMismatch(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {self.master.uuid:
>> "different-cert-digest"}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("does not match its entry")
>> -
>> -  def testVerifyMasterCandidateUnregistered(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {"other-node-uuid":
>> "different-cert-digest"}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("does not have an entry")
>> -
>> -  def testVerifyMasterCandidateOtherNodesCert(self):
>> -    client_cert = "client-cert-digest"
>> -    self.cluster.candidate_certs = {"other-node-uuid": client_cert}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("using a certificate of another
>> node")
>> -
>> -  def testNormalNodeStillInList(self):
>> -    self._AddNormalNode()
>> -    client_cert_master = "client-cert-digest-master"
>> -    client_cert_normal = "client-cert-digest-normal"
>> -    self.cluster.candidate_certs = {
>> -      self.normalnode.uuid: client_cert_normal,
>> -      self.master.uuid: client_cert_master}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.normalnode,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert_normal)}) \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert_master)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("not a master candidate")
>> -    self.mcpu.assertLogContainsRegex("still listed")
>> -
>> -  def testNormalNodeStealingMasterCandidateCert(self):
>> -    self._AddNormalNode()
>> -    client_cert_master = "client-cert-digest-master"
>> -    self.cluster.candidate_certs = {
>> -      self.master.uuid: client_cert_master}
>> -    self.rpc.call_node_verify.return_value = \
>> -      RpcResultsBuilder() \
>> -        .AddSuccessfulNode(self.normalnode,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert_master)}) \
>> -        .AddSuccessfulNode(self.master,
>> -          {constants.NV_CLIENT_CERT: (None, client_cert_master)}) \
>> -        .Build()
>> -    op = opcodes.OpClusterVerifyGroup(group_name="default", verbose=True)
>> -    self.ExecOpCode(op)
>> -    self.mcpu.assertLogContainsRegex("not a master candidate")
>> -    self.mcpu.assertLogContainsRegex(
>> -      "certificate of another node which is master candidate")
>> -
>> -
>>  class TestLUClusterVerifyGroupMethods(CmdlibTestCase):
>>    """Base class for testing individual methods in LUClusterVerifyGroup.
>>
>> --
>> 1.8.5.3
>>
>>
>
>
> --
> --
> Helga Velroyen | Software Engineer | [email protected] |
>
> Google Germany GmbH
> Dienerstr. 12
> 80331 München
>
> Registergericht und -nummer: Hamburg, HRB 86891
> Sitz der Gesellschaft: Hamburg
> Geschäftsführer: Graham Law, Christine Elizabeth Flores
>



-- 
-- 
Helga Velroyen | Software Engineer | [email protected] |

Google Germany GmbH
Dienerstr. 12
80331 München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores

Reply via email to