示例#1
0
def test_get_all_nonschema_objects_and_owners(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    expected = {
        SCHEMAS[0]: [
            context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]),
                               ROLES[0], False),
            context.ObjectInfo('sequences',
                               quoted_object(SCHEMAS[0], SEQUENCES[1]),
                               ROLES[0], False),
        ],
        SCHEMAS[1]: [
            context.ObjectInfo('tables', quoted_object(SCHEMAS[1], TABLES[0]),
                               ROLES[1], False),
            context.ObjectInfo('sequences',
                               quoted_object(SCHEMAS[1], SEQUENCES[2]),
                               ROLES[1], False),
        ],
    }
    actual = dbcontext.get_all_nonschema_objects_and_owners()

    # We are deliberately not checking pg_catalog or information_schema here since that's a
    # lot of work and those should not be touched
    for k, v in expected.items():
        assert set(v) == set(actual[k])

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_nonschema_objects_and_owners()
    assert actual_again == actual
示例#2
0
def verify_spec(rendered_template, spec, cursor, verbose, attributes,
                memberships, ownerships, privileges):
    assert isinstance(spec, dict)
    dbcontext = context.DatabaseContext(cursor, verbose)

    error_messages = []

    # Having all roles represented exactly once is critical for all submodules
    # so we check this regardless of which submodules are being used
    error_messages += ensure_no_duplicate_roles(rendered_template)
    error_messages += ensure_no_undocumented_roles(spec, dbcontext)
    error_messages += ensure_no_except_on_schema(spec)

    if ownerships:
        for objkind in context.PRIVILEGE_MAP.keys():
            if objkind == 'schemas':
                error_messages += ensure_no_unowned_schemas(spec, dbcontext)
                error_messages += ensure_no_schema_owned_twice(spec)
            else:
                # We run each of these functions once per object kind as it is possible that
                # two objects of different kinds could have the same name in the same schema
                error_messages += ensure_no_missing_objects(
                    spec, dbcontext, objkind)
                error_messages += ensure_no_object_owned_twice(
                    spec, dbcontext, objkind)
                error_messages += ensure_no_dependent_object_is_owned(
                    spec, dbcontext, objkind)

    if privileges:
        error_messages += ensure_no_redundant_privileges(spec)

    if error_messages:
        common.fail('\n'.join(error_messages))
示例#3
0
def test_get_schema_objects_no_entry():
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False)
    dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: {
        common.ObjectName('foo'): 'bar',
    }
    actual = dbcontext.get_schema_objects(common.ObjectName('key_not_in_response'))
    assert actual == []
示例#4
0
def test_get_schema_owner():
    schema = common.ObjectName('foo')
    expected_owner = 'bar'
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_schemas_and_owners'] = lambda: {schema: expected_owner}
    actual = dbcontext.get_schema_owner(schema)
    assert actual == expected_owner
示例#5
0
def test_get_schema_objects():
    schema = common.ObjectName('foo')
    expected = 'bar'
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False)
    dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: {
        common.ObjectName('foo'): expected
    }
    actual = dbcontext.get_schema_objects(schema)
    assert actual == expected
示例#6
0
def test_get_role_current_defaults(rolename, object_kind, access, expected):
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_current_defaults'] = lambda: {
        'role1': {
            'object_kind1': {
                'access1': set([1, 2, 3])
            }
        }
    }
    assert dbcontext.get_role_current_defaults(rolename, object_kind, access) == expected
示例#7
0
def test_get_schema_objects_no_entry():
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False)
    dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: {
        'foo': [
            context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]), ROLES[0], False),
            context.ObjectInfo('sequences', quoted_object(SCHEMAS[0], SEQUENCES[1]), ROLES[0], False),
        ],
    }
    actual = dbcontext.get_schema_objects('key_not_in_response')
    assert actual == []
示例#8
0
def test_get_schema_objects():
    schema = 'foo'
    expected = [
        context.ObjectInfo('tables', quoted_object(SCHEMAS[0], TABLES[0]), ROLES[0], False),
        context.ObjectInfo('sequences', quoted_object(SCHEMAS[0], SEQUENCES[1]), ROLES[0], False),
    ]
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=False)
    dbcontext._cache['get_all_nonschema_objects_and_owners'] = lambda: {schema: expected}
    actual = dbcontext.get_schema_objects(schema)
    assert actual == expected
示例#9
0
def test_get_all_role_attributes(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    actual = dbcontext.get_all_role_attributes()
    expected = set(['test_user', 'postgres', ROLES[0], ROLES[1]])
    assert set(actual.keys()) == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_role_attributes()
    assert actual_again == actual
示例#10
0
def test_get_all_personal_schemas(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    actual = dbcontext.get_all_personal_schemas()
    expected = set(ROLES[1:3])
    assert actual == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_personal_schemas()
    assert actual_again == actual
示例#11
0
def test_get_all_raw_object_attributes(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    raw_results = dbcontext.get_all_raw_object_attributes()
    assert isinstance(raw_results, list)
    assert len(raw_results) > 0
    assert isinstance(raw_results[0], tuple)

    # Make sure that this data is cached for future use
    cursor.close()
    raw_results_again = dbcontext.get_all_raw_object_attributes()
    assert raw_results_again == raw_results
示例#12
0
def test_get_version_info(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    actual = dbcontext.get_version_info()

    assert isinstance(actual, context.VersionInfo)
    assert not actual.is_redshift
    assert not actual.redshift_version
    # We do not check the Postgres version since we test against multiple Postgres versions

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_version_info()
    assert actual_again == actual
示例#13
0
def test_get_role_objects_with_access(access, expected):
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_current_nondefaults'] = lambda: {
        ROLES[0]: {
            'tables': {
                'read': set([
                    (quoted_object(SCHEMAS[0], TABLES[0]), 'SELECT'),
                    (quoted_object(SCHEMAS[0], TABLES[1]), 'SELECT'),
                ])
            }
        }
    }
    actual = dbcontext.get_role_objects_with_access(ROLES[0], SCHEMAS[0], 'tables', access)
    assert actual == expected
示例#14
0
def test_get_role_current_nondefaults(rolename, object_kind, access, expected):
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_current_nondefaults'] = lambda: {
        'role1': {
            'object_kind1': {
                'access1': set([
                    (common.ObjectName('foo', 'bar'), 'SELECT'),
                    (common.ObjectName('foo', 'baz'), 'SELECT'),
                    (common.ObjectName('foo', 'qux'), 'INSERT'),
                ])
            }
        }
    }
    actual = dbcontext.get_role_current_nondefaults(rolename, object_kind, access)
    assert actual == expected
示例#15
0
def test_has_default_privilege(rolename, schema, object_kind, access, expected):
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_current_defaults'] = lambda: {
        'role1': {
            'tables': {
                'read': set([
                    ('role1', common.ObjectName('schema2'), 'SELECT'),
                ]),
                'write': set([
                    ('not_this_role', common.ObjectName('schema1'), 'UPDATE'),
                ]),
            }
        }
    }
    assert dbcontext.has_default_privilege(rolename, schema, object_kind, access) == expected
示例#16
0
def test_get_all_role_attributes(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)

    expected = set(['test_user', 'postgres', ROLES[0], ROLES[1]])
    pg_version = dbcontext.get_version_info().postgres_version
    # Postgres 10 introduces several new roles that we have to account for
    if pg_version.startswith('10.'):
        expected.update(set([
            'pg_read_all_settings', 'pg_stat_scan_tables', 'pg_read_all_stats', 'pg_monitor']
        ))

    actual = dbcontext.get_all_role_attributes()
    assert set(actual.keys()) == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_role_attributes()
    assert actual_again == actual
示例#17
0
def test_get_all_current_defaults(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    expected = {
        ROLES[0]: {
            'tables': {
                'read': set([
                    (ROLES[3], SCHEMAS[0], 'SELECT'),
                ]),
                'write': set(),
            }
        }
    }
    actual = dbcontext.get_all_current_defaults()
    assert actual == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_current_defaults()
    assert actual_again == expected
示例#18
0
def test_get_all_memberships(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)

    expected = set([('role1', 'role0'), ('role2', 'role1')])
    pg_version = dbcontext.get_version_info().postgres_version
    # Postgres 10 introduces several new roles and memberships that we have to account for
    if pg_version >= 100000:
        expected.update(set([
            ('pg_monitor', 'pg_stat_scan_tables'),
            ('pg_monitor', 'pg_read_all_stats'),
            ('pg_monitor', 'pg_read_all_settings'),
        ]))

    actual = dbcontext.get_all_memberships()
    assert isinstance(actual, list)
    assert len(actual) == len(expected)

    # Convert actual to a set of tuples so comparison is easier
    actual_converted = set([tuple(i) for i in actual])
    assert actual_converted == expected
示例#19
0
def test_get_all_schemas_and_owners(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    expected = {
        SCHEMAS[0]: ROLES[0],
        SCHEMAS[1]: ROLES[0],
        SCHEMAS[2]: ROLES[1],
        ROLES[1]: ROLES[1],
        # These already existed
        'public': 'postgres',
        'information_schema': 'postgres',
        'pg_catalog': 'postgres',
    }

    actual = dbcontext.get_all_schemas_and_owners()
    assert actual == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_schemas_and_owners()
    assert actual_again == actual
示例#20
0
def test_get_all_object_attributes(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    expected = {
        'tables': {
            SCHEMAS[0]: {
                common.ObjectName(SCHEMAS[0], TABLES[0]): {'owner': ROLES[1], 'is_dependent': False},
                common.ObjectName(SCHEMAS[0], TABLES[1]): {'owner': ROLES[1], 'is_dependent': False},
                common.ObjectName(SCHEMAS[0], TABLES[2]): {'owner': ROLES[3], 'is_dependent': False},
            }
        },
        'sequences': {
            SCHEMAS[0]: {
                common.ObjectName(SCHEMAS[0], SEQUENCES[0]): {'owner': ROLES[1], 'is_dependent': False},
                common.ObjectName(SCHEMAS[0], SEQUENCES[1]): {'owner': ROLES[2], 'is_dependent': False},
                common.ObjectName(SCHEMAS[0], SEQUENCES[2]): {'owner': ROLES[2], 'is_dependent': False},
            }
        },
        'schemas': {
            SCHEMAS[0]: {
                common.ObjectName(SCHEMAS[0]): {'owner': ROLES[0], 'is_dependent': False},
            },
            'public': {
                'public': {'owner': 'postgres', 'is_dependent': False},
            }
        }
    }

    actual = dbcontext.get_all_object_attributes()

    # We do this to avoid having to look at / filter out entries from
    # information_schema or pg_catalog
    for key in expected.keys():
        expected_entries = expected[key][SCHEMAS[0]]
        actual_entries = actual[key][SCHEMAS[0]]
        assert expected_entries == actual_entries

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_object_attributes()
    assert actual_again == actual
示例#21
0
def test_get_all_current_nondefaults(cursor):
    dbcontext = context.DatabaseContext(cursor, verbose=True)
    expected = {
        ROLES[0]: {
            'tables': {
                'read':
                set([
                    (quoted_object(SCHEMAS[0], TABLES[1]), 'SELECT'),
                    (quoted_object(SCHEMAS[1], TABLES[3]), 'SELECT'),
                ]),
                'write':
                set(),
            }
        },
        ROLES[2]: {
            'schemas': {
                'read': set(),
                'write': set([
                    (SCHEMAS[0], 'CREATE'),
                    (SCHEMAS[1], 'CREATE'),
                ]),
            }
        },
        ROLES[3]: {
            'schemas': {
                'read': set(),
                'write': set([
                    (SCHEMAS[0], 'CREATE'),
                    (SCHEMAS[1], 'CREATE'),
                ]),
            }
        }
    }
    actual = dbcontext.get_all_current_nondefaults()
    assert actual == expected

    # Make sure that this data is cached for future use
    cursor.close()
    actual_again = dbcontext.get_all_current_nondefaults()
    assert actual_again == expected
示例#22
0
def test_is_superuser(all_role_attributes, expected):
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_role_attributes'] = lambda: all_role_attributes
    actual = dbcontext.is_superuser(ROLES[0])
    assert actual == expected
示例#23
0
def test_get_role_attributes_role_does_not_exist():
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_role_attributes'] = lambda: {}
    actual = dbcontext.get_role_attributes(ROLES[0])
    assert actual == dict()
示例#24
0
def test_get_role_attributes():
    expected = {'foo': 'bar'}
    dbcontext = context.DatabaseContext(cursor=DUMMY, verbose=True)
    dbcontext._cache['get_all_role_attributes'] = lambda: {ROLES[0]: expected}
    actual = dbcontext.get_role_attributes(ROLES[0])
    assert actual == expected