aimodelshare 0.3.7__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.
- aimodelshare/README.md +26 -0
- aimodelshare/__init__.py +100 -0
- aimodelshare/aimsonnx.py +2381 -0
- aimodelshare/api.py +836 -0
- aimodelshare/auth.py +163 -0
- aimodelshare/aws.py +511 -0
- aimodelshare/aws_client.py +173 -0
- aimodelshare/base_image.py +154 -0
- aimodelshare/bucketpolicy.py +106 -0
- aimodelshare/color_mappings/color_mapping_keras.csv +121 -0
- aimodelshare/color_mappings/color_mapping_pytorch.csv +117 -0
- aimodelshare/containerisation.py +244 -0
- aimodelshare/containerization.py +712 -0
- aimodelshare/containerization_templates/Dockerfile.txt +8 -0
- aimodelshare/containerization_templates/Dockerfile_PySpark.txt +23 -0
- aimodelshare/containerization_templates/buildspec.txt +14 -0
- aimodelshare/containerization_templates/lambda_function.txt +40 -0
- aimodelshare/custom_approach/__init__.py +1 -0
- aimodelshare/custom_approach/lambda_function.py +17 -0
- aimodelshare/custom_eval_metrics.py +103 -0
- aimodelshare/data_sharing/__init__.py +0 -0
- aimodelshare/data_sharing/data_sharing_templates/Dockerfile.txt +3 -0
- aimodelshare/data_sharing/data_sharing_templates/__init__.py +1 -0
- aimodelshare/data_sharing/data_sharing_templates/buildspec.txt +15 -0
- aimodelshare/data_sharing/data_sharing_templates/codebuild_policies.txt +129 -0
- aimodelshare/data_sharing/data_sharing_templates/codebuild_trust_relationship.txt +12 -0
- aimodelshare/data_sharing/download_data.py +620 -0
- aimodelshare/data_sharing/share_data.py +373 -0
- aimodelshare/data_sharing/utils.py +8 -0
- aimodelshare/deploy_custom_lambda.py +246 -0
- aimodelshare/documentation/Makefile +20 -0
- aimodelshare/documentation/karma_sphinx_theme/__init__.py +28 -0
- aimodelshare/documentation/karma_sphinx_theme/_version.py +2 -0
- aimodelshare/documentation/karma_sphinx_theme/breadcrumbs.html +70 -0
- aimodelshare/documentation/karma_sphinx_theme/layout.html +172 -0
- aimodelshare/documentation/karma_sphinx_theme/search.html +50 -0
- aimodelshare/documentation/karma_sphinx_theme/searchbox.html +14 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css +2 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css +2751 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css +2 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.eot +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.svg +32 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.ttf +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff2 +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/js/theme.js +68 -0
- aimodelshare/documentation/karma_sphinx_theme/theme.conf +9 -0
- aimodelshare/documentation/make.bat +35 -0
- aimodelshare/documentation/requirements.txt +2 -0
- aimodelshare/documentation/source/about.rst +18 -0
- aimodelshare/documentation/source/advanced_features.rst +137 -0
- aimodelshare/documentation/source/competition.rst +218 -0
- aimodelshare/documentation/source/conf.py +58 -0
- aimodelshare/documentation/source/create_credentials.rst +86 -0
- aimodelshare/documentation/source/example_notebooks.rst +132 -0
- aimodelshare/documentation/source/functions.rst +151 -0
- aimodelshare/documentation/source/gettingstarted.rst +390 -0
- aimodelshare/documentation/source/images/creds1.png +0 -0
- aimodelshare/documentation/source/images/creds2.png +0 -0
- aimodelshare/documentation/source/images/creds3.png +0 -0
- aimodelshare/documentation/source/images/creds4.png +0 -0
- aimodelshare/documentation/source/images/creds5.png +0 -0
- aimodelshare/documentation/source/images/creds_file_example.png +0 -0
- aimodelshare/documentation/source/images/predict_tab.png +0 -0
- aimodelshare/documentation/source/index.rst +110 -0
- aimodelshare/documentation/source/modelplayground.rst +132 -0
- aimodelshare/exceptions.py +11 -0
- aimodelshare/generatemodelapi.py +1270 -0
- aimodelshare/iam/codebuild_policy.txt +129 -0
- aimodelshare/iam/codebuild_trust_relationship.txt +12 -0
- aimodelshare/iam/lambda_policy.txt +15 -0
- aimodelshare/iam/lambda_trust_relationship.txt +12 -0
- aimodelshare/json_templates/__init__.py +1 -0
- aimodelshare/json_templates/api_json.txt +155 -0
- aimodelshare/json_templates/auth/policy.txt +1 -0
- aimodelshare/json_templates/auth/role.txt +1 -0
- aimodelshare/json_templates/eval/policy.txt +1 -0
- aimodelshare/json_templates/eval/role.txt +1 -0
- aimodelshare/json_templates/function/policy.txt +1 -0
- aimodelshare/json_templates/function/role.txt +1 -0
- aimodelshare/json_templates/integration_response.txt +5 -0
- aimodelshare/json_templates/lambda_policy_1.txt +15 -0
- aimodelshare/json_templates/lambda_policy_2.txt +8 -0
- aimodelshare/json_templates/lambda_role_1.txt +12 -0
- aimodelshare/json_templates/lambda_role_2.txt +16 -0
- aimodelshare/leaderboard.py +174 -0
- aimodelshare/main/1.txt +132 -0
- aimodelshare/main/1B.txt +112 -0
- aimodelshare/main/2.txt +153 -0
- aimodelshare/main/3.txt +134 -0
- aimodelshare/main/4.txt +128 -0
- aimodelshare/main/5.txt +109 -0
- aimodelshare/main/6.txt +105 -0
- aimodelshare/main/7.txt +144 -0
- aimodelshare/main/8.txt +142 -0
- aimodelshare/main/__init__.py +1 -0
- aimodelshare/main/authorization.txt +275 -0
- aimodelshare/main/eval_classification.txt +79 -0
- aimodelshare/main/eval_lambda.txt +1709 -0
- aimodelshare/main/eval_regression.txt +80 -0
- aimodelshare/main/lambda_function.txt +8 -0
- aimodelshare/main/nst.txt +149 -0
- aimodelshare/model.py +1543 -0
- aimodelshare/modeluser.py +215 -0
- aimodelshare/moral_compass/README.md +408 -0
- aimodelshare/moral_compass/__init__.py +65 -0
- aimodelshare/moral_compass/_version.py +3 -0
- aimodelshare/moral_compass/api_client.py +601 -0
- aimodelshare/moral_compass/apps/__init__.py +69 -0
- aimodelshare/moral_compass/apps/ai_consequences.py +540 -0
- aimodelshare/moral_compass/apps/bias_detective.py +714 -0
- aimodelshare/moral_compass/apps/ethical_revelation.py +898 -0
- aimodelshare/moral_compass/apps/fairness_fixer.py +889 -0
- aimodelshare/moral_compass/apps/judge.py +888 -0
- aimodelshare/moral_compass/apps/justice_equity_upgrade.py +853 -0
- aimodelshare/moral_compass/apps/mc_integration_helpers.py +820 -0
- aimodelshare/moral_compass/apps/model_building_game.py +1104 -0
- aimodelshare/moral_compass/apps/model_building_game_beginner.py +687 -0
- aimodelshare/moral_compass/apps/moral_compass_challenge.py +858 -0
- aimodelshare/moral_compass/apps/session_auth.py +254 -0
- aimodelshare/moral_compass/apps/shared_activity_styles.css +349 -0
- aimodelshare/moral_compass/apps/tutorial.py +481 -0
- aimodelshare/moral_compass/apps/what_is_ai.py +853 -0
- aimodelshare/moral_compass/challenge.py +365 -0
- aimodelshare/moral_compass/config.py +187 -0
- aimodelshare/placeholders/model.onnx +0 -0
- aimodelshare/placeholders/preprocessor.zip +0 -0
- aimodelshare/playground.py +1968 -0
- aimodelshare/postprocessormodules.py +157 -0
- aimodelshare/preprocessormodules.py +373 -0
- aimodelshare/pyspark/1.txt +195 -0
- aimodelshare/pyspark/1B.txt +181 -0
- aimodelshare/pyspark/2.txt +220 -0
- aimodelshare/pyspark/3.txt +204 -0
- aimodelshare/pyspark/4.txt +187 -0
- aimodelshare/pyspark/5.txt +178 -0
- aimodelshare/pyspark/6.txt +174 -0
- aimodelshare/pyspark/7.txt +211 -0
- aimodelshare/pyspark/8.txt +206 -0
- aimodelshare/pyspark/__init__.py +1 -0
- aimodelshare/pyspark/authorization.txt +258 -0
- aimodelshare/pyspark/eval_classification.txt +79 -0
- aimodelshare/pyspark/eval_lambda.txt +1441 -0
- aimodelshare/pyspark/eval_regression.txt +80 -0
- aimodelshare/pyspark/lambda_function.txt +8 -0
- aimodelshare/pyspark/nst.txt +213 -0
- aimodelshare/python/my_preprocessor.py +58 -0
- aimodelshare/readme.md +26 -0
- aimodelshare/reproducibility.py +181 -0
- aimodelshare/sam/Dockerfile.txt +8 -0
- aimodelshare/sam/Dockerfile_PySpark.txt +24 -0
- aimodelshare/sam/__init__.py +1 -0
- aimodelshare/sam/buildspec.txt +11 -0
- aimodelshare/sam/codebuild_policies.txt +129 -0
- aimodelshare/sam/codebuild_trust_relationship.txt +12 -0
- aimodelshare/sam/codepipeline_policies.txt +173 -0
- aimodelshare/sam/codepipeline_trust_relationship.txt +12 -0
- aimodelshare/sam/spark-class.txt +2 -0
- aimodelshare/sam/template.txt +54 -0
- aimodelshare/tools.py +103 -0
- aimodelshare/utils/__init__.py +78 -0
- aimodelshare/utils/optional_deps.py +38 -0
- aimodelshare/utils.py +57 -0
- aimodelshare-0.3.7.dist-info/METADATA +298 -0
- aimodelshare-0.3.7.dist-info/RECORD +171 -0
- aimodelshare-0.3.7.dist-info/WHEEL +5 -0
- aimodelshare-0.3.7.dist-info/licenses/LICENSE +5 -0
- aimodelshare-0.3.7.dist-info/top_level.txt +1 -0
aimodelshare/auth.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication and identity management helpers for aimodelshare.
|
|
3
|
+
|
|
4
|
+
Provides unified authentication around Cognito IdToken (JWT_AUTHORIZATION_TOKEN),
|
|
5
|
+
with backward compatibility for legacy AWS_TOKEN.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import warnings
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Optional, Dict, Any
|
|
12
|
+
import json
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger("aimodelshare.auth")
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
import jwt
|
|
18
|
+
except ImportError:
|
|
19
|
+
jwt = None
|
|
20
|
+
logger.warning("PyJWT not installed. JWT decode functionality will be limited.")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_primary_token() -> Optional[str]:
|
|
24
|
+
"""
|
|
25
|
+
Get the primary authentication token from environment variables.
|
|
26
|
+
|
|
27
|
+
Prefers JWT_AUTHORIZATION_TOKEN over legacy AWS_TOKEN.
|
|
28
|
+
Issues a deprecation warning if only AWS_TOKEN is present.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Optional[str]: The authentication token, or None if not found
|
|
32
|
+
"""
|
|
33
|
+
jwt_token = os.getenv('JWT_AUTHORIZATION_TOKEN')
|
|
34
|
+
if jwt_token:
|
|
35
|
+
return jwt_token
|
|
36
|
+
|
|
37
|
+
aws_token = os.getenv('AWS_TOKEN')
|
|
38
|
+
if aws_token:
|
|
39
|
+
warnings.warn(
|
|
40
|
+
"Using legacy AWS_TOKEN environment variable. "
|
|
41
|
+
"Please migrate to JWT_AUTHORIZATION_TOKEN. "
|
|
42
|
+
"AWS_TOKEN support will be deprecated in a future release.",
|
|
43
|
+
DeprecationWarning,
|
|
44
|
+
stacklevel=2
|
|
45
|
+
)
|
|
46
|
+
return aws_token
|
|
47
|
+
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_identity_claims(token: Optional[str] = None, verify: bool = False) -> Dict[str, Any]:
|
|
52
|
+
"""
|
|
53
|
+
Extract identity claims from a JWT token.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
token: JWT token string. If None, uses get_primary_token()
|
|
57
|
+
verify: If True, performs signature verification (requires JWKS endpoint)
|
|
58
|
+
Currently defaults to False as JWKS verification is future work
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Dict containing identity claims:
|
|
62
|
+
- sub: Subject (user ID)
|
|
63
|
+
- email: User email
|
|
64
|
+
- cognito:username: Username (if present)
|
|
65
|
+
- iss: Issuer
|
|
66
|
+
- principal: Derived principal identifier
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
ValueError: If token is invalid or missing
|
|
70
|
+
RuntimeError: If PyJWT is not installed
|
|
71
|
+
|
|
72
|
+
Note:
|
|
73
|
+
This currently performs unverified decode as JWKS signature verification
|
|
74
|
+
is planned for future work. Do not use in production security-critical
|
|
75
|
+
contexts without implementing signature verification.
|
|
76
|
+
"""
|
|
77
|
+
if token is None:
|
|
78
|
+
token = get_primary_token()
|
|
79
|
+
|
|
80
|
+
if not token:
|
|
81
|
+
raise ValueError("No authentication token available")
|
|
82
|
+
|
|
83
|
+
if jwt is None:
|
|
84
|
+
raise RuntimeError("PyJWT not installed. Install with: pip install PyJWT>=2.4.0")
|
|
85
|
+
|
|
86
|
+
# TODO: Implement JWKS signature verification (future work)
|
|
87
|
+
# For now, perform unverified decode
|
|
88
|
+
if verify:
|
|
89
|
+
warnings.warn(
|
|
90
|
+
"JWT signature verification requested but not yet implemented. "
|
|
91
|
+
"Using unverified decode. This should not be used in production "
|
|
92
|
+
"for security-critical operations.",
|
|
93
|
+
UserWarning,
|
|
94
|
+
stacklevel=2
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
# Unverified decode - JWKS verification is future work
|
|
99
|
+
claims = jwt.decode(token, options={"verify_signature": False})
|
|
100
|
+
|
|
101
|
+
# Derive principal from claims
|
|
102
|
+
# Priority: cognito:username > email > sub
|
|
103
|
+
principal = (
|
|
104
|
+
claims.get('cognito:username') or
|
|
105
|
+
claims.get('email') or
|
|
106
|
+
claims.get('sub')
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if principal:
|
|
110
|
+
claims['principal'] = principal
|
|
111
|
+
|
|
112
|
+
return claims
|
|
113
|
+
|
|
114
|
+
except jwt.DecodeError as e:
|
|
115
|
+
raise ValueError(f"Invalid JWT token: {e}")
|
|
116
|
+
except Exception as e:
|
|
117
|
+
raise ValueError(f"Failed to decode JWT token: {e}")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def derive_principal(claims: Dict[str, Any]) -> str:
|
|
121
|
+
"""
|
|
122
|
+
Derive a principal identifier from identity claims.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
claims: Identity claims dictionary
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
str: Principal identifier
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
ValueError: If no suitable principal identifier found
|
|
132
|
+
"""
|
|
133
|
+
principal = (
|
|
134
|
+
claims.get('principal') or
|
|
135
|
+
claims.get('cognito:username') or
|
|
136
|
+
claims.get('email') or
|
|
137
|
+
claims.get('sub')
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if not principal:
|
|
141
|
+
raise ValueError("No principal identifier found in claims")
|
|
142
|
+
|
|
143
|
+
return str(principal)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def is_admin(claims: Dict[str, Any]) -> bool:
|
|
147
|
+
"""
|
|
148
|
+
Check if the identity has admin privileges.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
claims: Identity claims dictionary
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
bool: True if user has admin privileges
|
|
155
|
+
|
|
156
|
+
Note:
|
|
157
|
+
Currently checks for 'cognito:groups' containing 'admin'.
|
|
158
|
+
Extend this logic as needed for your authorization model.
|
|
159
|
+
"""
|
|
160
|
+
groups = claims.get('cognito:groups', [])
|
|
161
|
+
if isinstance(groups, list):
|
|
162
|
+
return 'admin' in groups
|
|
163
|
+
return False
|
aimodelshare/aws.py
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import boto3
|
|
3
|
+
import botocore
|
|
4
|
+
import requests
|
|
5
|
+
import json
|
|
6
|
+
import base64
|
|
7
|
+
from aimodelshare.exceptions import AuthorizationError, AWSAccessError
|
|
8
|
+
from aimodelshare.modeluser import get_jwt_token
|
|
9
|
+
|
|
10
|
+
def set_credentials(credential_file=None, type="submit_model", apiurl="apiurl", manual = True, cloud="aws"):
|
|
11
|
+
import os
|
|
12
|
+
import getpass
|
|
13
|
+
from aimodelshare.aws import get_aws_token
|
|
14
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
15
|
+
if all([credential_file==None, type=="submit_model"]):
|
|
16
|
+
set_credentials_public(type="submit_model", apiurl=apiurl)
|
|
17
|
+
os.environ["AWS_TOKEN"]=get_aws_token()
|
|
18
|
+
elif all([credential_file==None, type=="deploy_model", cloud=="model_share"]):
|
|
19
|
+
set_credentials_public_aimscloud(credential_file=None, type="deploy_model", apiurl=apiurl)
|
|
20
|
+
os.environ["cloud_location"] = cloud
|
|
21
|
+
else:
|
|
22
|
+
##TODO: Require that "type" is provided, to ensure correct env vars get loaded
|
|
23
|
+
flag = False
|
|
24
|
+
|
|
25
|
+
# Set AI Modelshare Username & Password
|
|
26
|
+
if all([manual == True, credential_file==None]):
|
|
27
|
+
user = getpass.getpass(prompt="Modelshare.ai Username:")
|
|
28
|
+
os.environ["username"] = user
|
|
29
|
+
pw = getpass.getpass(prompt="Modelshare.ai Password:")
|
|
30
|
+
os.environ["password"] = pw
|
|
31
|
+
|
|
32
|
+
else:
|
|
33
|
+
f = open(credential_file)
|
|
34
|
+
|
|
35
|
+
for line in f:
|
|
36
|
+
if "aimodelshare_creds" in line or "AIMODELSHARE_CREDS" in line:
|
|
37
|
+
for line in f:
|
|
38
|
+
if line == "\n":
|
|
39
|
+
break
|
|
40
|
+
try:
|
|
41
|
+
value = line.split("=", 1)[1].strip()
|
|
42
|
+
value = value[1:-1]
|
|
43
|
+
key = line.split("=", 1)[0].strip()
|
|
44
|
+
os.environ[key.lower()] = value
|
|
45
|
+
|
|
46
|
+
except LookupError:
|
|
47
|
+
print(* "Warning: Review format of", credential_file, ". Format should be variablename = 'variable_value'")
|
|
48
|
+
break
|
|
49
|
+
|
|
50
|
+
#Validate Username & Password
|
|
51
|
+
try:
|
|
52
|
+
os.environ["AWS_TOKEN"]=get_aws_token()
|
|
53
|
+
|
|
54
|
+
print("Modelshare.ai login credentials set successfully.")
|
|
55
|
+
except:
|
|
56
|
+
print("Credential confirmation unsuccessful. Check username & password and try again.")
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# Set AWS Creds Manually (submit or deploy)
|
|
60
|
+
if all([manual == True,credential_file==None]):
|
|
61
|
+
flag = True
|
|
62
|
+
access_key = getpass.getpass(prompt="AWS_ACCESS_KEY_ID:")
|
|
63
|
+
os.environ["AWS_ACCESS_KEY_ID"] = access_key
|
|
64
|
+
os.environ["AWS_ACCESS_KEY_ID_AIMS"] = access_key
|
|
65
|
+
|
|
66
|
+
secret_key = getpass.getpass(prompt="AWS_SECRET_ACCESS_KEY:")
|
|
67
|
+
os.environ["AWS_SECRET_ACCESS_KEY"] = secret_key
|
|
68
|
+
os.environ["AWS_SECRET_ACCESS_KEY_AIMS"] = secret_key
|
|
69
|
+
|
|
70
|
+
region = getpass.getpass(prompt="AWS_REGION:")
|
|
71
|
+
os.environ["AWS_REGION"] = region
|
|
72
|
+
os.environ["AWS_REGION_AIMS"] = region
|
|
73
|
+
|
|
74
|
+
# Set AWS creds from file
|
|
75
|
+
else:
|
|
76
|
+
f = open(credential_file)
|
|
77
|
+
if type == "submit_model":
|
|
78
|
+
for line in f:
|
|
79
|
+
if (apiurl in line) and ((type in line) or (type.upper() in line)): ## searches on apiurl AND type
|
|
80
|
+
flag = True
|
|
81
|
+
for line in f:
|
|
82
|
+
if line == "\n":
|
|
83
|
+
break
|
|
84
|
+
try:
|
|
85
|
+
value = line.split("=", 1)[1].strip()
|
|
86
|
+
value = value[1:-1]
|
|
87
|
+
key = line.split("=", 1)[0].strip()
|
|
88
|
+
os.environ[key.upper()] = value
|
|
89
|
+
except LookupError:
|
|
90
|
+
print(* "Warning: Review format of", credential_file, ". Format should be variablename = 'variable_value'.")
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
elif type == "deploy_model":
|
|
94
|
+
for line in f:
|
|
95
|
+
if ((type in line) or (type.upper() in line)): ## only searches on type
|
|
96
|
+
flag = True
|
|
97
|
+
for line in f:
|
|
98
|
+
if line == "\n":
|
|
99
|
+
break
|
|
100
|
+
try:
|
|
101
|
+
value = line.split("=", 1)[1].strip()
|
|
102
|
+
value = value[1:-1]
|
|
103
|
+
key = line.split("=", 1)[0].strip()
|
|
104
|
+
os.environ[key.upper()] = value
|
|
105
|
+
except LookupError:
|
|
106
|
+
print(* "Warning: Review format of", credential_file, ". Format should be variablename = 'variable_value'.")
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
if "AWS_ACCESS_KEY_ID_AIMS" in os.environ:
|
|
110
|
+
pass
|
|
111
|
+
elif "AWS_ACCESS_KEY_ID" in os.environ:
|
|
112
|
+
os.environ['AWS_ACCESS_KEY_ID_AIMS']=os.environ.get("AWS_ACCESS_KEY_ID")
|
|
113
|
+
if "AWS_SECRET_ACCESS_KEY_AIMS" in os.environ:
|
|
114
|
+
pass
|
|
115
|
+
elif "AWS_SECRET_ACCESS_KEY" in os.environ:
|
|
116
|
+
os.environ['AWS_SECRET_ACCESS_KEY_AIMS']=os.environ.get("AWS_SECRET_ACCESS_KEY")
|
|
117
|
+
|
|
118
|
+
if 'AWS_REGION_AIMS' in os.environ:
|
|
119
|
+
pass
|
|
120
|
+
elif "AWS_REGION" in os.environ:
|
|
121
|
+
os.environ['AWS_REGION_AIMS']=os.environ.get("AWS_REGION")
|
|
122
|
+
# Validate AWS Creds
|
|
123
|
+
import boto3
|
|
124
|
+
try:
|
|
125
|
+
client = boto3.client('sts', aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY_AIMS"))
|
|
126
|
+
details = client.get_caller_identity()
|
|
127
|
+
print("AWS credentials set successfully.")
|
|
128
|
+
except:
|
|
129
|
+
print("AWS credential confirmation unsuccessful. Check AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY and try again.")
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
# Set Environment Variables for deploy models
|
|
133
|
+
if type == "deploy_model":
|
|
134
|
+
get_jwt_token(os.environ.get("username"), os.environ.get("password"))
|
|
135
|
+
setup_bucket_only() # Use new function that doesn't create IAM users
|
|
136
|
+
|
|
137
|
+
if not flag:
|
|
138
|
+
print("Error: apiurl or type not found in"+str(credential_file)+". Please correct entries and resubmit.")
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
f.close()
|
|
142
|
+
except:
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
def set_credentials_public(credential_file=None, type="submit_model", apiurl="apiurl", manual = True):
|
|
148
|
+
import os
|
|
149
|
+
import getpass
|
|
150
|
+
from aimodelshare.aws import get_aws_token
|
|
151
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
152
|
+
|
|
153
|
+
##TODO: Require that "type" is provided, to ensure correct env vars get loaded
|
|
154
|
+
flag = False
|
|
155
|
+
|
|
156
|
+
# Set AI Modelshare Username & Password
|
|
157
|
+
if all([manual == True, credential_file==None]):
|
|
158
|
+
user = getpass.getpass(prompt="Modelshare.ai Username:")
|
|
159
|
+
os.environ["username"] = user
|
|
160
|
+
pw = getpass.getpass(prompt="Modelshare.ai Password:")
|
|
161
|
+
os.environ["password"] = pw
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
f = open(credential_file)
|
|
165
|
+
|
|
166
|
+
for line in f:
|
|
167
|
+
if "aimodelshare_creds" in line or "AIMODELSHARE_CREDS" in line:
|
|
168
|
+
for line in f:
|
|
169
|
+
if line == "\n":
|
|
170
|
+
break
|
|
171
|
+
try:
|
|
172
|
+
value = line.split("=", 1)[1].strip()
|
|
173
|
+
value = value[1:-1]
|
|
174
|
+
key = line.split("=", 1)[0].strip()
|
|
175
|
+
os.environ[key.lower()] = value
|
|
176
|
+
|
|
177
|
+
except LookupError:
|
|
178
|
+
print(* "Warning: Review format of", credential_file, ". Format should be variablename = 'variable_value'")
|
|
179
|
+
break
|
|
180
|
+
if "AWS_ACCESS_KEY_ID_AIMS" in os.environ:
|
|
181
|
+
pass
|
|
182
|
+
elif "AWS_ACCESS_KEY_ID" in os.environ:
|
|
183
|
+
os.environ['AWS_ACCESS_KEY_ID_AIMS']=os.environ.get("AWS_ACCESS_KEY_ID")
|
|
184
|
+
if "AWS_SECRET_ACCESS_KEY_AIMS" in os.environ:
|
|
185
|
+
pass
|
|
186
|
+
elif "AWS_SECRET_ACCESS_KEY" in os.environ:
|
|
187
|
+
os.environ['AWS_SECRET_ACCESS_KEY_AIMS']=os.environ.get("AWS_SECRET_ACCESS_KEY")
|
|
188
|
+
|
|
189
|
+
if 'AWS_REGION_AIMS' in os.environ:
|
|
190
|
+
pass
|
|
191
|
+
elif "AWS_REGION" in os.environ:
|
|
192
|
+
os.environ['AWS_REGION_AIMS']=os.environ.get("AWS_REGION")
|
|
193
|
+
#Validate Username & Password
|
|
194
|
+
try:
|
|
195
|
+
os.environ["AWS_TOKEN"]=get_aws_token()
|
|
196
|
+
|
|
197
|
+
print("Modelshare.ai login credentials set successfully.")
|
|
198
|
+
except:
|
|
199
|
+
print("Credential confirmation unsuccessful. Check username & password and try again.")
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
# Set AWS creds from file
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
f.close()
|
|
206
|
+
except:
|
|
207
|
+
pass
|
|
208
|
+
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
def set_credentials_public_aimscloud(credential_file=None, type="deploy_model", apiurl="apiurl", manual = True):
|
|
212
|
+
import os
|
|
213
|
+
import getpass
|
|
214
|
+
from aimodelshare.aws import get_aws_token
|
|
215
|
+
from aimodelshare.modeluser import get_jwt_token, setup_bucket_only
|
|
216
|
+
|
|
217
|
+
##TODO: Require that "type" is provided, to ensure correct env vars get loaded
|
|
218
|
+
flag = False
|
|
219
|
+
|
|
220
|
+
# Set AI Modelshare Username & Password
|
|
221
|
+
if all([manual == True, credential_file==None]):
|
|
222
|
+
user = getpass.getpass(prompt="Modelshare.ai Username:")
|
|
223
|
+
os.environ["username"] = user
|
|
224
|
+
pw = getpass.getpass(prompt="Modelshare.ai Password:")
|
|
225
|
+
os.environ["password"] = pw
|
|
226
|
+
|
|
227
|
+
else:
|
|
228
|
+
f = open(credential_file)
|
|
229
|
+
|
|
230
|
+
for line in f:
|
|
231
|
+
if "aimodelshare_creds" in line or "AIMODELSHARE_CREDS" in line:
|
|
232
|
+
for line in f:
|
|
233
|
+
if line == "\n":
|
|
234
|
+
break
|
|
235
|
+
try:
|
|
236
|
+
value = line.split("=", 1)[1].strip()
|
|
237
|
+
value = value[1:-1]
|
|
238
|
+
key = line.split("=", 1)[0].strip()
|
|
239
|
+
os.environ[key.lower()] = value
|
|
240
|
+
|
|
241
|
+
except LookupError:
|
|
242
|
+
print(* "Warning: Review format of", credential_file, ". Format should be variablename = 'variable_value'")
|
|
243
|
+
break
|
|
244
|
+
if "AWS_ACCESS_KEY_ID_AIMS" in os.environ:
|
|
245
|
+
pass
|
|
246
|
+
elif "AWS_ACCESS_KEY_ID" in os.environ:
|
|
247
|
+
os.environ['AWS_ACCESS_KEY_ID_AIMS']=os.environ.get("AWS_ACCESS_KEY_ID")
|
|
248
|
+
if "AWS_SECRET_ACCESS_KEY_AIMS" in os.environ:
|
|
249
|
+
pass
|
|
250
|
+
elif "AWS_SECRET_ACCESS_KEY" in os.environ:
|
|
251
|
+
os.environ['AWS_SECRET_ACCESS_KEY_AIMS']=os.environ.get("AWS_SECRET_ACCESS_KEY")
|
|
252
|
+
|
|
253
|
+
if 'AWS_REGION_AIMS' in os.environ:
|
|
254
|
+
pass
|
|
255
|
+
elif "AWS_REGION" in os.environ:
|
|
256
|
+
os.environ['AWS_REGION_AIMS']=os.environ.get("AWS_REGION")
|
|
257
|
+
#Validate Username & Password
|
|
258
|
+
try:
|
|
259
|
+
os.environ["AWS_TOKEN"]=get_aws_token()
|
|
260
|
+
get_jwt_token(user,pw)
|
|
261
|
+
print("Modelshare.ai login credentials set successfully.")
|
|
262
|
+
except:
|
|
263
|
+
print("Credential confirmation unsuccessful. Check username & password and try again.")
|
|
264
|
+
return
|
|
265
|
+
|
|
266
|
+
# Set AWS creds from file
|
|
267
|
+
|
|
268
|
+
try:
|
|
269
|
+
f.close()
|
|
270
|
+
except:
|
|
271
|
+
pass
|
|
272
|
+
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
def get_aws_token():
|
|
276
|
+
config = botocore.config.Config(signature_version=botocore.UNSIGNED)
|
|
277
|
+
|
|
278
|
+
provider_client = boto3.client(
|
|
279
|
+
"cognito-idp", region_name="us-east-2", config=config
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
try:
|
|
283
|
+
response = provider_client.initiate_auth(
|
|
284
|
+
ClientId="7ptv9f8pt36elmg0e4v9v7jo9t",
|
|
285
|
+
AuthFlow="USER_PASSWORD_AUTH",
|
|
286
|
+
AuthParameters={"USERNAME": os.getenv('username'), "PASSWORD": os.getenv('password')},
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
except Exception as err:
|
|
290
|
+
raise AuthorizationError("Could not authorize user. " + str(err))
|
|
291
|
+
|
|
292
|
+
return response["AuthenticationResult"]["IdToken"]
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def get_token_from_session(session_id):
|
|
296
|
+
"""
|
|
297
|
+
Retrieve AWS JWT token from session API endpoint.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
session_id: The session identifier from URL parameter
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
str: JWT token if session is valid
|
|
304
|
+
|
|
305
|
+
Raises:
|
|
306
|
+
AuthorizationError: If session is invalid or API request fails
|
|
307
|
+
"""
|
|
308
|
+
try:
|
|
309
|
+
# NOTE: This URL should be configured via environment variable or config file
|
|
310
|
+
# Update AIMODELSHARE_SESSION_API_URL environment variable to override
|
|
311
|
+
session_api_url = os.getenv(
|
|
312
|
+
"AIMODELSHARE_SESSION_API_URL",
|
|
313
|
+
f"https://b22q73wp50.execute-api.us-east-1.amazonaws.com/dev/sessions/{session_id}"
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
response = requests.get(session_api_url, timeout=10)
|
|
317
|
+
response.raise_for_status()
|
|
318
|
+
|
|
319
|
+
data = response.json()
|
|
320
|
+
token = data.get("token") or data.get("id_token") or data.get("IdToken")
|
|
321
|
+
|
|
322
|
+
if not token:
|
|
323
|
+
raise AuthorizationError("No token found in session API response")
|
|
324
|
+
|
|
325
|
+
return token
|
|
326
|
+
|
|
327
|
+
except requests.RequestException as err:
|
|
328
|
+
raise AuthorizationError(f"Failed to retrieve token from session: {err}")
|
|
329
|
+
except (KeyError, ValueError) as err:
|
|
330
|
+
raise AuthorizationError(f"Invalid session API response: {err}")
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _get_username_from_token(token):
|
|
334
|
+
"""
|
|
335
|
+
Extract username from JWT token claims.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
token: JWT token string
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
str: Username extracted from 'cognito:username' or 'username' claim, or None if not found
|
|
342
|
+
"""
|
|
343
|
+
try:
|
|
344
|
+
# JWT tokens have 3 parts: header.payload.signature
|
|
345
|
+
parts = token.split('.')
|
|
346
|
+
if len(parts) != 3:
|
|
347
|
+
return None
|
|
348
|
+
|
|
349
|
+
# Decode the payload (second part)
|
|
350
|
+
# Add padding if needed for base64 decoding
|
|
351
|
+
payload = parts[1]
|
|
352
|
+
padding = 4 - (len(payload) % 4)
|
|
353
|
+
if padding != 4:
|
|
354
|
+
payload += '=' * padding
|
|
355
|
+
|
|
356
|
+
decoded = base64.urlsafe_b64decode(payload)
|
|
357
|
+
claims = json.loads(decoded)
|
|
358
|
+
|
|
359
|
+
# Try different possible username claim names
|
|
360
|
+
# Note: 'sub' is excluded as it's typically a UUID, not a human-readable username
|
|
361
|
+
username = claims.get('cognito:username') or claims.get('username')
|
|
362
|
+
|
|
363
|
+
return username
|
|
364
|
+
|
|
365
|
+
except (ValueError, json.JSONDecodeError, KeyError, IndexError) as err:
|
|
366
|
+
print(f"Warning: Could not extract username from token: {err}")
|
|
367
|
+
return None
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def get_aws_session(aws_key=None, aws_secret=None, aws_region=None):
|
|
371
|
+
session = boto3.Session(
|
|
372
|
+
aws_access_key_id=aws_key,
|
|
373
|
+
aws_secret_access_key=aws_secret,
|
|
374
|
+
region_name=aws_region
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
def get_aws_client(aws_key=None, aws_secret=None, aws_region=None):
|
|
378
|
+
key = aws_key if aws_key is not None else os.environ.get("AWS_ACCESS_KEY_ID_AIMS")
|
|
379
|
+
secret = (
|
|
380
|
+
aws_secret
|
|
381
|
+
if aws_secret is not None
|
|
382
|
+
else os.environ.get("AWS_SECRET_ACCESS_KEY_AIMS")
|
|
383
|
+
)
|
|
384
|
+
region = (
|
|
385
|
+
aws_region if aws_region is not None else os.environ.get("AWS_REGION_AIMS") #changed
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
if any([key is None, secret is None, region is None]):
|
|
389
|
+
raise ValueError("Invalid arguments")
|
|
390
|
+
|
|
391
|
+
usersession = boto3.session.Session(
|
|
392
|
+
aws_access_key_id=key, aws_secret_access_key=secret, region_name=region,
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
s3client = usersession.client("s3")
|
|
396
|
+
s3resource = usersession.resource("s3")
|
|
397
|
+
|
|
398
|
+
return {"client": s3client, "resource": s3resource}
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def get_s3_iam_client(aws_key=None,aws_password=None, aws_region=None):
|
|
402
|
+
|
|
403
|
+
key = aws_key if aws_key is not None else os.environ.get("AWS_ACCESS_KEY_ID_AIMS")
|
|
404
|
+
password = (
|
|
405
|
+
aws_password
|
|
406
|
+
if aws_password is not None
|
|
407
|
+
else os.environ.get("AWS_SECRET_ACCESS_KEY_AIMS"))
|
|
408
|
+
region = (
|
|
409
|
+
aws_region if aws_region is not None else os.environ.get("AWS_REGION_AIMS")) #changed
|
|
410
|
+
|
|
411
|
+
if any([key is None, password is None, region is None]):
|
|
412
|
+
raise AuthorizationError("Please set your aws credentials before creating your prediction API.")
|
|
413
|
+
|
|
414
|
+
usersession = boto3.session.Session(
|
|
415
|
+
aws_access_key_id=key, aws_secret_access_key=password, region_name=region,
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
s3_client = boto3.client('s3' , region_name ="us-east-1")
|
|
419
|
+
s3_resource = boto3.resource('s3')
|
|
420
|
+
iam_client = boto3.client('iam')
|
|
421
|
+
iam_resource = boto3.resource('iam')
|
|
422
|
+
|
|
423
|
+
s3 = {"client":s3_client,"resource":s3_resource}
|
|
424
|
+
iam = {"client":iam_client,"resource":iam_resource}
|
|
425
|
+
|
|
426
|
+
return s3,iam,region
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def run_function_on_lambda(url, username=None, token=None, **kwargs):
|
|
430
|
+
if username==None:
|
|
431
|
+
kwargs["apideveloper"] = os.environ.get("username")
|
|
432
|
+
else:
|
|
433
|
+
kwargs["apideveloper"] = username
|
|
434
|
+
kwargs["apiurl"] = url
|
|
435
|
+
if token==None:
|
|
436
|
+
headers_with_authentication = {
|
|
437
|
+
"content-type": "application/json",
|
|
438
|
+
"authorizationToken": os.environ.get("AWS_TOKEN"),
|
|
439
|
+
}
|
|
440
|
+
else:
|
|
441
|
+
headers_with_authentication = {
|
|
442
|
+
"content-type": "application/json",
|
|
443
|
+
"authorizationToken": token,
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
response = requests.post(
|
|
447
|
+
"https://bhrdesksak.execute-api.us-east-1.amazonaws.com/dev/modeldata",
|
|
448
|
+
json=kwargs,
|
|
449
|
+
headers=headers_with_authentication,
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
if response.status_code != 200:
|
|
453
|
+
return (
|
|
454
|
+
None,
|
|
455
|
+
AWSAccessError(
|
|
456
|
+
"Error:"
|
|
457
|
+
+ "Please make sure your api url and token are correct."
|
|
458
|
+
),
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
return response, None
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def get_token(username, password):
|
|
465
|
+
#get token for access to prediction lambas or to submit predictions to generate model evaluation metrics
|
|
466
|
+
tokenstring = '{\"username\": \"$usernamestring\", \"password\": \"$passwordstring\"}'
|
|
467
|
+
from string import Template
|
|
468
|
+
t = Template(tokenstring)
|
|
469
|
+
newdata = t.substitute(
|
|
470
|
+
usernamestring=username, passwordstring=password)
|
|
471
|
+
api_url='https://xgwe1d6wai.execute-api.us-east-1.amazonaws.com/dev'
|
|
472
|
+
headers={ 'Content-Type':'application/json'}
|
|
473
|
+
token =requests.post(api_url,headers=headers,data=json.dumps({"action": "login", "request":newdata}))
|
|
474
|
+
return token.text
|
|
475
|
+
|
|
476
|
+
def configure_credentials():
|
|
477
|
+
import getpass
|
|
478
|
+
user = getpass.getpass(prompt="Modelshare.ai Username:")
|
|
479
|
+
pw = getpass.getpass(prompt="Modelshare.ai Password:")
|
|
480
|
+
input_AWS_ACCESS_KEY_ID = getpass.getpass(prompt="AWS_ACCESS_KEY_ID:")
|
|
481
|
+
input_AWS_SECRET_ACCESS_KEY = getpass.getpass(prompt="AWS_SECRET_ACCESS_KEY:")
|
|
482
|
+
input_AWS_REGION = getpass.getpass(prompt="AWS_REGION:")
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
#Format output text
|
|
486
|
+
formatted_userpass = ('[aimodelshare_creds] \n'
|
|
487
|
+
'username = "' + user + '"\n'
|
|
488
|
+
'password = "' + pw + '"\n\n')
|
|
489
|
+
|
|
490
|
+
formatted_new_creds = ("#Deploy Credentials \n"
|
|
491
|
+
'[deploy_model]\n'
|
|
492
|
+
'AWS_ACCESS_KEY_ID = "' + input_AWS_ACCESS_KEY_ID + '"\n'
|
|
493
|
+
'AWS_SECRET_ACCESS_KEY = "' + input_AWS_SECRET_ACCESS_KEY +'"\n'
|
|
494
|
+
'AWS_REGION = "' + input_AWS_REGION + '"\n')
|
|
495
|
+
|
|
496
|
+
# Generate .txt file with new credentials
|
|
497
|
+
f= open("credentials.txt","w+")
|
|
498
|
+
f.write(formatted_userpass + formatted_new_creds)
|
|
499
|
+
f.close()
|
|
500
|
+
|
|
501
|
+
return print("Configuration successful. New credentials file saved as 'credentials.txt'")
|
|
502
|
+
|
|
503
|
+
__all__ = [
|
|
504
|
+
get_aws_token,
|
|
505
|
+
get_aws_client,
|
|
506
|
+
run_function_on_lambda,
|
|
507
|
+
get_s3_iam_client,
|
|
508
|
+
set_credentials,
|
|
509
|
+
configure_credentials,
|
|
510
|
+
set_credentials_public
|
|
511
|
+
]
|