def create_encryption_at_rest_file(self, extra_vars, ssh_options): node_ip = ssh_options["ssh_host"] encryption_key_path = extra_vars["encryption_key_file"] # Source file path key_node_dir = extra_vars["encryption_key_dir"] # Target file path with open(encryption_key_path, "r") as f: encryption_key = f.read() key_file = os.path.basename(encryption_key_path) common_path = os.path.join(self.CERTS_TEMP_DIR, node_ip) try: os.makedirs(common_path) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise YBOpsRuntimeError(common_path + " could not be be created") # Write encryption-at-rest key to file with open(os.path.join(common_path, key_file), 'wb') as key_out: key_out.write(encryption_key) # Copy files over to node remote_shell = RemoteShell(ssh_options) remote_shell.run_command('mkdir -p ' + key_node_dir) remote_shell.put_file(os.path.join(common_path, key_file), os.path.join(key_node_dir, key_file)) try: shutil.rmtree(common_path) except OSError as e: raise YBOpsRuntimeError("Error: %s - %s." % (e.filename, e.strerror))
def create_encryption_at_rest_file(self, extra_vars, ssh_options): encryption_key_path = extra_vars["encryption_key_file"] # Source file path key_node_dir = extra_vars["encryption_key_dir"] # Target file path with open(encryption_key_path, "r") as f: encryption_key = f.read() key_file = os.path.basename(encryption_key_path) with tempfile.TemporaryDirectory() as common_path: # Write encryption-at-rest key to file with open(os.path.join(common_path, key_file), 'wb') as key_out: key_out.write(encryption_key) # Copy files over to node remote_shell = RemoteShell(ssh_options) remote_shell.run_command('mkdir -p ' + key_node_dir) remote_shell.put_file(os.path.join(common_path, key_file), os.path.join(key_node_dir, key_file))
def append_new_root_cert(self, ssh_options, root_cert_path, certs_location, certs_dir): remote_shell = RemoteShell(ssh_options) yb_root_cert_path = os.path.join(certs_dir, self.ROOT_CERT_NAME) yb_root_cert_new_path = os.path.join(certs_dir, self.ROOT_CERT_NEW_NAME) # Give write permissions to cert directory remote_shell.run_command('chmod -f 666 {}/* || true'.format(certs_dir)) # Copy the new root cert to ca_new.crt if certs_location == self.CERT_LOCATION_NODE: remote_shell.run_command("cp '{}' '{}'".format(root_cert_path, yb_root_cert_new_path)) if certs_location == self.CERT_LOCATION_PLATFORM: remote_shell.put_file(root_cert_path, yb_root_cert_new_path) # Append new cert content to ca.crt remote_shell.run_command( "cat '{}' >> '{}'".format(yb_root_cert_new_path, yb_root_cert_path)) # Reset the write permissions remote_shell.run_command('chmod 400 {}/*'.format(certs_dir))
def copy_client_certs(self, ssh_options, root_cert_path, client_cert_path, client_key_path, certs_location): remote_shell = RemoteShell(ssh_options) yb_root_cert_path = os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_ROOT_NAME) yb_client_cert_path = os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_CERT_NAME) yb_client_key_path = os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_KEY_NAME) logging.info("Moving client certs located at {}, {}, {}.".format( root_cert_path, client_cert_path, client_key_path)) remote_shell.run_command('mkdir -p ' + self.YSQLSH_CERT_DIR) # Give write permissions. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format( self.YSQLSH_CERT_DIR)) if certs_location == self.CERT_LOCATION_NODE: remote_shell.run_command("cp '{}' '{}'".format( root_cert_path, yb_root_cert_path)) remote_shell.run_command("cp '{}' '{}'".format( client_cert_path, yb_client_cert_path)) remote_shell.run_command("cp '{}' '{}'".format( client_key_path, yb_client_key_path)) if certs_location == self.CERT_LOCATION_PLATFORM: remote_shell.put_file(root_cert_path, yb_root_cert_path) remote_shell.put_file(client_cert_path, yb_client_cert_path) remote_shell.put_file(client_key_path, yb_client_key_path) # Reset the write permission as a sanity check. remote_shell.run_command('chmod 400 {}/*'.format(self.YSQLSH_CERT_DIR))
def copy_server_certs(self, ssh_options, root_cert_path, server_cert_path, server_key_path, certs_location, certs_dir): remote_shell = RemoteShell(ssh_options) node_ip = ssh_options["ssh_host"] logging.info("Moving server certs located at {}, {}, {}.".format( root_cert_path, server_cert_path, server_key_path)) cert_file = 'node.{}.crt'.format(node_ip) key_file = 'node.{}.key'.format(node_ip) remote_shell.run_command('mkdir -p ' + certs_dir) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format(certs_dir)) if certs_location == self.CERT_LOCATION_NODE: self.verify_certs(root_cert_path, server_cert_path, ssh_options, verify_hostname=True) remote_shell.run_command('cp {} {}'.format( root_cert_path, os.path.join(certs_dir, self.ROOT_CERT_NAME))) remote_shell.run_command('cp {} {}'.format( server_cert_path, os.path.join(certs_dir, cert_file))) remote_shell.run_command('cp {} {}'.format( server_key_path, os.path.join(certs_dir, key_file))) if certs_location == self.CERT_LOCATION_PLATFORM: remote_shell.put_file(root_cert_path, os.path.join(certs_dir, self.ROOT_CERT_NAME)) remote_shell.put_file(server_cert_path, os.path.join(certs_dir, cert_file)) remote_shell.put_file(server_key_path, os.path.join(certs_dir, key_file)) # Reset the write permission as a sanity check. remote_shell.run_command('chmod 400 {}/*'.format(certs_dir))
def copy_xcluster_root_cert(self, ssh_options, root_cert_path, replication_config_name, producer_certs_dir): if producer_certs_dir is None: producer_certs_dir = self.PRODUCER_CERTS_DIR_NAME remote_shell = RemoteShell(ssh_options) node_ip = ssh_options["ssh_host"] src_root_cert_dir_path = os.path.join(producer_certs_dir, replication_config_name) src_root_cert_path = os.path.join(src_root_cert_dir_path, self.ROOT_CERT_NAME) logging.info("Moving server cert located at {} to {}:{}.".format( root_cert_path, node_ip, src_root_cert_dir_path)) remote_shell.run_command('mkdir -p ' + src_root_cert_dir_path) # Give write permissions. If the command fails, ignore. remote_shell.run_command( 'chmod -f 666 {}/* || true'.format(src_root_cert_dir_path)) remote_shell.put_file(root_cert_path, src_root_cert_path) # Reset the write permission as a sanity check. remote_shell.run_command( 'chmod 400 {}/*'.format(src_root_cert_dir_path))
def generate_client_cert(self, extra_vars, ssh_options): remote_shell = RemoteShell(ssh_options) if "rootCA_cert" in extra_vars: root_cert_path = extra_vars["rootCA_cert"] root_key_path = extra_vars["rootCA_key"] certs_node_dir = extra_vars["certs_node_dir"] self.__generate_client_cert(extra_vars, ssh_options, root_cert_path, root_key_path, certs_node_dir, remote_shell) if "clientRootCA_cert" in extra_vars: root_cert_path = extra_vars["clientRootCA_cert"] root_key_path = extra_vars["clientRootCA_key"] certs_client_dir = extra_vars["certs_client_dir"] self.__generate_client_cert(extra_vars, ssh_options, root_cert_path, root_key_path, certs_client_dir, remote_shell) if "client_cert" in extra_vars: if "rootCA_cert" in extra_vars: root_cert_path = extra_vars["rootCA_cert"] else: root_cert_path = extra_vars["clientRootCA_cert"] client_cert_path = extra_vars["client_cert"] client_key_path = extra_vars["client_key"] remote_shell.run_command('mkdir -p ' + self.YSQLSH_CERT_DIR) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format( self.YSQLSH_CERT_DIR)) remote_shell.put_file( root_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_ROOT_NAME)) remote_shell.put_file( client_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_CERT_NAME)) remote_shell.put_file( client_key_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_KEY_NAME)) remote_shell.run_command('chmod 400 {}/*'.format( self.YSQLSH_CERT_DIR))
def copy_server_certs(self, extra_vars, ssh_options): remote_shell = RemoteShell(ssh_options) root_cert_path = extra_vars["server_root_cert"] node_cert_path = extra_vars["server_node_cert"] node_key_path = extra_vars["server_node_key"] certs_dir = extra_vars["certs_client_dir"] node_ip = ssh_options["ssh_host"] logging.info("Copying server certs located at {}, {}, {}.".format( root_cert_path, node_cert_path, node_key_path)) key_file = 'node.{}.key'.format(node_ip) cert_file = 'node.{}.crt'.format(node_ip) remote_shell.run_command('mkdir -p ' + certs_dir) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format(certs_dir)) remote_shell.put_file(root_cert_path, os.path.join(certs_dir, self.ROOT_CERT_NAME)) remote_shell.put_file(node_cert_path, os.path.join(certs_dir, cert_file)) remote_shell.put_file(node_key_path, os.path.join(certs_dir, key_file)) remote_shell.run_command('chmod 400 {}/*'.format(certs_dir))
def copy_client_certs(self, ssh_options, root_cert_path, client_cert_path, client_key_path, certs_location): remote_shell = RemoteShell(ssh_options) node_ip = ssh_options["ssh_host"] logging.info("Moving client certs located at {}, {}, {}.".format( root_cert_path, client_cert_path, client_key_path)) cert_file = 'node.{}.crt'.format(node_ip) key_file = 'node.{}.key'.format(node_ip) remote_shell.run_command('mkdir -p ' + self.YSQLSH_CERT_DIR) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format( self.YSQLSH_CERT_DIR)) if certs_location == self.CERT_LOCATION_NODE: remote_shell.run_command('cp {} {}'.format( root_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.ROOT_CERT_NAME))) remote_shell.run_command('cp {} {}'.format( client_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_CERT_NAME))) remote_shell.run_command('cp {} {}'.format( client_key_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_KEY_NAME))) if certs_location == self.CERT_LOCATION_PLATFORM: remote_shell.put_file( root_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_ROOT_NAME)) remote_shell.put_file( client_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_CERT_NAME)) remote_shell.put_file( client_key_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_KEY_NAME)) remote_shell.run_command('chmod 400 {}/*'.format(self.YSQLSH_CERT_DIR))
def generate_client_cert(self, extra_vars, ssh_options): node_ip = ssh_options["ssh_host"] root_cert_path = extra_vars["rootCA_cert"] root_key_path = extra_vars["rootCA_key"] certs_node_dir = extra_vars["certs_node_dir"] with open(root_cert_path, 'r') as cert_in: certlines = cert_in.read() root_cert = x509.load_pem_x509_certificate(certlines, default_backend()) with open(root_key_path, 'r') as key_in: keylines = key_in.read() root_key = load_pem_private_key(keylines, None, default_backend()) private_key = rsa.generate_private_key( public_exponent=self.PUBLIC_EXPONENT, key_size=self.KEY_SIZE, backend=default_backend() ) public_key = private_key.public_key() builder = x509.CertificateBuilder() builder = builder.subject_name(x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, six.text_type(node_ip)), x509.NameAttribute(NameOID.ORGANIZATION_NAME, six.text_type(extra_vars["org_name"])) ])) builder = builder.issuer_name(root_cert.subject) builder = builder.not_valid_before(datetime.datetime.utcnow()) builder = builder.not_valid_after(datetime.datetime.utcnow() + datetime.timedelta( extra_vars["cert_valid_duration"])) builder = builder.serial_number(x509.random_serial_number()) builder = builder.public_key(public_key) builder = builder.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True) certificate = builder.sign(private_key=root_key, algorithm=hashes.SHA256(), backend=default_backend()) # Write private key to file pem = private_key.private_bytes( encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption() ) key_file = 'node.{}.key'.format(node_ip) cert_file = 'node.{}.crt'.format(node_ip) common_path = '{}/{}'.format(self.CERTS_TEMP_DIR, node_ip) try: os.makedirs(common_path) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise YBOpsRuntimeError(common_path + " could not be be created") with open(os.path.join(common_path, key_file), 'wb') as pem_out: pem_out.write(pem) # Write certificate to file pem = certificate.public_bytes(encoding=Encoding.PEM) with open(os.path.join(common_path, cert_file), 'wb') as pem_out: pem_out.write(pem) # Copy files over to node remote_shell = RemoteShell(ssh_options) remote_shell.run_command('mkdir -p ' + certs_node_dir) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format(certs_node_dir)) remote_shell.put_file(os.path.join(common_path, key_file), os.path.join(certs_node_dir, key_file)) remote_shell.put_file(os.path.join(common_path, cert_file), os.path.join(certs_node_dir, cert_file)) remote_shell.put_file(root_cert_path, os.path.join(certs_node_dir, self.ROOT_CERT_NAME)) remote_shell.run_command('chmod 400 {}/*'.format(certs_node_dir)) if "client_cert" in extra_vars: client_cert_path = extra_vars["client_cert"] client_key_path = extra_vars["client_key"] remote_shell.run_command('mkdir -p ' + self.YSQLSH_CERT_DIR) # Give write permission in case file exists. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format(self.YSQLSH_CERT_DIR)) remote_shell.put_file(root_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_ROOT_NAME)) remote_shell.put_file(client_cert_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_CERT_NAME)) remote_shell.put_file(client_key_path, os.path.join(self.YSQLSH_CERT_DIR, self.CLIENT_KEY_NAME)) remote_shell.run_command('chmod 400 {}/*'.format(self.YSQLSH_CERT_DIR)) try: shutil.rmtree(common_path) except OSError as e: raise YBOpsRuntimeError("Error: %s - %s." % (e.filename, e.strerror))
def copy_server_certs(self, ssh_options, root_cert_path, server_cert_path, server_key_path, certs_location, certs_dir, rotate_certs, skip_cert_validation): remote_shell = RemoteShell(ssh_options) node_ip = ssh_options["ssh_host"] cert_file = 'node.{}.crt'.format(node_ip) key_file = 'node.{}.key'.format(node_ip) yb_root_cert_path = os.path.join(certs_dir, self.ROOT_CERT_NAME) yb_server_cert_path = os.path.join(certs_dir, cert_file) yb_server_key_path = os.path.join(certs_dir, key_file) copy_root = True if rotate_certs: root_cert_command = remote_shell.run_command_raw( "cat '{}'".format(yb_root_cert_path)) # In case of tls toggle root cert might not be present if not root_cert_command.exited: root_cert = root_cert_command.stdout root_cert_new = None if certs_location == self.CERT_LOCATION_NODE: root_cert_new = remote_shell.run_command( "cat '{}'".format(root_cert_path)).stdout if certs_location == self.CERT_LOCATION_PLATFORM: with open(root_cert_path) as file: root_cert_new = file.read() if root_cert is not None and root_cert_new is not None: compare_result = self.compare_certs( root_cert_new, root_cert) if compare_result == 0 or compare_result == 1: # Don't copy root certs if the new root cert is # same or subset of the existing root cert copy_root = False else: raise YBOpsRuntimeError( "Unable to fetch the certificate {}".format( root_cert_path)) logging.info("Moving server certs located at {}, {}, {}.".format( root_cert_path, server_cert_path, server_key_path)) remote_shell.run_command('mkdir -p ' + certs_dir) # Give write permissions. If the command fails, ignore. remote_shell.run_command('chmod -f 666 {}/* || true'.format(certs_dir)) if certs_location == self.CERT_LOCATION_NODE: if skip_cert_validation == 'ALL': logging.info( "Skipping all validations for certs for node {}".format( node_ip)) else: verify_hostname = True if skip_cert_validation == 'HOSTNAME': logging.info( "Skipping host name validation for certs for node {}". format(node_ip)) verify_hostname = False self.verify_certs(root_cert_path, server_cert_path, ssh_options, verify_hostname) if copy_root: remote_shell.run_command("cp '{}' '{}'".format( root_cert_path, yb_root_cert_path)) remote_shell.run_command("cp '{}' '{}'".format( server_cert_path, yb_server_cert_path)) remote_shell.run_command("cp '{}' '{}'".format( server_key_path, yb_server_key_path)) if certs_location == self.CERT_LOCATION_PLATFORM: if copy_root: remote_shell.put_file(root_cert_path, yb_root_cert_path) remote_shell.put_file(server_cert_path, yb_server_cert_path) remote_shell.put_file(server_key_path, yb_server_key_path) # Reset the write permission as a sanity check. remote_shell.run_command('chmod 400 {}/*'.format(certs_dir))