forked from modal-labs/modal-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_implementation.py
More file actions
156 lines (128 loc) · 5.38 KB
/
Copy pathtest_implementation.py
File metadata and controls
156 lines (128 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Copyright Modal Labs 2025
#!/usr/bin/env python3
"""Test per-function firewall configuration implementation."""
import os
import pickle
import sys
def test_firewall_feature():
"""Test that the firewall feature is correctly implemented."""
print("Testing firewall feature implementation...")
# Test 1: Check that the parameter is added to @app.function decorator
print("\n1. Checking @app.function decorator...")
with open("/Users/yeldarb/Code/modal-client/modal/app.py", "r") as f:
content = f.read()
if "use_firewall: bool = False, # Whether to use rffickle firewall" in content:
print("✅ use_firewall parameter added to @app.function")
else:
print("❌ use_firewall parameter not found in @app.function")
return False
# Test 2: Check that the parameter is added to @app.cls decorator
print("\n2. Checking @app.cls decorator...")
if "use_firewall: bool = False, # Whether to use rffickle firewall" in content:
print("✅ use_firewall parameter added to @app.cls")
else:
print("❌ use_firewall parameter not found in @app.cls")
return False
# Test 3: Check that _Function class has the attribute
print("\n3. Checking _Function class attribute...")
with open("/Users/yeldarb/Code/modal-client/modal/_functions.py", "r") as f:
content = f.read()
if "_use_firewall: bool = False # Whether to use rffickle" in content:
print("✅ _use_firewall attribute added to _Function class")
else:
print("❌ _use_firewall attribute not found in _Function class")
return False
# Test 4: Check that _process_result accepts use_firewall parameter
print("\n4. Checking _process_result signature...")
with open("/Users/yeldarb/Code/modal-client/modal/_utils/function_utils.py", "r") as f:
content = f.read()
if "async def _process_result(result: api_pb2.GenericResult, data_format: int, stub, client=None, use_firewall: bool = False):" in content:
print("✅ _process_result accepts use_firewall parameter")
else:
print("❌ _process_result doesn't have use_firewall parameter")
return False
# Test 5: Check that deserialize function properly uses rffickle
print("\n5. Checking deserialize function...")
with open("/Users/yeldarb/Code/modal-client/modal/_serialization.py", "r") as f:
content = f.read()
if "from fickle import DefaultFirewall" in content:
print("✅ deserialize imports rffickle when firewall is enabled")
else:
print("❌ deserialize doesn't import rffickle")
return False
if "NEVER fall back to regular pickle" in content:
print("✅ deserialize has no unsafe fallback")
else:
print("❌ deserialize might have unsafe fallback")
return False
# Test 6: Check that _process_result calls are updated
print("\n6. Checking _process_result calls in _Function...")
with open("/Users/yeldarb/Code/modal-client/modal/_functions.py", "r") as f:
content = f.read()
if "use_firewall=self._use_firewall" in content:
print("✅ _process_result calls pass use_firewall from function")
else:
print("❌ _process_result calls don't pass use_firewall")
return False
return True
def test_example_usage():
"""Show example of how the feature would be used."""
print("\n" + "=" * 50)
print("EXAMPLE USAGE:")
print("=" * 50)
example = '''
import modal
app = modal.App()
# Trusted function - regular pickle (default)
@app.function()
def trusted_function(data):
"""This function processes trusted data."""
return complex_computation(data)
# Untrusted function - uses rffickle firewall
@app.function(use_firewall=True)
def run_user_code(code: str):
"""This function runs untrusted user code safely."""
# Even if user code returns malicious pickled objects,
# they will be blocked during deserialization
exec(code)
return result
# For class methods
@app.cls(use_firewall=True)
class UntrustedExecutor:
@modal.method()
def execute(self, code: str):
"""Execute untrusted code in a sandboxed environment."""
exec(code)
return result
'''
print(example)
return True
def main():
print("Modal Firewall Implementation Verification")
print("=" * 50)
try:
# Verify rffickle is available
try:
from fickle import DefaultFirewall
print("✅ rffickle is installed and available")
except ImportError:
print("❌ rffickle is not installed")
print("Run: pip install rffickle")
return 1
# Test the implementation
if not test_firewall_feature():
return 1
# Show example usage
test_example_usage()
except Exception as e:
print(f"❌ Test failed: {e}")
import traceback
traceback.print_exc()
return 1
print("\n" + "=" * 50)
print("✅ IMPLEMENTATION VERIFIED")
print("\nThe Modal fork (rfmodal) now supports per-function firewall configuration!")
print("Functions can individually opt-in to safe deserialization using use_firewall=True")
return 0
if __name__ == "__main__":
sys.exit(main())