1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 """Common functions for tool scripts.
31
32 """
33
34 import logging
35 import OpenSSL
36 import os
37 import time
38 from cStringIO import StringIO
39
40 from ganeti import constants
41 from ganeti import errors
42 from ganeti import pathutils
43 from ganeti import utils
44 from ganeti import serializer
45 from ganeti import ssconf
46 from ganeti import ssh
47
48
50 """Verifies options and arguments for correctness.
51
52 """
53 if args:
54 parser.error("No arguments are expected")
55
56 return opts
57
58
61 """Verifies a certificate against the local node daemon certificate.
62
63 Includes elaborate tests of encodings etc., and returns formatted
64 certificate.
65
66 @type cert_pem: string
67 @param cert_pem: Certificate and key in PEM format
68 @type error_fn: callable
69 @param error_fn: function to call in case of an error
70 @rtype: string
71 @return: Formatted key and certificate
72
73 """
74 try:
75 cert = \
76 OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
77 except Exception, err:
78 raise error_fn("(stdin) Unable to load certificate: %s" % err)
79
80 try:
81 key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
82 except OpenSSL.crypto.Error, err:
83 raise error_fn("(stdin) Unable to load private key: %s" % err)
84
85
86
87 try:
88 utils.X509CertKeyCheck(cert, key)
89 except OpenSSL.SSL.Error:
90 raise error_fn("(stdin) Certificate is not signed with given key")
91
92
93
94 _check_fn(cert)
95
96 key_encoded = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
97 cert_encoded = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM,
98 cert)
99 complete_cert_encoded = key_encoded + cert_encoded
100 if not cert_pem == complete_cert_encoded:
101 logging.error("The certificate differs after being reencoded. Please"
102 " renew the certificates cluster-wide to prevent future"
103 " inconsistencies.")
104
105
106 buf = StringIO()
107 buf.write(cert_pem)
108 return buf.getvalue()
109
110
113 """Verifies a certificate against the local node daemon certificate.
114
115 @type cert_pem: string
116 @param cert_pem: Certificate in PEM format (no key)
117
118 """
119 try:
120 OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
121 except OpenSSL.crypto.Error, err:
122 pass
123 else:
124 raise error_fn("No private key may be given")
125
126 try:
127 cert = \
128 OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_pem)
129 except Exception, err:
130 raise errors.X509CertError("(stdin)",
131 "Unable to load certificate: %s" % err)
132
133 _check_fn(cert)
134
135
137 """Verifies cluster certificate if existing.
138
139 @type data: dict
140 @type error_fn: callable
141 @param error_fn: function to call in case of an error
142 @rtype: string
143 @return: Formatted key and certificate
144
145 """
146 cert = data.get(constants.SSHS_NODE_DAEMON_CERTIFICATE)
147 if cert:
148 _verify_fn(cert, error_fn)
149
150
153 """Verifies cluster certificate. Throws error when not existing.
154
155 @type data: dict
156 @type error_fn: callable
157 @param error_fn: function to call in case of an error
158 @rtype: string
159 @return: Formatted key and certificate
160
161 """
162 cert = data.get(constants.NDS_NODE_DAEMON_CERTIFICATE)
163 if not cert:
164 raise error_fn("Node daemon certificate must be specified")
165
166 return _verify_fn(cert, error_fn)
167
168
171 """Verifies cluster name.
172
173 @type data: dict
174
175 """
176 name = data.get(cluster_name_constant)
177 if name:
178 _verify_fn(name)
179 else:
180 raise error_fn("Cluster name must be specified")
181
182 return name
183
184
186 """Verifies the presence of the hmac secret.
187
188 @type data: dict
189
190 """
191 hmac = data.get(constants.NDS_HMAC)
192 if not hmac:
193 raise error_fn("Hmac key must be provided")
194
195 return hmac
196
197
199 """Parses and verifies input data.
200
201 @rtype: dict
202
203 """
204 result = None
205 try:
206 result = serializer.LoadAndVerifyJson(raw, data_check)
207 logging.debug("Received data: %s", serializer.DumpJson(result))
208 except Exception as e:
209 logging.warn("Received data is not valid json: %s.", str(raw))
210 raise e
211 return result
212
213
216 """Generates root's SSH keys for this node.
217
218 """
219 ssh.InitSSHSetup(key_type, key_bits, error_fn=error_fn,
220 _homedir_fn=_homedir_fn, _suffix=_suffix)
221
222
226 """Regenerates the client certificate of the node.
227
228 @type data: string
229 @param data: the JSON-formated input data
230
231 """
232 if not os.path.exists(signing_cert):
233 raise error_fn("The signing certificate '%s' cannot be found."
234 % signing_cert)
235
236
237
238
239
240
241 serial_no = int(time.time())
242
243
244 hostname = data.get(constants.NDS_NODE_NAME)
245 if not hostname:
246 raise error_fn("No hostname found.")
247
248 utils.GenerateSignedSslCert(client_cert, serial_no, signing_cert,
249 common_name=hostname)
250