blob: 9911c41f020bdcac6939ed3a8d8a896c4a2161a9 [file] [log] [blame]
Adam Israelb8a82812019-03-27 14:50:11 -04001import logging
2import os
3
4import macaroonbakery.bakery as bakery
5import macaroonbakery.httpbakery as httpbakery
6import macaroonbakery.httpbakery.agent as agent
7from juju.errors import JujuAPIError
8from juju.model import Model
9
10import pytest
11
12from .. import base
13
14log = logging.getLogger(__name__)
15
16
17@base.bootstrapped
18@pytest.mark.asyncio
19@pytest.mark.xfail
20async 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
41async 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
68async 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
89def 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
100class 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 {}