diff options
Diffstat (limited to 'apachekerbauth/apachekerbauth/var/www/cgi-bin/swift-auth')
-rwxr-xr-x | apachekerbauth/apachekerbauth/var/www/cgi-bin/swift-auth | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/apachekerbauth/apachekerbauth/var/www/cgi-bin/swift-auth b/apachekerbauth/apachekerbauth/var/www/cgi-bin/swift-auth new file mode 100755 index 0000000..d04ebb2 --- /dev/null +++ b/apachekerbauth/apachekerbauth/var/www/cgi-bin/swift-auth @@ -0,0 +1,103 @@ +#!/usr/bin/python + +# Requires the python-memcached package to be installed. +# +# Requires the following command to be run: +# setsebool -P httpd_can_network_connect 1 +# setsebool -P httpd_can_network_memcache 1 + +import cgi +import json +from memcached import MemcacheRing +import os +import random +import re +import subprocess +from time import time + +# After how many seconds the cached information about an authentication +# token is discarded. +TOKEN_LIFE = 86400 + +# This is used as a prefix for tokens and memcache keys. We use the default +# value from the Swift tempauth filter. In the future, this should be turned +# into a configuration parameter. +RESELLER_PREFIX = 'AUTH_' + +MEMCACHE_SERVERS = ['rhs1.example.com:11211'] + +def main(): + remote_user = os.environ['REMOTE_USER'] + + matches = re.match('([^@]+)@.*', remote_user) + if not matches: + raise RuntimeError("Malformed REMOTE_USER \"%s\"" % remote_user) + + username = matches.group(1) + + mc = MemcacheRing(MEMCACHE_SERVERS) + + # Check if we already got a token for this user. + memcache_user_key = '%s/user/%s' % (RESELLER_PREFIX, username) + token = None + candidate_token = mc.get(memcache_user_key) + if candidate_token: + memcache_token_key = '%s/token/%s' % (RESELLER_PREFIX, candidate_token) + cached_auth_data = mc.get(memcache_token_key) + if cached_auth_data: + expires, groups = cached_auth_data + if expires > time(): + token = candidate_token + + if not token: + # We don't use uuid.uuid4() here because importing the uuid module + # causes (harmless) SELinux denials in the audit log on RHEL 6. If this + # is a security concern, a custom SELinux policy module could be written + # to not log those denials. + r = random.SystemRandom() + token = '%stk%s' % (RESELLER_PREFIX, + ''.join(r.choice('abcdef0123456789') for x in range(32))) + + # Retrieve the numerical group IDs. We cannot list the group names + # because group names from Active Directory may contain spaces, and + # we wouldn't be able to split the list of group names into its + # elements. + p = subprocess.Popen(['id', '-G', username], stdout=subprocess.PIPE) + if p.wait() != 0: + raise RuntimeError("Failure running id -G for %s" % remote_user) + + (p_stdout, p_stderr) = p.communicate() + + # Convert the group numbers into group names. + groups = [] + for gid in p_stdout.strip().split(" "): + groups.append(grp.getgrgid(int(gid))[0]) + + # The first element of the list is considered a unique identifier + # for the user. We add the username to accomplish this. + if username in groups: + groups.remove(username) + groups = [username] + groups + + groups = ','.join(groups) + + expires = time() + TOKEN_LIFE + auth_data = (expires, groups) + + memcache_token_key = "%s/token/%s" % (RESELLER_PREFIX, token) + mc.set(memcache_token_key, auth_data, timeout=TOKEN_LIFE) + + # Record the token with the user info for future use. + memcache_user_key = '%s/user/%s' % (RESELLER_PREFIX, username) + mc.set(memcache_user_key, token, timeout=TOKEN_LIFE) + + print "X-Auth-Token: %s\n" % token + + # For debugging. + print "<pre>%i / %s</pre>" % mc.get(memcache_token_key) + +try: + print("Content-Type: text/html") + main() +except: + cgi.print_exception() |