Everything starts with the notebook app itself. This app allows our users to insert JavaScript code, evaluate it and retrieve the output.
Key Features:
- Incorporate multiple JavaScript code blocks
- Execute JavaScript code securely
- Dynamically remove code blocks while maintaining at least one
Security Measures:
- Default strict-mode prevents code from accessing filesystem or network
- Default execution time limit set to 10 seconds
- Default memory limit for code execution is 10Mb
Using eval
in the browser is dangerous because it can execute arbitrary code,
leading to security vulnerabilities like code injection attacks. Malicious code
can access and manipulate the DOM, steal data, or perform unauthorized actions.
For more details, refer to MDN Web Docs on eval().
window.Document
refers to the Document
object representing the webpage.
In a sandboxed environment like PyMiniRacer, there is no DOM to interact with,
hence window.Document
will not behave as it does in a browser. This ensures a
secure and isolated execution context for JavaScript code.
PyV8 and its fork STPyV8, which allow interoperability between Python 3 and JavaScript running on the Google V8 engine, are not thread-safe. Using them with WSGI servers can often lead to segmentation faults. Installing PythonMonkey on my Mac was pretty problematic.
- Flask: Flask Documentation
- PyMiniRacer: PyMiniRacer repository
- Kubernetes Python Client: Kubernetes Python Client
Multitenancy in this application is managed within a Kubernetes environment. The /admin endpoint serves as a control plane, enabling the creation and management of multiple notebook application instances. Each instance corresponds to a separate Kubernetes deployment and service, all within the same namespace.
The main application’s Ingress resource is dynamically updated to include new paths for each instance, ensuring seamless access. This architecture ensures isolation and scalability for each tenant, leveraging Kubernetes’ orchestration capabilities.
Key Points:
• Control Plane: Accessible via /admin, allowing easy management of notebook instances.
• Isolation: Each instance runs as a separate deployment and service.
• Dynamic Ingress: Automatically updated to route traffic to the appropriate instance.
• Scalability: New instances can be created or removed as needed.
TODO: make the k8s_manager
code more maintainable.
RuntimeError: Native library not available
error:
# 1. Find your site-packages
python -m site
# 2. Download the Dylib file
wget https://github.com/sqreen/PyMiniRacer/files/7575004/libmini_racer.dylib.zip
# 3. Unzip The Dylib file
unzip libmini_racer.dylib.zip
# 4. Move Dylib file to your site-packages
mv libmini_racer.dylib <site-packages-path/py_mini_racer/.>
docker build -t the_notebook_app .
docker run --env-file .env -p 5000:5000 the_notebook_app
curl -X POST http://localhost:5000/run -H "Content-Type: application/json" -d \
'{"script": "function test() { return \"Hello, world!\"; } test();"}'
{
"result": "Hello, world!"
}
minikube start && minikube addons enable ingress
eval $(minikube docker-env)
docker build -t the_notebook_app .
kustomize build manifests/overlays/minikube | kubectl apply -f -
kubectl port-forward --namespace the-notebook-app service/the-notebook-app 5000:5000
curl -X POST http://localhost:5000/run -H "Content-Type: application/json" -d \
'{"script": "function test() { return \"Hello, world!\"; } test();"}'
{
"result": "Hello, world!"
}