Statistics
| Branch: | Tag: | Revision:

root / lib / utils / security.py @ 178ad717

History | View | Annotate | Download (4.7 kB)

1 3338a9ce Helga Velroyen
#
2 3338a9ce Helga Velroyen
#
3 3338a9ce Helga Velroyen
4 3338a9ce Helga Velroyen
# Copyright (C) 2013 Google Inc.
5 3338a9ce Helga Velroyen
#
6 3338a9ce Helga Velroyen
# This program is free software; you can redistribute it and/or modify
7 3338a9ce Helga Velroyen
# it under the terms of the GNU General Public License as published by
8 3338a9ce Helga Velroyen
# the Free Software Foundation; either version 2 of the License, or
9 3338a9ce Helga Velroyen
# (at your option) any later version.
10 3338a9ce Helga Velroyen
#
11 3338a9ce Helga Velroyen
# This program is distributed in the hope that it will be useful, but
12 3338a9ce Helga Velroyen
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 3338a9ce Helga Velroyen
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3338a9ce Helga Velroyen
# General Public License for more details.
15 3338a9ce Helga Velroyen
#
16 3338a9ce Helga Velroyen
# You should have received a copy of the GNU General Public License
17 3338a9ce Helga Velroyen
# along with this program; if not, write to the Free Software
18 3338a9ce Helga Velroyen
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 3338a9ce Helga Velroyen
# 02110-1301, USA.
20 3338a9ce Helga Velroyen
21 3338a9ce Helga Velroyen
"""Utility functions for security features of Ganeti.
22 3338a9ce Helga Velroyen

23 3338a9ce Helga Velroyen
"""
24 3338a9ce Helga Velroyen
25 3338a9ce Helga Velroyen
import logging
26 b544a3c2 Helga Velroyen
import OpenSSL
27 60cc531d Helga Velroyen
import os
28 b544a3c2 Helga Velroyen
29 b544a3c2 Helga Velroyen
from ganeti.utils import io
30 60cc531d Helga Velroyen
from ganeti.utils import x509
31 a6c43c02 Helga Velroyen
from ganeti import constants
32 a6c43c02 Helga Velroyen
from ganeti import errors
33 b544a3c2 Helga Velroyen
from ganeti import pathutils
34 3338a9ce Helga Velroyen
35 3338a9ce Helga Velroyen
36 3338a9ce Helga Velroyen
def AddNodeToCandidateCerts(node_uuid, cert_digest, candidate_certs,
37 3338a9ce Helga Velroyen
                            info_fn=logging.info, warn_fn=logging.warn):
38 3338a9ce Helga Velroyen
  """Adds an entry to the candidate certificate map.
39 3338a9ce Helga Velroyen

40 3338a9ce Helga Velroyen
  @type node_uuid: string
41 3338a9ce Helga Velroyen
  @param node_uuid: the node's UUID
42 3338a9ce Helga Velroyen
  @type cert_digest: string
43 3338a9ce Helga Velroyen
  @param cert_digest: the digest of the node's client SSL certificate
44 3338a9ce Helga Velroyen
  @type candidate_certs: dict of strings to strings
45 3338a9ce Helga Velroyen
  @param candidate_certs: map of node UUIDs to the digests of their client
46 3338a9ce Helga Velroyen
      SSL certificates, will be manipulated in this function
47 3338a9ce Helga Velroyen
  @type info_fn: function
48 3338a9ce Helga Velroyen
  @param info_fn: logging function for information messages
49 3338a9ce Helga Velroyen
  @type warn_fn: function
50 3338a9ce Helga Velroyen
  @param warn_fn: logging function for warning messages
51 3338a9ce Helga Velroyen

52 3338a9ce Helga Velroyen
  """
53 3338a9ce Helga Velroyen
  assert candidate_certs is not None
54 3338a9ce Helga Velroyen
55 3338a9ce Helga Velroyen
  if node_uuid in candidate_certs:
56 3338a9ce Helga Velroyen
    old_cert_digest = candidate_certs[node_uuid]
57 3338a9ce Helga Velroyen
    if old_cert_digest == cert_digest:
58 3338a9ce Helga Velroyen
      info_fn("Certificate digest for node %s already in config."
59 3338a9ce Helga Velroyen
              "Not doing anything." % node_uuid)
60 3338a9ce Helga Velroyen
      return
61 3338a9ce Helga Velroyen
    else:
62 3338a9ce Helga Velroyen
      warn_fn("Overriding differing certificate digest for node %s"
63 3338a9ce Helga Velroyen
              % node_uuid)
64 3338a9ce Helga Velroyen
  candidate_certs[node_uuid] = cert_digest
65 3338a9ce Helga Velroyen
66 3338a9ce Helga Velroyen
67 3338a9ce Helga Velroyen
def RemoveNodeFromCandidateCerts(node_uuid, candidate_certs,
68 3338a9ce Helga Velroyen
                                 warn_fn=logging.warn):
69 3338a9ce Helga Velroyen
  """Removes the entry of the given node in the certificate map.
70 3338a9ce Helga Velroyen

71 3338a9ce Helga Velroyen
  @type node_uuid: string
72 3338a9ce Helga Velroyen
  @param node_uuid: the node's UUID
73 3338a9ce Helga Velroyen
  @type candidate_certs: dict of strings to strings
74 3338a9ce Helga Velroyen
  @param candidate_certs: map of node UUIDs to the digests of their client
75 3338a9ce Helga Velroyen
      SSL certificates, will be manipulated in this function
76 3338a9ce Helga Velroyen
  @type warn_fn: function
77 3338a9ce Helga Velroyen
  @param warn_fn: logging function for warning messages
78 3338a9ce Helga Velroyen

79 3338a9ce Helga Velroyen
  """
80 3338a9ce Helga Velroyen
  if node_uuid not in candidate_certs:
81 3338a9ce Helga Velroyen
    warn_fn("Cannot remove certifcate for node %s, because it's not in the"
82 3338a9ce Helga Velroyen
            "candidate map." % node_uuid)
83 3338a9ce Helga Velroyen
    return
84 3338a9ce Helga Velroyen
  del candidate_certs[node_uuid]
85 b544a3c2 Helga Velroyen
86 b544a3c2 Helga Velroyen
87 b3cc1646 Helga Velroyen
def GetCertificateDigest(cert_filename=pathutils.NODED_CLIENT_CERT_FILE):
88 b544a3c2 Helga Velroyen
  """Reads the SSL certificate and returns the sha1 digest.
89 b544a3c2 Helga Velroyen

90 b544a3c2 Helga Velroyen
  """
91 b544a3c2 Helga Velroyen
  cert_plain = io.ReadFile(cert_filename)
92 b544a3c2 Helga Velroyen
  cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
93 b544a3c2 Helga Velroyen
                                         cert_plain)
94 b544a3c2 Helga Velroyen
  return cert.digest("sha1")
95 60cc531d Helga Velroyen
96 60cc531d Helga Velroyen
97 60cc531d Helga Velroyen
def GenerateNewSslCert(new_cert, cert_filename, log_msg):
98 60cc531d Helga Velroyen
  """Creates a new SSL certificate and backups the old one.
99 60cc531d Helga Velroyen

100 60cc531d Helga Velroyen
  @type new_cert: boolean
101 60cc531d Helga Velroyen
  @param new_cert: whether a new certificate should be created
102 60cc531d Helga Velroyen
  @type cert_filename: string
103 60cc531d Helga Velroyen
  @param cert_filename: filename of the certificate file
104 60cc531d Helga Velroyen
  @type log_msg: string
105 60cc531d Helga Velroyen
  @param log_msg: log message to be written on certificate creation
106 60cc531d Helga Velroyen

107 60cc531d Helga Velroyen
  """
108 60cc531d Helga Velroyen
  cert_exists = os.path.exists(cert_filename)
109 60cc531d Helga Velroyen
  if new_cert or not cert_exists:
110 60cc531d Helga Velroyen
    if cert_exists:
111 60cc531d Helga Velroyen
      io.CreateBackup(cert_filename)
112 60cc531d Helga Velroyen
113 60cc531d Helga Velroyen
    logging.debug(log_msg)
114 60cc531d Helga Velroyen
    x509.GenerateSelfSignedSslCert(cert_filename)
115 a6c43c02 Helga Velroyen
116 a6c43c02 Helga Velroyen
117 a6c43c02 Helga Velroyen
def VerifyCertificate(filename):
118 a6c43c02 Helga Velroyen
  """Verifies a SSL certificate.
119 a6c43c02 Helga Velroyen

120 a6c43c02 Helga Velroyen
  @type filename: string
121 a6c43c02 Helga Velroyen
  @param filename: Path to PEM file
122 a6c43c02 Helga Velroyen

123 a6c43c02 Helga Velroyen
  """
124 a6c43c02 Helga Velroyen
  try:
125 a6c43c02 Helga Velroyen
    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
126 a6c43c02 Helga Velroyen
                                           io.ReadFile(filename))
127 a6c43c02 Helga Velroyen
  except Exception, err: # pylint: disable=W0703
128 a6c43c02 Helga Velroyen
    return (constants.CV_ERROR,
129 a6c43c02 Helga Velroyen
            "Failed to load X509 certificate %s: %s" % (filename, err))
130 a6c43c02 Helga Velroyen
131 a6c43c02 Helga Velroyen
  (errcode, msg) = \
132 a6c43c02 Helga Velroyen
    x509.VerifyX509Certificate(cert, constants.SSL_CERT_EXPIRATION_WARN,
133 a6c43c02 Helga Velroyen
                                constants.SSL_CERT_EXPIRATION_ERROR)
134 a6c43c02 Helga Velroyen
135 a6c43c02 Helga Velroyen
  if msg:
136 a6c43c02 Helga Velroyen
    fnamemsg = "While verifying %s: %s" % (filename, msg)
137 a6c43c02 Helga Velroyen
  else:
138 a6c43c02 Helga Velroyen
    fnamemsg = None
139 a6c43c02 Helga Velroyen
140 a6c43c02 Helga Velroyen
  if errcode is None:
141 a6c43c02 Helga Velroyen
    return (None, fnamemsg)
142 a6c43c02 Helga Velroyen
  elif errcode == x509.CERT_WARNING:
143 a6c43c02 Helga Velroyen
    return (constants.CV_WARNING, fnamemsg)
144 a6c43c02 Helga Velroyen
  elif errcode == x509.CERT_ERROR:
145 a6c43c02 Helga Velroyen
    return (constants.CV_ERROR, fnamemsg)
146 a6c43c02 Helga Velroyen
147 a6c43c02 Helga Velroyen
  raise errors.ProgrammerError("Unhandled certificate error code %r" % errcode)