def request_vhost(locker, hostname, path, user=None, desc=''): """Request hostname as a vhost for the given locker and path. Throws a UserError if the request is invalid, otherwise returns a human-readable status message and sends a zephyr.""" locker = locker.encode('utf-8') hostname, reqtype = validate_hostname(hostname, locker) path = path.encode('utf-8') path = validate_path(path) message = "The hostname '%s' is now configured." % hostname if user is None: user = current_user() if reqtype == 'moira': # actually_create_vhost does this check for other reqtypes check_if_already_exists(hostname, locker) t = queue.Ticket.create(locker, hostname, path, requestor=user, purpose=desc) short = hostname[:-len('.mit.edu')] mail.create_ticket(subject="scripts-vhosts CNAME request: %s" % short, body="""Heyas, %(user)s requested %(hostname)s for locker '%(locker)s' path %(path)s. Go to %(url)s to approve it. Purpose: %(desc)s Love, ~Scripts Pony """ % dict(short=short, user=user, locker=locker, hostname=hostname, desc=desc, path=path, url=tg.request.host_url + tg.url('/ticket/%s' % t.id)), id=t.id, requestor=user) message = "We will request the hostname %s; mit.edu hostnames generally take 2-3 business days to become active." % hostname else: # Actually create the vhost actually_create_vhost(locker, hostname, path) if is_sudoing(): sudobit = '+scripts-pony-acl' forbit = ' (for %s)' % user else: sudobit = '' forbit = '' logmessage = "%s%s requested %s for locker '%s' path '%s'%s (Purpose: %s)" % ( current_user(), sudobit, hostname, locker, path, forbit, desc) log.info(logmessage) return message
def delete(locker, vhost): """Deletes an existing vhost owned by the locker.""" if vhost.lower().endswith(".mit.edu") and not vhost.lower().endswith( "." + locker + ".scripts.mit.edu" ): raise UserError("You cannot delete " + vhost + "!") locker = locker.encode("utf-8") scriptsVhostName = get_vhost_name(locker, vhost) conn.delete_s(scriptsVhostName) log.info("%s deleted vhost '%s' (locker '%s')." % (current_user(), vhost, locker))
def set_path(locker, vhost, path): """Sets the path of an existing vhost owned by the locker.""" path = validate_path(path) if vhost == locker + '.scripts.mit.edu': raise UserError("You cannot reconfigure " + vhost + "!") path = path.encode('utf-8') locker = locker.encode('utf-8') scriptsVhostName = get_vhost_name(locker, vhost) conn.modify_s(scriptsVhostName, [(ldap.MOD_REPLACE, 'scriptsVhostDirectory', [path])]) log.info("%s set path for vhost '%s' (locker '%s') to '%s'." % (current_user(), vhost, locker, path))
def add_alias(locker, hostname, alias): locker = locker.encode('utf-8') hostname = hostname.lower().encode('utf-8') if hostname.endswith('.mit.edu'): raise UserError("You can't add aliases to .mit.edu hostnames!") if alias.lower().encode('utf-8').endswith('.mit.edu'): raise UserError( "You can't add .mit.edu aliases to non-.mit.edu hostnames!") alias, reqtype = validate_hostname(alias, locker) if reqtype != 'external': raise RuntimeError( "We didn't catch that something wasn't a .mit.edu hostname.") check_if_already_exists(alias, locker) # If we got here, we're good scriptsVhostName = get_vhost_name(locker, hostname) conn.modify_s(scriptsVhostName, [(ldap.MOD_ADD, 'scriptsVhostAlias', [alias])]) log.info("%s added alias '%s' to '%s' (locker '%s')." % (current_user(), alias, hostname, locker))
def main(): msg = sys.stdin.read() pem = cert.msg_to_pem(msg) if pem is None: log.info("handle_cert_mail.py: No certificate") return chain = cert.pem_to_chain(pem) names = cert.chain_subject_names(chain) filter = ldap.filter.filter_format( "(&(objectClass=scriptsVhost)(|" + "".join("(scriptsVhostName=%s)" for name in names) + "".join("(scriptsVhostAlias=%s)" for name in names) + ")" + "".join("(!(scriptsVhostName=%s))" for name in BLACKLIST) + ")", list(names) + list(names) + BLACKLIST, ) vhosts.connect() res = vhosts.conn.search_s( "ou=VirtualHosts,dc=scripts,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, filter, ["scriptsVhostName", "scriptsVhostAccount", "scriptsVhostCertificate"], ) if res: for dn, attrs in res: vhost, = attrs["scriptsVhostName"] account, = attrs["scriptsVhostAccount"] if "scriptsVhostCertificate" in attrs: old_scripts, = attrs["scriptsVhostCertificate"] old_chain = cert.scripts_to_chain(old_scripts) else: old_chain = None if cert.chain_should_install(chain, old_chain): log.info( "handle_cert_mail.py: Installing certificate for %s on %s" % (vhost, account)) vhosts.conn.modify_s( dn, [ ( ldap.MOD_REPLACE, "scriptsVhostCertificate", cert.chain_to_scripts(chain), ), ( ldap.MOD_REPLACE, "scriptsVhostCertificateKeyFile", "scripts-2048.key", ), ], ) else: log.info( "handle_cert_mail.py: IGNORING certificate for %s on %s" % (vhost, account)) else: log.error("handle_cert_mail.py: Certificate for %s matches no vhost" % list(names))
def set_pool(locker, vhost, pool): """Sets the pool of an existing vhost owned by the locker.""" locker = locker.encode("utf-8") pool = pool.encode("utf-8") scriptsVhostName = get_vhost_name(locker, vhost) info = get_vhost_info(locker, vhost) if pool == "unchanged": pass elif pool == "default": if not info['poolIPv4']: return conn.modify_s(scriptsVhostName, [(ldap.MOD_DELETE, "scriptsVhostPoolIPv4", None)]) else: if info['poolIPv4'] == pool: return res = conn.search_s( "ou=Pools,dc=scripts,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, ldap.filter.filter_format( "(&(objectClass=scriptsVhostPool)(scriptsVhostPoolIPv4=%s))", [pool]), ["description", "scriptsVhostPoolUserSelectable"], ) if not res or not res[0][1].get('scriptsVhostPoolUserSelectable'): name = pool if res: name = res[0][1].get('description', name) raise UserError("You cannot switch to the %s pool!" % (name,)) conn.modify_s( scriptsVhostName, [(ldap.MOD_REPLACE, "scriptsVhostPoolIPv4", [pool])] ) log.info( "%s set pool for vhost '%s' (locker '%s') to '%s'." % (current_user(), vhost, locker, pool) )
def main(): msg = sys.stdin.read() pem = cert.msg_to_pem(msg) if pem is None: log.info('handle_cert_mail.py: No certificate') return chain = cert.pem_to_chain(pem) names = cert.chain_subject_names(chain) filter = ldap.filter.filter_format( '(&(objectClass=scriptsVhost)(|' + ''.join('(scriptsVhostName=%s)' for name in names) + ''.join('(scriptsVhostAlias=%s)' for name in names) + ')' + ''.join('(!(scriptsVhostName=%s))' for name in BLACKLIST) + ')', list(names) + list(names) + BLACKLIST) vhosts.connect() res = vhosts.conn.search_s( 'ou=VirtualHosts,dc=scripts,dc=mit,dc=edu', ldap.SCOPE_ONELEVEL, filter, ['scriptsVhostName', 'scriptsVhostAccount', 'scriptsVhostCertificate']) if res: for dn, attrs in res: vhost, = attrs['scriptsVhostName'] account, = attrs['scriptsVhostAccount'] if 'scriptsVhostCertificate' in attrs: old_scripts, = attrs['scriptsVhostCertificate'] old_chain = cert.scripts_to_chain(old_scripts) else: old_chain = None if cert.chain_should_install(chain, old_chain): log.info( 'handle_cert_mail.py: Installing certificate for %s on %s' % (vhost, account)) vhosts.conn.modify_s( dn, [(ldap.MOD_REPLACE, 'scriptsVhostCertificate', cert.chain_to_scripts(chain)), (ldap.MOD_REPLACE, 'scriptsVhostCertificateKeyFile', 'scripts-2048.key')]) else: log.info( 'handle_cert_mail.py: IGNORING certificate for %s on %s' % (vhost, account)) else: log.error('handle_cert_mail.py: Certificate for %s matches no vhost' % list(names))
def request_vhost(locker, hostname, path, user=None, desc=""): """Request hostname as a vhost for the given locker and path. Throws a UserError if the request is invalid, otherwise returns a human-readable status message and sends a zephyr.""" locker = locker.encode("utf-8") hostname, reqtype = validate_hostname(hostname, locker) path = path.encode("utf-8") path = validate_path(path) message = "The hostname '%s' is now configured." % hostname if user is None: user = current_user() if reqtype == "moira": # actually_create_vhost does this check for other reqtypes check_if_already_exists(hostname, locker) t = queue.Ticket.create(locker, hostname, path, requestor=user, purpose=desc) short = hostname[: -len(".mit.edu")] out = rt.call( "ticket/new", Queue="Scripts", Subject="scripts-vhosts CNAME request: %s" % short, Text="""Heyas, %(user)s requested %(hostname)s for locker '%(locker)s' path %(path)s. Go to %(url)s to approve it. Purpose: %(desc)s Love, ~Scripts Pony """ % dict( short=short, user=user, locker=locker, hostname=hostname, desc=desc, path=path, url=tg.request.host_url + tg.url("/ticket/%s" % t.id), ), Requestor=user, AdminCc=rt.ponyaddr(), ) for line in out.splitlines(): if line.startswith("# Ticket ") and line.endswith(" created."): t.rtid = int(line[len("# Ticket ") : -len(" created.")]) break else: raise RuntimeError("Could not open an RT ticket") message = ( "We will request the hostname %s; mit.edu hostnames generally take 2-3 business days to become active." % hostname ) else: # Actually create the vhost actually_create_vhost(locker, hostname, path) if is_sudoing(): sudobit = "+scripts-pony-acl" forbit = " (for %s)" % user else: sudobit = "" forbit = "" logmessage = "%s%s requested %s for locker '%s' path '%s'%s (Purpose: %s)" % ( current_user(), sudobit, hostname, locker, path, forbit, desc, ) log.info(logmessage) return message