Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Thomas Gambier
slapos
Commits
9f966b19
Commit
9f966b19
authored
Feb 20, 2023
by
Julien Muchembled
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
theia: make /public/ really public, but prevent JS execution
parent
00ac69e6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
38 additions
and
26 deletions
+38
-26
software/theia/buildout.hash.cfg
software/theia/buildout.hash.cfg
+1
-1
software/theia/instance-theia.cfg.jinja.in
software/theia/instance-theia.cfg.jinja.in
+28
-16
software/theia/test/test.py
software/theia/test/test.py
+9
-9
No files found.
software/theia/buildout.hash.cfg
View file @
9f966b19
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
[instance-theia]
[instance-theia]
_update_hash_filename_ = instance-theia.cfg.jinja.in
_update_hash_filename_ = instance-theia.cfg.jinja.in
md5sum =
3648844f372a96974582e7281c9987dd
md5sum =
a9d4ace568acdd5002d587816ab91737
[instance]
[instance]
_update_hash_filename_ = instance.cfg.in
_update_hash_filename_ = instance.cfg.in
...
...
software/theia/instance-theia.cfg.jinja.in
View file @
9f966b19
...
@@ -15,7 +15,6 @@ theia-environment-parts =
...
@@ -15,7 +15,6 @@ theia-environment-parts =
theia-parts =
theia-parts =
frontend-instance
frontend-instance
python-server
promises
promises
parts =
parts =
...
@@ -123,8 +122,7 @@ config-port = $${frontend-instance:port}
...
@@ -123,8 +122,7 @@ config-port = $${frontend-instance:port}
<= monitor-promise-base
<= monitor-promise-base
promise = check_socket_listening
promise = check_socket_listening
name = $${:_buildout_section_name_}.py
name = $${:_buildout_section_name_}.py
config-host = $${python-server-port:ip}
config-pathname = $${python-server:socket}
config-port = $${python-server-port:port}
[frontend-authentication-promise]
[frontend-authentication-promise]
<= monitor-promise-base
<= monitor-promise-base
...
@@ -262,13 +260,14 @@ content =
...
@@ -262,13 +260,14 @@ content =
log global
log global
bind $${:ip}:$${:port} ssl crt $${frontend-instance-certificate:cert-file} alpn h2,http/1.1
bind $${:ip}:$${:port} ssl crt $${frontend-instance-certificate:cert-file} alpn h2,http/1.1
# writing twice the same ACL is doing OR
# writing twice the same ACL is doing OR
acl is_public path_beg /public/
acl is_public path /$${frontend-instance-favicon.ico:filename}
acl is_public path /$${frontend-instance-favicon.ico:filename}
acl is_public path /$${frontend-instance-theia.webmanifest:filename}
acl is_public path /$${frontend-instance-theia.webmanifest:filename}
acl is_public path /$${frontend-instance-theia-serviceworker.js:filename}
acl is_public path /$${frontend-instance-theia-serviceworker.js:filename}
acl auth_ok http_auth(basic-auth-list)
acl auth_ok http_auth(basic-auth-list)
# No authentication for
some files
# No authentication for
public folder
http-request auth unless auth_ok || is_public
http-request auth unless auth_ok || is_public
use_backend static if { path_beg /$${frontend-instance-fonts:folder-name} } || { path_beg /$${frontend-instance-slapos.css:folder-name} } || { path /$${frontend-instance-logo:filename} } ||
{ path_beg /public/ } ||
is_public
use_backend static if { path_beg /$${frontend-instance-fonts:folder-name} } || { path_beg /$${frontend-instance-slapos.css:folder-name} } || { path /$${frontend-instance-logo:filename} } || is_public
default_backend nodejs
default_backend nodejs
backend nodejs
backend nodejs
...
@@ -277,7 +276,9 @@ content =
...
@@ -277,7 +276,9 @@ content =
backend static
backend static
log global
log global
server static_backend $${python-server-port:ip}:$${python-server-port:port}
server static_backend $${python-server:socket}
option forwardfor
http-response set-header Content-Security-Policy "default-src 'self'; img-src 'self' data:; script-src 'none'"
ip = $${frontend-instance-port:ip}
ip = $${frontend-instance-port:ip}
hostname = [$${:ip}]
hostname = [$${:ip}]
...
@@ -387,17 +388,28 @@ filename = favicon.ico
...
@@ -387,17 +388,28 @@ filename = favicon.ico
# Local Python Server
# Local Python Server
# -------------------
# -------------------
[python-server-port]
recipe = slapos.cookbook:free_port
minimum = 3000
maximum = 3100
ip = {{ ipv4_random }}
[python-server]
[python-server]
recipe = slapos.cookbook:wrapper
recipe = slapos.recipe.template
wrapper-path = $${directory:services}/$${:_buildout_section_name_}
output = $${directory:services}/$${:_buildout_section_name_}
command-line = $${buildout:executable} -m http.server $${python-server-port:port} --bind $${python-server-port:ip} --directory $${directory:frontend-static}
socket = $${directory:run}/$${:_buildout_section_name_}.sock
inline =
#!$${buildout:executable}
import atexit, os, socketserver
from http import server
class Server(socketserver.ThreadingUnixStreamServer):
daemon_threads = True
class Handler(server.SimpleHTTPRequestHandler):
def address_string(self): # insecure but ok for logging
return self.headers.get("X-Forwarded-For", "local")
s = "$${:socket}"
os.chdir("$${directory:frontend-static}")
def cleanup():
try:
os.remove(s)
except FileNotFoundError:
pass
atexit.register(cleanup)()
Server(s, Handler).serve_forever()
# Common Environment
# Common Environment
# ------------------
# ------------------
...
...
software/theia/test/test.py
View file @
9f966b19
...
@@ -146,16 +146,16 @@ class TestTheia(TheiaTestCase):
...
@@ -146,16 +146,16 @@ class TestTheia(TheiaTestCase):
)).
geturl
()
)).
geturl
()
self
.
get
(
authenticated_url
)
self
.
get
(
authenticated_url
)
# there's a public folder to serve file
# there's a public folder to serve file
(no need for authentication)
with
open
(
'{}/srv/frontend-static/public/test_file'
.
format
(
with
open
(
self
.
getPath
()
+
'/srv/frontend-static/public/test_file'
,
self
.
getPath
()),
'w'
)
as
f
:
'w'
)
as
f
:
f
.
write
(
"hello"
)
f
.
write
(
"hello"
)
resp
=
self
.
get
(
urljoin
(
authenticated_url
,
'/public/'
))
def
get
(
path_info
):
self
.
assertIn
(
'test_file'
,
resp
.
text
)
resp
=
self
.
get
(
urljoin
(
url
,
path_info
)
)
resp
=
self
.
get
(
urljoin
(
authenticated_url
,
'/public/test_file'
)
)
self
.
assertIn
(
'Content-Security-Policy'
,
resp
.
headers
)
self
.
assertEqual
(
'hello'
,
resp
.
text
)
return
resp
.
text
# make sure public folder is protected
self
.
assertIn
(
'test_file'
,
get
(
'/public/'
))
resp
=
self
.
get
(
urljoin
(
url
,
'/public/test_file'
),
requests
.
codes
.
unauthorized
)
self
.
assertEqual
(
'hello'
,
get
(
'/public/test_file'
)
)
# there's a (not empty) favicon (no need for authentication)
# there's a (not empty) favicon (no need for authentication)
resp
=
self
.
get
(
urljoin
(
url
,
'/favicon.ico'
))
resp
=
self
.
get
(
urljoin
(
url
,
'/favicon.ico'
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment