gitarsenal-cli 1.1.18 → 1.1.20
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.
- package/package.json +1 -1
- package/python/MODAL_TOKEN_README.md +77 -0
- package/python/credentials_manager.py +0 -0
- package/python/fetch_modal_tokens.py +108 -0
- package/python/fix_modal_token.py +75 -0
- package/python/fix_modal_token_advanced.py +228 -0
- package/python/gitarsenal_proxy_client.py +0 -0
- package/python/modal_auth_patch.py +180 -0
- package/python/modal_proxy_service.py +136 -63
- package/python/modal_token_solution.py +295 -0
- package/python/test_modalSandboxScript.py +88 -70
- package/python/test_modal_auth.py +92 -0
package/package.json
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Modal Token Solution
|
2
|
+
|
3
|
+
This directory contains several scripts to solve the Modal token authentication issue. The problem occurs when Modal cannot find or validate the authentication token, resulting in errors like "Token missing" or "Could not authenticate client".
|
4
|
+
|
5
|
+
## Overview of the Solution
|
6
|
+
|
7
|
+
We've implemented a comprehensive solution that uses multiple approaches to ensure Modal can authenticate properly:
|
8
|
+
|
9
|
+
1. **fetch_modal_tokens.py**: Fetches tokens from the proxy server.
|
10
|
+
2. **modal_token_solution.py**: The main comprehensive solution that combines all approaches.
|
11
|
+
3. **modal_auth_patch.py**: A direct patch for Modal's authentication system.
|
12
|
+
4. **fix_modal_token.py**: A basic token setup script.
|
13
|
+
5. **fix_modal_token_advanced.py**: An advanced version with more approaches.
|
14
|
+
|
15
|
+
## How It Works
|
16
|
+
|
17
|
+
Our solution uses multiple approaches to ensure Modal authentication works:
|
18
|
+
|
19
|
+
1. **Token Fetching**: Tries to fetch tokens from the proxy server.
|
20
|
+
2. **Environment Variables**: Sets `MODAL_TOKEN_ID` and `MODAL_TOKEN_SECRET` environment variables.
|
21
|
+
3. **Token Files**: Creates token files in various formats and locations that Modal might look for.
|
22
|
+
4. **Modal CLI**: Attempts to use the Modal CLI to set the token with the correct profile.
|
23
|
+
5. **Direct Patching**: Directly patches Modal's authentication system to always return our tokens.
|
24
|
+
6. **Monkey Patching**: Monkey-patches Modal's import system to inject our tokens.
|
25
|
+
7. **Authentication Testing**: Tests that the authentication works by creating a simple Modal app.
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
The scripts are used in this order of preference:
|
30
|
+
|
31
|
+
1. First, try `modal_token_solution.py` (most comprehensive)
|
32
|
+
2. If that fails, fall back to `modal_auth_patch.py`
|
33
|
+
3. If that fails, fall back to `fix_modal_token.py`
|
34
|
+
|
35
|
+
In most cases, you should simply import `modal_token_solution` before importing Modal:
|
36
|
+
|
37
|
+
```python
|
38
|
+
import modal_token_solution
|
39
|
+
import modal
|
40
|
+
|
41
|
+
# Now Modal will use our tokens
|
42
|
+
```
|
43
|
+
|
44
|
+
## Proxy Server Integration
|
45
|
+
|
46
|
+
The solution now integrates with the proxy server to fetch tokens:
|
47
|
+
|
48
|
+
1. **fetch_modal_tokens.py**: This script fetches tokens from the proxy server using the `MODAL_PROXY_URL` and `MODAL_PROXY_API_KEY` environment variables.
|
49
|
+
2. If the proxy server is not available, it falls back to hardcoded tokens.
|
50
|
+
3. All other scripts try to use the fetch_modal_tokens module first before falling back to hardcoded tokens.
|
51
|
+
|
52
|
+
## Troubleshooting
|
53
|
+
|
54
|
+
If you still encounter token issues:
|
55
|
+
|
56
|
+
1. Check that the tokens are correct (token ID: `ak-sLhYqCjkvixiYcb9LAuCHp`, token secret: `as-fPzD0Zm0dl6IFAEkhaH9pq`).
|
57
|
+
2. Verify that the token files are created in the correct locations:
|
58
|
+
- `~/.modal/token.json`
|
59
|
+
- `~/.modalconfig`
|
60
|
+
3. Check if the proxy server is accessible and returning valid tokens.
|
61
|
+
4. Try running the scripts manually to see detailed output.
|
62
|
+
|
63
|
+
## Implementation Details
|
64
|
+
|
65
|
+
- **Token Values**: We try to fetch tokens from the proxy server, with fallback to hardcoded values.
|
66
|
+
- **File Locations**: Token files are created in the user's home directory under `~/.modal/`.
|
67
|
+
- **Patching**: We use Python's dynamic nature to patch Modal's authentication system at runtime.
|
68
|
+
- **Profile**: We use the `fr8mafia` profile when setting tokens via the CLI.
|
69
|
+
|
70
|
+
## Files
|
71
|
+
|
72
|
+
- **fetch_modal_tokens.py**: Fetches tokens from the proxy server.
|
73
|
+
- **modal_token_solution.py**: Comprehensive solution combining all approaches.
|
74
|
+
- **modal_auth_patch.py**: Direct patch for Modal's authentication system.
|
75
|
+
- **fix_modal_token.py**: Basic token setup script.
|
76
|
+
- **fix_modal_token_advanced.py**: Advanced version with more approaches.
|
77
|
+
- **test_modal_auth.py**: Test script for Modal authentication.
|
File without changes
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Fetch Modal Tokens
|
4
|
+
|
5
|
+
This script fetches Modal tokens from the proxy server.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import sys
|
10
|
+
import json
|
11
|
+
import requests
|
12
|
+
from pathlib import Path
|
13
|
+
|
14
|
+
# Default tokens to use if we can't fetch from the server
|
15
|
+
DEFAULT_TOKEN_ID = "ak-sLhYqCjkvixiYcb9LAuCHp"
|
16
|
+
DEFAULT_TOKEN_SECRET = "as-fPzD0Zm0dl6IFAEkhaH9pq"
|
17
|
+
|
18
|
+
def fetch_tokens_from_proxy(proxy_url=None, api_key=None):
|
19
|
+
"""
|
20
|
+
Fetch Modal tokens from the proxy server.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
proxy_url: URL of the proxy server
|
24
|
+
api_key: API key for authentication
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
tuple: (token_id, token_secret) if successful, (None, None) otherwise
|
28
|
+
"""
|
29
|
+
# Use environment variables if not provided
|
30
|
+
if not proxy_url:
|
31
|
+
proxy_url = os.environ.get("MODAL_PROXY_URL")
|
32
|
+
|
33
|
+
if not api_key:
|
34
|
+
api_key = os.environ.get("MODAL_PROXY_API_KEY")
|
35
|
+
|
36
|
+
# Check if we have the necessary information
|
37
|
+
if not proxy_url:
|
38
|
+
print("❌ No proxy URL provided or found in environment")
|
39
|
+
return None, None
|
40
|
+
|
41
|
+
if not api_key:
|
42
|
+
print("❌ No API key provided or found in environment")
|
43
|
+
return None, None
|
44
|
+
|
45
|
+
# Ensure the URL ends with a slash
|
46
|
+
if not proxy_url.endswith("/"):
|
47
|
+
proxy_url += "/"
|
48
|
+
|
49
|
+
# Add the endpoint for fetching tokens
|
50
|
+
token_url = f"{proxy_url}api/modal-tokens"
|
51
|
+
|
52
|
+
try:
|
53
|
+
# Make the request
|
54
|
+
print(f"🔄 Fetching tokens from {token_url}")
|
55
|
+
response = requests.get(
|
56
|
+
token_url,
|
57
|
+
headers={"X-API-Key": api_key}
|
58
|
+
)
|
59
|
+
|
60
|
+
# Check if the request was successful
|
61
|
+
if response.status_code == 200:
|
62
|
+
data = response.json()
|
63
|
+
token_id = data.get("token_id")
|
64
|
+
token_secret = data.get("token_secret")
|
65
|
+
|
66
|
+
if token_id and token_secret:
|
67
|
+
print("✅ Successfully fetched tokens from proxy server")
|
68
|
+
return token_id, token_secret
|
69
|
+
else:
|
70
|
+
print("❌ Tokens not found in response")
|
71
|
+
return None, None
|
72
|
+
else:
|
73
|
+
print(f"❌ Failed to fetch tokens: {response.status_code} - {response.text}")
|
74
|
+
return None, None
|
75
|
+
except Exception as e:
|
76
|
+
print(f"❌ Error fetching tokens: {e}")
|
77
|
+
return None, None
|
78
|
+
|
79
|
+
def get_tokens():
|
80
|
+
"""
|
81
|
+
Get Modal tokens, trying to fetch from the proxy server first.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
tuple: (token_id, token_secret)
|
85
|
+
"""
|
86
|
+
# Try to fetch from the proxy server
|
87
|
+
token_id, token_secret = fetch_tokens_from_proxy()
|
88
|
+
|
89
|
+
# If we couldn't fetch from the server, use the default tokens
|
90
|
+
if not token_id or not token_secret:
|
91
|
+
print("⚠️ Using default tokens")
|
92
|
+
return DEFAULT_TOKEN_ID, DEFAULT_TOKEN_SECRET
|
93
|
+
|
94
|
+
return token_id, token_secret
|
95
|
+
|
96
|
+
if __name__ == "__main__":
|
97
|
+
token_id, token_secret = get_tokens()
|
98
|
+
print(f"Token ID: {token_id}")
|
99
|
+
print(f"Token Secret: {token_secret}")
|
100
|
+
|
101
|
+
# Write the tokens to a file for use by other scripts
|
102
|
+
tokens_file = Path(__file__).parent / "modal_tokens.json"
|
103
|
+
with open(tokens_file, 'w') as f:
|
104
|
+
json.dump({
|
105
|
+
"token_id": token_id,
|
106
|
+
"token_secret": token_secret
|
107
|
+
}, f)
|
108
|
+
print(f"✅ Tokens written to {tokens_file}")
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Fix Modal Token
|
4
|
+
|
5
|
+
This script tries different approaches to fix the Modal token issue.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import sys
|
10
|
+
import subprocess
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
# Just run the advanced token fixer
|
14
|
+
try:
|
15
|
+
# Get the directory of this script
|
16
|
+
script_dir = Path(__file__).parent.absolute()
|
17
|
+
|
18
|
+
# Path to the advanced fixer
|
19
|
+
advanced_fixer = script_dir / "fix_modal_token_advanced.py"
|
20
|
+
|
21
|
+
# Check if the advanced fixer exists
|
22
|
+
if advanced_fixer.exists():
|
23
|
+
print(f"🔄 Running advanced Modal token fixer: {advanced_fixer}")
|
24
|
+
|
25
|
+
# Execute the advanced fixer
|
26
|
+
result = subprocess.run(
|
27
|
+
["python", str(advanced_fixer)],
|
28
|
+
check=True # Raise an exception if the command fails
|
29
|
+
)
|
30
|
+
|
31
|
+
# Exit with the same code as the advanced fixer
|
32
|
+
sys.exit(result.returncode)
|
33
|
+
else:
|
34
|
+
print(f"❌ Advanced Modal token fixer not found at {advanced_fixer}")
|
35
|
+
# Fall back to the basic implementation
|
36
|
+
print("🔄 Falling back to basic implementation")
|
37
|
+
except Exception as e:
|
38
|
+
print(f"❌ Error running advanced Modal token fixer: {e}")
|
39
|
+
print("🔄 Falling back to basic implementation")
|
40
|
+
|
41
|
+
# Try to get tokens from the proxy server
|
42
|
+
try:
|
43
|
+
# First, try to import the fetch_modal_tokens module
|
44
|
+
from fetch_modal_tokens import get_tokens
|
45
|
+
TOKEN_ID, TOKEN_SECRET = get_tokens()
|
46
|
+
print(f"✅ Using tokens from proxy server or defaults")
|
47
|
+
except ImportError:
|
48
|
+
# If the module is not available, use hardcoded tokens
|
49
|
+
TOKEN_ID = "ak-sLhYqCjkvixiYcb9LAuCHp"
|
50
|
+
TOKEN_SECRET = "as-fPzD0Zm0dl6IFAEkhaH9pq" # Real token secret from fr8mafia profile
|
51
|
+
print(f"⚠️ Using hardcoded tokens")
|
52
|
+
|
53
|
+
print("🔧 Fixing Modal token (basic implementation)...")
|
54
|
+
|
55
|
+
# Set environment variables
|
56
|
+
os.environ["MODAL_TOKEN_ID"] = TOKEN_ID
|
57
|
+
os.environ["MODAL_TOKEN_SECRET"] = TOKEN_SECRET
|
58
|
+
print(f"✅ Set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables")
|
59
|
+
|
60
|
+
# Create token file
|
61
|
+
modal_dir = Path.home() / ".modal"
|
62
|
+
modal_dir.mkdir(exist_ok=True)
|
63
|
+
token_file = modal_dir / "token.json"
|
64
|
+
with open(token_file, 'w') as f:
|
65
|
+
f.write(f'{{"token_id": "{TOKEN_ID}", "token_secret": "{TOKEN_SECRET}"}}')
|
66
|
+
print(f"✅ Created token file at {token_file}")
|
67
|
+
|
68
|
+
# Create .modalconfig file
|
69
|
+
modalconfig_file = Path.home() / ".modalconfig"
|
70
|
+
with open(modalconfig_file, 'w') as f:
|
71
|
+
f.write(f"token_id = {TOKEN_ID}\n")
|
72
|
+
f.write(f"token_secret = {TOKEN_SECRET}\n")
|
73
|
+
print(f"✅ Created .modalconfig file at {modalconfig_file}")
|
74
|
+
|
75
|
+
print("\n✅ Done fixing Modal token. Please try your command again.")
|
@@ -0,0 +1,228 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Advanced Modal Token Fixer
|
4
|
+
|
5
|
+
This script tries multiple approaches to fix Modal token issues, including:
|
6
|
+
1. Setting environment variables
|
7
|
+
2. Creating token files in various formats
|
8
|
+
3. Using Modal CLI
|
9
|
+
4. Directly modifying Modal's internal configuration
|
10
|
+
5. Monkey-patching Modal's authentication system
|
11
|
+
"""
|
12
|
+
|
13
|
+
import os
|
14
|
+
import sys
|
15
|
+
import json
|
16
|
+
import subprocess
|
17
|
+
import importlib
|
18
|
+
import inspect
|
19
|
+
from pathlib import Path
|
20
|
+
import time
|
21
|
+
|
22
|
+
# Try to get tokens from the proxy server
|
23
|
+
try:
|
24
|
+
# First, try to import the fetch_modal_tokens module
|
25
|
+
from fetch_modal_tokens import get_tokens
|
26
|
+
TOKEN_ID, TOKEN_SECRET = get_tokens()
|
27
|
+
print(f"✅ Using tokens from proxy server or defaults")
|
28
|
+
except ImportError:
|
29
|
+
# If the module is not available, use hardcoded tokens
|
30
|
+
TOKEN_ID = "ak-sLhYqCjkvixiYcb9LAuCHp"
|
31
|
+
TOKEN_SECRET = "as-fPzD0Zm0dl6IFAEkhaH9pq" # Real token secret from fr8mafia profile
|
32
|
+
print(f"⚠️ Using hardcoded tokens")
|
33
|
+
|
34
|
+
print("🔧 Advanced Modal Token Fixer")
|
35
|
+
|
36
|
+
# Approach 1: Set environment variables
|
37
|
+
print("\n📋 Approach 1: Setting environment variables")
|
38
|
+
os.environ["MODAL_TOKEN_ID"] = TOKEN_ID
|
39
|
+
os.environ["MODAL_TOKEN_SECRET"] = TOKEN_SECRET
|
40
|
+
print(f"✅ Set MODAL_TOKEN_ID = {TOKEN_ID}")
|
41
|
+
print(f"✅ Set MODAL_TOKEN_SECRET = {TOKEN_SECRET}")
|
42
|
+
|
43
|
+
# Approach 2: Create token files in various formats
|
44
|
+
print("\n📋 Approach 2: Creating token files in various formats")
|
45
|
+
modal_dir = Path.home() / ".modal"
|
46
|
+
modal_dir.mkdir(exist_ok=True)
|
47
|
+
|
48
|
+
# Format 1: Standard token.json
|
49
|
+
token_file = modal_dir / "token.json"
|
50
|
+
with open(token_file, 'w') as f:
|
51
|
+
token_data = {
|
52
|
+
"token_id": TOKEN_ID,
|
53
|
+
"token_secret": TOKEN_SECRET
|
54
|
+
}
|
55
|
+
json.dump(token_data, f)
|
56
|
+
print(f"✅ Created token file at {token_file}")
|
57
|
+
|
58
|
+
# Format 2: Alternative token.json format
|
59
|
+
token_file_alt = modal_dir / "token_alt.json"
|
60
|
+
with open(token_file_alt, 'w') as f:
|
61
|
+
token_data_alt = {
|
62
|
+
"id": TOKEN_ID,
|
63
|
+
"secret": TOKEN_SECRET
|
64
|
+
}
|
65
|
+
json.dump(token_data_alt, f)
|
66
|
+
print(f"✅ Created alternative token file at {token_file_alt}")
|
67
|
+
|
68
|
+
# Format 3: Create .modalconfig file
|
69
|
+
modalconfig_file = Path.home() / ".modalconfig"
|
70
|
+
with open(modalconfig_file, 'w') as f:
|
71
|
+
f.write(f"token_id = {TOKEN_ID}\n")
|
72
|
+
f.write(f"token_secret = {TOKEN_SECRET}\n")
|
73
|
+
print(f"✅ Created .modalconfig file at {modalconfig_file}")
|
74
|
+
|
75
|
+
# Format 4: Create config.json file
|
76
|
+
config_file = modal_dir / "config.json"
|
77
|
+
with open(config_file, 'w') as f:
|
78
|
+
config_data = {
|
79
|
+
"token_id": TOKEN_ID,
|
80
|
+
"token_secret": TOKEN_SECRET
|
81
|
+
}
|
82
|
+
json.dump(config_data, f)
|
83
|
+
print(f"✅ Created config.json file at {config_file}")
|
84
|
+
|
85
|
+
# Approach 3: Use Modal CLI to set token
|
86
|
+
print("\n📋 Approach 3: Using Modal CLI")
|
87
|
+
try:
|
88
|
+
# Use the CLI to set the token directly
|
89
|
+
result = subprocess.run(
|
90
|
+
["modal", "token", "set", "--token-id", TOKEN_ID, "--token-secret", TOKEN_SECRET, "--profile=fr8mafia", "--no-verify"],
|
91
|
+
capture_output=True, text=True
|
92
|
+
)
|
93
|
+
|
94
|
+
if result.returncode == 0:
|
95
|
+
print(f"✅ Successfully set token via Modal CLI")
|
96
|
+
else:
|
97
|
+
print(f"❌ Failed to set token via Modal CLI: {result.stderr}")
|
98
|
+
except Exception as e:
|
99
|
+
print(f"❌ Error using Modal CLI: {e}")
|
100
|
+
|
101
|
+
# Approach 4: Use Modal Python API to set token
|
102
|
+
print("\n📋 Approach 4: Using Modal Python API")
|
103
|
+
try:
|
104
|
+
import modal
|
105
|
+
print(f"✅ Successfully imported Modal")
|
106
|
+
|
107
|
+
# Try to set token directly in Modal's config
|
108
|
+
try:
|
109
|
+
import modal.config
|
110
|
+
|
111
|
+
# Try different approaches to set the token
|
112
|
+
try:
|
113
|
+
# Approach 4.1: Set token via _auth_config
|
114
|
+
if hasattr(modal.config, '_auth_config'):
|
115
|
+
modal.config._auth_config.token_id = TOKEN_ID
|
116
|
+
modal.config._auth_config.token_secret = TOKEN_SECRET
|
117
|
+
print(f"✅ Set tokens via _auth_config")
|
118
|
+
except Exception as e:
|
119
|
+
print(f"❌ Error setting tokens via _auth_config: {e}")
|
120
|
+
|
121
|
+
try:
|
122
|
+
# Approach 4.2: Set token via set_token() if it exists
|
123
|
+
if hasattr(modal.config, 'set_token'):
|
124
|
+
modal.config.set_token(TOKEN_ID, TOKEN_SECRET)
|
125
|
+
print(f"✅ Set tokens via set_token()")
|
126
|
+
except Exception as e:
|
127
|
+
print(f"❌ Error setting tokens via set_token(): {e}")
|
128
|
+
|
129
|
+
try:
|
130
|
+
# Approach 4.3: Set token via Config
|
131
|
+
if hasattr(modal.config, 'Config'):
|
132
|
+
modal.config.Config.token_id = TOKEN_ID
|
133
|
+
modal.config.Config.token_secret = TOKEN_SECRET
|
134
|
+
print(f"✅ Set tokens via Config")
|
135
|
+
except Exception as e:
|
136
|
+
print(f"❌ Error setting tokens via Config: {e}")
|
137
|
+
|
138
|
+
# Approach 4.4: Inspect modal.config and try to find token-related attributes
|
139
|
+
print("\n🔍 Inspecting modal.config for token-related attributes...")
|
140
|
+
for name in dir(modal.config):
|
141
|
+
if "token" in name.lower() or "auth" in name.lower():
|
142
|
+
print(f"Found potential token-related attribute: {name}")
|
143
|
+
try:
|
144
|
+
attr = getattr(modal.config, name)
|
145
|
+
if hasattr(attr, "token_id"):
|
146
|
+
print(f" - Setting token_id in {name}")
|
147
|
+
setattr(attr, "token_id", TOKEN_ID)
|
148
|
+
if hasattr(attr, "token_secret"):
|
149
|
+
print(f" - Setting token_secret in {name}")
|
150
|
+
setattr(attr, "token_secret", TOKEN_SECRET)
|
151
|
+
except Exception as e:
|
152
|
+
print(f" - Error setting tokens in {name}: {e}")
|
153
|
+
except Exception as e:
|
154
|
+
print(f"❌ Error setting tokens in Modal config: {e}")
|
155
|
+
except Exception as e:
|
156
|
+
print(f"❌ Error importing Modal: {e}")
|
157
|
+
|
158
|
+
# Approach 5: Monkey-patch Modal's authentication system
|
159
|
+
print("\n📋 Approach 5: Monkey-patching Modal's authentication system")
|
160
|
+
try:
|
161
|
+
import modal
|
162
|
+
|
163
|
+
# Define functions that will always return our tokens
|
164
|
+
def get_token_id(*args, **kwargs):
|
165
|
+
return TOKEN_ID
|
166
|
+
|
167
|
+
def get_token_secret(*args, **kwargs):
|
168
|
+
return TOKEN_SECRET
|
169
|
+
|
170
|
+
# Find all authentication-related classes and functions
|
171
|
+
auth_related = []
|
172
|
+
for module_name in dir(modal):
|
173
|
+
if "auth" in module_name.lower() or "token" in module_name.lower() or "config" in module_name.lower():
|
174
|
+
try:
|
175
|
+
module = getattr(modal, module_name)
|
176
|
+
auth_related.append((module_name, module))
|
177
|
+
print(f"Found potential auth-related module: {module_name}")
|
178
|
+
except Exception:
|
179
|
+
pass
|
180
|
+
|
181
|
+
# Try to monkey-patch auth functions to always return valid credentials
|
182
|
+
for name, module in auth_related:
|
183
|
+
if inspect.ismodule(module):
|
184
|
+
for func_name in dir(module):
|
185
|
+
if "get" in func_name.lower():
|
186
|
+
if "token_id" in func_name.lower():
|
187
|
+
try:
|
188
|
+
original_func = getattr(module, func_name)
|
189
|
+
if callable(original_func):
|
190
|
+
print(f" - Patching {name}.{func_name} to return token_id")
|
191
|
+
setattr(module, func_name, get_token_id)
|
192
|
+
except Exception as e:
|
193
|
+
print(f" - Error patching {name}.{func_name}: {e}")
|
194
|
+
elif "token_secret" in func_name.lower() or "token" in func_name.lower():
|
195
|
+
try:
|
196
|
+
original_func = getattr(module, func_name)
|
197
|
+
if callable(original_func):
|
198
|
+
print(f" - Patching {name}.{func_name} to return token_secret")
|
199
|
+
setattr(module, func_name, get_token_secret)
|
200
|
+
except Exception as e:
|
201
|
+
print(f" - Error patching {name}.{func_name}: {e}")
|
202
|
+
except Exception as e:
|
203
|
+
print(f"❌ Error monkey-patching Modal: {e}")
|
204
|
+
|
205
|
+
# Approach 6: Create a test Modal app to verify token
|
206
|
+
print("\n📋 Approach 6: Testing Modal authentication")
|
207
|
+
try:
|
208
|
+
import modal
|
209
|
+
|
210
|
+
print("Creating a test Modal app...")
|
211
|
+
app = modal.App("test-auth")
|
212
|
+
|
213
|
+
@app.function()
|
214
|
+
def hello():
|
215
|
+
return "Hello, world!"
|
216
|
+
|
217
|
+
print("Running the test function...")
|
218
|
+
try:
|
219
|
+
with app.run():
|
220
|
+
result = hello.remote()
|
221
|
+
print(f"✅ Successfully ran Modal function: {result}")
|
222
|
+
print("🎉 Modal authentication is working!")
|
223
|
+
except Exception as e:
|
224
|
+
print(f"❌ Error running Modal function: {e}")
|
225
|
+
except Exception as e:
|
226
|
+
print(f"❌ Error testing Modal authentication: {e}")
|
227
|
+
|
228
|
+
print("\n✅ Done fixing Modal token. Please try your command again.")
|
File without changes
|
@@ -0,0 +1,180 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Modal Authentication Patcher
|
4
|
+
|
5
|
+
This script directly patches Modal's authentication system to always return our token.
|
6
|
+
It should be imported before any Modal code is used.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
import modal_auth_patch
|
10
|
+
import modal
|
11
|
+
# Now Modal will use our token
|
12
|
+
"""
|
13
|
+
|
14
|
+
import os
|
15
|
+
import sys
|
16
|
+
import importlib
|
17
|
+
import types
|
18
|
+
import json
|
19
|
+
from pathlib import Path
|
20
|
+
|
21
|
+
# Try to get tokens from the proxy server
|
22
|
+
try:
|
23
|
+
# First, try to import the fetch_modal_tokens module
|
24
|
+
from fetch_modal_tokens import get_tokens
|
25
|
+
TOKEN_ID, TOKEN_SECRET = get_tokens()
|
26
|
+
print(f"✅ Using tokens from proxy server or defaults")
|
27
|
+
except ImportError:
|
28
|
+
# If the module is not available, use hardcoded tokens
|
29
|
+
TOKEN_ID = "ak-sLhYqCjkvixiYcb9LAuCHp"
|
30
|
+
TOKEN_SECRET = "as-fPzD0Zm0dl6IFAEkhaH9pq" # Real token secret from fr8mafia profile
|
31
|
+
print(f"⚠️ Using hardcoded tokens")
|
32
|
+
|
33
|
+
# Set environment variables
|
34
|
+
os.environ["MODAL_TOKEN_ID"] = TOKEN_ID
|
35
|
+
os.environ["MODAL_TOKEN_SECRET"] = TOKEN_SECRET
|
36
|
+
|
37
|
+
# Create token files
|
38
|
+
modal_dir = Path.home() / ".modal"
|
39
|
+
modal_dir.mkdir(exist_ok=True)
|
40
|
+
token_file = modal_dir / "token.json"
|
41
|
+
with open(token_file, 'w') as f:
|
42
|
+
f.write(f'{{"token_id": "{TOKEN_ID}", "token_secret": "{TOKEN_SECRET}"}}')
|
43
|
+
|
44
|
+
modalconfig_file = Path.home() / ".modalconfig"
|
45
|
+
with open(modalconfig_file, 'w') as f:
|
46
|
+
f.write(f"token_id = {TOKEN_ID}\n")
|
47
|
+
f.write(f"token_secret = {TOKEN_SECRET}\n")
|
48
|
+
|
49
|
+
# Define functions that will always return our tokens
|
50
|
+
def get_token_id(*args, **kwargs):
|
51
|
+
return TOKEN_ID
|
52
|
+
|
53
|
+
def get_token_secret(*args, **kwargs):
|
54
|
+
return TOKEN_SECRET
|
55
|
+
|
56
|
+
# Patch Modal's authentication system
|
57
|
+
try:
|
58
|
+
# Try to import modal.config
|
59
|
+
import modal.config
|
60
|
+
|
61
|
+
# Create a fake auth config object
|
62
|
+
class FakeAuthConfig:
|
63
|
+
token_id = TOKEN_ID
|
64
|
+
token_secret = TOKEN_SECRET
|
65
|
+
|
66
|
+
def get_token_id(self, *args, **kwargs):
|
67
|
+
return TOKEN_ID
|
68
|
+
|
69
|
+
def get_token_secret(self, *args, **kwargs):
|
70
|
+
return TOKEN_SECRET
|
71
|
+
|
72
|
+
# Replace Modal's auth config with our fake one
|
73
|
+
modal.config._auth_config = FakeAuthConfig()
|
74
|
+
|
75
|
+
# Also patch any token-related functions
|
76
|
+
for name in dir(modal.config):
|
77
|
+
if "token_id" in name.lower():
|
78
|
+
try:
|
79
|
+
attr = getattr(modal.config, name)
|
80
|
+
if callable(attr):
|
81
|
+
setattr(modal.config, name, get_token_id)
|
82
|
+
except:
|
83
|
+
pass
|
84
|
+
elif "token_secret" in name.lower() or "token" in name.lower():
|
85
|
+
try:
|
86
|
+
attr = getattr(modal.config, name)
|
87
|
+
if callable(attr):
|
88
|
+
setattr(modal.config, name, get_token_secret)
|
89
|
+
except:
|
90
|
+
pass
|
91
|
+
|
92
|
+
print("✅ Modal authentication patched successfully")
|
93
|
+
except ImportError:
|
94
|
+
# Modal not installed yet, we'll monkey-patch it when it's imported
|
95
|
+
print("⚠️ Modal not installed yet, setting up import hook")
|
96
|
+
|
97
|
+
# Original import function
|
98
|
+
original_import = __import__
|
99
|
+
|
100
|
+
# Our custom import function
|
101
|
+
def custom_import(name, globals=None, locals=None, fromlist=(), level=0):
|
102
|
+
# Call the original import function
|
103
|
+
module = original_import(name, globals, locals, fromlist, level)
|
104
|
+
|
105
|
+
# Check if this is modal or a submodule
|
106
|
+
if name == "modal" or name.startswith("modal."):
|
107
|
+
try:
|
108
|
+
# Try to patch modal.config
|
109
|
+
if hasattr(module, "config"):
|
110
|
+
config = module.config
|
111
|
+
|
112
|
+
# Create a fake auth config object if needed
|
113
|
+
if not hasattr(config, "_auth_config"):
|
114
|
+
class FakeAuthConfig:
|
115
|
+
token_id = TOKEN_ID
|
116
|
+
token_secret = TOKEN_SECRET
|
117
|
+
|
118
|
+
def get_token_id(self, *args, **kwargs):
|
119
|
+
return TOKEN_ID
|
120
|
+
|
121
|
+
def get_token_secret(self, *args, **kwargs):
|
122
|
+
return TOKEN_SECRET
|
123
|
+
|
124
|
+
config._auth_config = FakeAuthConfig()
|
125
|
+
else:
|
126
|
+
# Patch existing auth config
|
127
|
+
config._auth_config.token_id = TOKEN_ID
|
128
|
+
config._auth_config.token_secret = TOKEN_SECRET
|
129
|
+
|
130
|
+
# Patch methods
|
131
|
+
if hasattr(config._auth_config, "get_token_id"):
|
132
|
+
config._auth_config.get_token_id = get_token_id
|
133
|
+
if hasattr(config._auth_config, "get_token_secret"):
|
134
|
+
config._auth_config.get_token_secret = get_token_secret
|
135
|
+
|
136
|
+
# Also patch any token-related functions
|
137
|
+
for name in dir(config):
|
138
|
+
if "token_id" in name.lower():
|
139
|
+
try:
|
140
|
+
attr = getattr(config, name)
|
141
|
+
if callable(attr):
|
142
|
+
setattr(config, name, get_token_id)
|
143
|
+
except:
|
144
|
+
pass
|
145
|
+
elif "token_secret" in name.lower() or "token" in name.lower():
|
146
|
+
try:
|
147
|
+
attr = getattr(config, name)
|
148
|
+
if callable(attr):
|
149
|
+
setattr(config, name, get_token_secret)
|
150
|
+
except:
|
151
|
+
pass
|
152
|
+
|
153
|
+
print("✅ Modal authentication patched during import")
|
154
|
+
except Exception as e:
|
155
|
+
print(f"⚠️ Error patching Modal: {e}")
|
156
|
+
|
157
|
+
return module
|
158
|
+
|
159
|
+
# Replace the built-in import function
|
160
|
+
sys.modules["builtins"].__import__ = custom_import
|
161
|
+
|
162
|
+
print("✅ Modal authentication patch installed")
|
163
|
+
|
164
|
+
# Test the patch if Modal is already imported
|
165
|
+
try:
|
166
|
+
import modal
|
167
|
+
print("Testing Modal authentication patch...")
|
168
|
+
|
169
|
+
# Create a simple app
|
170
|
+
app = modal.App("test-auth-patch")
|
171
|
+
|
172
|
+
@app.function()
|
173
|
+
def hello():
|
174
|
+
return "Hello from patched Modal!"
|
175
|
+
|
176
|
+
print("✅ Modal app created successfully")
|
177
|
+
except ImportError:
|
178
|
+
print("⚠️ Modal not installed, patch will be applied when it's imported")
|
179
|
+
except Exception as e:
|
180
|
+
print(f"❌ Error testing Modal patch: {e}")
|