include_recipe "tools"
blocks = data_bag_item("tile", "blocks")
+web_passwords = data_bag_item("web", "passwords")
apache_module "alias"
apache_module "cgi"
package "python-cairo"
package "python-mapnik"
+package "python-setuptools"
+
+easy_install_package "pyotp"
package "fonts-noto-cjk"
package "fonts-noto-hinted"
owner "tile"
group "tile"
mode 0o755
- variables :blocks => blocks
+ variables :blocks => blocks, :totp_key => web_passwords["totp_key"]
end
template "/srv/tile.openstreetmap.org/cgi-bin/debug" do
import cairo
import cgi
+import Cookie
import mapnik
import os
+import pyotp
+import resource
import shutil
+import signal
import sys
import tempfile
-import resource
-import signal
# Limit maximum CPU time
# The Postscript output format can sometimes take hours
print "</body>"
print "</html>"
+# Create TOTP token validator
+totp = pyotp.TOTP('<%= @totp_key %>', interval = 3600)
+
# Parse CGI parameters
form = cgi.FieldStorage()
+# Import cookies
+cookies = Cookie.SimpleCookie(os.environ.get('HTTP_COOKIE'))
+
# Make sure we have a user agent
if not os.environ.has_key('HTTP_USER_AGENT'):
os.environ['HTTP_USER_AGENT'] = 'NONE'
if not os.environ.has_key('HTTP_REFERER'):
os.environ['HTTP_REFERER'] = 'NONE'
+# Look for TOTP token
+if cookies.has_key('_osm_totp_token'):
+ token = cookies['_osm_totp_token'].value
+else:
+ token = None
+
# Get the load average
cputimes = [float(n) for n in open("/proc/stat").readline().rstrip().split()[1:-1]]
idletime = cputimes[3] / sum(cputimes)
# Process the request
-if idletime < 0.2:
+if not totp.verify(token, valid_window = 1):
+ # Abort if the request didn't have a valid TOTP token
+ output_error("Missing or invalid token")
+elif idletime < 0.2:
# Abort if the CPU idle time on the machine is too low
output_error("The server is too busy at the moment. Please wait a few minutes before trying again.", "503 Service Unavailable")
<% @blocks["user_agents"].each do |user_agent| -%>