coren has submitted this change and it was merged.

Change subject: toollabs: Add proxylistener that runs on the dynamicproxy 
machine
......................................................................


toollabs: Add proxylistener that runs on the dynamicproxy machine

Change-Id: Id7ad898dd1384906069e9b55196d6f54baabe417
---
A modules/toollabs/files/.pep8
A modules/toollabs/files/proxylistener.py
2 files changed, 121 insertions(+), 0 deletions(-)

Approvals:
  coren: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/modules/toollabs/files/.pep8 b/modules/toollabs/files/.pep8
new file mode 100644
index 0000000..609e631
--- /dev/null
+++ b/modules/toollabs/files/.pep8
@@ -0,0 +1,6 @@
+[pep8]
+
+# Suppress warnings:
+# E501: line too long
+# E241: multiple spaces after ','
+ignore = E501,E241
diff --git a/modules/toollabs/files/proxylistener.py 
b/modules/toollabs/files/proxylistener.py
new file mode 100644
index 0000000..97c2e5b
--- /dev/null
+++ b/modules/toollabs/files/proxylistener.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+#
+#  Copyright (C) 2013 Yuvi Panda <yuvipa...@gmail.com>
+#
+#  Permission to use, copy, modify, and/or distribute this software for any
+#  purpose with or without fee is hereby granted, provided that the above
+#  copyright notice and this permission notice appear in all copies.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+"""
+Simple TCP server that keeps routes in the Redis db for authenticated requests.
+
+The routes are kept as long as the socket making the request is open, and 
cleaned
+up right afterwards. identd is used for authentication - while normally that is
+a terrible idea, this is okay in the toollabs environment because we only have
+a limited number of trusted admins. This also allows routes to be added
+only for URLs that are under the URL prefix allocated for the tool making the
+request. For example, a tool named 'testtool' can ask only for URLs that
+start with /testtool/ to be routed to where it wants.
+
+The socket server is a threaded implementation. Python can not be truly 
parallel
+(hello, GIL!), but for our purposes it is good enough.
+"""
+import logging
+import socket
+import SocketServer
+
+import redis
+
+
+HOST, PORT = "0.0.0.0", 8282
+
+
+def get_remote_user(remote_host, remote_port, local_port):
+    """
+    Uses RFC1413 (ident protocol) to identify which user is making the request.
+
+    Returns username if found, None if there was an error.
+
+    This is secure enough for toollabs since we do not have arbitrary admins.
+    """
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.connect((remote_host, 113))
+
+    request = u"%s, %s\n" % (remote_port, local_port)
+
+    s.send(request.encode("ascii"))
+    resp = s.recv(256)
+    s.close()
+
+    resp_parts = [r.strip() for r in resp.split(":")]
+    if "USERID" not in resp_parts:
+        # Some auth error has occured. Abort!
+        logging.log(logging.INFO, "Identd auth failed, sent %s got back %s" % 
(request.strip(), resp.strip()))
+        return None
+
+    return resp_parts[-1]
+
+
+class RouteRequestHandler(SocketServer.BaseRequestHandler):
+    """
+    Handles incoming connections from clients asking for routes.
+    """
+    def handle(self):
+        route = self.request.recv(1024).strip()
+        destination = self.request.recv(1024).strip()
+        user = get_remote_user(self.client_address[0], self.client_address[1], 
PORT)
+
+        # For some reason the identd response gave us an error, or failed 
otherwise
+        # This should usually not happen, so we'll just ask folks to 'Contact 
an administrator'
+        if user is None:
+            self.request.send("Identd authentication failed. Please contact an 
administrator")
+            self.request.close()
+            return
+
+        # Only tool accounts are allowed to ask for routes
+        # Assume that *only* tool accounts will have local- prefix
+        # Since user accounts need to be approved, and I doubt anything with 
local-
+        # will make it.
+        if not user.startswith('local-'):
+            self.request.send("This service available only to tool accounts")
+            self.request.close()
+            return
+
+        toolname = user.replace("local-", "")
+
+        redis_key = "prefix:%s" % toolname
+
+        logging.log(logging.INFO, "Received request from %s for %s to %s", 
toolname, route, destination)
+
+        red = redis.Redis()  # Always connect to localhost
+        red.hset(redis_key, route, destination)
+        logging.log(logging.DEBUG, "Set redis key %s with key/value %s:%s", 
redis_key, route, destination)
+
+        while self.request.recv(1) != '':
+            pass
+
+        logging.log(logging.INFO, "Cleaning up request from %s for %s to %s", 
toolname, route, destination)
+
+        red.hdel(redis_key, route)
+        logging.log(logging.DEBUG, "Removed redis key %s with key/value 
%s:%s", redis_key, route, destination)
+
+        self.request.close()
+
+if __name__ == '__main__':
+    logging.log(logging.INFO, "Starting server on port %s", PORT)
+    server = SocketServer.ThreadingTCPServer((HOST, PORT), RouteRequestHandler)
+    server.serve_forever()

-- 
To view, visit https://gerrit.wikimedia.org/r/98352
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id7ad898dd1384906069e9b55196d6f54baabe417
Gerrit-PatchSet: 5
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Yuvipanda <yuvipa...@gmail.com>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: coren <mpellet...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to