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