diaspora-event-sdk 0.2.4__py3-none-any.whl → 0.2.6__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.
- diaspora_event_sdk/sdk/aws_iam_msk.py +119 -0
- diaspora_event_sdk/sdk/client.py +14 -0
- diaspora_event_sdk/sdk/kafka_client.py +3 -3
- diaspora_event_sdk/sdk/web_client.py +18 -0
- diaspora_event_sdk/version.py +1 -1
- {diaspora_event_sdk-0.2.4.dist-info → diaspora_event_sdk-0.2.6.dist-info}/METADATA +4 -4
- {diaspora_event_sdk-0.2.4.dist-info → diaspora_event_sdk-0.2.6.dist-info}/RECORD +10 -9
- {diaspora_event_sdk-0.2.4.dist-info → diaspora_event_sdk-0.2.6.dist-info}/LICENSE +0 -0
- {diaspora_event_sdk-0.2.4.dist-info → diaspora_event_sdk-0.2.6.dist-info}/WHEEL +0 -0
- {diaspora_event_sdk-0.2.4.dist-info → diaspora_event_sdk-0.2.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import base64
|
|
5
|
+
# import logging
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from urllib.parse import parse_qs, urlparse
|
|
8
|
+
|
|
9
|
+
# import boto3
|
|
10
|
+
# import botocore.session
|
|
11
|
+
# import pkg_resources
|
|
12
|
+
from .botocore.auth import SigV4QueryAuth
|
|
13
|
+
from .botocore.awsrequest import AWSRequest
|
|
14
|
+
# from botocore.config import Config
|
|
15
|
+
from .botocore.credentials import Credentials
|
|
16
|
+
|
|
17
|
+
ENDPOINT_URL_TEMPLATE = "https://kafka.{}.amazonaws.com/"
|
|
18
|
+
DEFAULT_TOKEN_EXPIRY_SECONDS = 900
|
|
19
|
+
DEFAULT_STS_SESSION_NAME = "MSKSASLDefaultSession"
|
|
20
|
+
ACTION_TYPE = "Action"
|
|
21
|
+
ACTION_NAME = "kafka-cluster:Connect"
|
|
22
|
+
SIGNING_NAME = "kafka-cluster"
|
|
23
|
+
USER_AGENT_KEY = "User-Agent"
|
|
24
|
+
LIB_NAME = "aws-msk-iam-sasl-signer-python"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __get_user_agent__():
|
|
28
|
+
return (f"{LIB_NAME}/1.0.1")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def __get_expiration_time_ms(request):
|
|
32
|
+
"""
|
|
33
|
+
Private function that parses the url and gets the expiration time
|
|
34
|
+
|
|
35
|
+
Args: request (AWSRequest): The signed aws request object
|
|
36
|
+
"""
|
|
37
|
+
# Parse the signed request
|
|
38
|
+
parsed_url = urlparse(request.url)
|
|
39
|
+
parsed_ul_params = parse_qs(parsed_url.query)
|
|
40
|
+
parsed_signing_time = datetime.strptime(parsed_ul_params['X-Amz-Date'][0],
|
|
41
|
+
"%Y%m%dT%H%M%SZ")
|
|
42
|
+
|
|
43
|
+
# Make the datetime object timezone-aware
|
|
44
|
+
signing_time = parsed_signing_time.replace(tzinfo=timezone.utc)
|
|
45
|
+
|
|
46
|
+
# Convert the Unix timestamp to milliseconds
|
|
47
|
+
expiration_timestamp_seconds = int(
|
|
48
|
+
signing_time.timestamp()) + DEFAULT_TOKEN_EXPIRY_SECONDS
|
|
49
|
+
|
|
50
|
+
# Get lifetime of token
|
|
51
|
+
expiration_timestamp_ms = expiration_timestamp_seconds * 1000
|
|
52
|
+
|
|
53
|
+
return expiration_timestamp_ms
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def __construct_auth_token(region, aws_credentials):
|
|
57
|
+
"""
|
|
58
|
+
Private function that constructs the authorization token using IAM
|
|
59
|
+
Credentials.
|
|
60
|
+
|
|
61
|
+
Args: region (str): The AWS region where the cluster is located.
|
|
62
|
+
aws_credentials (dict): The credentials to be used to generate signed
|
|
63
|
+
url. Returns: str: A base64-encoded authorization token.
|
|
64
|
+
"""
|
|
65
|
+
# Validate credentials are not empty
|
|
66
|
+
if not aws_credentials.access_key or not aws_credentials.secret_key:
|
|
67
|
+
raise ValueError("AWS Credentials can not be empty")
|
|
68
|
+
|
|
69
|
+
# Extract endpoint URL
|
|
70
|
+
endpoint_url = ENDPOINT_URL_TEMPLATE.format(region)
|
|
71
|
+
|
|
72
|
+
# Set up resource path and query parameters
|
|
73
|
+
query_params = {ACTION_TYPE: ACTION_NAME}
|
|
74
|
+
|
|
75
|
+
# Create SigV4 instance
|
|
76
|
+
sig_v4 = SigV4QueryAuth(
|
|
77
|
+
aws_credentials, SIGNING_NAME, region,
|
|
78
|
+
expires=DEFAULT_TOKEN_EXPIRY_SECONDS
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Create request with url and parameters
|
|
82
|
+
request = AWSRequest(method="GET", url=endpoint_url, params=query_params)
|
|
83
|
+
|
|
84
|
+
# Add auth to the request and prepare the request
|
|
85
|
+
sig_v4.add_auth(request)
|
|
86
|
+
query_params = {USER_AGENT_KEY: __get_user_agent__()}
|
|
87
|
+
request.params = query_params
|
|
88
|
+
prepped = request.prepare()
|
|
89
|
+
|
|
90
|
+
# Get the signed url
|
|
91
|
+
signed_url = prepped.url
|
|
92
|
+
|
|
93
|
+
# Base 64 encode and remove the padding from the end
|
|
94
|
+
signed_url_bytes = signed_url.encode("utf-8")
|
|
95
|
+
base64_bytes = base64.urlsafe_b64encode(signed_url_bytes)
|
|
96
|
+
base64_encoded_signed_url = base64_bytes.decode("utf-8").rstrip("=")
|
|
97
|
+
return base64_encoded_signed_url, __get_expiration_time_ms(request)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def generate_auth_token(region, aws_debug_creds=False):
|
|
101
|
+
"""
|
|
102
|
+
Generates an base64-encoded signed url as auth token to authenticate
|
|
103
|
+
with an Amazon MSK cluster using default IAM credentials.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
region (str): The AWS region where the cluster is located.
|
|
107
|
+
Returns:
|
|
108
|
+
str: A base64-encoded authorization token.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
# Load credentials
|
|
112
|
+
import os
|
|
113
|
+
assert os.environ["AWS_ACCESS_KEY_ID"]
|
|
114
|
+
assert os.environ["AWS_SECRET_ACCESS_KEY"]
|
|
115
|
+
|
|
116
|
+
aws_credentials = Credentials(os.environ["AWS_ACCESS_KEY_ID"],
|
|
117
|
+
os.environ["AWS_SECRET_ACCESS_KEY"])
|
|
118
|
+
|
|
119
|
+
return __construct_auth_token(region, aws_credentials)
|
diaspora_event_sdk/sdk/client.py
CHANGED
|
@@ -153,6 +153,13 @@ class Client:
|
|
|
153
153
|
"""
|
|
154
154
|
return self.web_client.update_topic_partitions(self.subject_openid, topic, new_partitions)
|
|
155
155
|
|
|
156
|
+
@requires_login
|
|
157
|
+
def reset_topic(self, topic):
|
|
158
|
+
"""
|
|
159
|
+
Deletes and recreates the topic, removing all messages and restoring the topic to the default configurations while user access is not affected.
|
|
160
|
+
"""
|
|
161
|
+
return self.web_client.reset_topic(self.subject_openid, topic)
|
|
162
|
+
|
|
156
163
|
@requires_login
|
|
157
164
|
def grant_user_access(self, topic, user):
|
|
158
165
|
"""
|
|
@@ -167,6 +174,13 @@ class Client:
|
|
|
167
174
|
"""
|
|
168
175
|
return self.web_client.grant_user_access(self.subject_openid, topic, user, "revoke")
|
|
169
176
|
|
|
177
|
+
@requires_login
|
|
178
|
+
def list_topic_users(self, topic):
|
|
179
|
+
"""
|
|
180
|
+
Returns a list of users that have access to the topic.
|
|
181
|
+
"""
|
|
182
|
+
return self.web_client.list_topic_users(self.subject_openid, topic)
|
|
183
|
+
|
|
170
184
|
@requires_login
|
|
171
185
|
def list_triggers(self):
|
|
172
186
|
"""
|
|
@@ -4,20 +4,20 @@ import warnings
|
|
|
4
4
|
import time
|
|
5
5
|
|
|
6
6
|
from .client import Client
|
|
7
|
+
from .aws_iam_msk import generate_auth_token
|
|
7
8
|
|
|
8
9
|
# If kafka-python is not installed, Kafka functionality is not available through diaspora-event-sdk.
|
|
9
10
|
kafka_available = True
|
|
10
11
|
try:
|
|
11
12
|
from kafka import KafkaProducer as KProd # type: ignore[import,import-not-found]
|
|
12
13
|
from kafka import KafkaConsumer as KCons # type: ignore[import,import-not-found]
|
|
13
|
-
from aws_msk_iam_sasl_signer import MSKAuthTokenProvider # type: ignore[import,import-not-found]
|
|
14
14
|
import os
|
|
15
15
|
|
|
16
16
|
class MSKTokenProvider:
|
|
17
17
|
def token(self):
|
|
18
|
-
token, _ =
|
|
18
|
+
token, _ = generate_auth_token("us-east-1")
|
|
19
19
|
return token
|
|
20
|
-
except
|
|
20
|
+
except Exception as e:
|
|
21
21
|
kafka_available = False
|
|
22
22
|
|
|
23
23
|
|
|
@@ -66,6 +66,15 @@ class WebClient(globus_sdk.BaseClient):
|
|
|
66
66
|
"NewPartitions": str(new_partitions)}
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
+
def reset_topic(
|
|
70
|
+
self, subject: UUID_LIKE_T, topic: str
|
|
71
|
+
) -> globus_sdk.GlobusHTTPResponse:
|
|
72
|
+
return self.post(
|
|
73
|
+
f"/api/v2/topic/{topic}/reset",
|
|
74
|
+
headers={"Subject": str(subject),
|
|
75
|
+
"Topic": topic}
|
|
76
|
+
)
|
|
77
|
+
|
|
69
78
|
def grant_user_access(
|
|
70
79
|
self, subject: UUID_LIKE_T, topic: str, user: UUID_LIKE_T, action: str
|
|
71
80
|
) -> globus_sdk.GlobusHTTPResponse:
|
|
@@ -75,6 +84,15 @@ class WebClient(globus_sdk.BaseClient):
|
|
|
75
84
|
"Topic": topic, "User": str(user)}
|
|
76
85
|
)
|
|
77
86
|
|
|
87
|
+
def list_topic_users(
|
|
88
|
+
self, subject: UUID_LIKE_T, topic: str
|
|
89
|
+
) -> globus_sdk.GlobusHTTPResponse:
|
|
90
|
+
return self.get(
|
|
91
|
+
f"/api/v2/topic/{topic}/users",
|
|
92
|
+
headers={"Subject": str(subject),
|
|
93
|
+
"Topic": topic}
|
|
94
|
+
)
|
|
95
|
+
|
|
78
96
|
def list_triggers(self, subject: UUID_LIKE_T) -> globus_sdk.GlobusHTTPResponse:
|
|
79
97
|
return self.get("/api/v2/triggers", headers={"Subject": str(subject)})
|
|
80
98
|
|
diaspora_event_sdk/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.6"
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: diaspora-event-sdk
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: SDK of Diaspora Event Fabric: Resilience-enabling services for science from HPC to edge
|
|
5
5
|
Home-page: https://github.com/globus-labs/diaspora-event-sdk
|
|
6
|
-
License:
|
|
6
|
+
License: Apache 2.0
|
|
7
7
|
Platform: UNKNOWN
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: globus-sdk <4,>=3.20.1
|
|
11
11
|
Provides-Extra: kafka-python
|
|
12
12
|
Requires-Dist: kafka-python ; extra == 'kafka-python'
|
|
13
|
-
Requires-Dist: aws-msk-iam-sasl-signer-python ; extra == 'kafka-python'
|
|
14
13
|
Provides-Extra: test
|
|
15
14
|
Requires-Dist: pytest ; extra == 'test'
|
|
16
15
|
Requires-Dist: pytest-cov ; extra == 'test'
|
|
@@ -19,7 +18,7 @@ Requires-Dist: mypy ; extra == 'test'
|
|
|
19
18
|
Requires-Dist: tox ; extra == 'test'
|
|
20
19
|
Requires-Dist: check-manifest ; extra == 'test'
|
|
21
20
|
|
|
22
|
-
# Diaspora:
|
|
21
|
+
# Diaspora: Hybrid Event-Driven Architecture for Distributed Scientific Computing
|
|
23
22
|
|
|
24
23
|
## Event Fabric SDK Installation Guide
|
|
25
24
|
### Recommended Method: Use with `kafka-python`
|
|
@@ -49,3 +48,4 @@ Note: This method does not include dependencies for `KafkaProducer` and `KafkaCo
|
|
|
49
48
|
|
|
50
49
|
**Advanced Consumer Functions**: See our [Colab example](https://colab.research.google.com/drive/1tPKfxU2qPsLvNTreF6nKINU62k7pQWxa?usp=sharing) for demonstration.
|
|
51
50
|
|
|
51
|
+
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
diaspora_event_sdk/__init__.py,sha256=v8IN3-WFpliakQKru8TAcmQ4IRdvRe_m9-abSDnGIFM,457
|
|
2
|
-
diaspora_event_sdk/version.py,sha256=
|
|
2
|
+
diaspora_event_sdk/version.py,sha256=Oz5HbwHMyE87nmwV80AZzpkJPf-wBg7eDuJr_BXZkhU,22
|
|
3
3
|
diaspora_event_sdk/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
diaspora_event_sdk/sdk/_environments.py,sha256=QyQA7dV4goUKUoxAoaes8OGv0xKxz2qiFBHNGr-vQNA,204
|
|
5
|
-
diaspora_event_sdk/sdk/
|
|
5
|
+
diaspora_event_sdk/sdk/aws_iam_msk.py,sha256=rT6RipRVt-Zf7pTsMf9UhH2HDNC0FW28LhciVH_45bc,3942
|
|
6
|
+
diaspora_event_sdk/sdk/client.py,sha256=fbjP_YRmGF2eItnMxNkdz5RIRvur0_P8DhE6AlYk4tM,8541
|
|
6
7
|
diaspora_event_sdk/sdk/decorators.py,sha256=Gel8AyhIjbf4-FNintTNcOqvC9hHH_YwbOH257Nfmf0,884
|
|
7
|
-
diaspora_event_sdk/sdk/kafka_client.py,sha256=
|
|
8
|
-
diaspora_event_sdk/sdk/web_client.py,sha256=
|
|
8
|
+
diaspora_event_sdk/sdk/kafka_client.py,sha256=xAxuPmMXIv0i_K_PFqc_BEG3wdGsFdYYvd7gUzeoLV8,4286
|
|
9
|
+
diaspora_event_sdk/sdk/web_client.py,sha256=Rkp0ZUUXCeqbfVFUqX2oxvuLwqqW5_jsJJNN-v2L4FI,4770
|
|
9
10
|
diaspora_event_sdk/sdk/login_manager/__init__.py,sha256=yeqVgjeHLMX0WZJu2feJmq-fbeXvSxWghVV81ygfY-w,239
|
|
10
11
|
diaspora_event_sdk/sdk/login_manager/client_login.py,sha256=8ild28_cgPSrLtg3Jhmzpg3EymAvH2UdAhKY52oOB_c,1835
|
|
11
12
|
diaspora_event_sdk/sdk/login_manager/decorators.py,sha256=EFEp71d0oJ7vo2H8W7DJ2gPrDfGzeNXUNxri1C0l8h0,1047
|
|
@@ -18,8 +19,8 @@ diaspora_event_sdk/sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
18
19
|
diaspora_event_sdk/sdk/utils/uuid_like.py,sha256=xbxf0YXpDhdii16lwPLWRN21qFekHrNrqODSToMPtCg,470
|
|
19
20
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
21
|
tests/unit/test_client.py,sha256=sJUtPmnNGnohnP38RQrwcJ4D5j3-g1WFQ6gaKf520AQ,3019
|
|
21
|
-
diaspora_event_sdk-0.2.
|
|
22
|
-
diaspora_event_sdk-0.2.
|
|
23
|
-
diaspora_event_sdk-0.2.
|
|
24
|
-
diaspora_event_sdk-0.2.
|
|
25
|
-
diaspora_event_sdk-0.2.
|
|
22
|
+
diaspora_event_sdk-0.2.6.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
23
|
+
diaspora_event_sdk-0.2.6.dist-info/METADATA,sha256=2JJCyb4-F55L3mHG25HfgESP4OEgpTWuEs-UsRUxoOQ,2449
|
|
24
|
+
diaspora_event_sdk-0.2.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
25
|
+
diaspora_event_sdk-0.2.6.dist-info/top_level.txt,sha256=OVun-67t3fkLFEIwvJuNINgFFvAc--bClYhXjLhMmvs,25
|
|
26
|
+
diaspora_event_sdk-0.2.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|