Ejemplo n.º 1
0
def create_spec(host, port, user, password, dbname, verbose):
    db_connection = common.get_db_connection(host, port, dbname, user,
                                             password)
    # We will only be reading, so it is worth being safe here and ensuring that we can't write
    db_connection.set_session(readonly=True)
    cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor)

    dbcontext = DatabaseContext(cursor, verbose)
    spec = initialize_spec(dbcontext)
    spec = add_attributes(spec, dbcontext)
    spec = add_memberships(spec, dbcontext)
    spec = add_ownerships(spec, dbcontext)
    spec = add_privileges(spec, dbcontext)

    return spec
Ejemplo n.º 2
0
def test_get_db_connection_autocommit(db_config):
        db_connection = common.get_db_connection(**db_config)
        assert db_connection.autocommit is False
Ejemplo n.º 3
0
def test_get_db_connection_fails(capsys):
    with pytest.raises(SystemExit) as err:
        common.get_db_connection('foo', 'foo', 'foo', 'foo', 'foo')

    out, err = capsys.readouterr()
    assert common.DATABASE_CONNECTION_ERROR_MSG.format('') in out
Ejemplo n.º 4
0
def configure(spec_path, host, port, user, password, dbname, prompt, attributes, memberships,
              ownerships, privileges, live, verbose, attributes_source_table):
    """
    Configure the role attributes, memberships, object ownerships, and/or privileges of a
    database cluster to match a desired spec.

    Note that attributes and memberships are database cluster-wide settings, i.e. they are the
    same across multiple databases within a given Postgres instance. Ownerships and privileges
    are specific to each individual database within a Postgres instance.

    Inputs:

        spec_path - str; the path for the configuration file

        host - str; the database server host

        port - str; the database server port

        user - str; the database user name

        password - str; the database user's password

        dbname - str; the database to connect to and configure

        prompt - bool; whether to prompt for a password

        attributes - bool; whether to configure the role attributes for the specified
            database cluster

        memberships - bool; whether to configure the role memberships for the specified
            database cluster

        ownerships - bool; whether to configure the ownerships for the specified database

        privileges - bool; whether to configure the privileges for the specified database

        live - bool; whether to apply the changes (True) or just show what changes
            would be made without actually appyling them (False)

        verbose - bool; whether to show all queries that are executed and all debug log
            messages during execution

        attributes_source_table - str; the table to read use attributes from (pg_authid or pg_roles)
    """
    if verbose:
        root_logger = logging.getLogger('')
        root_logger.setLevel(logging.DEBUG)

    if prompt:
        password = getpass.getpass()

    db_connection = common.get_db_connection(host, port, dbname, user, password)
    cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor)

    spec = load_spec(spec_path, cursor, verbose, attributes, memberships, ownerships, privileges)

    sql_to_run = []
    password_changed = False  # Initialize this in case the attributes module isn't run

    if attributes:
        sql_to_run.append(create_divider('attributes'))
        # Password changes happen within the attributes.py module itself so we don't leak
        # passwords; as a result we need to see if password changes occurred
        module_sql, all_password_sql_to_run = analyze_attributes(spec, cursor, verbose, attributes_source_table)
        run_module_sql(module_sql, cursor, verbose)
        if all_password_sql_to_run:
            password_changed = True
            run_password_sql(cursor, all_password_sql_to_run)

        sql_to_run.extend(module_sql)

    if memberships:
        sql_to_run.append(create_divider('memberships'))
        module_sql = analyze_memberships(spec, cursor, verbose)
        run_module_sql(module_sql, cursor, verbose)
        sql_to_run.extend(module_sql)

    if ownerships:
        sql_to_run.append(create_divider('ownerships'))
        module_sql = analyze_ownerships(spec, cursor, verbose)
        run_module_sql(module_sql, cursor, verbose)
        sql_to_run.extend(module_sql)

    if privileges:
        sql_to_run.append(create_divider('privileges'))
        module_sql = analyze_privileges(spec, cursor, verbose)
        run_module_sql(module_sql, cursor, verbose)
        sql_to_run.extend(module_sql)

    changed = password_changed or has_changes(sql_to_run)
    if changed and live:
        logger.debug('Committing changes')
        db_connection.commit()
    else:
        db_connection.rollback()

    # Make sure there is at least 1 line with a real change (vs. all headers)
    if changed:
        click.secho(HEADER.format('LIVE' if live else 'CHECK'), fg='green')
        for statement in sql_to_run:
            click.secho(statement, fg='green')
    else:
        click.secho(SUCCESS_MSG, fg='green')