コード例 #1
0
ファイル: vrrp_notify.py プロジェクト: agdsn/hades
def main() -> int:
    description = textwrap.dedent(
        """
        Hades keepalived VRRP notify script.
        
        This script is called by keepalived, if a VRRP instance's state changes.
        """
    )
    parser = ArgumentParser(description=description,
                            parents=[common_parser])
    parser.add_argument('type', choices=['GROUP', 'INSTANCE'],
                        help="Type indication")
    parser.add_argument('name', help="The name of the group or instance")
    parser.add_argument('state', choices=['MASTER', 'BACKUP', 'FAULT'],
                        help="The state it's transitioning to")
    parser.add_argument('priority', type=int, help="The priority value")
    args = parser.parse_args()
    logger.fatal("Transitioning %s to %s with priority %d", args.name,
                 args.state, args.priority)
    try:
        config = load_config(args.config, runtime_checks=True,
                             option_cls=CeleryOption)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    app.config_from_object(config)
    if args.name == 'hades-auth':
        return notify_auth(args.state, args.priority)
    elif args.name == 'hades-radius':
        return notify_radius(args.state, args.priority)
    elif args.name == 'hades-unauth':
        return notify_unauth(args.state, args.priority)
コード例 #2
0
def create_parser() -> ArgumentParser:
    parser = ArgumentParser(parents=[common_parser])
    parser.add_argument('-m',
                        '--mode',
                        type=mode,
                        default=0o0750,
                        help="The mode of created files and directories. Only "
                        "read, write, setgid, and sticky bits are "
                        "respected. Files are never executable or setuid. "
                        "Directories are always executable if they are "
                        "readable and optionally have setgid and sticky "
                        "bits set.")
    parser.add_argument('-g',
                        '--group',
                        type=group,
                        default=None,
                        metavar='GROUP | GID',
                        help="The group of created files and directories.")
    parser.add_argument(dest='source',
                        type=relative_path,
                        metavar='SOURCE',
                        help="Template file name or template directory name")
    parser.add_argument(
        dest='destination',
        metavar='DESTINATION',
        nargs='?',
        help="Destination file or directory (default is stdout "
        "for files; required for directories)")
    return parser
コード例 #3
0
ファイル: check_database.py プロジェクト: agdsn/hades
def main():
    parser = ArgumentParser(parents=[common_parser])
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    try:
        config = load_config(args.config)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    try:
        engine = db.create_engine(config, poolclass=NullPool)
        agent_pwd = pwd.getpwnam(constants.AGENT_USER)
        with dropped_privileges(agent_pwd):
            check_database(engine, agent_pwd.pw_name,
                           (db.radacct, db.radpostauth))
        portal_pwd = pwd.getpwnam(constants.PORTAL_USER)
        with dropped_privileges(portal_pwd):
            check_database(engine, portal_pwd.pw_name,
                           (db.radacct, db.radpostauth, db.radusergroup))
        radius_pwd = pwd.getpwnam(constants.RADIUS_USER)
        with dropped_privileges(radius_pwd):
            check_database(engine, radius_pwd.pw_name,
                           (db.radacct, db.radgroupcheck, db.radgroupreply,
                            db.radpostauth, db.radreply, db.radusergroup))
    except DBAPIError:
        return os.EX_TEMPFAIL
    return os.EX_OK
コード例 #4
0
ファイル: deputy.py プロジェクト: zhangjh953166/hades
def main():
    parser = ArgumentParser(
        description='Provides a DBus API to perform privileged operations',
        parents=[common_parser])
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    load_config(args.config)
    run_event_loop()
コード例 #5
0
ファイル: su.py プロジェクト: agdsn/hades
def main():
    parser = ArgumentParser(parents=[common_parser])
    parser.add_argument('user')
    parser.add_argument('command')
    parser.add_argument('arguments', nargs='*')
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    try:
        passwd = pwd.getpwnam(args.user)
        group = grp.getgrgid(passwd.pw_gid)
    except KeyError:
        logger.critical("No such user or group")
        return os.EX_NOUSER
    filename = args.command
    try:
        drop_privileges(passwd, group)
    except PermissionError:
        logging.exception("Can't drop privileges")
        return os.EX_NOPERM
    try:
        os.execvp(filename, [filename] + args.arguments)
    except (FileNotFoundError, PermissionError):
        logger.critical("Could not execute %s", filename)
        return os.EX_NOINPUT
    except OSError:
        logger.exception("An OSError occurred")
        return os.EX_OSERR
コード例 #6
0
ファイル: deputy.py プロジェクト: agdsn/hades
def main():
    parser = ArgumentParser(
        description='Provides a DBus API to perform privileged operations',
        parents=[common_parser])
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    try:
        load_config(args.config)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    run_event_loop()
コード例 #7
0
ファイル: agent.py プロジェクト: agdsn/hades
def main():
    description = textwrap.dedent(
        """
        Run the celery command configured for Hades.

        All arguments except -c/--config and -A/--app are passed to the Celery
        celery as is. You may not provide the -A/--app argument.
        """
    )
    parser = ArgumentParser(description=description,
                            formatter_class=Formatter,
                            parents=[common_parser])
    parser.add_argument('-A', '--app', dest='app', help=argparse.SUPPRESS)
    parser.add_argument('command')
    args, argv = parser.parse_known_args()
    try:
        config = load_config(args.config)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    app.config_from_object(config.of_type(CeleryOption))
    if args.app:
        parser.error("You may not provide the -A/--app worker argument")
    argv.insert(0, parser.prog)
    argv.insert(1, args.command)
    argv.extend(['-A', 'hades.bin.agent:app'])
    if args.command == 'worker':
        argv.extend(['-n', config.HADES_CELERY_WORKER_HOSTNAME])
    return app.start(argv)
コード例 #8
0
def main():
    parser = ArgumentParser(parents=[common_parser])
    parser.add_argument(dest='source',
                        metavar='SOURCE',
                        help="Template file name or template directory name")
    parser.add_argument(dest='destination',
                        metavar='DESTINATION',
                        nargs='?',
                        help="Destination file or directory (default is stdout"
                        "for files; required for directories)")
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    config = load_config(args.config)
    template_dir = constants.templatedir
    generator = ConfigGenerator(template_dir, config)
    source_path = os.path.join(template_dir, args.source)
    if os.path.isdir(source_path):
        generator.from_directory(args.source, args.destination)
    elif os.path.isfile(source_path):
        if args.destination is None:
            generator.from_file(args.source, sys.stdout)
        else:
            with open(args.destination, 'w', encoding='utf-8') as f:
                generator.from_file(args.source, f)
    else:
        logger.critical("No such file or directory %s in %s", args.source,
                        template_dir)
        return os.EX_NOINPUT
コード例 #9
0
ファイル: vrrp_notify.py プロジェクト: agdsn/hades
def create_parser() -> ArgumentParser:
    description = textwrap.dedent("""
        Hades keepalived VRRP notify script.
        
        This script is called by keepalived, if a VRRP instance's state changes.
        """)
    parser = ArgumentParser(description=description, parents=[common_parser])
    parser.add_argument('type',
                        choices=['GROUP', 'INSTANCE'],
                        help="Type indication")
    parser.add_argument(
        "name",
        help="The name of the group or instance",
        choices=["hades-auth", "hades-root", "hades-unauth"],
    )
    parser.add_argument('state',
                        choices=['MASTER', 'BACKUP', 'FAULT'],
                        help="The state it's transitioning to")
    parser.add_argument('priority', type=int, help="The priority value")
    return parser
コード例 #10
0
ファイル: agent.py プロジェクト: agdsn/hades
def create_parser() -> ArgumentParser:
    description = inspect.cleandoc(
        """
        Run the celery command configured for Hades.

        All arguments except -c/--config and -A/--app are passed to the Celery
        celery as is. You may not provide the -A/--app argument.
        """
    )
    parser = ArgumentParser(
        description=description,
        formatter_class=Formatter,
        parents=[common_parser],
    )
    parser.add_argument(
        "--pid-file",
        type=str,
        default=f"{constants.pkgrunstatedir}/agent/agent.pid",
    )
    return parser
コード例 #11
0
ファイル: check_database.py プロジェクト: zhangjh953166/hades
def main():
    parser = ArgumentParser(parents=[common_parser])
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    config = load_config(args.config, runtime_checks=True)
    try:
        engine = db.create_engine(config, poolclass=NullPool)
        agent_pwd = pwd.getpwnam(constants.AGENT_USER)
        with dropped_privileges(agent_pwd):
            check_database(engine, agent_pwd.pw_name,
                           (db.radacct, db.radpostauth))
        portal_pwd = pwd.getpwnam(constants.PORTAL_USER)
        with dropped_privileges(portal_pwd):
            check_database(engine, portal_pwd.pw_name,
                           (db.radacct, db.radpostauth, db.radusergroup))
        radius_pwd = pwd.getpwnam(constants.RADIUS_USER)
        with dropped_privileges(radius_pwd):
            check_database(engine, radius_pwd.pw_name,
                           (db.radacct, db.radgroupcheck, db.radgroupreply,
                            db.radpostauth, db.radreply, db.radusergroup))
    except DBAPIError:
        return os.EX_TEMPFAIL
    return os.EX_OK
コード例 #12
0
ファイル: agent.py プロジェクト: zhangjh953166/hades
def main():
    description = textwrap.dedent("""
        Run the celery command configured for Hades.

        All arguments except -c/--config and -A/--app are passed to the Celery
        celery as is. You may not provide the -A/--app argument.
        """)
    parser = ArgumentParser(description=description,
                            formatter_class=Formatter,
                            parents=[common_parser])
    parser.add_argument('-A', '--app', dest='app', help=argparse.SUPPRESS)
    parser.add_argument('command')
    args, argv = parser.parse_known_args()
    config = load_config(args.config)
    app.config_from_object(config.of_type(CeleryOption))
    if args.app:
        parser.error("You may not provide the -A/--app worker argument")
    argv.insert(0, parser.prog)
    argv.insert(1, args.command)
    argv.extend(['-A', 'hades.bin.agent:app'])
    if args.command == 'worker':
        argv.extend(['-n', config.HADES_CELERY_WORKER_HOSTNAME])
    return app.start(argv)
コード例 #13
0
ファイル: export_options.py プロジェクト: agdsn/hades
def create_parser():
    parser = ArgumentParser(description='Export options as shell variables',
                            epilog='Python sequence and mapping types will '
                                   'only be exported, if the destination '
                                   'format support it',
                            parents=[parent_parser])
    parser.add_argument('--format', choices=('systemd', 'posix', 'bash', 'ksh',
                                             'zsh'),
                        default='systemd', help='Export format.')
    parser.add_argument('file', type=argparse.FileType('wb'), metavar='FILE',
                        default='-', nargs='?',
                        help='Output destination (default: stdout)')
    return parser
コード例 #14
0
ファイル: export_options.py プロジェクト: zhangjh953166/hades
def main():
    parser = ArgumentParser(description='Export options as shell variables',
                            epilog='Python sequence and mapping types will '
                            'only be exported, if the destination '
                            'format support it',
                            parents=[parent_parser])
    parser.add_argument('--format',
                        choices=('systemd', 'posix', 'bash', 'ksh', 'zsh'),
                        default='systemd',
                        help='Export format.')
    parser.add_argument('file',
                        type=argparse.FileType('wb'),
                        metavar='FILE',
                        default='-',
                        nargs='?',
                        help='Output destination (default: stdout)')
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    config = load_config(args.config)
    export(config, args.format, args.file)
    return os.EX_OK
コード例 #15
0
ファイル: export_options.py プロジェクト: agdsn/hades
def main():
    parser = ArgumentParser(description='Export options as shell variables',
                            epilog='Python sequence and mapping types will '
                                   'only be exported, if the destination '
                                   'format support it',
                            parents=[parent_parser])
    parser.add_argument('--format', choices=('systemd', 'posix', 'bash', 'ksh',
                                             'zsh'),
                        default='systemd', help='Export format.')
    parser.add_argument('file', type=argparse.FileType('wb'), metavar='FILE',
                        default='-', nargs='?',
                        help='Output destination (default: stdout)')
    args = parser.parse_args()
    setup_cli_logging(parser.prog, args)
    try:
        config = load_config(args.config)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    export(config, args.format, args.file)
    return os.EX_OK
コード例 #16
0
ファイル: deputy.py プロジェクト: agdsn/hades
def create_parser() -> ArgumentParser:
    parser = ArgumentParser(
        description='Provides a DBus API to perform privileged operations',
        parents=[common_parser])
    return parser
コード例 #17
0
def main() -> int:
    description = textwrap.dedent(
        """
        Hades keepalived VRRP notify script.
        
        This script is called by keepalived, if a VRRP instance's state changes.
        """
    )
    parser = ArgumentParser(description=description,
                            parents=[common_parser])
    parser.add_argument('type', choices=['GROUP', 'INSTANCE'],
                        help="Type indication")
    parser.add_argument('name', help="The name of the group or instance")
    parser.add_argument('state', choices=['MASTER', 'BACKUP', 'FAULT'],
                        help="The state it's transitioning to")
    parser.add_argument('priority', type=int, help="The priority value")
    args = parser.parse_args()
    logger.fatal("Transitioning %s to %s with priority %d", args.name,
                 args.state, args.priority)
    app.config_from_object(
        load_config(args.config, runtime_checks=True, option_cls=CeleryOption))
    if args.name == 'hades-auth':
        return notify_auth(args.state, args.priority)
    elif args.name == 'hades-radius':
        return notify_radius(args.state, args.priority)
    elif args.name == 'hades-unauth':
        return notify_unauth(args.state, args.priority)
コード例 #18
0
ファイル: lease_server.py プロジェクト: agdsn/hades
def main():
    parser = ArgumentParser(
        description="Listens for commands as output by `hades-dhcp-script`.",
        epilog=f"""\
            This server listens on a socket for commands communicating lease events.
            For detailed information about the functionality see `hades-dhcp-script --help`.
            It is the server component for what could have been a single python program,
            however because of performance reasons, it was necessary to circumvent the need
            for a complete python interpreter startup every time such a notification happens.\
        """,
        parents=[common_parser],
    )
    parser.add_argument(
        '--socket',
        nargs='?',
        default=constants.AUTH_DHCP_SCRIPT_SOCKET,
        help=
        f"Socket to listen on. Default: {constants.AUTH_DHCP_SCRIPT_SOCKET}")
    args = parser.parse_args()
    SCRIPT_SOCKET = args.socket
    setup_cli_logging(parser.prog, args)
    try:
        config = load_config(args.config)
    except ConfigError as e:
        print_config_error(e)
        return os.EX_CONFIG
    fds = listen_fds()
    if len(fds) == 0:
        logger.info(
            "Opening UNIX socket at %s.",
            SCRIPT_SOCKET,
        )
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
        try:
            os.unlink(SCRIPT_SOCKET)
        except FileNotFoundError:
            pass
        sock.bind(SCRIPT_SOCKET)
        sock.listen(Server.request_queue_size)
    elif len(fds) == 1:
        logger.info("Using systemd activation socket")
        sock = fds[0]
        if not is_socket_unix(sock, socket.SOCK_STREAM):
            logger.critical(
                "Passed socket is not an AF_UNIX SOCK_STREAM socket")
            return os.EX_USAGE
    else:
        logger.critical(
            "More than one (%d) socket passed via socket activation",
            len(fds),
        )
        return os.EX_USAGE
    engine = db.create_engine(
        config,
        pool_size=1,
        max_overflow=2,
        pool_pre_ping=True,
        pool_reset_on_return='rollback',
    )
    try:
        engine.connect()
    except DBAPIError as e:
        logger.critical("Could not connect to database", exc_info=e)
        return os.EX_TEMPFAIL

    server = Server(sock, engine)
    server.serve_forever()
    return os.EX_OK
コード例 #19
0
ファイル: check_database.py プロジェクト: agdsn/hades
def create_parser() -> ArgumentParser:
    parser = ArgumentParser(parents=[common_parser])
    return parser