diff --git a/sources/Dockerfile b/sources/Dockerfile index 2dd65e1..b66c21f 100644 --- a/sources/Dockerfile +++ b/sources/Dockerfile @@ -10,7 +10,8 @@ MAINTAINER Dan Callahan # Base system setup -RUN DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ +RUN DEBIAN_FRONTEND=noninteractive apt-get update \ + && apt-get install --no-install-recommends -y \ vim locales \ && apt-get clean @@ -24,7 +25,6 @@ RUN useradd --create-home app RUN DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ ca-certificates \ - curl \ build-essential \ libzmq-dev \ python-dev \ @@ -34,11 +34,10 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ USER app RUN mkdir -p /home/app/syncserver +ADD Makefile *.ini *.wsgi *.rst *.txt *.py /home/app/syncserver/ +ADD ./syncserver/ /home/app/syncserver/syncserver/ WORKDIR /home/app/syncserver -RUN curl -L https://github.com/mozilla-services/syncserver/tarball/master |\ - tar xzf - --strip-components=1 - RUN make build # Run the Sync server diff --git a/sources/Makefile b/sources/Makefile index 52adba5..5f0b0c9 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -6,18 +6,23 @@ TOOLS := $(addprefix $(ENV)/bin/,flake8 nosetests) # Hackety-hack around OSX system python bustage. # The need for this should go away with a future osx/xcode update. ARCHFLAGS = -Wno-error=unused-command-line-argument-hard-error-in-future -INSTALL = ARCHFLAGS=$(ARCHFLAGS) $(ENV)/bin/pip install + +# Hackety-hack around errors duing compile of ultramemcached. +CFLAGS = "-Wno-error -Wno-error=format-security" + +INSTALL = CFLAGS=$(CFLAGS) ARCHFLAGS=$(ARCHFLAGS) $(ENV)/bin/pip install + .PHONY: all all: build .PHONY: build -build: | $(ENV) -$(ENV): requirements.txt +build: | $(ENV)/COMPLETE +$(ENV)/COMPLETE: requirements.txt $(VIRTUALENV) --no-site-packages $(ENV) $(INSTALL) -r requirements.txt $(ENV)/bin/python ./setup.py develop - touch $(ENV) + touch $(ENV)/COMPLETE .PHONY: test test: | $(TOOLS) @@ -33,11 +38,11 @@ test: | $(TOOLS) --use-token-server http://localhost:5000/token/1.0/sync/1.5; \ kill $$SERVER_PID -$(TOOLS): | $(ENV) +$(TOOLS): | $(ENV)/COMPLETE $(INSTALL) nose flake8 .PHONY: serve -serve: | $(ENV) +serve: | $(ENV)/COMPLETE $(ENV)/bin/pserve ./syncserver.ini .PHONY: clean diff --git a/sources/requirements.txt b/sources/requirements.txt index 4fce41d..fffde2a 100644 --- a/sources/requirements.txt +++ b/sources/requirements.txt @@ -1,9 +1,14 @@ cornice==0.16.2 +gunicorn==19.1.1 pyramid==1.5 requests==2.2.1 simplejson==3.4 SQLAlchemy==0.9.4 unittest2==0.5.1 -http://github.com/mozilla-services/mozservices/archive/5fabece891bbd3bd2c9528cb3bf0562b3efb4af1.zip -https://github.com/mozilla-services/tokenserver/archive/1.2.7.zip +zope.component==4.2.1 +https://github.com/mozilla-services/mozservices/archive/e00e1b68130423ad98d0f6185655bde650443da8.zip +https://github.com/mozilla-services/tokenserver/archive/d7e513e8a4f5c588b70d685a8df1d2e508c341c0.zip http://github.com/mozilla-services/server-syncstorage/archive/1.5.5.zip +# Newer releases of configparser have b/w compat bug: +# https://github.com/mozilla-services/syncserver/issues/39 +configparser==3.3.0r2 diff --git a/sources/syncserver.ini b/sources/syncserver.ini index de9c7da..63cb2d5 100644 --- a/sources/syncserver.ini +++ b/sources/syncserver.ini @@ -26,3 +26,10 @@ public_url = http://localhost:5000/ # Set this to "false" to disable new-user signups on the server. # Only request by existing accounts will be honoured. # allow_new_users = false + +# Uncomment and edit the following to use a local BrowserID verifier +# rather than posing assertions to the mozilla-hosted verifier. +# Audiences should be set to your public_url without a trailing slash. +#[browserid] +#backend = tokenserver.verifiers.LocalVerifier +#audiences = https://localhost:5000 diff --git a/sources/syncserver/__init__.py b/sources/syncserver/__init__.py index 465bf62..eb90f6a 100644 --- a/sources/syncserver/__init__.py +++ b/sources/syncserver/__init__.py @@ -11,6 +11,10 @@ from pyramid.events import NewRequest, subscriber import mozsvc.config +from tokenserver.util import _JSONError + +logger = logging.getLogger("syncserver") + def includeme(config): """Install SyncServer application into the given Pyramid configurator.""" @@ -93,18 +97,36 @@ def includeme(config): @subscriber(NewRequest) -def fixup_script_name(event): - """Event-listener to fix up SCRIPT_NAME based on public_url setting. +def reconcile_wsgi_environ_with_public_url(event): + """Event-listener that checks and tweaks WSGI environ based on public_url. - This is a simple little trick to avoid futzing with configuration in - multiple places. The public_url setting tells us exactly what the root - URL of the app should be, so we can use it to infer the proper value of - SCRIPT_NAME without depending on it being configured in the WSGI server. + This is a simple trick to help ensure that the configured public_url + matches the actual deployed address. It fixes fixes parts of the WSGI + environ where it makes sense (e.g. SCRIPT_NAME) and warns about any parts + that seem obviously mis-configured (e.g. http:// versus https://). + + It's very important to get public_url and WSGI environ matching exactly, + since they're used for browserid audience checking and HAWK signature + validation, so mismatches can easily cause strange and cryptic errors. """ request = event.request public_url = request.registry.settings["syncserver.public_url"] + p_public_url = urlparse(public_url) + # If we don't have a SCRIPT_NAME, take it from the public_url. + # This is often the case if we're behind e.g. an nginx proxy that + # is serving us at some sub-path. if not request.script_name: - request.script_name = urlparse(public_url).path.rstrip("/") + request.script_name = p_public_url.path.rstrip("/") + # Log a noisy error if the application url is different to what we'd + # expect based on public_url setting. + application_url = request.application_url + if public_url != application_url: + msg = "The public_url setting does not match the application url.\n" + msg += "This will almost certainly cause authentication failures!\n" + msg += " public_url setting is: %s\n" % (public_url,) + msg += " application url is: %s\n" % (application_url,) + logger.error(msg) + raise _JSONError([msg], status_code=500) def get_configurator(global_config, **settings):