Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Docker-in-Docker (DinD) capabilities of public runners deactivated.
More info
Open sidebar
pipelet
Pipelet
Commits
ace424e5
Commit
ace424e5
authored
Dec 15, 2010
by
Marc Betoule
Browse files
Various level of authentication
parent
22fd692f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
144 additions
and
40 deletions
+144
-40
README.org
README.org
+40
-6
pipelet/auth.py
pipelet/auth.py
+75
-16
pipelet/web.py
pipelet/web.py
+29
-18
No files found.
README.org
View file @
ace424e5
...
...
@@ -1035,15 +1035,49 @@ Pipeline(pipedot, codedir=, prefix=, env=MyEnvironment)
Pipeweb use the cherrypy web framework server and can be run behind an
apache webserver which brings essentially two advantages:
- https support.
- faster static files serving.
See the [[http://www.cherrypy.org/wiki/TableOfContents][cherrypy]] documentation for hints about this.
- access to *_mod apache facilities (https, gzip, authentication facilities ...).
- faster static files serving (the pipelet appli actually use quite few of them so the actual gain is marginal).
There is actually several way of doing so, the [[http://tools.cherrypy.org/wiki/BehindApache][cherrypy]] documentation
giving hints about each. We describe here an example case using
mod_rewrite and virtual hosting.
1. The first thing we need is a working installation of apache with
mod_rewrite activated. On a debian-like distribution this usually
obtain by:
=sudo a2enmod rewrite=
=sudo a2enmod proxy=
=sudo a2enmod proxy_http=
2. We then configure apache to rewrite request to the cherrypy apps
except for the static files of the application that will be served
directly. Here is a sample configuration file for a dedicated
virtual host named pipeweb with pipelet installed under
=/usr/local/lib/python2.6/dist-packages/=.
#+begin_src apache
<VirtualHost pipeweb:80>
ServerAdmin pipeweb_admin@localhost
DocumentRoot /usr/local/lib/python2.6/dist-packages/pipelet
# ErrorLog /some/custom/error_file.log
# CustomLog /some/custom/access_file.log common
RewriteEngine on
RewriteRule ^/static/(.*) /usr/local/lib/python2.6/dist-packages/pipelet/static/$1 [L]
RewriteRule ^(.*) http://127.0.0.1:8080$1 [proxy]
</VirtualHost>
#+end_src
3. Restart apache and start the pipeweb application to serve on the
specified address and port:
=pipeweb start -H 127.0.0.1=
When deploying the pipeweb interface in a production environment, one may want
* The Pipelet actors
This section document the code for developers.
The code documentation can be built using the doxygen configuration
file
This section document the code for developers. The code documentation
can be built using the doxygen configuration file
pipelet/doc/pipelet.dox
...
...
pipelet/auth.py
View file @
ace424e5
# Form based authentication for CherryPy. Requires the
# Session tool to be loaded.
#
""" Simple authentication for pipeweb.
"""
import
cherrypy
import
sqlite3
def
read_access
(
func
):
""" Decorator to set read only access to a web page (cherrypy web function)
Parameters
----------
func: web function
def
check_access
(
auth_type
,
access_level
):
""" Check whether user has sufficient access rights.
Depending on the configuration passed through auth_type:
- grant access without verification
- check the access level of an otherwise authenticated user
- perform Basic http authentication and check access rights
- perform Digest http authentication and check access rights
Parameters:
-----------
auth_type: either 'None', 'ACL', 'Basic', 'Digest'
access_level: the required access level.
"""
return
cherrypy
.
tools
.
digest_auth
(
realm
=
"pipeweb"
,
users
=
lambda
:
get_credentials
(
1
))(
func
)
cherrypy
.
log
.
error
(
'auth_type:%s'
%
auth_type
)
realm
=
"pipeweb"
if
auth_type
==
'None'
:
#No autorization check required
return
True
def
write_access
(
func
):
""" Decorator to set read only accessto a web page (cherrypy web function)
if
not
'authorization'
in
cherrypy
.
request
.
headers
:
return
False
ah
=
cherrypy
.
lib
.
httpauth
.
parseAuthorization
(
cherrypy
.
request
.
headers
[
'authorization'
])
if
ah
is
None
:
raise
cherrypy
.
HTTPError
(
400
,
'Bad Request'
)
Parameters
----------
func: web function
"""
return
cherrypy
.
tools
.
digest_auth
(
realm
=
"pipeweb"
,
users
=
lambda
:
get_credentials
(
2
))(
func
)
dic
=
get_credentials
(
access_level
)
if
auth_type
==
'ACL'
:
#Check that otherwise authenticated user has the required
#access level
if
ah
[
'username'
]
in
dic
.
keys
():
return
True
else
:
return
False
password
=
dic
.
get
(
ah
[
"username"
],
None
)
encrypt
=
lambda
x
:
x
cherrypy
.
log
.
error
(
'password:%s'
%
password
)
if
cherrypy
.
lib
.
httpauth
.
checkResponse
(
ah
,
password
,
method
=
cherrypy
.
request
.
method
,
encrypt
=
encrypt
,
realm
=
realm
):
cherrypy
.
request
.
login
=
ah
[
"username"
]
return
True
cherrypy
.
request
.
login
=
False
return
False
def
get_credentials
(
access_level
=
1
):
""" Get users/passwd from pipe data base.
...
...
@@ -49,6 +78,36 @@ def get_credentials(access_level=1):
conn
.
close
()
return
dic
def
ask_auth
(
auth_type
):
realm
=
"pipeweb"
if
auth_type
==
"Basic"
:
cherrypy
.
response
.
headers
[
'www-authenticate'
]
=
cherrypy
.
lib
.
httpauth
.
basicAuth
(
realm
)
elif
auth_type
==
"Digest"
:
cherrypy
.
response
.
headers
[
'www-authenticate'
]
=
cherrypy
.
lib
.
httpauth
.
digestAuth
(
realm
)
def
read_access
(
auth_type
=
"Digest"
):
""" Require read only access on a web page
"""
if
check_access
(
auth_type
,
1
):
return
ask_auth
(
auth_type
)
raise
cherrypy
.
HTTPError
(
401
,
"You are not authorized to access that resource"
)
def
write_access
(
auth_type
=
"Digest"
):
""" Require write accessto a web page
"""
if
check_access
(
auth_type
,
2
):
return
ask_auth
(
auth_type
)
raise
cherrypy
.
HTTPError
(
401
,
"You are not authorized to access that resource"
)
# Making this module a custom cherrypy toolbox
pipeauth
=
cherrypy
.
_cptools
.
Toolbox
(
'pipeauth'
)
pipeauth
.
read_access
=
cherrypy
.
Tool
(
'on_start_resource'
,
read_access
)
pipeauth
.
write_access
=
cherrypy
.
Tool
(
'on_start_resource'
,
write_access
)
def
acl_setup
(
db_file
):
""" Set user/passwd table in pipe database.
...
...
pipelet/web.py
View file @
ace424e5
...
...
@@ -23,7 +23,8 @@ current_dir = os.path.dirname(os.path.abspath(__file__))
from
glob
import
glob
import
shutil
from
cherrypy.lib.static
import
serve_file
from
auth
import
read_access
,
write_access
#from auth import read_access, write_access
import
auth
import
re
import
pickle
...
...
@@ -103,7 +104,7 @@ class Web:
return
list
(
set
(
lst
))
@
cherrypy
.
expose
@
write_access
@
auth
.
pipeauth
.
write_access
()
def
addtag
(
self
,
segid
,
tag
):
""" Add new tag to the database
...
...
@@ -147,7 +148,7 @@ class Web:
r
=
pickle
.
dump
(
d
,
f
)
@
cherrypy
.
expose
@
write_access
@
auth
.
pipeauth
.
write_access
()
def
deltag
(
self
,
tag
):
""" Delete tag from the database
...
...
@@ -196,7 +197,7 @@ class Web:
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
filter
(
self
,
tag
=
None
,
date
=
None
):
""" Print the pipeline instances matching tag and date.
...
...
@@ -229,7 +230,7 @@ class Web:
return
html
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
index
(
self
,
highlight
=
None
,
thumbnail
=
None
):
""" Pipeline instances tree view
...
...
@@ -239,7 +240,6 @@ class Web:
----------
highlight: list of segid (optional), filter the printed seg by segid.
"""
conn
=
sqlite3
.
connect
(
self
.
db_file
,
check_same_thread
=
True
)
conn
.
text_factory
=
str
# get all instances
...
...
@@ -356,7 +356,7 @@ class Web:
return
html
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
product
(
self
,
segid
=
None
,
status
=
None
):
""" Products index.
...
...
@@ -468,7 +468,7 @@ class Web:
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
code
(
self
,
segid
=
None
):
""" Segment's files index.
...
...
@@ -559,7 +559,7 @@ class Web:
@
cherrypy
.
expose
@
write_access
@
auth
.
pipeauth
.
write_access
()
def
del_lst_seg
(
self
,
seglist
):
""" Delete a pipeline instance.
...
...
@@ -586,7 +586,7 @@ class Web:
@
cherrypy
.
expose
@
write_access
@
auth
.
pipeauth
.
write_access
()
def
del_lst_prod
(
self
,
segid
,
taskid
):
""" Delete recursively a list of products.
...
...
@@ -611,7 +611,7 @@ class Web:
raise
cherrypy
.
HTTPRedirect
(
'/'
+
self
.
name
+
'/'
,
303
)
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
pipedir
(
self
,
segid
=
None
,
directory
=
None
):
""" Print the content of a directory.
...
...
@@ -660,7 +660,7 @@ class Web:
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
log
(
self
,
logdir
):
""" Print the content of the log directory.
"""
...
...
@@ -674,14 +674,14 @@ class Web:
return
html
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
serve_log
(
self
,
filename
):
""" Print the content of the log file.
"""
return
serve_file
(
filename
,
content_type
=
'text/plain'
,
disposition
=
"inline"
)
@
cherrypy
.
expose
@
write_access
@
auth
.
pipeauth
.
write_access
()
def
delete_log
(
self
,
logdir
):
""" Delete the content of the log directory.
"""
...
...
@@ -706,7 +706,7 @@ class Web:
return
filepath
@
cherrypy
.
expose
@
read_access
@
auth
.
pipeauth
.
read_access
()
def
download
(
self
,
segid
=
None
,
filepath
=
None
):
""" Download a file.
...
...
@@ -880,6 +880,9 @@ def main():
parser
.
add_option
(
'-a'
,
'--access-file'
,
help
=
'Logging file for access when run in daemon mode'
,
default
=
os
.
path
.
expanduser
(
'~/pipelet.access'
))
parser
.
add_option
(
'-A'
,
'--authentication-type'
,
help
=
'What kind of authentication is performed by cherrypy, can be one of ["Digest", "Basic", "ACL", "None"]'
,
default
=
"Digest"
)
parser
.
add_option
(
'-i'
,
'--pid-file'
,
help
=
'Store the pid in daemon mode'
,
default
=
os
.
path
.
expanduser
(
'~/pipelet.pid'
))
...
...
@@ -895,21 +898,29 @@ def main():
'log.screen'
:
False
,
'log.error_file'
:
options
.
error_file
,
'log.access_file'
:
options
.
access_file
,
'server.pidfile'
:
options
.
pid_file
}
'server.pidfile'
:
options
.
pid_file
,
'pipeauth.read_access.auth_type'
:
options
.
authentication_type
,
'pipeauth.write_access.auth_type'
:
options
.
authentication_type
}
}
if
options
.
no_daemon
:
config
[
'global'
][
'log.screen'
]
=
True
cherrypy
.
config
.
update
(
config
)
cherrypy
.
config
.
update
(
options
.
config_file
)
cherrypy
.
tree
.
mount
(
PipeIndex
(),
""
,
config
)
app
=
cherrypy
.
tree
.
mount
(
PipeIndex
(),
""
,
config
)
if
hasattr
(
app
,
'toolboxes'
):
# CherryPy 3.1+
app
.
toolboxes
[
'pipeauth'
]
=
auth
.
pipeauth
cherrypy
.
engine
.
start
()
cherrypy
.
engine
.
block
()
exit
(
0
)
if
options
.
krenew
:
cherrypy
.
config
.
update
(
config
)
cherrypy
.
config
.
update
(
options
.
config_file
)
cherrypy
.
tree
.
mount
(
PipeIndex
(),
""
,
config
)
app
=
cherrypy
.
tree
.
mount
(
PipeIndex
(),
""
,
config
)
if
hasattr
(
app
,
'toolboxes'
):
# CherryPy 3.1+
app
.
toolboxes
[
'pipeauth'
]
=
auth
.
pipeauth
cherrypy
.
engine
.
start
()
cherrypy
.
engine
.
block
()
exit
(
0
)
...
...
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