示例#1
0
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
示例#2
0
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))
示例#3
0
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))
示例#4
0
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))
示例#6
0
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)
    )
示例#7
0
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))
示例#8
0
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