changeset 189:101c66da848d

watcher script
author Matt Johnston <matt@ucc.asn.au>
date Sun, 09 Feb 2014 11:41:13 +0800
parents ae5efca89001
children 8318d50d766d
files web/config.py web/secure.py web/templog.py web/views/set.tpl web/watch.py
diffstat 5 files changed, 120 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/web/config.py	Fri Feb 07 23:32:08 2014 +0800
+++ b/web/config.py	Sun Feb 09 11:41:13 2014 +0800
@@ -8,6 +8,8 @@
 
 HMAC_KEY = 'a hmac key' # override in local config file
 
+ALLOWED_USERS = [] # local config. list of sha1 hashes of client ssl keys
+
 UPDATE_URL = 'http://evil.ucc.asn.au/~matt/templog/update'
 
 GRAPH_WIDTH = 1200
--- a/web/secure.py	Fri Feb 07 23:32:08 2014 +0800
+++ b/web/secure.py	Sun Feb 09 11:41:13 2014 +0800
@@ -4,13 +4,27 @@
 import hmac
 import binascii
 import sys
+import hashlib
+
+import bottle
 
 import config
 
-__all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf"]
+__all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf", "get_user_hash"]
+
+HASH=hashlib.sha1
 
 def get_user_hash():
-    return "aaa"
+    if bottle.request.environ.get('SSL_CLIENT_VERIFY', '') != 'GENEROUS':
+        return 'FAILVERIFY'
+    blob = bottle.request.environ.get('SSL_CLIENT_CERT')
+    if not blob:
+        return 'NOCERT'
+
+    b64 = ''.join(l for l in blob.split('\n')
+        if not l.startswith('-'))
+
+    return HASH(binascii.a2b_base64(b64)).hexdigest()
 
 def setup_csrf():
     NONCE_SIZE=16
--- a/web/templog.py	Fri Feb 07 23:32:08 2014 +0800
+++ b/web/templog.py	Sun Feb 09 11:41:13 2014 +0800
@@ -58,9 +58,11 @@
 
 @route('/set')
 def set():
+    allowed = ["false", "true"][secure.get_user_hash() in config.ALLOWED_USERS]
     return bottle.template('set', 
         inline_data = log.get_params(), 
-        csrf_blob = secure.get_csrf_blob())
+        csrf_blob = secure.get_csrf_blob(),
+        allowed = allowed)
 
 @route('/set_current.json')
 def set_fresh():
@@ -113,8 +115,8 @@
 @route('/env')
 def env():
     response.set_header('Content-Type', 'text/plain')
-    return '\n'.join(traceback.format_stack())
-    #return '\n'.join(("%s %s" % k) for k in  request.environ.items())
+    #return '\n'.join(traceback.format_stack())
+    return '\n'.join(("%s %s" % k) for k in  request.environ.items())
     #return str(request.environ)
     #yield "\n"
     #var_lookup = environ['mod_ssl.var_lookup']
--- a/web/views/set.tpl	Fri Feb 07 23:32:08 2014 +0800
+++ b/web/views/set.tpl	Sun Feb 09 11:41:13 2014 +0800
@@ -2,7 +2,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=8,minimum-scale=0.1">
+<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,minimum-scale=1">
 <script src="jquery-2.1.0.min.js"></script>
 <script src="jquery.mobile.custom.min.js"></script>
 <script>
@@ -17,7 +17,7 @@
 }
 
 body {
-    font-family: "sans-serif";
+    font-family: sans-serif;
 }
 
 input {
@@ -26,34 +26,45 @@
     background-color: white;
     border-color: black;
     padding: 0;
-    font-size: 80%;
+    font-size: 30pt;
+    height: 34pt;
 }
 
 input[type="button"] {
-    width: 4em;
-    height: 4em;
-    margin-left: 0.5em;
+    width: 34pt;
+    margin-left: 4pt;
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    background:#fff;
+    vertical-align: center;
 }
 
 input[type="submit"] {
-    width: 10em;
-    height: 4em;
     margin-top: 1em;
     align: center;
+    width: 10em;
 }
 
 input[type="text"], input[type="number"] {
-    height: 4em;
     text-align: center;
+    width: 4em;
 }
 
 #savebox {
-    align: center;
+    vertical-align: center;
     width: 100%;
 }
 
-.onbutton {
-    background-color: #cdf;
+input[type="button"].onbutton {
+    background: #ccc;
+}
+
+input[type="button"].yesno {
+    width: 2.5em;
+}
+
+input[type="button"]#savebutton {
+    width: 5em;
 }
 
 .modified {
@@ -62,8 +73,7 @@
 }
 
 .existing {
-    margin-top: 1em;
-    font-size: 70%;
+    margin-top: 10pt;
 }
 
 </style>
@@ -85,8 +95,8 @@
 <div id="{id}">
 <span class="existing">{title} <span id="oldvalue">{oldvaluetext}</span></span>
 <br/>
-<input type="button" class="button_no" value="No"/>
-<input type="button" class="button_yes" value="Yes"/>
+<input type="button" class="button_no yesno" value="No"/>
+<input type="button" class="button_yes yesno" value="Yes"/>
 </div>
 </script>
 
@@ -157,6 +167,7 @@
 
 var params = {{!inline_data}};
 var csrf_blob = "{{!csrf_blob}}";
+var allowed = {{allowed}};
 window.setter = new Setter(params, csrf_blob);
 
 var number_template = $("[type='html/num_input']").html();
@@ -205,21 +216,14 @@
         add(p);
     })
 
+    if (!allowed) {
+        $("#savebutton").attr("disabled", true);
+        $('#status').text("No cert")
+    }
+
     $("#savebutton").click(function() {
         setter.save();
     })
-
-    var gofn = function() {
-        var r = '#';
-        r += (5+Math.floor(Math.random() * 5));
-        r += (5+Math.floor(Math.random() * 5));
-        r += (5+Math.floor(Math.random() * 5));
-        document.body.style.background = r;
-        this.value = r;
-    }
-    //$("#go").addEventListener("touchstart", gofn, false)
-    //$("#go").addEventListener("click", gofn, false)
-    $("#go").on("vmousedown", gofn);
 }
 
 function set_text_state(el, param)
@@ -291,18 +295,14 @@
 </script>
 
 <body>
-<input type="button" id="go" value="go"/>
-
 
 <section id="paramlist">
 </section>
 
-<div id="savebox">
+<span id="savebox">
 <input type="button" id="savebutton" value="Save"/>
-
-<div id="status">
-</div>
-</div>
+<span id="status"></span>
+</span>
 
 
 </body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/watch.py	Sun Feb 09 11:41:13 2014 +0800
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3.3
+
+import pyinotify
+import glob
+import sys
+import fnmatch
+import os
+
+def GlobWatcher(object):
+	def __init__(self, g, watcher):
+		self.glob = g
+		self.watches = []
+		self.watcher = watcher
+
+def add_glob(watcher, g):
+	d = os.path.dirname(g)
+
+	file_watches = add_glob_files
+
+def main():
+	touchf = sys.argv[1]
+
+	watcher = pyinotify.WatchManager()
+	dirpatterns = {}
+	for g in sys.argv[2:]:
+		d = os.path.dirname(g)
+		pattern = os.path.basename(g)
+		dirpatterns.setdefault(d, []).append(pattern)
+
+	print(dirpatterns)
+
+	watchpatterns = {}
+	for d, patterns in dirpatterns.items():
+
+		w = watcher.add_watch(d,
+			(pyinotify.IN_MODIFY
+			|pyinotify.IN_CREATE
+			|pyinotify.IN_DELETE
+			|pyinotify.IN_MOVED_FROM
+			|pyinotify.IN_MOVED_TO))
+
+		wd = w[d]
+		watchpatterns[wd] = patterns
+
+	def triggered(event):
+		if event.name is None:
+			return
+
+		print("%s %s " % (event.name, event.maskname))
+		patterns = watchpatterns[event.wd]
+		for p in patterns:
+			print(p)
+			if fnmatch.fnmatch(event.name, p):
+				print("matched %s" % p)
+				os.utime(touchf, None)
+
+	n = pyinotify.Notifier(watcher, triggered)
+	n.loop()
+
+if __name__ == '__main__':
+	main()
+