appmesh 1.4.2__py3-none-any.whl → 1.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
appmesh/http_client.py CHANGED
@@ -7,7 +7,7 @@ import os
7
7
  from datetime import datetime
8
8
  from enum import Enum, unique
9
9
  from http import HTTPStatus
10
- from typing import Tuple, Union
10
+ from typing import Optional, Tuple, Union
11
11
  from urllib import parse
12
12
  import aniso8601
13
13
  import requests
@@ -107,6 +107,8 @@ class AppMeshClient(metaclass=abc.ABCMeta):
107
107
  DEFAULT_SSL_CLIENT_CERT_PATH = "/opt/appmesh/ssl/client.pem"
108
108
  DEFAULT_SSL_CLIENT_KEY_PATH = "/opt/appmesh/ssl/client-key.pem"
109
109
 
110
+ DEFAULT_JWT_AUDIENCE = "appmesh-service"
111
+
110
112
  JSON_KEY_MESSAGE = "message"
111
113
  HTTP_USER_AGENT = "appmesh/python"
112
114
  HTTP_HEADER_KEY_USER_AGENT = "User-Agent"
@@ -251,7 +253,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
251
253
  ########################################
252
254
  # Security
253
255
  ########################################
254
- def login(self, user_name: str, user_pwd: str, totp_code="", timeout_seconds=DURATION_ONE_WEEK_ISO) -> str:
256
+ def login(self, user_name: str, user_pwd: str, totp_code: Optional[str] = "", timeout_seconds: Union[str, int] = DURATION_ONE_WEEK_ISO, audience: Optional[str] = None) -> str:
255
257
  """Login with user name and password
256
258
 
257
259
  Args:
@@ -259,6 +261,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
259
261
  user_pwd (str): the password of the user.
260
262
  totp_code (str, optional): the TOTP code if enabled for the user.
261
263
  timeout_seconds (int | str, optional): token expire timeout of seconds. support ISO 8601 durations (e.g., 'P1Y2M3DT4H5M6S' 'P1W').
264
+ audience (str, optional): The audience of the JWT token, should be available by JWT service configuration (default is 'appmesh-service').
262
265
 
263
266
  Returns:
264
267
  str: JWT token.
@@ -270,6 +273,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
270
273
  header={
271
274
  "Authorization": "Basic " + base64.b64encode((user_name + ":" + user_pwd).encode()).decode(),
272
275
  "Expire-Seconds": self._parse_duration(timeout_seconds),
276
+ **({"Audience": audience} if audience else {}),
273
277
  },
274
278
  )
275
279
  if resp.status_code == HTTPStatus.OK:
@@ -308,11 +312,11 @@ class AppMeshClient(metaclass=abc.ABCMeta):
308
312
  self.jwt_token = None
309
313
  return resp.status_code == HTTPStatus.OK
310
314
 
311
- def authentication(self, token: str, permission=None) -> bool:
315
+ def authentication(self, token: str, permission: Optional[str] = None, audience: Optional[str] = None) -> bool:
312
316
  """Deprecated: Use authenticate() instead."""
313
317
  return self.authenticate(token, permission)
314
318
 
315
- def authenticate(self, token: str, permission: str = None) -> bool:
319
+ def authenticate(self, token: str, permission: Optional[str] = None, audience: Optional[str] = None) -> bool:
316
320
  """Authenticate with a token and verify permission if specified.
317
321
 
318
322
  Args:
@@ -321,15 +325,17 @@ class AppMeshClient(metaclass=abc.ABCMeta):
321
325
  permission ID can be:
322
326
  - pre-defined by App Mesh from security.yaml (e.g 'app-view', 'app-delete')
323
327
  - defined by input from role_update() or security.yaml
328
+ audience (str, optional):The audience of the JWT token used to verify the target service.
324
329
 
325
330
  Returns:
326
331
  bool: authentication success or failure.
327
332
  """
328
333
  old_token = self.jwt_token
329
334
  self.jwt_token = token
330
- headers = {}
331
- if permission:
332
- headers["Auth-Permission"] = permission
335
+ headers = {
336
+ **({"Audience": audience} if audience else {}),
337
+ **({"Auth-Permission": permission} if permission else {}),
338
+ }
333
339
  resp = self._request_http(AppMeshClient.Method.POST, path="/appmesh/auth", header=headers)
334
340
  if resp.status_code != HTTPStatus.OK:
335
341
  self.jwt_token = old_token
@@ -343,7 +349,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
343
349
  timeout_seconds (int | str, optional): token expire timeout of seconds. support ISO 8601 durations (e.g., 'P1Y2M3DT4H5M6S' 'P1W').
344
350
 
345
351
  Returns:
346
- str: The new JWT token if renew success, otherwise return None.
352
+ str: The new JWT token if renew success, the old token will be blocked.
347
353
  """
348
354
  assert self.jwt_token
349
355
  resp = self._request_http(
@@ -378,16 +384,19 @@ class AppMeshClient(metaclass=abc.ABCMeta):
378
384
  totp_code (str): TOTP code
379
385
 
380
386
  Returns:
381
- bool: success or failure.
387
+ str: The new JWT token if setup success, the old token will be blocked.
382
388
  """
383
389
  resp = self._request_http(
384
390
  method=AppMeshClient.Method.POST,
385
391
  path="/appmesh/totp/setup",
386
392
  header={"Totp": totp_code},
387
393
  )
388
- if resp.status_code != HTTPStatus.OK:
394
+ if resp.status_code == HTTPStatus.OK:
395
+ if "Access-Token" in resp.json():
396
+ self.jwt_token = resp.json()["Access-Token"]
397
+ return self.jwt_token
398
+ else:
389
399
  raise Exception(resp.text)
390
- return resp.status_code == HTTPStatus.OK
391
400
 
392
401
  def disable_totp(self, user: str = "self") -> bool:
393
402
  """Disable 2FA for the specified user.
@@ -574,105 +583,6 @@ class AppMeshClient(metaclass=abc.ABCMeta):
574
583
  raise Exception(resp.text)
575
584
  return resp.status_code == HTTPStatus.OK
576
585
 
577
- ########################################
578
- # Cloud management
579
- ########################################
580
- def view_all_cloud_apps(self) -> dict:
581
- """Get information about all cloud applications.
582
-
583
- Returns:
584
- dict: cloud applications in JSON format.
585
- """
586
- resp = self._request_http(AppMeshClient.Method.GET, path="/appmesh/cloud/applications")
587
- if resp.status_code != HTTPStatus.OK:
588
- raise Exception(resp.text)
589
- return resp.json()
590
-
591
- def view_cloud_app(self, app_name: str) -> dict:
592
- """Get information about a specific cloud application.
593
-
594
- Args:
595
- app_name (str): the application name.
596
-
597
- Returns:
598
- dict: application in JSON format.
599
- """
600
- resp = self._request_http(AppMeshClient.Method.GET, path=f"/appmesh/cloud/app/{app_name}")
601
- if resp.status_code != HTTPStatus.OK:
602
- raise Exception(resp.text)
603
- return resp.json()
604
-
605
- def get_cloud_app_output(self, app_name: str, host_name: str, stdout_position: int = 0, stdout_index: int = 0, stdout_maxsize: int = 10240, process_uuid: str = ""):
606
- """Get the stdout/stderr of a cloud application.
607
-
608
- Args:
609
- app_name (str): the application name
610
- host_name (str): the target host name where the application is running
611
- stdout_position (int, optional): start read position, 0 means start from beginning.
612
- stdout_index (int, optional): index of history process stdout, 0 means get from current running process,
613
- the stdout number depends on 'stdout_cache_size' of the application.
614
- stdout_maxsize (int, optional): max buffer size to read.
615
- process_uuid (str, optional): used to get the specified process.
616
-
617
- Returns:
618
- bool: success or failure.
619
- str: output string.
620
- int or None: current read position.
621
- int or None: process exit code.
622
- """
623
- resp = self._request_http(
624
- AppMeshClient.Method.GET,
625
- path=f"/appmesh/cloud/app/{app_name}/output/{host_name}",
626
- query={
627
- "stdout_position": str(stdout_position),
628
- "stdout_index": str(stdout_index),
629
- "stdout_maxsize": str(stdout_maxsize),
630
- "process_uuid": process_uuid,
631
- },
632
- )
633
- out_position = int(resp.headers["Output-Position"]) if "Output-Position" in resp.headers else None
634
- exit_code = int(resp.headers["Exit-Code"]) if "Exit-Code" in resp.headers else None
635
- return (resp.status_code == HTTPStatus.OK), resp.text, out_position, exit_code
636
-
637
- def delete_cloud_app(self, app_name: str) -> bool:
638
- """Delete a cloud application.
639
-
640
- Args:
641
- app_name (str): The application name for cloud
642
-
643
- Returns:
644
- bool: success or failure.
645
- """
646
- resp = self._request_http(AppMeshClient.Method.DELETE, path=f"/appmesh/cloud/app/{app_name}")
647
- if resp.status_code != HTTPStatus.OK:
648
- raise Exception(resp.text)
649
- return resp.status_code == HTTPStatus.OK
650
-
651
- def add_cloud_app(self, app_json: dict) -> dict:
652
- """Add a new cloud application.
653
-
654
- Args:
655
- app_json (dict): the cloud application definition with replication, condition and resource requirement
656
-
657
- Returns:
658
- dict: cluster application json.
659
- """
660
- resp = self._request_http(AppMeshClient.Method.PUT, path=f"/appmesh/cloud/app/{app_json['content']['name']}", body=app_json)
661
- if resp.status_code != HTTPStatus.OK:
662
- raise Exception(resp.text)
663
- return resp.json()
664
-
665
- def view_cloud_nodes(self) -> dict:
666
- """Get a list of cluster nodes.
667
-
668
- Returns:
669
- dict: cluster node list json.
670
- """
671
- resp = self._request_http(AppMeshClient.Method.GET, path="/appmesh/cloud/nodes")
672
- if resp.status_code != HTTPStatus.OK:
673
- raise Exception(resp.text)
674
- return resp.json()
675
-
676
586
  ########################################
677
587
  # Configuration
678
588
  ########################################
@@ -885,7 +795,7 @@ class AppMeshClient(metaclass=abc.ABCMeta):
885
795
 
886
796
  Args:
887
797
  role_name (str): the role name.
888
- role_permission_json (dict): role permission definition array, e.g: ["app-control", "app-delete", "cloud-app-reg", "cloud-app-delete"]
798
+ role_permission_json (dict): role permission definition array, e.g: ["app-control", "app-delete"]
889
799
 
890
800
  Returns:
891
801
  bool: success or failure.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: appmesh
3
- Version: 1.4.2
3
+ Version: 1.4.4
4
4
  Summary: Client SDK for App Mesh
5
5
  Home-page: https://github.com/laoshanxi/app-mesh
6
6
  Author: laoshanxi
@@ -16,6 +16,17 @@ Requires-Dist: requests
16
16
  Requires-Dist: msgpack
17
17
  Requires-Dist: requests_toolbelt
18
18
  Requires-Dist: aniso8601
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: classifier
22
+ Dynamic: description
23
+ Dynamic: description-content-type
24
+ Dynamic: home-page
25
+ Dynamic: keywords
26
+ Dynamic: license
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
19
30
 
20
31
  [![language.badge]][language.url] [![standard.badge]][standard.url] [![release.badge]][release.url] [![pypi.badge]][pypi.url] [![unittest.badge]][unittest.url] [![docker.badge]][docker.url] [![cockpit.badge]][cockpit.url]
21
32
  [![Documentation Status](https://readthedocs.org/projects/app-mesh/badge/?version=latest)](https://app-mesh.readthedocs.io/en/latest/?badge=latest) [![Join the chat at https://gitter.im/app-mesh/community](https://badges.gitter.im/app-mesh/community.svg)](https://gitter.im/app-mesh/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -52,7 +63,7 @@ Refer to the [Installation doc](https://app-mesh.readthedocs.io/en/latest/Instal
52
63
  - [Read the Docs](https://app-mesh.readthedocs.io/)
53
64
  - [REST API](https://app-mesh.readthedocs.io/en/latest/Development.html#rest-apis)
54
65
  - [Command lines](https://app-mesh.readthedocs.io/en/latest/CLI.html)
55
- - [Security](https://app-mesh.readthedocs.io/en/latest/JWT.html)
66
+ - [Security](https://app-mesh.readthedocs.io/en/latest/Security.html)
56
67
 
57
68
  ## Comparison
58
69
 
@@ -111,6 +122,7 @@ Refer to the [Installation doc](https://app-mesh.readthedocs.io/en/latest/Instal
111
122
  - [Remote execute](https://app-mesh.readthedocs.io/en/latest/success/remote_run_cli_and_python.html)
112
123
  - [Python parallel run](https://app-mesh.readthedocs.io/en/latest/success/python_parallel_run.html)
113
124
  - [Secure consul cluster](https://app-mesh.readthedocs.io/en/latest/success/secure_consul_cluster.html)
125
+ - [JWT service with REST and UI](https://github.com/laoshanxi/app-mesh/blob/main/script/docker-compose-auth-service.yaml)
114
126
 
115
127
  ---
116
128
 
@@ -3,11 +3,11 @@ appmesh/app.py,sha256=9Q-SOOej-MH13BU5Dv2iTa-p-sECCJQp6ZX9DjWWmwE,10526
3
3
  appmesh/app_output.py,sha256=JK_TMKgjvaw4n_ys_vmN5S4MyWVZpmD7NlKz_UyMIM8,1015
4
4
  appmesh/app_run.py,sha256=9ISKGZ3k3kkbQvSsPfRfkOLqD9xhbqNOM7ork9F4w9c,1712
5
5
  appmesh/appmesh_client.py,sha256=0ltkqHZUq094gKneYmC0bEZCP0X9kHTp9fccKdWFWP0,339
6
- appmesh/http_client.py,sha256=byVfHkZycZFv5LePlFgKT0Pu1HBC6AhEFbnrWFR-6PA,47679
6
+ appmesh/http_client.py,sha256=wd-H4vyHlLSCy1N8znHMf3-Zwgs7ow6-voWUludtMdA,44364
7
7
  appmesh/tcp_client.py,sha256=RkHl5s8jE333BJOgxJqJ_fvjbdRQza7ciV49vLT6YO4,10923
8
8
  appmesh/tcp_messages.py,sha256=w1Kehz_aX4X2CYAUsy9mFVJRhxnLQwwc6L58W4YkQqs,969
9
9
  appmesh/tcp_transport.py,sha256=UMGby2oKV4k7lyXZUMSOe2Je34fb1w7nTkxEpatKLKg,7256
10
- appmesh-1.4.2.dist-info/METADATA,sha256=R0wCzPXHfSqN2G0jtfkOKYkikbbcyM_JwJLSMx2ToZM,11142
11
- appmesh-1.4.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
12
- appmesh-1.4.2.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
13
- appmesh-1.4.2.dist-info/RECORD,,
10
+ appmesh-1.4.4.dist-info/METADATA,sha256=lV4XJMIWhe2jKNV5NOv_q6SFdVrzN1BZLoVrvEd90Is,11501
11
+ appmesh-1.4.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
12
+ appmesh-1.4.4.dist-info/top_level.txt,sha256=-y0MNQOGJxUzLdHZ6E_Rfv5_LNCkV-GTmOBME_b6pg8,8
13
+ appmesh-1.4.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5