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
Labels
Merge Requests
104
Merge Requests
104
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
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
Pipeline
#27274
failed with stage
Changes
3
Pipelines
2
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 @@
[instance-theia]
_update_hash_filename_ = instance-theia.cfg.jinja.in
md5sum =
3648844f372a96974582e7281c9987dd
md5sum =
a9d4ace568acdd5002d587816ab91737
[instance]
_update_hash_filename_ = instance.cfg.in
...
...
software/theia/instance-theia.cfg.jinja.in
View file @
9f966b19
...
...
@@ -15,7 +15,6 @@ theia-environment-parts =
theia-parts =
frontend-instance
python-server
promises
parts =
...
...
@@ -123,8 +122,7 @@ config-port = $${frontend-instance:port}
<= monitor-promise-base
promise = check_socket_listening
name = $${:_buildout_section_name_}.py
config-host = $${python-server-port:ip}
config-port = $${python-server-port:port}
config-pathname = $${python-server:socket}
[frontend-authentication-promise]
<= monitor-promise-base
...
...
@@ -262,13 +260,14 @@ content =
log global
bind $${:ip}:$${:port} ssl crt $${frontend-instance-certificate:cert-file} alpn h2,http/1.1
# 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-theia.webmanifest:filename}
acl is_public path /$${frontend-instance-theia-serviceworker.js:filename}
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
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
backend nodejs
...
...
@@ -277,7 +276,9 @@ content =
backend static
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}
hostname = [$${:ip}]
...
...
@@ -387,17 +388,28 @@ filename = favicon.ico
# Local Python Server
# -------------------
[python-server-port]
recipe = slapos.cookbook:free_port
minimum = 3000
maximum = 3100
ip = {{ ipv4_random }}
[python-server]
recipe = slapos.cookbook:wrapper
wrapper-path = $${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}
recipe = slapos.recipe.template
output = $${directory:services}/$${:_buildout_section_name_}
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
# ------------------
...
...
software/theia/test/test.py
View file @
9f966b19
...
...
@@ -146,16 +146,16 @@ class TestTheia(TheiaTestCase):
)).
geturl
()
self
.
get
(
authenticated_url
)
# there's a public folder to serve file
with
open
(
'{}/srv/frontend-static/public/test_file'
.
format
(
self
.
getPath
()),
'w'
)
as
f
:
# there's a public folder to serve file
(no need for authentication)
with
open
(
self
.
getPath
()
+
'/srv/frontend-static/public/test_file'
,
'w'
)
as
f
:
f
.
write
(
"hello"
)
resp
=
self
.
get
(
urljoin
(
authenticated_url
,
'/public/'
))
self
.
assertIn
(
'test_file'
,
resp
.
text
)
resp
=
self
.
get
(
urljoin
(
authenticated_url
,
'/public/test_file'
)
)
self
.
assertEqual
(
'hello'
,
resp
.
text
)
# make sure public folder is protected
resp
=
self
.
get
(
urljoin
(
url
,
'/public/test_file'
),
requests
.
codes
.
unauthorized
)
def
get
(
path_info
):
resp
=
self
.
get
(
urljoin
(
url
,
path_info
)
)
self
.
assertIn
(
'Content-Security-Policy'
,
resp
.
headers
)
return
resp
.
text
self
.
assertIn
(
'test_file'
,
get
(
'/public/'
))
self
.
assertEqual
(
'hello'
,
get
(
'/public/test_file'
)
)
# there's a (not empty) favicon (no need for authentication)
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