Skip to content

Commit de05f5c

Browse files
ISSUE #390
1 parent 772e330 commit de05f5c

File tree

5 files changed

+116
-5
lines changed

5 files changed

+116
-5
lines changed

packages/plugins/minos-discovery-kong/minos/plugins/kong/client.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,37 @@
1+
from __future__ import (
2+
annotations,
3+
)
4+
from abc import ABC
15
from uuid import (
26
UUID,
37
)
48

59
import httpx as httpx
10+
from datetime import datetime
11+
from datetime import timedelta
12+
13+
import jwt
14+
from minos.common import (
15+
SetupMixin,
16+
Config,
17+
)
18+
from pytz import utc
619

720

8-
class KongClient:
21+
class KongClient: #(ABC, SetupMixin):
922
"""Kong Client class."""
1023

11-
def __init__(self, route):
12-
self.route = route
24+
def __init__(self, route: str, **kwargs): #def __init__(self, host: str, port: str, token_expiration_minutes: int, **kwargs):
25+
super().__init__(**kwargs)
26+
self.route = route #f"http://{host}:{port}"
27+
#self.token_expiration_minutes = token_expiration_minutes
28+
29+
# @classmethod
30+
# def _from_config(cls, config: Config, **kwargs) -> KongClient:
31+
# discovery_config = config.get_discovery()
32+
#
33+
# token_expiration = discovery_config.get("token-exp-minutes")
34+
# return cls(token_expiration=token_expiration, **kwargs)
1335

1436
@staticmethod
1537
async def register_service(
@@ -130,8 +152,23 @@ async def activate_basic_auth_plugin_on_route(self, route_id: str):
130152
return resp
131153

132154
async def activate_jwt_plugin_on_route(self, route_id: str):
133-
payload = {"name": "jwt", "config": {"secret_is_base64": False, "run_on_preflight": True}}
155+
payload = {"name": "jwt",
156+
"config": {"secret_is_base64": False, "run_on_preflight": True, "claims_to_verify": ["exp", "nbf"]}}
134157

135158
async with httpx.AsyncClient() as client:
136159
resp = await client.post(f"{self.route}/routes/{route_id}/plugins", json=payload)
137160
return resp
161+
162+
async def get_jwt_token(self, key: str, secret: str, algorithm: str = 'HS256', exp: datetime = None, nbf: datetime = None) -> str:
163+
payload = {"iss": key, "exp": exp, "nbf": nbf}
164+
165+
current = datetime.now(tz=utc)
166+
167+
if not exp:
168+
#payload["exp"] = current + timedelta(minutes=self.token_expiration_minutes)
169+
payload["exp"] = current + timedelta(minutes=120)
170+
171+
if not nbf:
172+
payload["nbf"] = current
173+
174+
return jwt.encode(payload, secret, algorithm=algorithm)

packages/plugins/minos-discovery-kong/poetry.lock

Lines changed: 31 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/plugins/minos-discovery-kong/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ python = "^3.9"
3535
minos-microservice-common = { version ="^0.7.0*", allow-prereleases = true }
3636
minos-microservice-networks = { version ="^0.7.0*", allow-prereleases = true }
3737
httpx = "^0.22.0"
38+
pytz = "^2022.1"
39+
PyJWT = "^2.3.0"
3840

3941
[tool.poetry.dev-dependencies]
4042
minos-microservice-common = { path = "../../core/minos-microservice-common", develop = true }

packages/plugins/minos-discovery-kong/tests/test_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ discovery:
22
connector: minos.networks.DiscoveryConnector
33
client: minos.networks.InMemoryDiscoveryClient
44
auth-type: jwt
5+
token-exp-minutes: 60
56
host: localhost
67
port: 8001

packages/plugins/minos-discovery-kong/tests/test_kong/test_client.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
from tests.utils import (
1414
TEST_HOST,
1515
)
16+
from datetime import datetime
17+
from datetime import timedelta
18+
19+
import jwt
20+
from pytz import utc
1621

1722
PROTOCOL = "http"
1823

@@ -177,6 +182,42 @@ async def test_activate_jwt_plugin_on_route(self):
177182

178183
self.assertTrue(201 == response.status_code)
179184

185+
async def test_jwt_token_generation(self):
186+
user_uuid = uuid4()
187+
user_name = self.generate_underscore_uuid()
188+
response = await self.kong.create_consumer(username=user_name, user=user_uuid, tags=[])
189+
190+
self.assertTrue(201 == response.status_code)
191+
resp = response.json()
192+
193+
response = await self.kong.add_jwt_to_consumer(consumer=resp["id"])
194+
195+
self.assertTrue(201 == response.status_code)
196+
resp = response.json()
197+
198+
token = await self.kong.get_jwt_token(key=resp['key'], secret=resp['secret'])
199+
200+
self.assertGreater(len(token), 50)
201+
202+
async def test_jwt_token_generation_with_expiration(self):
203+
user_uuid = uuid4()
204+
user_name = self.generate_underscore_uuid()
205+
response = await self.kong.create_consumer(username=user_name, user=user_uuid, tags=[])
206+
207+
self.assertTrue(201 == response.status_code)
208+
resp = response.json()
209+
210+
response = await self.kong.add_jwt_to_consumer(consumer=resp["id"])
211+
212+
self.assertTrue(201 == response.status_code)
213+
resp = response.json()
214+
215+
current = datetime.now(tz=utc)
216+
token = await self.kong.get_jwt_token(key=resp['key'], secret=resp['secret'],
217+
exp=current + timedelta(minutes=10), nbf=current + timedelta(minutes=9))
218+
219+
self.assertGreater(len(token), 50)
220+
180221

181222
if __name__ == "__main__":
182223
unittest.main()

0 commit comments

Comments
 (0)