def init_enc_key_cmd(force, dump, keys): """Creates a LinOTP secret file to encrypt and decrypt values in database The key file is used via the default security provider to encrypt token seeds, configuration values... If --force or -f is set and the encKey file exists already, it will be overwritten. """ filename = current_app.config["SECRET_FILE"] if os.path.exists(filename): if not force: if not _overwrite_check("enc-key", filename): sys.exit(0) if not _make_backup("enc-key", filename): sys.exit(1) try: create_secret_key(filename, data=keys.replace(' ', '')) current_app.echo(f"Wrote enc-key to {filename}", v=1) except OSError as ex: current_app.echo(f"Error writing enc-key to {filename}: {ex!s}") sys.exit(1) if dump or keys: dump_key(filename, instructions=dump)
def create_audit_keys(privkey_filename, pubkey_filename): ret = _run_command("Creating private audit key", [ "openssl", "genrsa", "-out", privkey_filename, str(AUDIT_PRIVKEY_BITS) ]) if ret.exit_code == 0: try: current_app.echo(f"Wrote private audit key to {privkey_filename}", v=1) except RuntimeError: pass else: sys.exit(1) # The public key can always be reconstructed from the private key, so # we don't worry about a backup of the public key file. ret = _run_command("Extracting public audit key", [ "openssl", "rsa", "-in", privkey_filename, "-pubout", "-out", pubkey_filename ]) if ret.exit_code == 0: try: current_app.echo( f"Extracted public audit key to {pubkey_filename}", v=1) except RuntimeError: pass else: sys.exit(1)
def _run_command(task: str, cmd: List[str], **kwargs: Dict[str, Any]) -> bool: """Execute a shell command given as a list of strings, with error checking. """ @dataclass class CmdResult: exception: bool = True exit_code: int = 0 output: str = "" kwargs.update({'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT}) try: result = subprocess.run(cmd, **kwargs) except OSError as ex: ret = CmdResult(True, None, str(ex)) else: ret = CmdResult(False, result.returncode, result.stdout.decode("utf-8")) if ret.exception or ret.exit_code != 0: cmd_str = " ".join(cmd) current_app.echo(f"{task} failed:") if ret.exception: current_app.echo(f"Command '{cmd_str}' raised exception") elif ret.exit_code < 0: current_app.echo( f"Command '{cmd_str}' terminated by signal {-ret.exit_code}") else: current_app.echo( f"Command '{cmd_str}' returned exit code {ret.exit_code}") current_app.echo(f"Output was:\n{ret.output}") return ret
def _make_backup(what: str, filename: str) -> bool: backup_filename = get_backup_filename(filename) try: os.replace(filename, backup_filename) current_app.echo(f"Moved existing {what} to {backup_filename}", v=1) except OSError as ex: current_app.echo(f"Error moving {what} to {backup_filename}: {ex!s}") return False return True
def is_support_valid(filename): """checks if the linotp support info is valid similar to isSupportValid""" try: _setup_security_context() session = db.session() if filename: with open(filename, "rb") as license_file: license_text = license_file.read() license_text = license_text.decode("utf-8").replace("\n", "\n") license_dict, license_signature = parseSupportLicense(license_text) else: license_dict, license_signature = getSupportLicenseInfo() valid = isSupportLicenseValid( lic_dict=license_dict, lic_sign=license_signature, raiseException=True, ) session.close() except InvalidLicenseException as exx: current_app.echo(f"Invalid License: {exx}") sys.exit(2) except Exception as exx: current_app.echo(f"Validating support could not be completed: {exx}") sys.exit(1) if not license_dict: if isinstance(license_dict, dict): current_app.echo("No support license installed") else: current_app.echo("Validating support failed!") sys.exit(2) if not valid or not isinstance(valid, tuple): current_app.echo("Validating support error: %r" % valid) sys.exit(2) print(valid[0]) sys.exit(0)
def list_command(): """list available database snapshots.""" try: current_app.echo("Available snapshots to restore", v=1) for backup_date, backup_file in list_database_backups(): current_app.echo(f"{backup_date} {backup_file}", err=False) current_app.echo("Finished", v=1) except Exception as exx: current_app.echo("Failed to list snapshot files: {exx!r}") sys.exit(1)
def list_command(): """ list available database backups.""" try: current_app.echo("Available backup files for restore", v=1) for backup_date, backup_file in list_database_backups(): current_app.echo(f'{backup_date} {backup_file}', err=False) current_app.echo("finished", v=1) except Exception as exx: current_app.echo('Failed to list backup files: %r' % exx) sys.exit(1)
def get_support(): """get the linotp support info similar to system/getSupportInfo""" try: _setup_security_context() session = db.session() license_dict, license_signature = getSupportLicenseInfo() session.close() except Exception as exx: current_app.echo(f"Getting support could not be completed: {exx}") sys.exit(1) if not license_dict: if isinstance(license_dict, dict): current_app.echo("No support license installed") else: current_app.echo("Getting support failed!") sys.exit(2) print(json.dumps(license_dict, indent=4, sort_keys=True)) sys.exit(0)
def set_support(license_file_name): """set a linotp support similar to system/setSupport.""" try: _setup_security_context() with open(license_file_name, "rb") as license_file: license_text = license_file.read() session = db.session() success, status = setSupportLicense(license_text.decode("utf-8")) session.commit() except Exception as exx: current_app.echo(f"Setting license could not be completed: {exx}") sys.exit(1) if not success: current_app.echo(f"Failed to set license! {status}") sys.exit(2) current_app.echo("Successfully set license.") sys.exit(0)
def backup_mysql_command(): """ Backup MySQL database.""" try: current_app.echo("Backup MySQL database ...", v=1) backup_mysql_database() current_app.echo("Finished", v=1) except Exception as exx: current_app.echo(f"Failed to create MySQL backup: {exx!r}") sys.exit(1)
def restore_mysql_command(file): """ Restore MySQL backups.""" try: current_app.echo("Restoring legacy database ...", v=1) restore_mysql_database(filename=file) current_app.echo("Finished", v=1) except Exception as exx: current_app.echo(f"Failed to restore MySQL backup: {exx!r}") sys.exit(1)
def backup_mysql_command(): """ backup mysql database.""" try: current_app.echo("Backup mysql database ...", v=1) backup_mysql_database() current_app.echo("finished", v=1) except Exception as exx: current_app.echo('Failed to backup mysql: %r' % exx) sys.exit(1)
def restore_mysql_command(file): """ restore mysql backups.""" try: current_app.echo("Restoring legacy database ...", v=1) restore_mysql_database(filename=file) current_app.echo("finished", v=1) except Exception as exx: current_app.echo('Failed to restore mysql backup: %r' % exx) sys.exit(1)
def create_command(): """Create backup file for your database tables""" try: current_app.echo("Backup database ...", v=1) backup_database_tables() current_app.echo("finished", v=1) except Exception as exx: current_app.echo("Failed to backup: %r" % exx) sys.exit(1)
def restore_command(file=None, date=None, table=None): """ restore a database backup @param file - the backup file name, could be absolute or relative @param date - select a backup for restore by date @param table - allows to restore only one database table """ try: current_app.echo("Restoring database ...", v=1) restore_database_tables(file, date, table) current_app.echo("finished", v=1) except Exception as exx: current_app.echo('Failed to restore: %r' % exx) sys.exit(1)
def restore_command(file=None, date=None, table=None): """restore a database snapshot @param file - the snapshot file name, could be absolute or relative @param date - select a snapshot to restore by date @param table - allows to restore only one database table """ try: current_app.echo("Restoring snapshot ...", v=1) restore_database_tables(file, date, table) current_app.echo("Finished", v=1) except Exception as exx: current_app.echo(f"Failed to restore: {exx!r}") sys.exit(1)
def init_audit_keys_cmd(force): privkey_filename = current_app.config["AUDIT_PRIVATE_KEY_FILE"] pubkey_filename = current_app.config["AUDIT_PUBLIC_KEY_FILE"] if os.path.exists(privkey_filename): if not force: if not _overwrite_check("private audit key", privkey_filename): sys.exit(0) if not _make_backup("private audit key", privkey_filename): sys.exit(1) try: create_audit_keys(privkey_filename, pubkey_filename) current_app.echo(f"Wrote private audit key to {privkey_filename}", v=1) current_app.echo(f"Extracted public audit key to {pubkey_filename}", v=1) except Exception as ex: current_app.echo( f"Error writing audit key to {privkey_filename}: {ex!s}") sys.exit(1)
def fix_db_encoding_command(): """Fix the python2+mysql iso8859 encoding by conversion to utf-8.""" try: # Even though we skip initialising the database when doing # `linotp init …`, at this point we do need a database engine # after all. setup_db(current_app) result, response = fix_db_encoding(current_app) except Exception as exx: current_app.echo(f"Conversion could not be completed: {exx}") sys.exit(1) if not result: current_app.echo(f"Conversion failed: {response}") sys.exit(1) current_app.echo(f"Conversion response: {response}") sys.exit(0)
def init_db_command(erase_all_data): """ Create new tables The database is initialized and optionally data is cleared. """ if erase_all_data: info = 'Recreating database' else: info = 'Creating database' current_app.echo(info, v=1) try: # Even though we skip initialising the database when doing # `linotp init …`, at this point we do need a database engine # after all. current_app.cli_cmd = 'init-database' # anything but `init` setup_db(current_app) init_db_tables(current_app, erase_all_data) except Exception as exx: current_app.echo(f'Failed to create database: {exx!s}') raise sys.exit(1) current_app.echo('Database created', v=1)
def enable_cmd(): res = LocalAdminResolver(current_app) current_app.echo("Adding local admin resolver to admin realm", v=1) res.add_to_admin_realm() current_app.echo("Done", v=1)