Index: experimental/webtry/DESIGN.md |
diff --git a/experimental/webtry/DESIGN.md b/experimental/webtry/DESIGN.md |
deleted file mode 100644 |
index 79bb178dd1b55cc28e3a5ea5640519ba98a5c88a..0000000000000000000000000000000000000000 |
--- a/experimental/webtry/DESIGN.md |
+++ /dev/null |
@@ -1,286 +0,0 @@ |
-Design |
-====== |
- |
- |
-Overview |
--------- |
-Allows trying out Skia code in the browser. |
- |
- |
-Security |
--------- |
- |
-We're putting a C++ compiler on the web, and promising to run the results of |
-user submitted code, so security is a large concern. Security is handled in a |
-layered approach, using a combination of seccomp-bpf, chroot jail and rlimits. |
- |
-*seccomp-bpf* - Used to limit the types of system calls that the user code can |
-make. Any attempts to make a system call that isn't allowed causes the |
-application to terminate immediately. |
- |
-*chroot jail* - The code is run in a chroot jail, making the rest of the |
-operating system files unreachable from the running code. |
- |
-*rlimits* - Used to limit the resources the running code can get access to, |
-for example runtime is limited to 5s of CPU. |
- |
-User submitted code is also restricted in the following ways: |
- * Limited to 10K of code total. |
- * No preprocessor use is allowed (no lines can begin with #includes). |
- |
- |
-Architecture |
------------- |
- |
-The server runs on GCE, and consists of a Go Web Server that calls out to the |
-c++ compiler and executes code in a chroot jail. See the diagram below: |
- |
- +–––––––––––––+ |
- | | |
- | Browser | |
- | | |
- +––––––+––––––+ |
- | |
- +––––––+––––––+ |
- | | |
- | | |
- | Web Server | |
- | | |
- | (Go) | |
- | | |
- | | |
- +–––––––+–––––+ |
- | |
- +–––––––+––––––––––+ |
- | chroot jail | |
- | +––––––––––––––+| |
- | | seccomp || |
- | | +––––––––––+|| |
- | | |User code ||| |
- | | | ||| |
- | | +––––––––––+|| |
- | +––––––––––––––+| |
- | | |
- +––––––––––––––––––+ |
- |
-The user code is expanded into a simple template and linked against libskia |
-and a couple other .o files that contain main() and the code that sets up the |
-seccomp and rlimit restrictions. This code also sets up the SkCanvas that is |
-handed to the user code. Any code the user submits is restricted to running in |
-a single function that looks like this: |
- |
- |
- void draw(SkCanvas* canvas) { |
- // User code goes here. |
- } |
- |
-The user code is tracked by taking an MD5 hash of the code The template is |
-expanded out into <hash>.cpp, which is compiled into <hash>.o, which is then |
-linked together with all the other libs and object files to create an |
-executable named <hash>. That executable is copied into a directory |
-/home/webtry/inout, that is accessible to both the web server and the schroot |
-jail. The application is then run in the schroot jail, writing its response, |
-<hash>.png, out into the same directory, /home/webtry/inout/, where is it read |
-by the web server and returned to the user. |
- |
-Startup and config |
------------------- |
-The server is started and stopped via: |
- |
- sudo /etc/init.d/webtry [start|stop|restart] |
- |
-But sysv init only handles starting and stopping a program once, so we use |
-Monit to monitor the application and restart it if it crashes. The config |
-is in: |
- |
- /etc/monit/conf.d/webtry |
- |
-The chroot jail is implemented using schroot, its configuration |
-file is found in: |
- |
- /etc/schroot/chroot.d/webtry |
- |
-The seccomp configuration is in main.cpp and only allows the following system |
-calls: |
- |
- exit_group |
- exit |
- fstat |
- read |
- write |
- close |
- mmap |
- munmap |
- brk |
- |
-Database |
--------- |
- |
-Code submitted is stored in an SQL database so that it can be referenced |
-later, i.e. we can let users bookmark their SkFiddles. |
- |
-The storage layer will be Cloud SQL (a cloud version of MySQL). Back of the |
-envelope estimates of traffic come out to a price of a about $1/month. |
- |
-All passwords for MySQL are stored in valentine. |
- |
-To connect to the database from the skia-webtry-b server: |
- |
- $ mysql --host=173.194.83.52 --user=root --password |
- |
-Initial setup of the database, the user, and the tables: |
- |
- CREATE DATABASE webtry; |
- USE webtry; |
- CREATE USER 'webtry'@'%' IDENTIFIED BY '<password is in valentine>'; |
- GRANT SELECT, INSERT, UPDATE ON webtry.webtry TO 'webtry'@'%'; |
- GRANT SELECT, INSERT, UPDATE ON webtry.workspace TO 'webtry'@'%'; |
- GRANT SELECT, INSERT, UPDATE ON webtry.workspacetry TO 'webtry'@'%'; |
- GRANT SELECT, INSERT, UPDATE ON webtry.source_images TO 'webtry'@'%'; |
- |
- // If this gets changed also update the sqlite create statement in webtry.go. |
- |
- CREATE TABLE webtry ( |
- code TEXT DEFAULT '' NOT NULL, |
- create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
- hash CHAR(64) DEFAULT '' NOT NULL, |
- width INTEGER DEFAULT 256 NOT NULL, |
- height INTEGER DEFAULT 256 NOT NULL, |
- source_image_id INTEGER DEFAULT 0 NOT NULL, |
- PRIMARY KEY(hash), |
- |
- FOREIGN KEY (source) REFERENCES sources(id) |
- ); |
- |
- CREATE TABLE workspace ( |
- name CHAR(64) DEFAULT '' NOT NULL, |
- create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
- PRIMARY KEY(name), |
- ); |
- |
- CREATE TABLE workspacetry ( |
- name CHAR(64) DEFAULT '' NOT NULL, |
- create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
- hash CHAR(64) DEFAULT '' NOT NULL, |
- width INTEGER DEFAULT 256 NOT NULL, |
- height INTEGER DEFAULT 256 NOT NULL, |
- source_image_id INTEGER DEFAULT 0 NOT NULL, |
- hidden INTEGER DEFAULT 0 NOT NULL, |
- |
- FOREIGN KEY (name) REFERENCES workspace(name), |
- ); |
- |
- CREATE TABLE source_images ( |
- id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, |
- image MEDIUMBLOB DEFAULT '' NOT NULL, -- Stored as PNG. |
- width INTEGER DEFAULT 0 NOT NULL, |
- height INTEGER DEFAULT 0 NOT NULL, |
- create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
- hidden INTEGER DEFAULT 0 NOT NULL |
- ); |
- |
- ALTER TABLE webtry ADD COLUMN source_image_id INTEGER DEFAULT 0 NOT NULL AFTER hash; |
- ALTER TABLE workspacetry ADD COLUMN source_image_id INTEGER DEFAULT 0 NOT NULL AFTER hash; |
- |
-Common queries webtry.go will use: |
- |
- INSERT INTO webtry (code, hash) VALUES('int i = 0;...', 'abcdef...'); |
- |
- SELECT code, create_ts, hash FROM webtry WHERE hash='abcdef...'; |
- |
- SELECT code, create_ts, hash FROM webtry ORDER BY create_ts DESC LIMIT 2; |
- |
- // To change the password for the webtry sql client: |
- SET PASSWORD for 'webtry'@'%' = PASSWORD('<password is in valentine>'); |
- |
- // Run before and after to confirm the password changed: |
- SELECT Host, User, Password FROM mysql.user; |
- |
-Common queries for workspaces: |
- |
- SELECT hash, create_ts FROM workspace ORDER BY create_ts DESC; |
- |
- INSERT INTO workspace (name, hash) VALUES('autumn-river-12354', 'abcdef...'); |
- |
- SELECT name FROM workspace GROUP BY name; |
- |
-Common queries for sources: |
- |
- SELECT id, image, width, height, create_ts FROM source_images ORDER BY create_ts DESC LIMIT 100; |
- |
-Password for the database will be stored in the metadata instance, if the |
-metadata server can't be found, i.e. running locally, then a local sqlite |
-database will be used. To see the current password stored in metadata and the |
-fingerprint: |
- |
- gcutil --project=google.com:skia-buildbots getinstance skia-webtry-b |
- |
-To set the mysql password that webtry is to use: |
- |
- gcutil --project=google.com:skia-buildbots setinstancemetadata skia-webtry-b --metadata=password:'[mysql client webtry password]' --fingerprint=[some fingerprint] |
- |
-To retrieve the password from the running instance just GET the right URL from |
-the metadata server: |
- |
- curl "http://metadata/computeMetadata/v1/instance/attributes/password" -H "X-Google-Metadata-Request: True" |
- |
-N.B. If you need to change the MySQL password that webtry uses, you must change |
-it both in MySQL and the value stored in the metadata server. |
- |
-Source Images |
-------------- |
- |
-For every try the user can select an optional source image to use as an input. |
-The id of the source image is just an integer and is stored in the database |
-along with the other try information, such as the code. |
- |
-The actual image itself is also stored in a separate table, 'sources', in the |
-database. On startup we check that all the images are available in 'inout', |
-and write out the images if not. Since they are all written to 'inout' we can |
-use the same /i/ image handler to serve them. |
- |
-When a user uploads an image it is decoded and converted to PNG and stored |
-as a binary blob in the database. |
- |
-The bitmap is available to user code as a module level variable: |
- |
- SkBitmap source; |
- |
-The bitmap is read, decoded and stored in source before the seccomp jail is |
-instantiated. |
- |
- |
-Squid |
------ |
- |
-Squid is configured to run on port 80 and run as an accelerator for the actual |
-Go program which is running on port 8000. The config for the squid proxy is |
-held in setup/sys/webtry_squid, which is copied into place during installation |
-and squid is kept running via monit. |
- |
-Workspaces |
----------- |
- |
-Workspaces are implemented by the workspace and workspacetry tables. The |
-workspace table keeps the unique list of all workspaces. The workspacetry table |
-keeps track of all the tries that have occured in a workspace. Right now the |
-hidden column of workspacetry is not used, it's for future functionality. |
- |
-Code Editor |
------------ |
-[CodeMirror](http://codemirror.net/) is used for rich code editing. The |
-following files are included from the official CodeMirror distribution and can |
-be updated in place (no local customizations): |
- |
- * codemirror.js - base CM implementation |
- * codemirror.css - base CM stylesheet |
- * clike.js - C-like syntax highlighting support |
- |
-Alternatively, we may consider pulling CM as an external dependency at some |
-point. |
- |
-Installation |
------------- |
-See the README file. |
- |
- |