Exemplo n.º 1
0
    def test_process_close(self):
        def check_contents(o):
            self.assertEqual(o.audit_author, self.persons.fd)
            self.assertEqual(o.audit_notes, "test message")
            self.assertIsInstance(o.audit_time, datetime.datetime)
            self.assertEqual(o.process, self.processes.app)

        o = pops.ProcessClose(audit_author=self.persons.fd,
                              audit_notes="test message",
                              process=self.processes.app)
        self.check_op(o, check_contents)
Exemplo n.º 2
0
 def test_close_process_dm(self):
     self.processes.app.applying_for = const.STATUS_DM
     self.processes.app.save()
     op = pops.ProcessClose(audit_author=self.persons.dam,
                            audit_notes="audit_closed",
                            process=self.processes.app,
                            logtext="closed",
                            audit_time=self.now)
     op.execute()
     self.persons.app.refresh_from_db()
     self.processes.app.refresh_from_db()
     self.assertEqual(self.persons.app.status, const.STATUS_DM)
     self.assertEqual(self.persons.app.status_changed, op.audit_time)
     self.assertEqual(self.processes.app.closed_by, op.audit_author)
     self.assertEqual(self.processes.app.closed_time, op.audit_time)
     self.assertEqual(len(mail.outbox), 0)
Exemplo n.º 3
0
 def test_close_process_dd_u(self):
     self.processes.app.applying_for = const.STATUS_DD_U
     self.processes.app.save()
     op = pops.ProcessClose(audit_author=self.persons.dam,
                            audit_notes="audit_closed",
                            process=self.processes.app,
                            logtext="closed",
                            audit_time=self.now)
     op.execute()
     self.persons.app.refresh_from_db()
     self.processes.app.refresh_from_db()
     self.assertEqual(self.persons.app.status, const.STATUS_DD_U)
     self.assertEqual(self.persons.app.status_changed, self.now)
     self.assertEqual(self.processes.app.closed_by, op.audit_author)
     self.assertEqual(self.processes.app.closed_time, self.now)
     self.assertEqual(len(mail.outbox), 1)
     self.assertEqual(mail.outbox[0].to, ["*****@*****.**"])
Exemplo n.º 4
0
Arquivo: git_ops.py Projeto: lamby/nm2
    def ops(self):
        person = self.process.person

        if person.fpr != self.fpr:
            raise OperationError(
                self.log_entry,
                "{} in process {} has fingerprint {} but the commit has {}".
                format(person.lookup_key, self.details, person.fpr, self.fpr))

        if self.process.closed: return

        if self.rt:
            logtext = "Closed from keyring changelog {}, RT #{}".format(
                self.log_entry.shasum, self.rt)
        else:
            logtext = "Closed from keyring changelog {}, RT unknown".format(
                self.log_entry.shasum)
        yield pops.ProcessClose(
            process=self.process,
            audit_time=self.log_entry.dt,
            audit_author=self.author,
            audit_notes=logtext,
        )
Exemplo n.º 5
0
Arquivo: git_ops.py Projeto: lamby/nm2
    def ops(self):
        # Check for existing records in the database
        person = self._get_person()

        # If it is all new, keyring has a DD that DAM does not know about:
        # yell.
        if person is None:
            raise OperationError(
                self.log_entry,
                "commit has new DD {} {} that we do not know about".format(
                    self.uid, self.fpr))

        if person.fpr != self.fpr:
            # Keyring-maint added a different key: sync with them
            if self.rt:
                audit_notes = "Set fingerprint to {}, RT #{}".format(
                    self.fpr, self.rt)
            else:
                audit_notes = "Set fingerprint to {}, RT unknown".format(
                    self.fpr)
            yield bops.ChangeFingerprint(person=person,
                                         fpr=self.fpr,
                                         audit_author=self.author,
                                         audit_notes=audit_notes)
            #person.save(audit_author=self.author, audit_notes=audit_notes)
            #log.info("%s: %s: %s", self.logtag, self.person_link(person), audit_notes)
            # Do not return yet, we still need to check the status

        role_status_map = {
            "DD": const.STATUS_DD_U,
            "DN": const.STATUS_DD_NU,
        }

        if person.status == role_status_map[self.role]:
            # Status already matches
            #log.info("%s: %s is already %s: skipping duplicate entry", self.logtag, self.person_link(person), const.ALL_STATUS_DESCS[person.status])
            return

        # Look for a process to close
        applying_for = role_status_map[self.role]

        found = False
        for p in pmodels.Process.objects.filter(person=person,
                                                applying_for=applying_for,
                                                closed_time__isnull=True):
            if self.rt:
                logtext = "Added to {} keyring, RT #{}".format(
                    self.role, self.rt)
            else:
                logtext = "Added to {} keyring, RT unknown".format(self.role)
            yield pops.ProcessClose(
                process=p,
                audit_time=self.log_entry.dt,
                audit_author=self.author,
                audit_notes=logtext,
            )
            #log.info("%s: %s has an open process to become %s, keyring added them as %s",
            #            self.logtag, self.person_link(person), const.ALL_STATUS_DESCS[p.applying_for], self.role)
            found = True

        if not found:
            # f3d1c1ee92bba3ebe05f584b7efea0cfd6e4ebe4 is an example commit
            # that triggers this
            raise OperationError(
                self.log_entry,
                "commit adds {} as {}, but we have no active process for it".
                format(person.lookup_key, self.role))
Exemplo n.º 6
0
    def run_main(self, stage):
        for entry in dmodels.list_people():
            # Skip DDs
            if entry.is_dd and entry.single("keyFingerPrint") is not None:
                continue

            fpr = entry.single("keyFingerPrint")

            # Skip people without fingerprints
            if fpr is None: continue

            email = entry.single("emailForward")

            # Skip entries without emails (happens when running outside of the Debian network)
            if email is None: continue

            # Find the corresponding person in our database
            person = bmodels.Person.objects.get_from_other_db(
                "LDAP",
                uid=entry.uid,
                fpr=fpr,
                email=email,
                format_person=self.hk.link,
            )

            if not person:
                # New DC_GA
                audit_notes = "created new guest account entry from LDAP"
                person = bmodels.Person.objects.create_user(
                    cn=entry.single("cn"),
                    mn=entry.single("mn") or "",
                    sn=entry.single("sn") or "",
                    email=email,
                    email_ldap=email,
                    uid=entry.uid,
                    fpr=fpr,
                    status=const.STATUS_DC_GA,
                    username="******".format(entry.uid),
                    audit_author=self.hk.housekeeper.user,
                    audit_notes=audit_notes,
                )
                log.warn("%s: %s %s", self.IDENTIFIER, self.hk.link(person),
                         audit_notes)
            else:
                # Validate fields
                if person.uid is not None and person.uid != entry.uid:
                    log.warn(
                        "%s: LDAP has uid %s for person %s, but uid is %s in our database",
                        self.IDENTIFIER, entry.uid, self.hk.link(person),
                        person.uid)
                    continue

                if person.fpr is not None and person.fpr != fpr:
                    log.warn(
                        "%s: LDAP has fingerprint %s for person %s, but fingerprint is %s in our database",
                        self.IDENTIFIER, fpr, self.hk.link(person), person.fpr)
                    continue

                audit_notes = ["entry found in LDAP"]

                # Ignore differences in email forward: they are caught by
                # CheckLDAPConsistency

                if person.status in (const.STATUS_DC_GA, const.STATUS_DM_GA):
                    # We already know about it: nothing to do
                    pass
                elif person.status in (const.STATUS_DC, const.STATUS_DM):
                    if person.status == const.STATUS_DM:
                        # DM that becomes DM_GA (acquires uid)
                        new_status = const.STATUS_DM_GA
                    else:
                        # DC that becomes DC_GA (acquires uid)
                        new_status = const.STATUS_DC_GA
                    audit_notes = "entry found in LDAP, adding 'guest account' status"

                    try:
                        process = pmodels.Process.objects.get(
                            person=person,
                            closed_by__isnull=True,
                            applying_for=new_status)
                    except pmodels.Process.DoesNotExist:
                        process = None

                    if process is None:
                        op = bops.ChangeStatus(
                            audit_author=self.hk.housekeeper.user,
                            audit_notes=audit_notes,
                            person=person,
                            status=new_status)
                        op.execute()
                    else:
                        op = pops.ProcessClose(
                            audit_author=self.hk.housekeeper.user,
                            audit_notes=audit_notes,
                            process=process,
                        )
                        op.execute()

                    log.info("%s: %s %s", self.IDENTIFIER,
                             self.hk.link(person), audit_notes)
                else:
                    # New uid on a status that is not supposed to have one:
                    # just warn about it
                    log.warn(
                        "%s: LDAP has new uid %s for person %s, which already has status %s in our database",
                        self.IDENTIFIER, entry.uid, self.hk.link(person),
                        const.ALL_STATUS_DESCS[person.status])
Exemplo n.º 7
0
    def run_main(self, stage):
        # Prefetch people and index them by uid
        people_by_uid = dict()
        for p in bmodels.Person.objects.all():
            if p.uid is None: continue
            people_by_uid[p.uid] = p

        for entry in dmodels.list_people():
            person = people_by_uid.get(entry.uid, None)

            if person is None:
                fpr = entry.single("keyFingerPrint")
                if fpr:
                    log.warn(
                        "%s: %s has fingerprint %s and gid %s in LDAP, but is not in our db",
                        self.IDENTIFIER, entry.uid, fpr,
                        entry.single("gidNumber"))
                else:
                    args = {
                        "cn": entry.single("cn"),
                        "mn": entry.single("mn") or "",
                        "sn": entry.single("sn") or "",
                        "email": entry.single("emailForward"),
                        "email_ldap": entry.single("emailForward"),
                        "uid": entry.uid,
                        "fpr": "FIXME-REMOVED-" + entry.uid,
                        "username": "******".format(entry.uid),
                        "audit_author": self.hk.housekeeper.user,
                    }
                    if entry.is_dd:
                        args["status"] = const.STATUS_REMOVED_DD
                        args[
                            "audit_notes"] = "created to mirror a removed DD account from LDAP"
                        if not args["email"]:
                            args["email"] = "{}@debian.org".format(entry.uid)
                    else:
                        args["status"] = const.STATUS_DC_GA
                        args[
                            "audit_notes"] = "created to mirror a removed guest account from LDAP"
                        if not args["email"]:
                            args["email"] = "{}@example.org".format(entry.uid)
                    person = bmodels.Person.objects.create_user(**args)
                    log.warn("%s: %s: %s", self.IDENTIFIER,
                             self.hk.link(person), args["audit_notes"])
            else:
                dsa_status = entry.single("accountStatus")
                if dsa_status is not None:
                    dsa_status = dsa_status.split()[0]

                if dsa_status in ("retiring", "inactive"):
                    if person.status in (const.STATUS_DC_GA,
                                         const.STATUS_DM_GA):
                        pass  # TODO: handle guest accounts that have been closed
                    elif person.status not in (const.STATUS_REMOVED_DD,
                                               const.STATUS_EMERITUS_DD):
                        try:
                            process = pmodels.Process.objects.get(
                                person=person,
                                closed_by__isnull=True,
                                applying_for__in=(const.STATUS_REMOVED_DD,
                                                  const.STATUS_EMERITUS_DD))
                        except pmodels.Process.DoesNotExist:
                            process = None

                        if process is not None:
                            audit_notes = "closed from dsa: " + entry.single(
                                "accountStatus")
                            op = pops.ProcessClose(
                                audit_author=self.hk.housekeeper.user,
                                audit_notes=audit_notes,
                                process=process,
                            )
                            op.execute()
                            log.info("%s: %s %s", self.IDENTIFIER,
                                     self.hk.link(person), audit_notes)
                        else:
                            log.warn(
                                "%s: %s has accountStatus '%s' but in our db the state is %s",
                                self.IDENTIFIER, self.hk.link(person),
                                entry.single("accountStatus"),
                                const.ALL_STATUS_DESCS[person.status])

                if entry.is_dd and entry.single("keyFingerPrint") is not None:
                    if person.status not in (const.STATUS_DD_U,
                                             const.STATUS_DD_NU):
                        log.warn(
                            "%s: %s has supplementaryGid 'Debian' and fingerprint %s in LDAP, but in our db the state is %s",
                            self.IDENTIFIER, self.hk.link(person),
                            entry.single("keyFingerPrint"),
                            const.ALL_STATUS_DESCS[person.status])

                email = entry.single("emailForward")
                if email != person.email:
                    if email is not None:
                        log.info(
                            "%s: %s changing email_ldap from %s to %s (source: LDAP)",
                            self.IDENTIFIER, self.hk.link(person),
                            person.email, email)
                        person.email_ldap = email
                        person.save(audit_author=self.hk.housekeeper.user,
                                    audit_notes="updated email_ldap from LDAP")