Skip to content
Snippets Groups Projects
Commit 874b5428 authored by Jonas Haag's avatar Jonas Haag
Browse files

Whole-site password protection #88

It's now possible to require HTTP authentication for all of the Web
interface (not only push/pull). This isn't available from the command
line.

Note that when both whole-site password protection and Smart HTTP mode
is enabled, push is allowed by default. It can be disallowed using the
'disable_push' option.
parent 1ed87e3f
No related branches found
No related tags found
No related merge requests found
...@@ -61,10 +61,24 @@ class Klaus(flask.Flask): ...@@ -61,10 +61,24 @@ class Klaus(flask.Flask):
self.add_url_rule(rule, view_func=getattr(views, endpoint)) self.add_url_rule(rule, view_func=getattr(views, endpoint))
def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None): def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None,
require_browser_auth=False, disable_push=False):
""" """
Returns a WSGI app with all the features (smarthttp, authentication) Returns a WSGI app with all the features (smarthttp, authentication)
already patched in. already patched in.
:param repos: List of paths of repositories to serve.
:param site_name: Name of the Web site (e.g. "John Doe's Git Repositories")
:param use_smarthttp: Enable Git Smart HTTP mode, which makes it possible to
pull from the served repositories. If `htdigest_file` is set as well,
also allow to push for authenticated users.
:param require_browser_auth: Require HTTP authentication according to the
credentials in `htdigest_file` for ALL access to the Web interface.
Requires the `htdigest_file` option to be set.
:param disable_push: Disable push support. This is required in case both
`use_smarthttp` and `require_browser_auth` (and thus `htdigest_file`)
are set, but push should not be supported.
:param htdigest_file: A *file-like* object that contains the HTTP auth credentials.
""" """
app = Klaus( app = Klaus(
repos, repos,
...@@ -84,6 +98,7 @@ def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None): ...@@ -84,6 +98,7 @@ def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None):
backend=dulwich_backend, backend=dulwich_backend,
fallback_app=app.wsgi_app, fallback_app=app.wsgi_app,
) )
dulwich_wrapped_app = utils.SubUri(dulwich_wrapped_app)
# `receive-pack` is requested by the "client" on a push # `receive-pack` is requested by the "client" on a push
# (the "server" is asked to *receive* packs), i.e. we need to secure # (the "server" is asked to *receive* packs), i.e. we need to secure
...@@ -100,21 +115,33 @@ def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None): ...@@ -100,21 +115,33 @@ def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None):
# failed for /info/refs, but since it's used to upload stuff to the server # failed for /info/refs, but since it's used to upload stuff to the server
# we must secure it anyway for security reasons. # we must secure it anyway for security reasons.
PATTERN = r'^/[^/]+/(info/refs\?service=git-receive-pack|git-receive-pack)$' PATTERN = r'^/[^/]+/(info/refs\?service=git-receive-pack|git-receive-pack)$'
if htdigest_file: if htdigest_file and not disable_push:
# .htdigest file given. Use it to read the push-er credentials from. # .htdigest file given. Use it to read the push-er credentials from.
app.wsgi_app = httpauth.DigestFileHttpAuthMiddleware( if require_browser_auth:
htdigest_file, # No need to secure push'ing if we already require HTTP auth
wsgi_app=utils.SubUri(dulwich_wrapped_app), # for all of the Web interface.
routes=[PATTERN], app.wsgi_app = dulwich_wrapped_app
) else:
# Web interface isn't already secured. Require authentication for push'ing.
app.wsgi_app = httpauth.DigestFileHttpAuthMiddleware(
htdigest_file,
wsgi_app=dulwich_wrapped_app,
routes=[PATTERN],
)
else: else:
# no .htdigest file given. Disable push-ing. Semantically we should # No .htdigest file given. Disable push-ing. Semantically we should
# use HTTP 403 here but since that results in freaky error messages # use HTTP 403 here but since that results in freaky error messages
# (see above) we keep asking for authentication (401) instead. # (see above) we keep asking for authentication (401) instead.
# Git will print a nice error message after a few tries. # Git will print a nice error message after a few tries.
app.wsgi_app = httpauth.AlwaysFailingAuthMiddleware( app.wsgi_app = httpauth.AlwaysFailingAuthMiddleware(
wsgi_app=utils.SubUri(dulwich_wrapped_app), wsgi_app=dulwich_wrapped_app,
routes=[PATTERN], routes=[PATTERN],
) )
if require_browser_auth:
app.wsgi_app = httpauth.DigestFileHttpAuthMiddleware(
htdigest_file,
wsgi_app=app.wsgi_app
)
return app return app
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment