Revision 0aee8ee9
b/lib/bootstrap.py | ||
---|---|---|
88 | 88 |
backup=True) |
89 | 89 |
|
90 | 90 |
|
91 |
def GenerateClusterCrypto(new_cluster_cert, new_rapi_cert, new_spice_cert, |
|
92 |
new_confd_hmac_key, new_cds, |
|
93 |
rapi_cert_pem=None, spice_cert_pem=None, |
|
94 |
spice_cacert_pem=None, cds=None, |
|
91 |
def GenerateClusterCrypto(new_cluster_cert, new_rapi_cert, new_confd_hmac_key, |
|
92 |
new_cds, rapi_cert_pem=None, cds=None, |
|
95 | 93 |
nodecert_file=constants.NODED_CERT_FILE, |
96 | 94 |
rapicert_file=constants.RAPI_CERT_FILE, |
97 |
spicecert_file=constants.SPICE_CERT_FILE, |
|
98 |
spicecacert_file=constants.SPICE_CACERT_FILE, |
|
99 | 95 |
hmackey_file=constants.CONFD_HMAC_KEY, |
100 | 96 |
cds_file=constants.CLUSTER_DOMAIN_SECRET_FILE): |
101 | 97 |
"""Updates the cluster certificates, keys and secrets. |
... | ... | |
104 | 100 |
@param new_cluster_cert: Whether to generate a new cluster certificate |
105 | 101 |
@type new_rapi_cert: bool |
106 | 102 |
@param new_rapi_cert: Whether to generate a new RAPI certificate |
107 |
@type new_spice_cert: bool |
|
108 |
@param new_spice_cert: Whether to generate a new SPICE certificate |
|
109 | 103 |
@type new_confd_hmac_key: bool |
110 | 104 |
@param new_confd_hmac_key: Whether to generate a new HMAC key |
111 | 105 |
@type new_cds: bool |
112 | 106 |
@param new_cds: Whether to generate a new cluster domain secret |
113 | 107 |
@type rapi_cert_pem: string |
114 | 108 |
@param rapi_cert_pem: New RAPI certificate in PEM format |
115 |
@type spice_cert_pem: string |
|
116 |
@param spice_cert_pem: New SPICE certificate in PEM format |
|
117 |
@type spice_cacert_pem: string |
|
118 |
@param spice_cacert_pem: Certificate of the CA that signed the SPICE |
|
119 |
certificate, in PEM format |
|
120 | 109 |
@type cds: string |
121 | 110 |
@param cds: New cluster domain secret |
122 | 111 |
@type nodecert_file: string |
123 | 112 |
@param nodecert_file: optional override of the node cert file path |
124 | 113 |
@type rapicert_file: string |
125 | 114 |
@param rapicert_file: optional override of the rapi cert file path |
126 |
@type spicecert_file: string |
|
127 |
@param spicecert_file: optional override of the spice cert file path |
|
128 |
@type spicecacert_file: string |
|
129 |
@param spicecacert_file: optional override of the spice CA cert file path |
|
130 | 115 |
@type hmackey_file: string |
131 | 116 |
@param hmackey_file: optional override of the hmac key file path |
132 | 117 |
|
... | ... | |
160 | 145 |
logging.debug("Generating new RAPI certificate at %s", rapicert_file) |
161 | 146 |
utils.GenerateSelfSignedSslCert(rapicert_file) |
162 | 147 |
|
163 |
# SPICE |
|
164 |
spice_cert_exists = os.path.exists(spicecert_file) |
|
165 |
spice_cacert_exists = os.path.exists(spicecacert_file) |
|
166 |
if spice_cert_pem: |
|
167 |
# spice_cert_pem implies also spice_cacert_pem |
|
168 |
logging.debug("Writing SPICE certificate at %s", spicecert_file) |
|
169 |
utils.WriteFile(spicecert_file, data=spice_cert_pem, backup=True) |
|
170 |
logging.debug("Writing SPICE CA certificate at %s", spicecacert_file) |
|
171 |
utils.WriteFile(spicecacert_file, data=spice_cacert_pem, backup=True) |
|
172 |
elif new_spice_cert or not spice_cert_exists: |
|
173 |
if spice_cert_exists: |
|
174 |
utils.CreateBackup(spicecert_file) |
|
175 |
if spice_cacert_exists: |
|
176 |
utils.CreateBackup(spicecacert_file) |
|
177 |
|
|
178 |
logging.debug("Generating new self-signed SPICE certificate at %s", |
|
179 |
spicecert_file) |
|
180 |
(_, cert_pem) = utils.GenerateSelfSignedSslCert(spicecert_file) |
|
181 |
|
|
182 |
# Self-signed certificate -> the public certificate is also the CA public |
|
183 |
# certificate |
|
184 |
logging.debug("Writing the public certificate to %s", |
|
185 |
spicecert_file) |
|
186 |
utils.io.WriteFile(spicecacert_file, mode=0400, data=cert_pem) |
|
187 |
|
|
188 | 148 |
# Cluster domain secret |
189 | 149 |
if cds: |
190 | 150 |
logging.debug("Writing cluster domain secret to %s", cds_file) |
... | ... | |
206 | 166 |
|
207 | 167 |
""" |
208 | 168 |
# Generate cluster secrets |
209 |
GenerateClusterCrypto(True, False, False, False, False)
|
|
169 |
GenerateClusterCrypto(True, False, False, False) |
|
210 | 170 |
|
211 | 171 |
result = utils.RunCmd([constants.DAEMON_UTIL, "start", constants.NODED]) |
212 | 172 |
if result.failed: |
b/lib/cli.py | ||
---|---|---|
109 | 109 |
"NEW_CONFD_HMAC_KEY_OPT", |
110 | 110 |
"NEW_RAPI_CERT_OPT", |
111 | 111 |
"NEW_SECONDARY_OPT", |
112 |
"NEW_SPICE_CERT_OPT", |
|
113 | 112 |
"NIC_PARAMS_OPT", |
114 | 113 |
"NODE_FORCE_JOIN_OPT", |
115 | 114 |
"NODE_LIST_OPT", |
... | ... | |
160 | 159 |
"SHOWCMD_OPT", |
161 | 160 |
"SHUTDOWN_TIMEOUT_OPT", |
162 | 161 |
"SINGLE_NODE_OPT", |
163 |
"SPICE_CACERT_OPT", |
|
164 |
"SPICE_CERT_OPT", |
|
165 | 162 |
"SRC_DIR_OPT", |
166 | 163 |
"SRC_NODE_OPT", |
167 | 164 |
"SUBMIT_OPT", |
... | ... | |
1089 | 1086 |
help=("Generate a new self-signed RAPI" |
1090 | 1087 |
" certificate")) |
1091 | 1088 |
|
1092 |
SPICE_CERT_OPT = cli_option("--spice-certificate", dest="spice_cert", |
|
1093 |
default=None, |
|
1094 |
help="File containing new SPICE certificate") |
|
1095 |
|
|
1096 |
SPICE_CACERT_OPT = cli_option("--spice-ca-certificate", dest="spice_cacert", |
|
1097 |
default=None, |
|
1098 |
help="File containing the certificate of the CA" |
|
1099 |
" which signed the SPICE certificate") |
|
1100 |
|
|
1101 |
NEW_SPICE_CERT_OPT = cli_option("--new-spice-certificate", |
|
1102 |
dest="new_spice_cert", default=None, |
|
1103 |
action="store_true", |
|
1104 |
help=("Generate a new self-signed SPICE" |
|
1105 |
" certificate")) |
|
1106 |
|
|
1107 | 1089 |
NEW_CONFD_HMAC_KEY_OPT = cli_option("--new-confd-hmac-key", |
1108 | 1090 |
dest="new_confd_hmac_key", |
1109 | 1091 |
default=False, action="store_true", |
b/lib/client/gnt_cluster.py | ||
---|---|---|
672 | 672 |
ToStdout("%s %s", path, tag) |
673 | 673 |
|
674 | 674 |
|
675 |
def _ReadAndVerifyCert(cert_filename, verify_private_key=False): |
|
676 |
"""Reads and verifies an X509 certificate. |
|
677 |
|
|
678 |
@type cert_filename: string |
|
679 |
@param cert_filename: the path of the file containing the certificate to |
|
680 |
verify encoded in PEM format |
|
681 |
@type verify_private_key: bool |
|
682 |
@param verify_private_key: whether to verify the private key in addition to |
|
683 |
the public certificate |
|
684 |
@rtype: string |
|
685 |
@return: a string containing the PEM-encoded certificate. |
|
686 |
|
|
687 |
""" |
|
688 |
try: |
|
689 |
pem = utils.ReadFile(cert_filename) |
|
690 |
except IOError, err: |
|
691 |
raise errors.X509CertError(cert_filename, |
|
692 |
"Unable to read certificate: %s" % str(err)) |
|
693 |
|
|
694 |
try: |
|
695 |
OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem) |
|
696 |
except Exception, err: |
|
697 |
raise errors.X509CertError(cert_filename, |
|
698 |
"Unable to load certificate: %s" % str(err)) |
|
699 |
|
|
700 |
if verify_private_key: |
|
701 |
try: |
|
702 |
OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, pem) |
|
703 |
except Exception, err: |
|
704 |
raise errors.X509CertError(cert_filename, |
|
705 |
"Unable to load private key: %s" % str(err)) |
|
706 |
|
|
707 |
return pem |
|
708 |
|
|
709 |
|
|
710 |
def _RenewCrypto(new_cluster_cert, new_rapi_cert, #pylint: disable=R0911 |
|
711 |
rapi_cert_filename, new_spice_cert, spice_cert_filename, |
|
712 |
spice_cacert_filename, new_confd_hmac_key, new_cds, |
|
713 |
cds_filename, force): |
|
675 |
def _RenewCrypto(new_cluster_cert, new_rapi_cert, rapi_cert_filename, |
|
676 |
new_confd_hmac_key, new_cds, cds_filename, |
|
677 |
force): |
|
714 | 678 |
"""Renews cluster certificates, keys and secrets. |
715 | 679 |
|
716 | 680 |
@type new_cluster_cert: bool |
... | ... | |
719 | 683 |
@param new_rapi_cert: Whether to generate a new RAPI certificate |
720 | 684 |
@type rapi_cert_filename: string |
721 | 685 |
@param rapi_cert_filename: Path to file containing new RAPI certificate |
722 |
@type new_spice_cert: bool |
|
723 |
@param new_spice_cert: Whether to generate a new SPICE certificate |
|
724 |
@type spice_cert_filename: string |
|
725 |
@param spice_cert_filename: Path to file containing new SPICE certificate |
|
726 |
@type spice_cacert_filename: string |
|
727 |
@param spice_cacert_filename: Path to file containing the certificate of the |
|
728 |
CA that signed the SPICE certificate |
|
729 | 686 |
@type new_confd_hmac_key: bool |
730 | 687 |
@param new_confd_hmac_key: Whether to generate a new HMAC key |
731 | 688 |
@type new_cds: bool |
... | ... | |
747 | 704 |
" the same time.") |
748 | 705 |
return 1 |
749 | 706 |
|
750 |
if new_spice_cert and (spice_cert_filename or spice_cacert_filename):
|
|
751 |
ToStderr("When using --new-spice-certificate, the --spice-certificate"
|
|
752 |
" and --spice-ca-certificate must not be used.")
|
|
753 |
return 1
|
|
707 |
if rapi_cert_filename:
|
|
708 |
# Read and verify new certificate
|
|
709 |
try:
|
|
710 |
rapi_cert_pem = utils.ReadFile(rapi_cert_filename)
|
|
754 | 711 |
|
755 |
if bool(spice_cacert_filename) ^ bool(spice_cert_filename): |
|
756 |
ToStderr("Both --spice-certificate and --spice-ca-certificate must be" |
|
757 |
" specified.") |
|
758 |
return 1 |
|
712 |
OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, |
|
713 |
rapi_cert_pem) |
|
714 |
except Exception, err: # pylint: disable=W0703 |
|
715 |
ToStderr("Can't load new RAPI certificate from %s: %s" % |
|
716 |
(rapi_cert_filename, str(err))) |
|
717 |
return 1 |
|
759 | 718 |
|
760 |
rapi_cert_pem, spice_cert_pem, spice_cacert_pem = (None, None, None) |
|
761 |
try: |
|
762 |
if rapi_cert_filename: |
|
763 |
rapi_cert_pem = _ReadAndVerifyCert(rapi_cert_filename, True) |
|
764 |
if spice_cert_filename: |
|
765 |
spice_cert_pem = _ReadAndVerifyCert(spice_cert_filename, True) |
|
766 |
spice_cacert_pem = _ReadAndVerifyCert(spice_cacert_filename) |
|
767 |
except errors.X509CertError, err: |
|
768 |
ToStderr("Unable to load X509 certificate from %s: %s", err[0], err[1]) |
|
769 |
return 1 |
|
719 |
try: |
|
720 |
OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, rapi_cert_pem) |
|
721 |
except Exception, err: # pylint: disable=W0703 |
|
722 |
ToStderr("Can't load new RAPI private key from %s: %s" % |
|
723 |
(rapi_cert_filename, str(err))) |
|
724 |
return 1 |
|
725 |
|
|
726 |
else: |
|
727 |
rapi_cert_pem = None |
|
770 | 728 |
|
771 | 729 |
if cds_filename: |
772 | 730 |
try: |
... | ... | |
786 | 744 |
|
787 | 745 |
def _RenewCryptoInner(ctx): |
788 | 746 |
ctx.feedback_fn("Updating certificates and keys") |
789 |
bootstrap.GenerateClusterCrypto(new_cluster_cert, |
|
790 |
new_rapi_cert, |
|
791 |
new_spice_cert, |
|
747 |
bootstrap.GenerateClusterCrypto(new_cluster_cert, new_rapi_cert, |
|
792 | 748 |
new_confd_hmac_key, |
793 | 749 |
new_cds, |
794 | 750 |
rapi_cert_pem=rapi_cert_pem, |
795 |
spice_cert_pem=spice_cert_pem, |
|
796 |
spice_cacert_pem=spice_cacert_pem, |
|
797 | 751 |
cds=cds) |
798 | 752 |
|
799 | 753 |
files_to_copy = [] |
... | ... | |
804 | 758 |
if new_rapi_cert or rapi_cert_pem: |
805 | 759 |
files_to_copy.append(constants.RAPI_CERT_FILE) |
806 | 760 |
|
807 |
if new_spice_cert or spice_cert_pem: |
|
808 |
files_to_copy.append(constants.SPICE_CERT_FILE) |
|
809 |
files_to_copy.append(constants.SPICE_CACERT_FILE) |
|
810 |
|
|
811 | 761 |
if new_confd_hmac_key: |
812 | 762 |
files_to_copy.append(constants.CONFD_HMAC_KEY) |
813 | 763 |
|
... | ... | |
836 | 786 |
return _RenewCrypto(opts.new_cluster_cert, |
837 | 787 |
opts.new_rapi_cert, |
838 | 788 |
opts.rapi_cert, |
839 |
opts.new_spice_cert, |
|
840 |
opts.spice_cert, |
|
841 |
opts.spice_cacert, |
|
842 | 789 |
opts.new_confd_hmac_key, |
843 | 790 |
opts.new_cluster_domain_secret, |
844 | 791 |
opts.cluster_domain_secret, |
... | ... | |
1427 | 1374 |
RenewCrypto, ARGS_NONE, |
1428 | 1375 |
[NEW_CLUSTER_CERT_OPT, NEW_RAPI_CERT_OPT, RAPI_CERT_OPT, |
1429 | 1376 |
NEW_CONFD_HMAC_KEY_OPT, FORCE_OPT, |
1430 |
NEW_CLUSTER_DOMAIN_SECRET_OPT, CLUSTER_DOMAIN_SECRET_OPT, |
|
1431 |
NEW_SPICE_CERT_OPT, SPICE_CERT_OPT, SPICE_CACERT_OPT], |
|
1377 |
NEW_CLUSTER_DOMAIN_SECRET_OPT, CLUSTER_DOMAIN_SECRET_OPT], |
|
1432 | 1378 |
"[opts...]", |
1433 | 1379 |
"Renews cluster certificates, keys and secrets"), |
1434 | 1380 |
"epo": ( |
b/lib/errors.py | ||
---|---|---|
277 | 277 |
""" |
278 | 278 |
|
279 | 279 |
|
280 |
class X509CertError(GenericError): |
|
281 |
"""Invalid X509 certificate. |
|
282 |
|
|
283 |
This error has two arguments: the certificate filename and the error cause. |
|
284 |
|
|
285 |
""" |
|
286 |
|
|
287 |
|
|
288 | 280 |
class TagError(GenericError): |
289 | 281 |
"""Generic tag error. |
290 | 282 |
|
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
794 | 794 |
"""Generate KVM information to start an instance. |
795 | 795 |
|
796 | 796 |
""" |
797 |
# pylint: disable=R0914,R0915
|
|
797 |
# pylint: disable=R0914 |
|
798 | 798 |
_, v_major, v_min, _ = self._GetKVMVersion() |
799 | 799 |
|
800 | 800 |
pidfile = self._InstancePidFile(instance.name) |
b/lib/utils/x509.py | ||
---|---|---|
259 | 259 |
@param common_name: commonName value |
260 | 260 |
@type validity: int |
261 | 261 |
@param validity: Validity for certificate in seconds |
262 |
@return: a tuple of strings containing the PEM-encoded private key and |
|
263 |
certificate |
|
264 | 262 |
|
265 | 263 |
""" |
266 | 264 |
# Create private and public key |
... | ... | |
294 | 292 |
@param common_name: commonName value |
295 | 293 |
@type validity: int |
296 | 294 |
@param validity: validity of certificate in number of days |
297 |
@return: a tuple of strings containing the PEM-encoded private key and |
|
298 |
certificate |
|
299 | 295 |
|
300 | 296 |
""" |
301 | 297 |
# TODO: Investigate using the cluster name instead of X505_CERT_CN for |
... | ... | |
305 | 301 |
validity * 24 * 60 * 60) |
306 | 302 |
|
307 | 303 |
utils_io.WriteFile(filename, mode=0400, data=key_pem + cert_pem) |
308 |
return (key_pem, cert_pem) |
b/tools/cfgupgrade | ||
---|---|---|
122 | 122 |
options.SERVER_PEM_PATH = options.data_dir + "/server.pem" |
123 | 123 |
options.KNOWN_HOSTS_PATH = options.data_dir + "/known_hosts" |
124 | 124 |
options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem" |
125 |
options.SPICE_CERT_FILE = options.data_dir + "/spice.pem" |
|
126 |
options.SPICE_CACERT_FILE = options.data_dir + "/spice-ca.pem" |
|
127 | 125 |
options.RAPI_USERS_FILE = options.data_dir + "/rapi/users" |
128 | 126 |
options.RAPI_USERS_FILE_PRE24 = options.data_dir + "/rapi_users" |
129 | 127 |
options.CONFD_HMAC_KEY = options.data_dir + "/hmac.key" |
... | ... | |
224 | 222 |
backup=True) |
225 | 223 |
|
226 | 224 |
if not options.dry_run: |
227 |
bootstrap.GenerateClusterCrypto(False, False, False, False, False, |
|
228 |
nodecert_file=options.SERVER_PEM_PATH, |
|
229 |
rapicert_file=options.RAPI_CERT_FILE, |
|
230 |
spicecert_file=options.SPICE_CERT_FILE, |
|
231 |
spicecacert_file=options.SPICE_CACERT_FILE, |
|
232 |
hmackey_file=options.CONFD_HMAC_KEY, |
|
233 |
cds_file=options.CDS_FILE) |
|
225 |
bootstrap.GenerateClusterCrypto(False, False, False, False, |
|
226 |
nodecert_file=options.SERVER_PEM_PATH, |
|
227 |
rapicert_file=options.RAPI_CERT_FILE, |
|
228 |
hmackey_file=options.CONFD_HMAC_KEY, |
|
229 |
cds_file=options.CDS_FILE) |
|
234 | 230 |
|
235 | 231 |
except Exception: |
236 | 232 |
logging.critical("Writing configuration failed. It is probably in an" |
Also available in: Unified diff