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.
Files changed (171) hide show
  1. aimodelshare/README.md +26 -0
  2. aimodelshare/__init__.py +100 -0
  3. aimodelshare/aimsonnx.py +2381 -0
  4. aimodelshare/api.py +836 -0
  5. aimodelshare/auth.py +163 -0
  6. aimodelshare/aws.py +511 -0
  7. aimodelshare/aws_client.py +173 -0
  8. aimodelshare/base_image.py +154 -0
  9. aimodelshare/bucketpolicy.py +106 -0
  10. aimodelshare/color_mappings/color_mapping_keras.csv +121 -0
  11. aimodelshare/color_mappings/color_mapping_pytorch.csv +117 -0
  12. aimodelshare/containerisation.py +244 -0
  13. aimodelshare/containerization.py +712 -0
  14. aimodelshare/containerization_templates/Dockerfile.txt +8 -0
  15. aimodelshare/containerization_templates/Dockerfile_PySpark.txt +23 -0
  16. aimodelshare/containerization_templates/buildspec.txt +14 -0
  17. aimodelshare/containerization_templates/lambda_function.txt +40 -0
  18. aimodelshare/custom_approach/__init__.py +1 -0
  19. aimodelshare/custom_approach/lambda_function.py +17 -0
  20. aimodelshare/custom_eval_metrics.py +103 -0
  21. aimodelshare/data_sharing/__init__.py +0 -0
  22. aimodelshare/data_sharing/data_sharing_templates/Dockerfile.txt +3 -0
  23. aimodelshare/data_sharing/data_sharing_templates/__init__.py +1 -0
  24. aimodelshare/data_sharing/data_sharing_templates/buildspec.txt +15 -0
  25. aimodelshare/data_sharing/data_sharing_templates/codebuild_policies.txt +129 -0
  26. aimodelshare/data_sharing/data_sharing_templates/codebuild_trust_relationship.txt +12 -0
  27. aimodelshare/data_sharing/download_data.py +620 -0
  28. aimodelshare/data_sharing/share_data.py +373 -0
  29. aimodelshare/data_sharing/utils.py +8 -0
  30. aimodelshare/deploy_custom_lambda.py +246 -0
  31. aimodelshare/documentation/Makefile +20 -0
  32. aimodelshare/documentation/karma_sphinx_theme/__init__.py +28 -0
  33. aimodelshare/documentation/karma_sphinx_theme/_version.py +2 -0
  34. aimodelshare/documentation/karma_sphinx_theme/breadcrumbs.html +70 -0
  35. aimodelshare/documentation/karma_sphinx_theme/layout.html +172 -0
  36. aimodelshare/documentation/karma_sphinx_theme/search.html +50 -0
  37. aimodelshare/documentation/karma_sphinx_theme/searchbox.html +14 -0
  38. aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css +2 -0
  39. aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css.map +1 -0
  40. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css +2751 -0
  41. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css.map +1 -0
  42. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css +2 -0
  43. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css.map +1 -0
  44. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.eot +0 -0
  45. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.svg +32 -0
  46. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.ttf +0 -0
  47. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff +0 -0
  48. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff2 +0 -0
  49. aimodelshare/documentation/karma_sphinx_theme/static/js/theme.js +68 -0
  50. aimodelshare/documentation/karma_sphinx_theme/theme.conf +9 -0
  51. aimodelshare/documentation/make.bat +35 -0
  52. aimodelshare/documentation/requirements.txt +2 -0
  53. aimodelshare/documentation/source/about.rst +18 -0
  54. aimodelshare/documentation/source/advanced_features.rst +137 -0
  55. aimodelshare/documentation/source/competition.rst +218 -0
  56. aimodelshare/documentation/source/conf.py +58 -0
  57. aimodelshare/documentation/source/create_credentials.rst +86 -0
  58. aimodelshare/documentation/source/example_notebooks.rst +132 -0
  59. aimodelshare/documentation/source/functions.rst +151 -0
  60. aimodelshare/documentation/source/gettingstarted.rst +390 -0
  61. aimodelshare/documentation/source/images/creds1.png +0 -0
  62. aimodelshare/documentation/source/images/creds2.png +0 -0
  63. aimodelshare/documentation/source/images/creds3.png +0 -0
  64. aimodelshare/documentation/source/images/creds4.png +0 -0
  65. aimodelshare/documentation/source/images/creds5.png +0 -0
  66. aimodelshare/documentation/source/images/creds_file_example.png +0 -0
  67. aimodelshare/documentation/source/images/predict_tab.png +0 -0
  68. aimodelshare/documentation/source/index.rst +110 -0
  69. aimodelshare/documentation/source/modelplayground.rst +132 -0
  70. aimodelshare/exceptions.py +11 -0
  71. aimodelshare/generatemodelapi.py +1270 -0
  72. aimodelshare/iam/codebuild_policy.txt +129 -0
  73. aimodelshare/iam/codebuild_trust_relationship.txt +12 -0
  74. aimodelshare/iam/lambda_policy.txt +15 -0
  75. aimodelshare/iam/lambda_trust_relationship.txt +12 -0
  76. aimodelshare/json_templates/__init__.py +1 -0
  77. aimodelshare/json_templates/api_json.txt +155 -0
  78. aimodelshare/json_templates/auth/policy.txt +1 -0
  79. aimodelshare/json_templates/auth/role.txt +1 -0
  80. aimodelshare/json_templates/eval/policy.txt +1 -0
  81. aimodelshare/json_templates/eval/role.txt +1 -0
  82. aimodelshare/json_templates/function/policy.txt +1 -0
  83. aimodelshare/json_templates/function/role.txt +1 -0
  84. aimodelshare/json_templates/integration_response.txt +5 -0
  85. aimodelshare/json_templates/lambda_policy_1.txt +15 -0
  86. aimodelshare/json_templates/lambda_policy_2.txt +8 -0
  87. aimodelshare/json_templates/lambda_role_1.txt +12 -0
  88. aimodelshare/json_templates/lambda_role_2.txt +16 -0
  89. aimodelshare/leaderboard.py +174 -0
  90. aimodelshare/main/1.txt +132 -0
  91. aimodelshare/main/1B.txt +112 -0
  92. aimodelshare/main/2.txt +153 -0
  93. aimodelshare/main/3.txt +134 -0
  94. aimodelshare/main/4.txt +128 -0
  95. aimodelshare/main/5.txt +109 -0
  96. aimodelshare/main/6.txt +105 -0
  97. aimodelshare/main/7.txt +144 -0
  98. aimodelshare/main/8.txt +142 -0
  99. aimodelshare/main/__init__.py +1 -0
  100. aimodelshare/main/authorization.txt +275 -0
  101. aimodelshare/main/eval_classification.txt +79 -0
  102. aimodelshare/main/eval_lambda.txt +1709 -0
  103. aimodelshare/main/eval_regression.txt +80 -0
  104. aimodelshare/main/lambda_function.txt +8 -0
  105. aimodelshare/main/nst.txt +149 -0
  106. aimodelshare/model.py +1543 -0
  107. aimodelshare/modeluser.py +215 -0
  108. aimodelshare/moral_compass/README.md +408 -0
  109. aimodelshare/moral_compass/__init__.py +65 -0
  110. aimodelshare/moral_compass/_version.py +3 -0
  111. aimodelshare/moral_compass/api_client.py +601 -0
  112. aimodelshare/moral_compass/apps/__init__.py +69 -0
  113. aimodelshare/moral_compass/apps/ai_consequences.py +540 -0
  114. aimodelshare/moral_compass/apps/bias_detective.py +714 -0
  115. aimodelshare/moral_compass/apps/ethical_revelation.py +898 -0
  116. aimodelshare/moral_compass/apps/fairness_fixer.py +889 -0
  117. aimodelshare/moral_compass/apps/judge.py +888 -0
  118. aimodelshare/moral_compass/apps/justice_equity_upgrade.py +853 -0
  119. aimodelshare/moral_compass/apps/mc_integration_helpers.py +820 -0
  120. aimodelshare/moral_compass/apps/model_building_game.py +1104 -0
  121. aimodelshare/moral_compass/apps/model_building_game_beginner.py +687 -0
  122. aimodelshare/moral_compass/apps/moral_compass_challenge.py +858 -0
  123. aimodelshare/moral_compass/apps/session_auth.py +254 -0
  124. aimodelshare/moral_compass/apps/shared_activity_styles.css +349 -0
  125. aimodelshare/moral_compass/apps/tutorial.py +481 -0
  126. aimodelshare/moral_compass/apps/what_is_ai.py +853 -0
  127. aimodelshare/moral_compass/challenge.py +365 -0
  128. aimodelshare/moral_compass/config.py +187 -0
  129. aimodelshare/placeholders/model.onnx +0 -0
  130. aimodelshare/placeholders/preprocessor.zip +0 -0
  131. aimodelshare/playground.py +1968 -0
  132. aimodelshare/postprocessormodules.py +157 -0
  133. aimodelshare/preprocessormodules.py +373 -0
  134. aimodelshare/pyspark/1.txt +195 -0
  135. aimodelshare/pyspark/1B.txt +181 -0
  136. aimodelshare/pyspark/2.txt +220 -0
  137. aimodelshare/pyspark/3.txt +204 -0
  138. aimodelshare/pyspark/4.txt +187 -0
  139. aimodelshare/pyspark/5.txt +178 -0
  140. aimodelshare/pyspark/6.txt +174 -0
  141. aimodelshare/pyspark/7.txt +211 -0
  142. aimodelshare/pyspark/8.txt +206 -0
  143. aimodelshare/pyspark/__init__.py +1 -0
  144. aimodelshare/pyspark/authorization.txt +258 -0
  145. aimodelshare/pyspark/eval_classification.txt +79 -0
  146. aimodelshare/pyspark/eval_lambda.txt +1441 -0
  147. aimodelshare/pyspark/eval_regression.txt +80 -0
  148. aimodelshare/pyspark/lambda_function.txt +8 -0
  149. aimodelshare/pyspark/nst.txt +213 -0
  150. aimodelshare/python/my_preprocessor.py +58 -0
  151. aimodelshare/readme.md +26 -0
  152. aimodelshare/reproducibility.py +181 -0
  153. aimodelshare/sam/Dockerfile.txt +8 -0
  154. aimodelshare/sam/Dockerfile_PySpark.txt +24 -0
  155. aimodelshare/sam/__init__.py +1 -0
  156. aimodelshare/sam/buildspec.txt +11 -0
  157. aimodelshare/sam/codebuild_policies.txt +129 -0
  158. aimodelshare/sam/codebuild_trust_relationship.txt +12 -0
  159. aimodelshare/sam/codepipeline_policies.txt +173 -0
  160. aimodelshare/sam/codepipeline_trust_relationship.txt +12 -0
  161. aimodelshare/sam/spark-class.txt +2 -0
  162. aimodelshare/sam/template.txt +54 -0
  163. aimodelshare/tools.py +103 -0
  164. aimodelshare/utils/__init__.py +78 -0
  165. aimodelshare/utils/optional_deps.py +38 -0
  166. aimodelshare/utils.py +57 -0
  167. aimodelshare-0.3.7.dist-info/METADATA +298 -0
  168. aimodelshare-0.3.7.dist-info/RECORD +171 -0
  169. aimodelshare-0.3.7.dist-info/WHEEL +5 -0
  170. aimodelshare-0.3.7.dist-info/licenses/LICENSE +5 -0
  171. 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
+ ]