Beispiel #1
0
    def run_control_script(self, process, command, args, extra_vars,
                           host_info):
        updated_vars = {"process": process, "command": command}
        updated_vars.update(extra_vars)
        updated_vars.update(get_ssh_host_port(host_info, args.custom_ssh_port))
        remote_shell = RemoteShell(updated_vars)

        if process == "thirdparty" or process == "platform-services":
            self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars,
                                         host_info)
            return

        if args.systemd_services:
            if command == "start":
                remote_shell.run_command(
                    "sudo systemctl enable yb-{}".format(process))
            remote_shell.run_command("sudo systemctl {} yb-{}".format(
                command, process))
            if command == "stop":
                remote_shell.run_command(
                    "sudo systemctl disable yb-{}".format(process))
            return

        if os.environ.get("YB_USE_FABRIC", False):
            file_path = os.path.join(YB_HOME_DIR, "bin/yb-server-ctl.sh")
            remote_shell.run_command("{} {} {}".format(file_path, process,
                                                       command))
        else:
            self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars,
                                         host_info)
Beispiel #2
0
 def expand_file_system(self, args, ssh_options):
     remote_shell = RemoteShell(ssh_options)
     mount_points = self.get_mount_points_csv(args).split(',')
     for mount_point in mount_points:
         logging.info("Expanding file system with mount point: {}".format(
             mount_point))
         remote_shell.run_command('sudo xfs_growfs {}'.format(mount_point))
Beispiel #3
0
 def initYSQL(self, master_addresses, ssh_options):
     remote_shell = RemoteShell(ssh_options)
     init_db_path = os.path.join(YB_HOME_DIR, "tserver/postgres/bin/initdb")
     remote_shell.run_command(
         "bash -c \"YB_ENABLED_IN_POSTGRES=1 FLAGS_pggate_master_addresses={} "
         "{} -D /tmp/yb_pg_initdb_tmp_data_dir "
         "-U postgres\"".format(master_addresses, init_db_path))
Beispiel #4
0
def get_mount_roots(ssh_options, paths):
    remote_shell = RemoteShell(ssh_options)
    remote_cmd = 'df --output=target {}'.format(" ".join(paths.split(",")))
    # Example output of the df cmd
    # $ df --output=target /bar/foo/rnd /storage/abc
    # Mounted on
    # /bar
    # /storage

    mount_roots = remote_shell.run_command(remote_cmd).stdout.split('\n')[1:]
    return ",".join([mroot.strip() for mroot in mount_roots if mroot.strip()])
Beispiel #5
0
 def run_control_script(self, process, command, args, extra_vars,
                        host_info):
     updated_vars = {"process": process, "command": command}
     updated_vars.update(extra_vars)
     updated_vars.update(get_ssh_host_port(host_info, args.custom_ssh_port))
     if os.environ.get("YB_USE_FABRIC", False):
         remote_shell = RemoteShell(updated_vars)
         file_path = os.path.join(YB_HOME_DIR, "bin/yb-server-ctl.sh")
         remote_shell.run_command("{} {} {}".format(file_path, process,
                                                    command))
     else:
         self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars,
                                      host_info)
Beispiel #6
0
    def verify_certs(self,
                     root_crt_path,
                     node_crt_path,
                     ssh_options,
                     verify_hostname=False):
        remote_shell = RemoteShell(ssh_options)
        # Verify that both cert are present in FS and have read rights
        root_file_verify = remote_shell.run_command_raw(
            "test -r {}".format(root_crt_path))
        if root_file_verify.exited == 1:
            raise YBOpsRuntimeError(
                "Root cert: {} is absent or is not readable.".format(
                    root_crt_path))
        node_file_verify = remote_shell.run_command_raw(
            "test -r {}".format(node_crt_path))
        if node_file_verify.exited == 1:
            raise YBOpsRuntimeError(
                "Node cert: {} is absent or is not readable.".format(
                    node_crt_path))
        try:
            remote_shell.run_command('which openssl')
        except YBOpsRuntimeError:
            logging.debug(
                "Openssl not found, skipping certificate verification.")
            return

        # Verify if root and node certs are valid
        cert_verify = remote_shell.run_command_raw(
            ("openssl crl2pkcs7 -nocrl -certfile {} -certfile {} "
             "| openssl pkcs7 -print_certs -text -noout").format(
                 root_crt_path, node_crt_path))
        if cert_verify.exited == 1:
            raise YBOpsRuntimeError(
                "Provided certs ({}, {}) are not valid.".format(
                    root_crt_path, node_crt_path))

        # Verify if the node cert is not expired
        validity_verify = remote_shell.run_command_raw(
            "openssl x509 -noout -checkend 86400 -in {}".format(node_crt_path))
        if validity_verify.exited == 1:
            raise YBOpsRuntimeError(
                "Node cert: {} is expired or will expire in one day.".format(
                    node_crt_path))

        # Verify if node cert has valid signature
        signature_verify = remote_shell.run_command_raw(
            "openssl verify -CAfile {} {} | egrep error".format(
                root_crt_path, node_crt_path))
        if signature_verify.exited != 1:
            raise YBOpsRuntimeError(
                "Node cert: {} is not signed by the provided root cert: {}.".
                format(node_crt_path, root_crt_path))

        if verify_hostname:
            self.__verify_certs_hostname(node_crt_path, ssh_options)
Beispiel #7
0
    def remove_xcluster_root_cert(self, ssh_options, replication_config_name,
                                  producer_certs_dir):
        def check_rm_result(rm_result):
            if rm_result.exited and rm_result.stderr.find(
                    "No such file or directory") == -1:
                raise YBOpsRuntimeError(
                    "Remote shell command 'rm' failed with "
                    "return code '{}' and error '{}'".format(
                        rm_result.stderr.encode('utf-8'), rm_result.exited))

        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(
            "Removing server cert located at {} from server {}.".format(
                src_root_cert_dir_path, node_ip))

        remote_shell.run_command(
            'chmod -f 666 {}/* || true'.format(src_root_cert_dir_path))
        result = remote_shell.run_command_raw('rm ' + src_root_cert_path)
        check_rm_result(result)
        # Remove the directory only if it is empty.
        result = remote_shell.run_command_raw('rm -d ' +
                                              src_root_cert_dir_path)
        check_rm_result(result)
        # No need to check the result of this command.
        remote_shell.run_command_raw('rm -d ' + producer_certs_dir)
Beispiel #8
0
 def run_control_script(self, process, command, args, extra_vars,
                        host_info):
     updated_vars = {"process": process, "command": command}
     updated_vars.update(extra_vars)
     updated_vars.update(get_ssh_host_port(host_info))
     if os.environ.get("YB_USE_FABRIC", False):
         remote_shell = RemoteShell(updated_vars)
         ssh_user = updated_vars.get("ssh_user")
         # TODO: change the home directory from being hard coded into a param passed in.
         remote_shell.run_command(
             "/home/yugabyte/bin/yb-server-ctl.sh {} {}".format(
                 process, command))
     else:
         self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars,
                                      host_info)
Beispiel #9
0
    def verify_certificates(self, cert_type, root_cert_path, cert_path,
                            key_path, ssh_options, skip_cert_validation,
                            results):
        result_var = True
        remote_shell = RemoteShell(ssh_options)
        if not self.test_file_readable(remote_shell, root_cert_path):
            results["File {} is present and readable".format(
                root_cert_path)] = False
            result_var = False
        if not self.test_file_readable(remote_shell, cert_path):
            results["File {} is present and readable".format(
                cert_path)] = False
            result_var = False
        if not self.test_file_readable(remote_shell, key_path):
            results["File {} is present and readable".format(key_path)] = False
            result_var = False
        if result_var and skip_cert_validation != 'ALL':
            try:
                self.cloud.verify_certs(root_cert_path, cert_path, ssh_options,
                                        skip_cert_validation != 'HOSTNAME')
            except YBOpsRuntimeError as e:
                result_var = False
                results["Check {} certificate".format(cert_type)] = str(e)

        if result_var:
            results["Check {} certificate".format(cert_type)] = True
        return result_var
Beispiel #10
0
    def __verify_certs_hostname(self, node_crt_path, ssh_options):
        host = ssh_options["ssh_host"]
        remote_shell = RemoteShell(ssh_options)
        logging.info("Verifying Subject for certs {}".format(node_crt_path))

        # Get readable text version of cert
        cert_text = remote_shell.run_command(
            "openssl x509 -noout -text -in {}".format(node_crt_path))
        if "Certificate:" not in cert_text.stdout:
            raise YBOpsRuntimeError(
                "Unable to decode the node cert: {}.".format(node_crt_path))

        # Extract commonName and subjectAltName from the cert text output
        regex_out = re.findall(
            " Subject:.*CN=([\\S]*)$| (DNS|IP Address):([\\S]*?)(,|$)",
            cert_text.stdout, re.M)
        # Hostname will be present in group 0 for CN and in group 1 and 2 for SAN
        cn_entry = [x[0] for x in regex_out if x[0] != '']
        san_entry = {(x[1], x[2]) for x in regex_out if x[0] == ''}

        # Create cert object following the below dictionary format
        # https://docs.python.org/3/library/ssl.html#ssl.SSLSocket.getpeercert
        cert_cn = {
            'subject':
            ((('commonName', cn_entry[0] if len(cn_entry) > 0 else ''), ), )
        }
        cert_san = {'subjectAltName': tuple(san_entry)}

        # Check if the provided hostname matches with either CN or SAN
        cn_matched = False
        san_matched = False
        try:
            ssl.match_hostname(cert_cn, host)
            cn_matched = True
        except ssl.CertificateError:
            pass
        try:
            ssl.match_hostname(cert_san, host)
            san_matched = True
        except ssl.CertificateError:
            pass

        if not cn_matched and not san_matched:
            raise YBOpsRuntimeError(
                "'{}' does not match with any entry in CN or SAN of the node cert: {}, "
                "cert_cn: {}, cert_san: {}".format(host, node_crt_path,
                                                   cert_cn, cert_san))
Beispiel #11
0
 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 verify_certs(self,
                     root_crt_path,
                     node_crt_path,
                     ssh_options,
                     verify_hostname=False):
        remote_shell = RemoteShell(ssh_options)

        try:
            remote_shell.run_command('which openssl')
        except YBOpsRuntimeError:
            logging.debug(
                "Openssl not found, skipping certificate verification.")
            return

        # Verify if the node cert is not expired
        validity_verify = remote_shell.run_command_raw(
            "openssl x509 -noout -checkend 86400 -in {}".format(node_crt_path))
        if validity_verify.exited == 1:
            raise YBOpsRuntimeError(
                "Node cert: {} is expired or will expire in one day.".format(
                    node_crt_path))

        # Verify if node cert has valid signature
        signature_verify = remote_shell.run_command_raw(
            "openssl verify -CAfile {} {} | egrep error".format(
                root_crt_path, node_crt_path))
        if signature_verify.exited != 1:
            raise YBOpsRuntimeError(
                "Node cert: {} is not signed by the provided root cert: {}.".
                format(node_crt_path, root_crt_path))

        if verify_hostname:
            self.__verify_certs_hostname(node_crt_path, ssh_options)
Beispiel #13
0
 def remove_old_root_cert(self, ssh_options, 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)
     # Check if ca_new.crt is present, it will be present if
     # APPEND_NEW_ROOT_CERT action was performed before
     file_verify = remote_shell.run_command_raw(
         "test -f '{}'".format(yb_root_cert_new_path))
     # No action needed if ca_new.crt is not present
     if not file_verify.exited:
         # Give write permissions to cert directory
         remote_shell.run_command(
             'chmod -f 666 {}/* || true'.format(certs_dir))
         # Remove ca.crt and rename ca_new.crt to ca.crt
         remote_shell.run_command("mv '{}' '{}'".format(
             yb_root_cert_new_path, yb_root_cert_path))
         # Reset the write permissions
         remote_shell.run_command('chmod 400 {}/*'.format(certs_dir))
Beispiel #14
0
    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))
Beispiel #15
0
    def cleanup_client_certs(self, ssh_options):
        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("Removing client certs located at {}, {}, {}.".format(
            yb_root_cert_path, yb_client_cert_path, yb_client_key_path))

        # Give write permissions. If the command fails, ignore.
        remote_shell.run_command('chmod -f 666 {}/* || true'.format(
            self.YSQLSH_CERT_DIR))
        # Remove client certs
        remote_shell.run_command("rm '{}' '{}' '{}' || true".format(
            yb_root_cert_path, yb_client_cert_path, yb_client_key_path))
        # Reset the write permission as a sanity check.
        remote_shell.run_command('chmod 400 {}/* || true'.format(
            self.YSQLSH_CERT_DIR))
Beispiel #16
0
 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))
Beispiel #17
0
    def compare_root_certs(self, extra_vars, ssh_options):
        has_openssl = True
        root_cert_path = extra_vars["root_cert_path"]
        certs_node_dir = extra_vars["certs_node_dir"]
        yb_root_cert_path = os.path.join(certs_node_dir, self.ROOT_CERT_NAME)
        remote_shell = RemoteShell(ssh_options)
        try:
            remote_shell.run_command('which openssl')
        except YBOpsRuntimeError as e:
            # No openssl, just compare files.
            has_openssl = False

        # Check if files exist. If not, let it error out (since the root files should be there.)
        remote_shell.run_command('test -f {}'.format(root_cert_path))
        remote_shell.run_command('test -f {}'.format(yb_root_cert_path))

        # Compare the openssl hash if openssl is present.
        if has_openssl:
            md5_cmd = "openssl x509 -noout -modulus -in '{}' | openssl md5"
            curr_root = remote_shell.run_command(md5_cmd.format(yb_root_cert_path))
            new_root = remote_shell.run_command(md5_cmd.format(root_cert_path))
            if curr_root.stdout != new_root.stdout:
                raise YBOpsRuntimeError("Root certs are different.")
        # Openssl not present, just compare the files after removing whitespace.
        else:
            # If there is an error code, that means the files are different. Should fail.
            remote_shell.run_command('diff -Z {} {}'.format(root_cert_path, yb_root_cert_path))
Beispiel #18
0
    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))
Beispiel #19
0
    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_certs(self, extra_vars, ssh_options):
        remote_shell = RemoteShell(ssh_options)

        if "root_cert_path" in extra_vars:
            root_cert_path = extra_vars["root_cert_path"]
            node_cert_path = extra_vars["node_cert_path"]
            node_key_path = extra_vars["node_key_path"]
            certs_node_dir = extra_vars["certs_node_dir"]
            self.verify_certs(root_cert_path,
                              node_cert_path,
                              ssh_options,
                              verify_hostname=True)
            self.__copy_certs(ssh_options, remote_shell, root_cert_path,
                              node_cert_path, node_key_path, certs_node_dir)

        if "client_root_cert_path" in extra_vars:
            root_cert_path = extra_vars["client_root_cert_path"]
            node_cert_path = extra_vars["client_node_cert_path"]
            node_key_path = extra_vars["client_node_key_path"]
            certs_client_dir = extra_vars["certs_client_dir"]
            self.verify_certs(root_cert_path,
                              node_cert_path,
                              ssh_options,
                              verify_hostname=False)
            self.__copy_certs(ssh_options, remote_shell, root_cert_path,
                              node_cert_path, node_key_path, certs_client_dir)

        if "client_cert_path" in extra_vars:
            client_cert_path = extra_vars["client_cert_path"]
            client_key_path = extra_vars["client_key_path"]
            logging.info("Moving client certs located at {}, {}.".format(
                client_cert_path, client_key_path))
            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.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)))
            remote_shell.run_command('chmod 400 {}/*'.format(
                self.YSQLSH_CERT_DIR))
Beispiel #21
0
    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))
    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))
Beispiel #23
0
    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))
Beispiel #24
0
    def copy_certs(self, extra_vars, ssh_options):
        node_ip = ssh_options["ssh_host"]
        root_cert_path = extra_vars["root_cert_path"]
        node_cert_path = extra_vars["node_cert_path"]
        node_key_path = extra_vars["node_key_path"]
        certs_node_dir = extra_vars["certs_node_dir"]
        logging.info("Moving 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 = 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.run_command('cp {} {}'.format(root_cert_path,
                                                   os.path.join(certs_node_dir,
                                                                self.ROOT_CERT_NAME)))
        remote_shell.run_command('cp {} {}'.format(node_cert_path,
                                                   os.path.join(certs_node_dir, cert_file)))
        remote_shell.run_command('cp {} {}'.format(node_key_path,
                                                   os.path.join(certs_node_dir, key_file)))
        remote_shell.run_command('chmod 400 {}/*'.format(certs_node_dir))
        if "client_cert_path" in extra_vars:
            client_cert_path = extra_vars["client_cert_path"]
            client_key_path = extra_vars["client_key_path"]
            logging.info("Moving client certs located at {}, {}.".format(client_cert_path,
                                                                         client_key_path))
            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.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)))
            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))
Beispiel #26
0
    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))
Beispiel #27
0
 def initYSQL(self, master_addresses, ssh_options):
     remote_shell = RemoteShell(ssh_options)
     remote_shell.run_command(
         "bash -c \"YB_ENABLED_IN_POSTGRES=1 FLAGS_pggate_master_addresses={} "
         "/home/yugabyte/tserver/postgres/bin/initdb -D /tmp/yb_pg_initdb_tmp_data_dir "
         "-U postgres\"".format(master_addresses))
Beispiel #28
0
    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))
Beispiel #29
0
    def run_control_script(self, process, command, args, extra_vars, host_info):
        updated_vars = {
            "process": process,
            "command": command
        }
        updated_vars.update(extra_vars)
        updated_vars.update(get_ssh_host_port(host_info, args.custom_ssh_port))
        remote_shell = RemoteShell(updated_vars)
        if args.num_volumes:
            volume_cnt = remote_shell.run_command(
                "df | awk '{{print $6}}' | egrep '^{}[0-9]+' | wc -l".format(
                    AbstractCloud.MOUNT_PATH_PREFIX
                )
            )
            if int(volume_cnt.stdout) < int(args.num_volumes):
                raise YBOpsRuntimeError(
                    "Not all data volumes attached: needed {} found {}".format(
                        args.num_volumes, volume_cnt.stdout
                    )
                )

        if process == "thirdparty" or process == "platform-services":
            self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars, host_info)
            return

        if args.systemd_services:
            if command == "start":
                remote_shell.run_command(
                    "sudo systemctl enable yb-{}".format(process)
                )
            remote_shell.run_command(
                "sudo systemctl {} yb-{}".format(command, process)
            )
            if command == "stop":
                remote_shell.run_command(
                    "sudo systemctl disable yb-{}".format(process)
                )
            return

        if os.environ.get("YB_USE_FABRIC", False):
            file_path = os.path.join(YB_HOME_DIR, "bin/yb-server-ctl.sh")
            remote_shell.run_command(
                "{} {} {}".format(file_path, process, command)
            )
        else:
            self.setup_ansible(args).run("yb-server-ctl.yml", updated_vars, host_info)