ospluginutils.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # Licensed under the Apache License, Version 2.0 (the "License");
  2. # you may not use this file except in compliance with the License.
  3. # You may obtain a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS,
  9. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  10. # implied.
  11. # See the License for the specific language governing permissions and
  12. # limitations under the License.
  13. import os
  14. import yaml
  15. from OpenSSL import crypto
  16. from time import time
  17. from packstack.installer import basedefs
  18. from packstack.installer import utils
  19. from packstack.installer.setup_controller import Controller
  20. controller = Controller()
  21. PUPPET_DIR = os.path.join(basedefs.DIR_PROJECT_DIR, "puppet")
  22. PUPPET_TEMPLATE_DIR = os.path.join(PUPPET_DIR, "templates")
  23. HIERA_COMMON_YAML = os.path.join(basedefs.HIERADATA_DIR, "common.yaml")
  24. # For compatibility with hiera < 3.0
  25. HIERA_DEFAULTS_YAML = os.path.join(basedefs.HIERADATA_DIR, "defaults.yaml")
  26. class ManifestFiles(object):
  27. def __init__(self):
  28. self.filelist = []
  29. self.data = {}
  30. # continuous manifest file that have the same marker can be
  31. # installed in parallel, if on different servers
  32. def addFile(self, filename, marker, data=''):
  33. self.data[filename] = self.data.get(filename, '') + '\n' + data
  34. for f, p in self.filelist:
  35. if f == filename:
  36. return
  37. self.filelist.append((filename, marker))
  38. def prependFile(self, filename, marker, data=''):
  39. self.data[filename] = data + '\n' + self.data.get(filename, '')
  40. for f, p in self.filelist:
  41. if f == filename:
  42. return
  43. self.filelist.append((filename, marker))
  44. def getFiles(self):
  45. return [f for f in self.filelist]
  46. def writeManifests(self):
  47. """
  48. Write out the manifest data to disk, this should only be called once
  49. write before the puppet manifests are copied to the various servers
  50. """
  51. os.mkdir(basedefs.PUPPET_MANIFEST_DIR, 0o700)
  52. for fname, data in self.data.items():
  53. path = os.path.join(basedefs.PUPPET_MANIFEST_DIR, fname)
  54. fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
  55. with os.fdopen(fd, 'w') as fp:
  56. fp.write(data)
  57. manifestfiles = ManifestFiles()
  58. def getManifestTemplate(template_name):
  59. if not template_name.endswith(".pp"):
  60. template_name += ".pp"
  61. with open(os.path.join(PUPPET_TEMPLATE_DIR, template_name)) as fp:
  62. return fp.read() % controller.CONF
  63. def appendManifestFile(manifest_name, data, marker=''):
  64. manifestfiles.addFile(manifest_name, marker, data)
  65. def generateHieraDataFile():
  66. os.mkdir(basedefs.HIERADATA_DIR, 0o700)
  67. with open(HIERA_COMMON_YAML, 'w') as outfile:
  68. outfile.write(yaml.dump(controller.CONF,
  69. explicit_start=True,
  70. default_flow_style=False))
  71. os.symlink(os.path.basename(HIERA_COMMON_YAML), HIERA_DEFAULTS_YAML)
  72. def generate_ssl_cert(config, host, service, ssl_key_file, ssl_cert_file):
  73. """
  74. Wrapper on top of openssl
  75. """
  76. # We have to check whether the certificate already exists
  77. cert_dir = os.path.join(config['CONFIG_SSL_CERT_DIR'], 'certs')
  78. local_cert_name = host + os.path.basename(ssl_cert_file)
  79. local_cert_path = os.path.join(cert_dir, local_cert_name)
  80. if not os.path.exists(local_cert_path):
  81. ca_file = open(config['CONFIG_SSL_CACERT_FILE'], 'rt').read()
  82. ca_key_file = open(config['CONFIG_SSL_CACERT_KEY_FILE'], 'rt').read()
  83. ca_key = crypto.load_privatekey(crypto.FILETYPE_PEM, ca_key_file)
  84. ca = crypto.load_certificate(crypto.FILETYPE_PEM, ca_file)
  85. k = crypto.PKey()
  86. k.generate_key(crypto.TYPE_RSA, 4096)
  87. mail = config['CONFIG_SSL_CERT_SUBJECT_MAIL']
  88. hostinfo = config['HOST_DETAILS'][host]
  89. fqdn = hostinfo['fqdn']
  90. cert = crypto.X509()
  91. subject = cert.get_subject()
  92. subject.C = config['CONFIG_SSL_CERT_SUBJECT_C']
  93. subject.ST = config['CONFIG_SSL_CERT_SUBJECT_ST']
  94. subject.L = config['CONFIG_SSL_CERT_SUBJECT_L']
  95. subject.O = config['CONFIG_SSL_CERT_SUBJECT_O']
  96. subject.OU = config['CONFIG_SSL_CERT_SUBJECT_OU']
  97. subject.CN = "%s/%s" % (service, fqdn)
  98. subject.emailAddress = mail
  99. cert.add_extensions([
  100. crypto.X509Extension(
  101. "keyUsage".encode('ascii'),
  102. False,
  103. "nonRepudiation,digitalSignature,keyEncipherment".encode('ascii')),
  104. crypto.X509Extension(
  105. "extendedKeyUsage".encode('ascii'),
  106. False,
  107. "clientAuth,serverAuth".encode('ascii')),
  108. ])
  109. cert.gmtime_adj_notBefore(0)
  110. cert.gmtime_adj_notAfter(315360000)
  111. cert.set_issuer(ca.get_subject())
  112. cert.set_pubkey(k)
  113. serial = int(time())
  114. cert.set_serial_number(serial)
  115. cert.sign(ca_key, 'sha1')
  116. final_cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
  117. final_key = crypto.dump_privatekey(crypto.FILETYPE_PEM, k)
  118. deliver_ssl_file(ca_file, config['CONFIG_SSL_CACERT'], host)
  119. deliver_ssl_file(final_cert, ssl_cert_file, host)
  120. deliver_ssl_file(final_key, ssl_key_file, host)
  121. with open(local_cert_path, 'w') as f:
  122. f.write(final_cert)
  123. def deliver_ssl_file(content, path, host):
  124. server = utils.ScriptRunner(host)
  125. server.append("grep -- '{content}' {path} || "
  126. "echo '{content}' > {path} ".format(
  127. content=content,
  128. path=path))
  129. server.execute()
  130. def gethostlist(CONF):
  131. hosts = []
  132. for key, value in CONF.items():
  133. if key.endswith("_HOST"):
  134. value = value.split('/')[0]
  135. if value and value not in hosts:
  136. hosts.append(value)
  137. if key.endswith("_HOSTS"):
  138. for host in value.split(","):
  139. host = host.strip()
  140. host = host.split('/')[0]
  141. if host and host not in hosts:
  142. hosts.append(host)
  143. return hosts