示例#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 addEvent(self,
                 type,
                 state,
                 by=None,
                 target=None,
                 subject=None,
                 body=None):
        if by is None:
            by = auth.current_user()
        event = Event(ticket=self,
                      type=type,
                      target=target,
                      subject=subject,
                      body=body,
                      by=by)
        DBSession.add(event)
        if state != self.state:
            self.state = state
            pat = "%s's %s changed the ticket re: %s to %s"
        else:
            pat = "%s's %s left the ticket re: %s as %s"
        try:
            url = "%s%s" % (tg.request.host_url, tg.url("/queue"))
        except:
            # Default to something sane if we're not in the context of a request
            url = "https://pony.scripts.mit.edu:444/queue"

        log.zwrite(pat % (by, type, self.hostname, state),
                   instance=self.id,
                   zsig=url)
示例#3
0
    def reject(self, id, subject=None, body=None, token=None, silent=False):
        t = queue.Ticket.get(int(id))
        if t.state != 'open':
            flash("This ticket's not open!")
            redirect('/ticket/%s' % id)
        if t.rtid is None:
            flash("This ticket has no RT ID!")
            redirect('/ticket/%s' % id)
        if (subject and body) or silent:
            if token != auth.token():
                flash("Invalid token!")
            else:
                # Send mail and records it as an event
                if not silent:
                    mail.send_correspondence(subject, body, t.rtid,
                                             auth.current_user())
                    t.addEvent(type=u'mail',
                               state=u'rejected',
                               target=u'user',
                               subject=subject,
                               body=body)
                    flash("Ticket rejected; mail sent to user.")
                else:
                    mail.send_comment(subject,
                                      "Ticket rejected silently.\n\n" + body,
                                      t.id, t.rtid, auth.current_user())
                    t.addEvent(type=u'mail',
                               state=u'rejected',
                               target=u'rt',
                               subject=subject,
                               body=body)
                    flash("Ticket rejected silently.")
                redirect('/queue')
        return dict(tickets=[t],
                    action=url('/reject/%s' % id),
                    subject="Re: Request for hostname %s" % t.hostname,
                    body="""Hello,

Unfortunately, the hostname %(hostname)s is not available.  You can go to http://pony.scripts.mit.edu/ to request a different one.

Sorry for the inconvenience,
-%(first)s

/set status=rejected
""" % dict(hostname=t.hostname, first=auth.first_name()),
                    submit='Send to %s' % t.requestor,
                    extra_buttons={'silent': 'Send as Comment'})
示例#4
0
    def new(self,
            locker,
            hostname="",
            path="",
            desc="",
            token=None,
            confirmed=False,
            personal_ok=False,
            requestor=None,
            **kwargs):
        personal = locker == auth.current_user()
        if confirmed:
            auth.scripts_team_sudo()
        else:
            requestor = None
        if request.response_ext:
            locker += request.response_ext
        if hostname:
            if token != auth.token():
                flash("Invalid token!")
            elif not desc and not confirmed:
                flash("Please specify the purpose of this hostname.")
            elif requestor is not None and not requestor.strip():
                flash("Please specify requestor.")
            elif personal and not personal_ok:
                flash(
                    "Please acknowledge that your hostname will be served from your personal locker and will be deleted when you leave MIT."
                )
            else:
                try:
                    status = vhosts.request_vhost(locker,
                                                  hostname,
                                                  path,
                                                  user=requestor,
                                                  desc=desc)
                except vhosts.UserError as e:
                    flash(e.message)
                else:
                    flash(status)
                    if confirmed:
                        redirect("/queue")
                    else:
                        redirect("/index/" + locker)
        else:
            try:
                auth.validate_locker(locker, sudo_ok=True)
            except auth.AuthError as e:
                flash(e.message)
                redirect("/")

        return dict(
            locker=locker,
            hostname=hostname,
            path=path,
            desc=desc,
            confirmed=confirmed,
            personal=personal,
        )
示例#5
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))
示例#6
0
 def create(locker, hostname, path, requestor=None, purpose=""):
     if requestor is None:
         requestor = auth.current_user()
     t = Ticket(requestor=requestor,
                hostname=hostname,
                locker=locker,
                path=path,
                state="open",
                purpose=purpose)
     session.flush()
     t.addEvent(type='request', state="open", target='us')
     return t
示例#7
0
    def index(self, locker=None, sudo=False):
        """Handle the front-page."""
        if locker is not None and request.response_ext:
            locker += request.response_ext

        olocker = locker
        hosts = None
        user = auth.current_user()
        https = auth.is_https()
        # Find or create the associated user info object.
        # TODO: is there a find_or_create sqlalchemy method?
        if user:
            if sudo and auth.on_scripts_team():
                # override_template(self.index, 'mako:scripts.templates.confirm')
                # return dict(action=url('/new/'+locker),title="Really use Scripts Team bits to request a hostname as locker '%s'?"%locker,question="Only do this in response to a user support request, and after checking to make sure that the request comes from someone authorized to make requests for the locker.",
                #           backurl=url('/index'))
                redirect("/new/%s?confirmed=true" % locker)
            try:
                user_info = (
                    DBSession.query(UserInfo).filter(UserInfo.user == user).one()
                )
            except NoResultFound:
                user_info = UserInfo(user)
                DBSession.add(user_info)
        else:
            user_info = None

        if user is not None:
            if locker is None:
                locker = user
            try:
                hosts = vhosts.list_vhosts(locker)
                hosts.sort(key=lambda k: k[0])
            except auth.AuthError as e:
                flash(e.message)
                # User has been deauthorized from this locker
                if locker in user_info.lockers:
                    user_info.lockers.remove(locker)
                    DBSession.add(user_info)
                if olocker is not None:
                    return self.index()
                else:
                    return dict(hosts={}, locker=locker, user_info=user_info)
            else:
                # Append locker to the list in user_info if it's not there
                if not locker in user_info.lockers:
                    user_info.lockers.append(locker)
                    user_info.lockers.sort()
                    DBSession.add(user_info)
                    flash('You can administer the "%s" locker.' % locker)
        return dict(hosts=hosts, locker=locker, user_info=user_info, https=https)
示例#8
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))
示例#9
0
 def approve(self, id, subject=None, body=None, token=None, silent=False):
     t = queue.Ticket.get(int(id))
     if t.state != 'open':
         flash("This ticket's not open!")
         redirect('/ticket/%s' % id)
     if t.rtid is None:
         flash("This ticket has no RT ID!")
         redirect('/ticket/%s' % id)
     if subject and body:
         if token != auth.token():
             flash("Invalid token!")
         else:
             try:
                 vhosts.actually_create_vhost(t.locker, t.hostname, t.path)
             except vhosts.UserError, e:
                 flash(e.message)
             else:
                 if not silent:
                     # Send mail and records it as an event
                     mail.send_comment(subject, body, t.id, t.rtid,
                                       auth.current_user(),
                                       'accounts-internal')
                     t.addEvent(type='mail',
                                state='moira',
                                target='accounts-internal',
                                subject=subject,
                                body=body)
                     flash(
                         "Ticket approved; mail sent to accounts-internal.")
                 else:
                     mail.send_comment(
                         subject, "Ticket approved silently.\n\n" + body,
                         t.id, t.rtid, auth.current_user())
                     t.addEvent(type='mail', state='dns', target='us')
                     flash("Ticket approved silently.")
                 redirect('/queue')
示例#10
0
 def new(self,
         locker,
         hostname='',
         path='',
         desc='',
         token=None,
         confirmed=False,
         personal_ok=False,
         requestor=None):
     personal = locker == auth.current_user()
     if confirmed:
         auth.scripts_team_sudo()
     else:
         requestor = None
     if pylons.request.response_ext:
         locker += pylons.request.response_ext
     if hostname:
         if token != auth.token():
             flash("Invalid token!")
         elif not desc and not confirmed:
             flash("Please specify the purpose of this hostname.")
         elif requestor is not None and not requestor.strip():
             flash("Please specify requestor.")
         elif personal and not personal_ok:
             flash(
                 "Please acknowledge that your hostname will be served from your personal locker and will be deleted when you leave MIT."
             )
         else:
             try:
                 status = vhosts.request_vhost(locker,
                                               hostname,
                                               path,
                                               user=requestor,
                                               desc=desc)
             except vhosts.UserError, e:
                 flash(e.message)
             else:
                 flash(status)
                 if confirmed:
                     redirect('/queue')
                 else:
                     redirect('/index/' + locker)
示例#11
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))
示例#12
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)
    )
示例#13
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