Example #1
0
def test_creation_with_maximal_fields():
    info = ConnectionInfo(
        server='https://localhost',
        ca_path='/ca/path',
        ca_data=b'ca_data',
        insecure=True,
        username='******',
        password='******',
        scheme='scheme',
        token='token',
        certificate_path='/cert/path',
        certificate_data=b'cert_data',
        private_key_path='/pkey/path',
        private_key_data=b'pkey_data',
        default_namespace='default',
    )
    assert info.server == 'https://localhost'
    assert info.ca_path == '/ca/path'
    assert info.ca_data == b'ca_data'
    assert info.insecure is True
    assert info.username == 'username'
    assert info.password == 'password'
    assert info.scheme == 'scheme'
    assert info.token == 'token'
    assert info.certificate_path == '/cert/path'
    assert info.certificate_data == b'cert_data'
    assert info.private_key_path == '/pkey/path'
    assert info.private_key_data == b'pkey_data'
    assert info.default_namespace == 'default'
Example #2
0
async def test_duplicates_are_remembered(mocker):
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    info2 = ConnectionInfo(
        server='https://expected/')  # another instance, same fields
    vault = Vault()
    mocker.patch.object(vault._ready, 'wait_for')

    await vault.populate({key1: info1})
    await vault.invalidate(key1)
    await vault.populate({key1: info2})

    # There should be nothing to yield, despite the second populate() call.
    with pytest.raises(LoginError):
        async for _, _ in vault:
            pass
Example #3
0
async def test_invalidation_continues_if_something_is_left():
    exc = Exception("Sample error.")
    key1 = VaultKey('key1')
    key2 = VaultKey('key2')
    info1 = ConnectionInfo(server='https://server1/')
    info2 = ConnectionInfo(server='https://server2/')
    vault = Vault()

    await vault.populate({key1: info1})
    await vault.populate({key2: info2})
    await vault.invalidate(key1, exc=exc)  # no exception!

    results = []
    async for key, info in vault:
        results.append((key, info))

    assert len(results) == 1
    assert results[0][0] == key2
    assert results[0][1] is info2
Example #4
0
async def test_invalidation_continues_if_nothing_is_left_without_exception(
        mocker):
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    mocker.patch.object(vault._ready, 'wait_for')

    await vault.populate({key1: info1})
    await vault.invalidate(key1)

    assert vault._ready.wait_for.await_args_list == [((True, ), )]
Example #5
0
async def test_yielding_after_invalidation(mocker):
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    mocker.patch.object(vault._ready, 'wait_for')

    await vault.populate({key1: info1})
    await vault.invalidate(key1)

    with pytest.raises(LoginError):
        async for _, _ in vault:
            pass
Example #6
0
async def test_ca_insecure(vault, cafile):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            insecure=True,
        ),
    })
    session = await fn()

    async with session:
        ctx = session.connector._ssl
        assert ctx.verify_mode == ssl.CERT_NONE
Example #7
0
async def test_header_with_schema_only(vault):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            scheme='Digest xyz',
        ),
    })
    session = await fn()

    async with session:
        assert session._default_auth is None
        assert session._default_headers['Authorization'] == 'Digest xyz'
Example #8
0
async def test_header_with_token_only(vault):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            token='token',
        ),
    })
    session = await fn()

    async with session:
        assert session._default_auth is None
        assert session._default_headers['Authorization'] == 'Bearer token'
Example #9
0
async def test_invalidation_reraises_if_nothing_is_left_with_exception(mocker):
    exc = Exception("Sample error.")
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    mocker.patch.object(vault._ready, 'wait_for')

    await vault.populate({key1: info1})
    with pytest.raises(Exception) as e:
        await vault.invalidate(key1, exc=exc)

    assert e.value is exc
    assert vault._ready.wait_for.await_args_list == [((True, ), )]
Example #10
0
async def test_clientcert_as_data(vault, cafile, certbase64, pkeybase64):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            ca_path=cafile,
            certificate_data=certbase64,
            private_key_data=pkeybase64,
        ),
    })
    session = await fn()

    async with session:
        pass
async def test_session_is_passed_through(fake_vault, resp_mocker, aresponses,
                                         hostname, resource, namespace):

    result = {}
    get_mock = resp_mocker(return_value=aiohttp.web.json_response(result))
    aresponses.add(hostname, resource.get_url(namespace=namespace, name='xyz'),
                   'get', get_mock)

    explicit_context = APIContext(ConnectionInfo(server='http://irrelevant/'))
    context, result = await fn(1, context=explicit_context)

    async with context.session:
        assert context is explicit_context
        assert result == 101
Example #12
0
async def test_ca_as_data(vault, cabase64):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            ca_data=cabase64,
        ),
    })
    session = await fn()

    async with session:
        ctx = session.connector._ssl
        assert len(ctx.get_ca_certs()) == 1
        assert ctx.cert_store_stats()['x509'] == 1
        assert ctx.cert_store_stats()['x509_ca'] == 1
Example #13
0
async def test_basic_auth(vault):
    await vault.populate({
        'id': ConnectionInfo(
            server='http://localhost',
            username='******',
            password='******',
        ),
    })
    session = await fn()

    async with session:
        assert session._default_auth.login == 'username'
        assert session._default_auth.password == 'password'
        assert 'Authorization' not in session._default_headers
Example #14
0
async def test_yielding_after_population(mocker):
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    mocker.patch.object(vault._ready, 'wait_for')

    await vault.populate({key1: info1})

    results = []
    async for key, info in vault:
        results.append((key, info))

    assert len(results) == 1
    assert results[0][0] == key1
    assert results[0][1] is info1
Example #15
0
def test_creation_with_minimal_fields():
    info = ConnectionInfo(server='https://localhost', )
    assert info.server == 'https://localhost'
    assert info.ca_path is None
    assert info.ca_data is None
    assert info.insecure is None
    assert info.username is None
    assert info.password is None
    assert info.scheme is None
    assert info.token is None
    assert info.certificate_path is None
    assert info.certificate_data is None
    assert info.private_key_path is None
    assert info.private_key_data is None
    assert info.default_namespace is None
Example #16
0
async def test_caches_with_different_purposes(mocker):
    key1 = VaultKey('some-key')
    obj1 = object()
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    await vault.populate({key1: info1})

    def factory(_: ConnectionInfo) -> object:
        return obj1

    factory_spy = mocker.MagicMock(spec=factory, wraps=factory)

    async for _, _, _ in vault.extended(factory_spy, purpose='A'):
        pass

    async for _, _, _ in vault.extended(factory_spy, purpose='B'):
        pass

    assert factory_spy.call_count == 2  # once per purpose.
Example #17
0
def fake_vault(mocker, hostname):
    """
    Provide a freshly created and populated authentication vault for every test.

    Most of the tests expect some credentials to be at least provided
    (even if not used). So, we create and set the vault as if every coroutine
    is invoked from the central `operator` method (where it is set normally).

    Any blocking activities are mocked, so that the tests do not hang.
    """
    from kopf._cogs.clients import auth

    key = VaultKey('fixture')
    info = ConnectionInfo(server=f'https://{hostname}')
    vault = Vault({key: info})
    token = auth.vault_var.set(vault)
    mocker.patch.object(vault._ready, 'wait_for')
    try:
        yield vault
    finally:
        auth.vault_var.reset(token)
Example #18
0
async def test_caches_from_factory(mocker):
    key1 = VaultKey('some-key')
    obj1 = object()
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    await vault.populate({key1: info1})

    def factory(_: ConnectionInfo) -> object:
        return obj1

    factory_spy = mocker.MagicMock(spec=factory, wraps=factory)

    results = []
    async for key, info, obj in vault.extended(factory_spy):
        results.append((key, info, obj))

    assert len(results) == 1
    assert results[0][0] == key1
    assert results[0][1] is info1
    assert results[0][2] is obj1

    assert factory_spy.called
async def test_single_credentials_provided_to_vault(settings):
    info = ConnectionInfo(server='https://expected/')
    vault = Vault()
    registry = OperatorRegistry()

    def login_fn(**_):
        return info

    # NB: id auto-detection does not work, as it is local to the test function.
    registry._activities.append(
        ActivityHandler(
            fn=login_fn,
            id='login_fn',
            activity=Activity.AUTHENTICATION,
            param=None,
            errors=None,
            timeout=None,
            retries=None,
            backoff=None,
        ))

    await authenticate(
        registry=registry,
        settings=settings,
        vault=vault,
        memo=Memo(),
        indices=OperatorIndexers().indices,
    )

    assert vault

    items = []
    async for key, info in vault:
        items.append((key, info))

    assert len(items) == 1
    assert items[0][0] == 'login_fn'
    assert items[0][1] is info
Example #20
0
async def test_evals_as_true_when_filled():
    key1 = VaultKey('some-key')
    info1 = ConnectionInfo(server='https://expected/')
    vault = Vault()
    await vault.populate({key1: info1})
    assert vault