Skip to content

Commit 4709a2a

Browse files
authored
Merge pull request #19 from SergeyTsaplin/fix-auth-for-with-scope-calls
Fix password auth for `with_scope` calls
2 parents 3274ab4 + 624bc88 commit 4709a2a

File tree

8 files changed

+194
-105
lines changed

8 files changed

+194
-105
lines changed

aioetcd3/base.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,7 @@ def _update_cluster_info(self, header):
4949
def get_cluster_info(self):
5050
return self.last_response_info
5151

52-
async def grpc_call(self, stub_func, request, timeout=_default_timeout, skip_auth=False):
53-
if timeout is _default_timeout:
54-
timeout = self.timeout
55-
56-
# If the username and password are set, trying to call the auth.authenticate
57-
# method to get the auth token. If the token already received - just use it.
52+
async def _authenticate_if_needed(self, skip_auth=False):
5853
if self.username is not None and self.password is not None and not skip_auth:
5954
if self._metadata is None: # We need to call self._authenticate for the first rpc call only
6055
try:
@@ -64,6 +59,14 @@ async def grpc_call(self, stub_func, request, timeout=_default_timeout, skip_aut
6459
raise AuthError(exc._state.details, exc._state.debug_error_string)
6560
raise exc
6661

62+
async def grpc_call(self, stub_func, request, timeout=_default_timeout, skip_auth=False):
63+
if timeout is _default_timeout:
64+
timeout = self.timeout
65+
66+
# If the username and password are set, trying to call the auth.authenticate
67+
# method to get the auth token. If the token already received - just use it.
68+
await self._authenticate_if_needed(skip_auth=skip_auth)
69+
6770
try:
6871
response = await stub_func(
6972
request, timeout=timeout, credentials=self._call_credentials, metadata=self._metadata

aioetcd3/lease.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,13 @@ async def generate_request(request):
8787
for re in [request]:
8888
yield re
8989

90+
await self._authenticate_if_needed()
9091
new_lease = None
91-
async with self._lease_stub.LeaseKeepAlive.with_scope(generate_request(lease_request)) as result:
92+
async with self._lease_stub.LeaseKeepAlive.with_scope(
93+
generate_request(lease_request),
94+
credentials=self._call_credentials,
95+
metadata=self._metadata
96+
) as result:
9297
async for r in result:
9398
self._update_cluster_info(r.header)
9499
new_lease = RLease(r.TTL, r.ID, self)

aioetcd3/watch.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,12 @@ async def input_iterator(input_queue):
205205
if n is None:
206206
break
207207
yield n
208+
208209
async def watch_call(input_queue, watch_stub, output_pipe):
209-
async with watch_stub.Watch.with_scope(input_iterator(input_queue)) as response_iter:
210+
await self._authenticate_if_needed()
211+
async with watch_stub.Watch.with_scope(
212+
input_iterator(input_queue), credentials=self._call_credentials, metadata=self._metadata
213+
) as response_iter:
210214
async for r in response_iter:
211215
await output_pipe.put(r)
212216
last_received_revision = None

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from setuptools import setup, find_packages
44

5-
version = "1.12"
5+
version = "1.13"
66

77
try:
88
import pypandoc

test/test_auth.py

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from aioetcd3.help import range_all, PER_RW
77
from aioetcd3.exceptions import AuthError, Unauthenticated, PermissionDenied
88

9+
from .utils import switch_auth_off, switch_auth_on
10+
911

1012
def asynctest(f):
1113
@functools.wraps(f)
@@ -153,22 +155,12 @@ async def setUp(self):
153155
self.endpoints = "127.0.0.1:2379"
154156
self.unauthenticated_client = client(endpoint=self.endpoints)
155157
await self.cleanUp()
156-
await self.prepare_users_and_roles()
158+
await switch_auth_on(self.unauthenticated_client)
157159
self.client_client = client(
158160
endpoint=self.endpoints, username="client", password="client"
159161
)
160162
self.root_client = client(endpoint=self.endpoints, username="root", password="root")
161163

162-
async def prepare_users_and_roles(self):
163-
await self.unauthenticated_client.user_add(username="root", password="root")
164-
await self.unauthenticated_client.role_add(name='root')
165-
await self.unauthenticated_client.user_grant_role(username='root', role='root')
166-
167-
await self.unauthenticated_client.user_add(username='client', password='client')
168-
await self.unauthenticated_client.role_add(name='client')
169-
await self.unauthenticated_client.user_grant_role(username='client', role='client')
170-
await self.unauthenticated_client.auth_enable()
171-
172164
async def create_kv_for_test(self):
173165
await self.root_client.put('/foo', '/foo')
174166
value, meta = await self.root_client.get('/foo')
@@ -208,30 +200,12 @@ async def test_wrong_token(self):
208200
with self.assertRaises(Unauthenticated) as exc:
209201
await new_client.get("/foo")
210202

211-
async def delete_all_users(self):
212-
# It's necessary to use unauthenticated client here, because root user
213-
# cannot be deleted when the auth is enabled
214-
users = await self.unauthenticated_client.user_list()
215-
216-
for u in users:
217-
await self.unauthenticated_client.user_delete(username=u)
218-
219-
async def delete_all_roles(self):
220-
# It's necessary to use unauthenticated client here, because root user
221-
# cannot be deleted when the auth is enabled
222-
roles = await self.unauthenticated_client.role_list()
223-
224-
for r in roles:
225-
await self.unauthenticated_client.role_delete(name=r)
226-
227203
async def cleanUp(self):
228204
await self.unauthenticated_client.delete(range_all())
229-
await self.delete_all_users()
230-
await self.delete_all_roles()
231205

232206
@asynctest
233207
async def tearDown(self):
234-
await self.root_client.auth_disable()
208+
await switch_auth_off(self.root_client, self.unauthenticated_client)
235209
await self.cleanUp()
236210

237211

@@ -244,23 +218,13 @@ async def setUp(self):
244218
ca_file="test/cfssl/ca.pem",
245219
)
246220
await self.cleanUp()
247-
await self.prepare_users_and_roles()
221+
await switch_auth_on(self.unauthenticated_client)
248222
self.root_client = ssl_client(endpoint=self.endpoints, ca_file="test/cfssl/ca.pem",
249223
username="root", password="root")
250224

251225
self.client_client = ssl_client(endpoint=self.endpoints, ca_file="test/cfssl/ca.pem",
252226
username="client", password="client")
253227

254-
async def prepare_users_and_roles(self):
255-
await self.unauthenticated_client.user_add(username="root", password="root")
256-
await self.unauthenticated_client.role_add(name='root')
257-
await self.unauthenticated_client.user_grant_role(username='root', role='root')
258-
259-
await self.unauthenticated_client.user_add(username='client', password='client')
260-
await self.unauthenticated_client.role_add(name='client')
261-
await self.unauthenticated_client.user_grant_role(username='client', role='client')
262-
await self.unauthenticated_client.auth_enable()
263-
264228
async def create_kv_for_test(self):
265229
await self.root_client.put('/foo', '/foo')
266230
value, meta = await self.root_client.get('/foo')
@@ -306,28 +270,10 @@ async def test_wrong_token(self):
306270
with self.assertRaises(Unauthenticated) as exc:
307271
await new_client.get("/foo")
308272

309-
async def delete_all_users(self):
310-
# It's necessary to use unauthenticated client here, because root user
311-
# cannot be deleted when the auth is enabled
312-
users = await self.unauthenticated_client.user_list()
313-
314-
for u in users:
315-
await self.unauthenticated_client.user_delete(username=u)
316-
317-
async def delete_all_roles(self):
318-
# It's necessary to use unauthenticated client here, because root user
319-
# cannot be deleted when the auth is enabled
320-
roles = await self.unauthenticated_client.role_list()
321-
322-
for r in roles:
323-
await self.unauthenticated_client.role_delete(name=r)
324-
325273
async def cleanUp(self):
326274
await self.unauthenticated_client.delete(range_all())
327-
await self.delete_all_users()
328-
await self.delete_all_roles()
329275

330276
@asynctest
331277
async def tearDown(self):
332-
await self.root_client.auth_disable()
278+
await switch_auth_off(self.root_client, self.unauthenticated_client)
333279
await self.cleanUp()

test/test_lease.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import functools
44

55
from aioetcd3.client import client
6-
from aioetcd3.help import range_all
6+
from aioetcd3.help import range_all, range_prefix, PER_RW
7+
8+
from .utils import switch_auth_on, switch_auth_off
79

810

911
def asynctest(f):
@@ -17,13 +19,12 @@ def _f(self):
1719
class LeaseTest(unittest.TestCase):
1820
@asynctest
1921
async def setUp(self):
20-
endpoints = "127.0.0.1:2379"
21-
self.client = client(endpoint=endpoints)
22+
self.endpoints = "127.0.0.1:2379"
23+
self.client = client(endpoint=self.endpoints)
2224

2325
await self.cleanUp()
2426

25-
@asynctest
26-
async def test_lease_1(self):
27+
async def _lease_1(self):
2728
lease = await self.client.grant_lease(ttl=5)
2829
self.assertEqual(lease.ttl, 5)
2930

@@ -42,7 +43,10 @@ async def test_lease_1(self):
4243
self.assertEqual(len(keys), 0)
4344

4445
@asynctest
45-
async def test_lease_2(self):
46+
async def test_lease_1(self):
47+
await self._lease_1()
48+
49+
async def _lease_2(self):
4650
lease = await self.client.grant_lease(ttl=5)
4751
self.assertEqual(lease.ttl, 5)
4852

@@ -68,9 +72,11 @@ async def test_lease_2(self):
6872
self.assertIsNone(lease)
6973
self.assertEqual(len(keys), 0)
7074

71-
7275
@asynctest
73-
async def test_lease_3(self):
76+
async def test_lease_2(self):
77+
await self._lease_2()
78+
79+
async def _lease_3(self):
7480
lease = await self.client.grant_lease(ttl=5)
7581
self.assertEqual(lease.ttl, 5)
7682

@@ -85,6 +91,39 @@ async def test_lease_3(self):
8591
self.assertIsNone(value)
8692
self.assertIsNone(meta)
8793

94+
@asynctest
95+
async def test_lease_3(self):
96+
await self._lease_3()
97+
98+
async def _run_test_with_auth(self, test):
99+
default_client = self.client
100+
await switch_auth_on(default_client)
101+
root_client = client(endpoint=self.endpoints, username="root", password="root")
102+
await root_client.role_grant_permission(name='client', key_range=range_prefix('/testlease'), permission=PER_RW)
103+
self.client = client(endpoint=self.endpoints, username="client", password="client")
104+
try:
105+
await test()
106+
finally:
107+
await switch_auth_off(
108+
root_client,
109+
default_client
110+
)
111+
await root_client.close()
112+
await self.client.close()
113+
self.client = default_client
114+
115+
@asynctest
116+
async def test_lease_1_with_auth(self):
117+
await self._run_test_with_auth(self._lease_1)
118+
119+
@asynctest
120+
async def test_lease_2_with_auth(self):
121+
await self._run_test_with_auth(self._lease_2)
122+
123+
@asynctest
124+
async def test_lease_3_with_auth(self):
125+
await self._run_test_with_auth(self._lease_3)
126+
88127
@asynctest
89128
async def tearDown(self):
90129
await self.cleanUp()

0 commit comments

Comments
 (0)