def test_load_file(mocker): environ = dict() mod = 'ldap2pg.config.' mocker.patch(mod + 'os.environ', environ) ff = mocker.patch(mod + 'Configuration.find_filename') mocker.patch(mod + 'open', create=True) read = mocker.patch(mod + 'Configuration.read') warn = mocker.patch(mod + 'logger.warning') from ldap2pg.config import Configuration config = Configuration() ff.return_value = ['filename.yml', 0o0] read.return_value = dict( sync_map=[dict(role='alice')], # To trigger a warning. unknown_key=True, # Should not trigger a warning. privileges=dict(ro=['__connect__']), ) # send one env var environ.update(dict(PGDSN=b'envdsn')) config.load(argv=['--verbose']) assert 'envdsn' == config['postgres']['dsn'] maplist = config['sync_map'] assert 1 == len(maplist) assert 'DEBUG' == config['verbosity'] # logger.warning is called once for unknown_key, not for privileges. assert 1 == warn.call_count
def test_find_filename_default(mocker): stat = mocker.patch('ldap2pg.config.stat') from ldap2pg.config import Configuration, NoConfigurationError config = Configuration() def mk_oserror(errno=None): e = OSError() e.errno = errno return e # Search default path stat.side_effect = [ mk_oserror(), mk_oserror(13), mocker.Mock(st_mode=0o600), ] filename, mode = config.find_filename(environ=dict()) assert config._file_candidates[2] == filename assert 0o600 == mode # No files at all stat.side_effect = OSError() with pytest.raises(NoConfigurationError): config.find_filename(environ=dict())
def test_security(): from ldap2pg.config import Configuration config = Configuration() minimal_config = dict(sync_map=[]) with pytest.raises(ValueError): config.merge(environ=dict(), file_config=dict( minimal_config, ldap=dict(password='******'), )) with pytest.raises(ValueError): # Refuse world readable postgres URI with password config.merge(environ=dict(), file_config=dict( minimal_config, postgres=dict(dsn='password=unsecure'), )) with pytest.raises(ValueError): # Refuse world readable postgres URI with password config.merge(environ=dict(), file_config=dict( minimal_config, postgres=dict(dsn='postgres://*****:*****@h'), )) config.merge(environ=dict(), file_config=dict( minimal_config, postgres=dict(dsn='postgres://u@h'), ))
def test_find_filename_custom(mocker): stat = mocker.patch('ldap2pg.config.stat') from ldap2pg.config import Configuration, UserError config = Configuration() # Read from env var LDAP2PG_CONFIG stat.reset_mock() stat.side_effect = [ OSError(), AssertionError("Not reached."), ] with pytest.raises(UserError): config.find_filename(environ=dict(LDAP2PG_CONFIG=b'my.yml')) # Read from args stat.reset_mock() stat.side_effect = [ mocker.Mock(st_mode=0o600), AssertionError("Not reached."), ] filename, mode = config.find_filename( environ=dict(LDAP2PG_CONFIG=b'env.yml'), args=MockArgs(config='argv.yml'), ) assert filename.endswith('argv.yml')
def test_find_filename_stdin(): from ldap2pg.config import Configuration config = Configuration() filename, mode = config.find_filename(environ=dict(LDAP2PG_CONFIG=b'-'), ) assert '-' == filename assert 0o400 == mode
def test_has_ldap(): from ldap2pg.config import Configuration config = Configuration() config['sync_map'] = [dict(roles=dict())] assert not config.has_ldap_query() config['sync_map'] = [dict(ldap=dict())] assert config.has_ldap_query()
def test_read_yml(): from io import StringIO from ldap2pg.config import Configuration, ConfigurationError config = Configuration() fo = StringIO("- role: alice") payload = config.read(fo, 'memory', mode=0o0) assert 'sync_map' in payload fo = StringIO("sync_map: []") payload = config.read(fo, 'memory', mode=0o644) assert 'sync_map' in payload assert payload['world_readable'] is True # Refuse empty file (e.g. /dev/null) with pytest.raises(ConfigurationError): fo = StringIO("") config.read(fo, 'memory', mode=0o600) with pytest.raises(ConfigurationError): fo = StringIO("bad_value") payload = config.read(fo, 'memory', mode=0o600) with pytest.raises(ConfigurationError): fo = StringIO("bad: { yaml ] *&") payload = config.read(fo, 'memory', mode=0o600) # No sync_map. with pytest.raises(ConfigurationError): fo = StringIO("postgres: {}") payload = config.read(fo, 'memory', mode=0o600)
def test_logging_config(): from ldap2pg.config import Configuration, UserError config = Configuration() config['verbosity'] = 'DEBUG' dict_ = config.logging_dict() assert 'DEBUG' == dict_['loggers']['ldap2pg']['level'] with pytest.raises(UserError): config.bootstrap(environ=dict(VERBOSITY='TOTO'))
def test_logging_config(): from ldap2pg.config import Configuration config = Configuration() config['verbose'] = True l = config.logging_dict() assert 'DEBUG' == l['loggers']['ldap2pg']['level'] config['verbose'] = False l = config.logging_dict() assert 'INFO' == l['loggers']['ldap2pg']['level']
def test_load_badfiles(mocker): environ = dict() mocker.patch('ldap2pg.config.os.environ', environ) ff = mocker.patch('ldap2pg.config.Configuration.find_filename') merge = mocker.patch('ldap2pg.config.Configuration.merge') from ldap2pg.config import ( Configuration, ConfigurationError, NoConfigurationError, UserError, ) config = Configuration() # No file specified ff.side_effect = NoConfigurationError() config.load(argv=['--color']) ff.side_effect = None # Invalid file ff.return_value = ['filename.yml', 0o0] merge.side_effect = ValueError() o = mocker.patch('ldap2pg.config.open', mocker.mock_open(), create=True) with pytest.raises(ConfigurationError): config.load(argv=[]) # Not readable. o.side_effect = OSError("failed to open") with pytest.raises(UserError): config.load(argv=[])
def test_read_yml(): from io import StringIO from ldap2pg.config import Configuration, ConfigurationError config = Configuration() fo = StringIO("- role: alice") payload = config.read(fo, 'memory', mode=0o0) assert 'sync_map' in payload fo = StringIO("entry: value") payload = config.read(fo, 'memory', mode=0o644) assert 'entry' in payload assert payload['world_readable'] is True # Accept empty file (e.g. /dev/null) fo = StringIO("") payload = config.read(fo, 'memory', mode=0o600) assert payload['world_readable'] is False with pytest.raises(ConfigurationError): fo = StringIO("bad_value") payload = config.read(fo, 'memory', mode=0o600) with pytest.raises(ConfigurationError): fo = StringIO("bad: { yaml ] *&") payload = config.read(fo, 'memory', mode=0o600)
def test_load_stdin(mocker): environ = dict() mocker.patch('ldap2pg.config.os.environ', environ) ff = mocker.patch('ldap2pg.config.Configuration.find_filename') mocker.patch('ldap2pg.config.open', create=True) read = mocker.patch('ldap2pg.config.Configuration.read') from ldap2pg.config import Configuration config = Configuration() ff.return_value = ['-', 0o400] read.return_value = dict(sync_map=[dict(role='alice')]) config.load(argv=[]) maplist = config['sync_map'] assert 1 == len(maplist)
def test_load_file(mocker): environ = dict() mocker.patch('ldap2pg.config.os.environ', environ) ff = mocker.patch('ldap2pg.config.Configuration.find_filename') mocker.patch('ldap2pg.config.open', create=True) read = mocker.patch('ldap2pg.config.Configuration.read') from ldap2pg.config import Configuration config = Configuration() ff.return_value = ['filename.yml', 0o0] read.return_value = dict(sync_map=[dict(role='alice')]) # send one env var for LDAP bind environ.update(dict(LDAPPASSWORD=b'envpass')) config.load(argv=['--verbose']) assert 'envpass' == config['ldap']['password'] maplist = config['sync_map'] assert 1 == len(maplist) assert 'DEBUG' == config['verbosity']
def test_merge(): from ldap2pg.config import Configuration # Noop config = Configuration() config.merge(file_config={}, environ={}) minimal_config = dict(verbose=True, sync_map=[]) config.merge( file_config=minimal_config, environ=dict(), ) config.merge( file_config=minimal_config, environ=dict(LDAPPASSWORD=b'envpass', PGDSN=b'envdsn'), ) assert 'envpass' == config['ldap']['password'] assert 'envdsn' == config['postgres']['dsn']
def test_load(mocker): environ = dict() mocker.patch('ldap2pg.config.os.environ', environ) ff = mocker.patch('ldap2pg.config.Configuration.find_filename') read = mocker.patch('ldap2pg.config.Configuration.read') o = mocker.patch('ldap2pg.config.open', create=True) from ldap2pg.config import ( Configuration, ConfigurationError, NoConfigurationError, UserError, ) config = Configuration() ff.side_effect = NoConfigurationError() # Missing sync_map with pytest.raises(ConfigurationError): config.load(argv=[]) ff.side_effect = None # Find `filename.yml` ff.return_value = ['filename.yml', 0o0] # Not readable. o.side_effect = OSError("failed to open") with pytest.raises(UserError): config.load(argv=[]) # Readable.. o.side_effect = None # ...containing mapping read.return_value = dict(sync_map=dict(ldap=dict(), role=dict())) # send one env var for LDAP bind environ.update(dict(LDAP_BIND='envbind')) config.load(argv=['--verbose']) assert 'envbind' == config['ldap']['bind'] assert 1 == len(config['sync_map']) assert 'ldap' in config['sync_map'][0] assert config['verbose'] is True
def test_merge_and_mappings(): from ldap2pg.config import Configuration # Noop config = Configuration() with pytest.raises(ValueError): config.merge(file_config={}, environ={}) # Minimal configuration minimal_config = dict( ldap=dict(host='confighost'), sync_map=dict(ldap=dict(), role=dict()), ) config.merge( file_config=minimal_config, environ=dict(), ) config.merge( file_config=minimal_config, environ=dict(LDAP_PASSWORD='******', PGDSN='envdsn'), ) assert 'confighost' == config['ldap']['host'] assert 'envpass' == config['ldap']['password'] assert 'envdsn' == config['postgres']['dsn']
def test_read_yml(): from io import StringIO from ldap2pg.config import Configuration, ConfigurationError config = Configuration() # Deny list file fo = StringIO("- listentry") with pytest.raises(ConfigurationError): config.read(fo, mode=0o0) fo = StringIO("entry: value") payload = config.read(fo, mode=0o644) assert 'entry' in payload assert payload['world_readable'] is True # Accept empty file (e.g. /dev/null) fo = StringIO("") payload = config.read(fo, mode=0o600) assert payload['world_readable'] is False
def test_show_versions(mocker): from ldap2pg.config import Configuration config = Configuration() with pytest.raises(SystemExit): config.load(argv=['--version'])