| Adam Israel | b8a8281 | 2019-03-27 14:50:11 -0400 | [diff] [blame^] | 1 | import logging |
| 2 | import os |
| 3 | |
| 4 | import macaroonbakery.bakery as bakery |
| 5 | import macaroonbakery.httpbakery as httpbakery |
| 6 | import macaroonbakery.httpbakery.agent as agent |
| 7 | from juju.errors import JujuAPIError |
| 8 | from juju.model import Model |
| 9 | |
| 10 | import pytest |
| 11 | |
| 12 | from .. import base |
| 13 | |
| 14 | log = logging.getLogger(__name__) |
| 15 | |
| 16 | |
| 17 | @base.bootstrapped |
| 18 | @pytest.mark.asyncio |
| 19 | @pytest.mark.xfail |
| 20 | async def test_macaroon_auth(event_loop): |
| 21 | auth_info, username = agent_auth_info() |
| 22 | # Create a bakery client that can do agent authentication. |
| 23 | client = httpbakery.Client( |
| 24 | key=auth_info.key, |
| 25 | interaction_methods=[agent.AgentInteractor(auth_info)], |
| 26 | ) |
| 27 | |
| 28 | async with base.CleanModel(bakery_client=client) as m: |
| 29 | async with await m.get_controller() as c: |
| 30 | await c.grant_model(username, m.info.uuid, 'admin') |
| 31 | async with Model( |
| 32 | jujudata=NoAccountsJujuData(m._connector.jujudata), |
| 33 | bakery_client=client, |
| 34 | ): |
| 35 | pass |
| 36 | |
| 37 | |
| 38 | @base.bootstrapped |
| 39 | @pytest.mark.asyncio |
| 40 | @pytest.mark.xfail |
| 41 | async def test_macaroon_auth_with_bad_key(event_loop): |
| 42 | auth_info, username = agent_auth_info() |
| 43 | # Use a random key rather than the correct key. |
| 44 | auth_info = auth_info._replace(key=bakery.generate_key()) |
| 45 | # Create a bakery client can do agent authentication. |
| 46 | client = httpbakery.Client( |
| 47 | key=auth_info.key, |
| 48 | interaction_methods=[agent.AgentInteractor(auth_info)], |
| 49 | ) |
| 50 | |
| 51 | async with base.CleanModel(bakery_client=client) as m: |
| 52 | async with await m.get_controller() as c: |
| 53 | await c.grant_model(username, m.info.uuid, 'admin') |
| 54 | try: |
| 55 | async with Model( |
| 56 | jujudata=NoAccountsJujuData(m._connector.jujudata), |
| 57 | bakery_client=client, |
| 58 | ): |
| 59 | pytest.fail('Should not be able to connect with invalid key') |
| 60 | except httpbakery.BakeryException: |
| 61 | # We're expecting this because we're using the |
| 62 | # wrong key. |
| 63 | pass |
| 64 | |
| 65 | |
| 66 | @base.bootstrapped |
| 67 | @pytest.mark.asyncio |
| 68 | async def test_macaroon_auth_with_unauthorized_user(event_loop): |
| 69 | auth_info, username = agent_auth_info() |
| 70 | # Create a bakery client can do agent authentication. |
| 71 | client = httpbakery.Client( |
| 72 | key=auth_info.key, |
| 73 | interaction_methods=[agent.AgentInteractor(auth_info)], |
| 74 | ) |
| 75 | async with base.CleanModel(bakery_client=client) as m: |
| 76 | # Note: no grant of rights to the agent user. |
| 77 | try: |
| 78 | async with Model( |
| 79 | jujudata=NoAccountsJujuData(m._connector.jujudata), |
| 80 | bakery_client=client, |
| 81 | ): |
| 82 | pytest.fail('Should not be able to connect without grant') |
| 83 | except (JujuAPIError, httpbakery.DischargeError): |
| 84 | # We're expecting this because we're using the |
| 85 | # wrong user name. |
| 86 | pass |
| 87 | |
| 88 | |
| 89 | def agent_auth_info(): |
| 90 | agent_data = os.environ.get('TEST_AGENTS') |
| 91 | if agent_data is None: |
| 92 | pytest.skip('skipping macaroon_auth because no TEST_AGENTS ' |
| 93 | 'environment variable is set') |
| 94 | auth_info = agent.read_auth_info(agent_data) |
| 95 | if len(auth_info.agents) != 1: |
| 96 | raise Exception('TEST_AGENTS agent data requires exactly one agent') |
| 97 | return auth_info, auth_info.agents[0].username |
| 98 | |
| 99 | |
| 100 | class NoAccountsJujuData: |
| 101 | def __init__(self, jujudata): |
| 102 | self.__jujudata = jujudata |
| 103 | |
| 104 | def __getattr__(self, name): |
| 105 | return getattr(self.__jujudata, name) |
| 106 | |
| 107 | def accounts(self): |
| 108 | return {} |