"Fossies" - the Fresh Open Source Software Archive

Member "magnum-8.1.0/magnum/conductor/handlers/common/cert_manager.py" (1 Oct 2019, 8650 Bytes) of package /linux/misc/openstack/magnum-8.1.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "cert_manager.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 7.1.0_vs_8.0.0.

    1 # Copyright 2015 NEC Corporation.  All rights reserved.
    2 #
    3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 # not use this file except in compliance with the License. You may obtain
    5 # a copy of the License at
    6 #
    7 #      http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 # License for the specific language governing permissions and limitations
   13 # under the License.
   14 
   15 from oslo_log import log as logging
   16 from oslo_utils import encodeutils
   17 import six
   18 
   19 from magnum.common import cert_manager
   20 from magnum.common import exception
   21 from magnum.common import short_id
   22 from magnum.common.x509 import operations as x509
   23 
   24 import magnum.conf
   25 import os
   26 import shutil
   27 import tempfile
   28 
   29 CONDUCTOR_CLIENT_NAME = six.u('Magnum-Conductor')
   30 
   31 LOG = logging.getLogger(__name__)
   32 CONF = magnum.conf.CONF
   33 
   34 
   35 def _generate_ca_cert(issuer_name, context=None):
   36     """Generate and store ca_cert
   37 
   38     :param issuer_name: CA subject name
   39     :returns: CA cert uuid and CA cert, CA private key password
   40     """
   41     ca_password = short_id.generate_id()
   42     ca_cert = x509.generate_ca_certificate(issuer_name,
   43                                            encryption_password=ca_password)
   44     ca_cert_ref = cert_manager.get_backend().CertManager.store_cert(
   45         certificate=ca_cert['certificate'],
   46         private_key=ca_cert['private_key'],
   47         private_key_passphrase=ca_password,
   48         name=issuer_name,
   49         context=context,
   50     )
   51     LOG.debug('CA cert is created: %s', ca_cert_ref)
   52     return ca_cert_ref, ca_cert, ca_password
   53 
   54 
   55 def _generate_client_cert(issuer_name, ca_cert, ca_password, context=None):
   56     """Generate and store magnum_client_cert
   57 
   58     :param issuer_name: CA subject name
   59     :param ca_cert: CA certificate
   60     :param ca_password: CA private key password
   61     :returns: Magnum client cert uuid
   62     """
   63     client_password = short_id.generate_id()
   64     # TODO(strigazi): set subject name and organization per driver
   65     # For RBAC kubernetes cluster we need the client to have:
   66     # subject_name: admin
   67     # organization_name system:masters
   68     # Non kubernetes drivers are not using the certificates fields
   69     # for authorization
   70     subject_name = 'admin'
   71     organization_name = 'system:masters'
   72     client_cert = x509.generate_client_certificate(
   73         issuer_name,
   74         subject_name,
   75         organization_name,
   76         ca_cert['private_key'],
   77         encryption_password=client_password,
   78         ca_key_password=ca_password,
   79     )
   80     magnum_cert_ref = cert_manager.get_backend().CertManager.store_cert(
   81         certificate=client_cert['certificate'],
   82         private_key=client_cert['private_key'],
   83         private_key_passphrase=client_password,
   84         name=CONDUCTOR_CLIENT_NAME,
   85         context=context
   86     )
   87     LOG.debug('Magnum client cert is created: %s', magnum_cert_ref)
   88     return magnum_cert_ref
   89 
   90 
   91 def _get_issuer_name(cluster):
   92     issuer_name = cluster.name
   93     # When user create a Cluster without name, the cluster.name is None.
   94     # We should use cluster.uuid as issuer name.
   95     if issuer_name is None:
   96         issuer_name = cluster.uuid
   97     return issuer_name
   98 
   99 
  100 def generate_certificates_to_cluster(cluster, context=None):
  101     """Generate ca_cert and magnum client cert and set to cluster
  102 
  103     :param cluster: The cluster to set CA cert and magnum client cert
  104     :returns: CA cert uuid and magnum client cert uuid
  105     """
  106     try:
  107         issuer_name = _get_issuer_name(cluster)
  108 
  109         LOG.debug('Start to generate certificates: %s', issuer_name)
  110 
  111         ca_cert_ref, ca_cert, ca_password = _generate_ca_cert(issuer_name,
  112                                                               context=context)
  113         magnum_cert_ref = _generate_client_cert(issuer_name,
  114                                                 ca_cert,
  115                                                 ca_password,
  116                                                 context=context)
  117 
  118         cluster.ca_cert_ref = ca_cert_ref
  119         cluster.magnum_cert_ref = magnum_cert_ref
  120     except Exception:
  121         LOG.exception('Failed to generate certificates for Cluster: %s',
  122                       cluster.uuid)
  123         raise exception.CertificatesToClusterFailed(cluster_uuid=cluster.uuid)
  124 
  125 
  126 def get_cluster_ca_certificate(cluster, context=None):
  127     ca_cert = cert_manager.get_backend().CertManager.get_cert(
  128         cluster.ca_cert_ref,
  129         resource_ref=cluster.uuid,
  130         context=context
  131     )
  132 
  133     return ca_cert
  134 
  135 
  136 def get_cluster_magnum_cert(cluster, context=None):
  137     magnum_cert = cert_manager.get_backend().CertManager.get_cert(
  138         cluster.magnum_cert_ref,
  139         resource_ref=cluster.uuid,
  140         context=context
  141     )
  142 
  143     return magnum_cert
  144 
  145 
  146 def create_client_files(cluster, context=None):
  147     if not os.path.isdir(CONF.cluster.temp_cache_dir):
  148         LOG.debug("Certificates will not be cached in the filesystem: they "
  149                   "will be created as tempfiles.")
  150         ca_cert = get_cluster_ca_certificate(cluster, context)
  151         magnum_cert = get_cluster_magnum_cert(cluster, context)
  152 
  153         ca_file = tempfile.NamedTemporaryFile(mode="w+")
  154         ca_file.write(encodeutils.safe_decode(ca_cert.get_certificate()))
  155         ca_file.flush()
  156 
  157         key_file = tempfile.NamedTemporaryFile(mode="w+")
  158         key_file.write(encodeutils.safe_decode(
  159             magnum_cert.get_decrypted_private_key()))
  160         key_file.flush()
  161 
  162         cert_file = tempfile.NamedTemporaryFile(mode="w+")
  163         cert_file.write(encodeutils.safe_decode(magnum_cert.get_certificate()))
  164         cert_file.flush()
  165 
  166     else:
  167         cached_cert_dir = os.path.join(CONF.cluster.temp_cache_dir,
  168                                        cluster.uuid)
  169         cached_ca_file = os.path.join(cached_cert_dir, 'ca.crt')
  170         cached_key_file = os.path.join(cached_cert_dir, 'client.key')
  171         cached_cert_file = os.path.join(cached_cert_dir, 'client.crt')
  172 
  173         if not os.path.isdir(cached_cert_dir):
  174             os.mkdir(cached_cert_dir)
  175 
  176             ca_cert = get_cluster_ca_certificate(cluster, context)
  177             magnum_cert = get_cluster_magnum_cert(cluster, context)
  178 
  179             ca_file = open(cached_ca_file, "w+")
  180             ca_file.write(encodeutils.safe_decode(ca_cert.get_certificate()))
  181             ca_file.flush()
  182 
  183             key_file = open(cached_key_file, "w+")
  184             key_file.write(encodeutils.safe_decode(
  185                 magnum_cert.get_decrypted_private_key()))
  186             key_file.flush()
  187 
  188             cert_file = open(cached_cert_file, "w+")
  189             cert_file.write(
  190                 encodeutils.safe_decode(magnum_cert.get_certificate()))
  191             cert_file.flush()
  192 
  193             os.chmod(cached_ca_file, 0o600)
  194             os.chmod(cached_key_file, 0o600)
  195             os.chmod(cached_cert_file, 0o600)
  196 
  197         else:
  198             ca_file = open(cached_ca_file, "r")
  199             key_file = open(cached_key_file, "r")
  200             cert_file = open(cached_cert_file, "r")
  201 
  202     return ca_file, key_file, cert_file
  203 
  204 
  205 def sign_node_certificate(cluster, csr, context=None):
  206     ca_cert = cert_manager.get_backend().CertManager.get_cert(
  207         cluster.ca_cert_ref,
  208         resource_ref=cluster.uuid,
  209         context=context
  210     )
  211 
  212     node_cert = x509.sign(csr,
  213                           _get_issuer_name(cluster),
  214                           ca_cert.get_private_key(),
  215                           ca_cert.get_private_key_passphrase())
  216     return node_cert
  217 
  218 
  219 def delete_certificates_from_cluster(cluster, context=None):
  220     """Delete ca cert and magnum client cert from cluster
  221 
  222     :param cluster: The cluster which has certs
  223     """
  224     for cert_ref in ['ca_cert_ref', 'magnum_cert_ref']:
  225         try:
  226             cert_ref = getattr(cluster, cert_ref, None)
  227             if cert_ref:
  228                 cert_manager.get_backend().CertManager.delete_cert(
  229                     cert_ref, resource_ref=cluster.uuid, context=context)
  230         except Exception:
  231             LOG.warning("Deleting certs is failed for Cluster %s",
  232                         cluster.uuid)
  233 
  234 
  235 def delete_client_files(cluster, context=None):
  236         cached_cert_dir = os.path.join(CONF.cluster.temp_cache_dir,
  237                                        cluster.uuid)
  238         try:
  239             if os.path.isdir(cached_cert_dir):
  240                 shutil.rmtree(cached_cert_dir)
  241         except Exception:
  242             LOG.warning("Deleting client files failed for Cluster %s",
  243                         cluster.uuid)