예제 #1
0
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = self._get_response_content(response)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})
        notify_type = handler_options.get("To", NOTIFY_TYPE.TOKENOWNER)
        reply_to_type = handler_options.get("reply_to")
        try:
            logged_in_user = g.logged_in_user
        except Exception:
            logged_in_user = {}

        tokenowner = self._get_tokenowner(request)
        log.debug(u"Executing event for action {0!r}, user {1!r}, "
                  u"logged_in_user {2!r}".format(action, tokenowner,
                                                 logged_in_user))

        # Determine recipient
        recipient = None
        reply_to = None

        if reply_to_type == NOTIFY_TYPE.NO_REPLY_TO:
            reply_to = ""

        elif reply_to_type == NOTIFY_TYPE.TOKENOWNER and not tokenowner.is_empty(
        ):
            reply_to = tokenowner.info.get("email")

        elif reply_to_type == NOTIFY_TYPE.INTERNAL_ADMIN:
            username = handler_options.get("reply_to " +
                                           NOTIFY_TYPE.INTERNAL_ADMIN)
            internal_admin = get_db_admin(username)
            reply_to = internal_admin.email if internal_admin else ""

        elif reply_to_type == NOTIFY_TYPE.ADMIN_REALM:
            # Adds all email addresses from a specific admin realm to the reply-to-header
            admin_realm = handler_options.get("reply_to " +
                                              NOTIFY_TYPE.ADMIN_REALM)
            attr = is_attribute_at_all()
            ulist = get_user_list({"realm": admin_realm},
                                  custom_attributes=attr)
            # create a list of all user-emails, if the user has an email
            emails = [u.get("email") for u in ulist if u.get("email")]
            reply_to = ",".join(emails)

        elif reply_to_type == NOTIFY_TYPE.LOGGED_IN_USER:
            # Add email address from the logged in user into the reply-to header
            if logged_in_user.get(
                    "username") and not logged_in_user.get("realm"):
                # internal admins have no realm
                internal_admin = get_db_admin(logged_in_user.get("username"))
                if internal_admin:
                    reply_to = internal_admin.email if internal_admin else ""

            else:
                # Try to find the user in the specified realm
                user_obj = User(logged_in_user.get("username"),
                                logged_in_user.get("realm"))
                if user_obj:
                    reply_to = user_obj.info.get("email") if user_obj else ""

        elif reply_to_type == NOTIFY_TYPE.EMAIL:
            email = handler_options.get("reply_to " + NOTIFY_TYPE.EMAIL,
                                        "").split(",")
            reply_to = email[0]

        else:
            log.warning("Was not able to determine the email for the reply-to "
                        "header: {0!s}".format(handler_def))

        if notify_type == NOTIFY_TYPE.TOKENOWNER and not tokenowner.is_empty():
            recipient = {
                "givenname": tokenowner.info.get("givenname"),
                "surname": tokenowner.info.get("surname"),
                "username": tokenowner.login,
                "userrealm": tokenowner.realm,
                "email": tokenowner.info.get("email"),
                "mobile": tokenowner.info.get("mobile")
            }
        elif notify_type == NOTIFY_TYPE.INTERNAL_ADMIN:
            username = handler_options.get("To " + NOTIFY_TYPE.INTERNAL_ADMIN)
            internal_admin = get_db_admin(username)
            recipient = {
                "givenname": username,
                "email": internal_admin.email if internal_admin else ""
            }
        elif notify_type == NOTIFY_TYPE.ADMIN_REALM:
            # Send emails to all the users in the specified admin realm
            admin_realm = handler_options.get("To " + NOTIFY_TYPE.ADMIN_REALM)
            attr = is_attribute_at_all()
            ulist = get_user_list({"realm": admin_realm},
                                  custom_attributes=attr)
            # create a list of all user-emails, if the user has an email
            emails = [u.get("email") for u in ulist if u.get("email")]
            recipient = {
                "givenname": "admin of realm {0!s}".format(admin_realm),
                "email": emails
            }
        elif notify_type == NOTIFY_TYPE.LOGGED_IN_USER:
            # Send notification to the logged in user
            if logged_in_user.get(
                    "username") and not logged_in_user.get("realm"):
                # internal admins have no realm
                internal_admin = get_db_admin(logged_in_user.get("username"))
                if internal_admin:
                    recipient = {
                        "givenname": logged_in_user.get("username"),
                        "email": internal_admin.email if internal_admin else ""
                    }
            else:
                # Try to find the user in the specified realm
                user_obj = User(logged_in_user.get("username"),
                                logged_in_user.get("realm"))
                if user_obj:
                    recipient = {
                        "givenname": user_obj.info.get("givenname"),
                        "surname": user_obj.info.get("surname"),
                        "email": user_obj.info.get("email"),
                        "mobile": user_obj.info.get("mobile")
                    }

        elif notify_type == NOTIFY_TYPE.EMAIL:
            email = handler_options.get("To " + NOTIFY_TYPE.EMAIL,
                                        "").split(",")
            recipient = {"email": email}
        else:
            log.warning("Was not able to determine the recipient for the user "
                        "notification: {0!s}".format(handler_def))

        if recipient or action.lower() == "savefile":
            # In case of "savefile" we do not need a recipient
            # Collect all data
            body = handler_options.get("body") or DEFAULT_BODY
            if body.startswith("file:"):  # pragma no cover
                # We read the template from the file.
                filename = body[5:]
                try:
                    with open(filename, "r", encoding="utf-8") as f:
                        body = f.read()
                except Exception as e:
                    log.warning(
                        u"Failed to read email template from file {0!r}: {1!r}"
                        .format(filename, e))
                    log.debug(u"{0!s}".format(traceback.format_exc()))

            subject = handler_options.get("subject") or \
                      "An action was performed on your token."
            serial = request.all_data.get("serial") or \
                     content.get("detail", {}).get("serial") or \
                     g.audit_object.audit_data.get("serial")
            registrationcode = content.get("detail",
                                           {}).get("registrationcode")
            pin = content.get("detail", {}).get("pin")
            googleurl_value = content.get("detail", {}).get("googleurl",
                                                            {}).get("value")
            googleurl_img = content.get("detail", {}).get("googleurl",
                                                          {}).get("img")
            tokentype = None
            if serial:
                tokens = get_tokens(serial=serial)
                if tokens:
                    tokentype = tokens[0].get_tokentype()
            else:
                token_objects = get_tokens(user=tokenowner)
                serial = ','.join([tok.get_serial() for tok in token_objects])

            tags = create_tag_dict(
                logged_in_user=logged_in_user,
                request=request,
                client_ip=g.client_ip,
                pin=pin,
                googleurl_value=googleurl_value,
                recipient=recipient,
                tokenowner=tokenowner,
                serial=serial,
                tokentype=tokentype,
                registrationcode=registrationcode,
                escape_html=action.lower() == "sendmail"
                and handler_options.get("mimetype", "").lower() == "html")

            body = to_unicode(body).format(googleurl_img=googleurl_img, **tags)
            subject = subject.format(**tags)
            # Send notification
            if action.lower() == "sendmail":
                emailconfig = handler_options.get("emailconfig")
                mimetype = handler_options.get("mimetype", "plain")
                useremail = recipient.get("email")
                attach_qrcode = handler_options.get("attach_qrcode", False)

                if attach_qrcode and googleurl_img:
                    # get the image part of the googleurl
                    googleurl = urlopen(googleurl_img)
                    mail_body = MIMEMultipart('related')
                    mail_body.attach(MIMEText(body, mimetype))
                    mail_img = MIMEImage(googleurl.read())
                    mail_img.add_header('Content-ID', '<token_image>')
                    mail_img.add_header(
                        'Content-Disposition',
                        'inline; filename="{0!s}.png"'.format(serial))
                    mail_body.attach(mail_img)
                    body = mail_body
                try:
                    ret = send_email_identifier(emailconfig,
                                                recipient=useremail,
                                                subject=subject,
                                                body=body,
                                                reply_to=reply_to,
                                                mimetype=mimetype)
                except Exception as exx:
                    log.error("Failed to send email: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification email to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

            elif action.lower() == "savefile":
                spooldir = get_app_config_value(
                    "PI_NOTIFICATION_HANDLER_SPOOLDIRECTORY",
                    "/var/lib/privacyidea/notifications/")
                filename = handler_options.get("filename")
                random = get_alphanum_str(16)
                filename = filename.format(random=random,
                                           **tags).lstrip(os.path.sep)
                outfile = os.path.normpath(os.path.join(spooldir, filename))
                if not outfile.startswith(spooldir):
                    log.error(
                        u'Cannot write outside of spooldir {0!s}!'.format(
                            spooldir))
                else:
                    try:
                        with open(outfile, "w") as f:
                            f.write(body)
                    except Exception as err:
                        log.error(
                            u"Failed to write notification file: {0!s}".format(
                                err))

            elif action.lower() == "sendsms":
                smsconfig = handler_options.get("smsconfig")
                userphone = recipient.get("mobile")
                try:
                    ret = send_sms_identifier(smsconfig, userphone, body)
                except Exception as exx:
                    log.error("Failed to send sms: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification sms to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

        return ret
예제 #2
0
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = json.loads(response.data)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})
        notify_type = handler_options.get("To", NOTIFY_TYPE.TOKENOWNER)
        try:
            logged_in_user = g.logged_in_user
        except Exception:
            logged_in_user = {}

        tokenowner = self._get_tokenowner(request)
        log.debug("Executing event for action {0!s}, user {1!s},"
                  "logged_in_user {2!s}".format(action, tokenowner,
                                                logged_in_user))

        # Determine recipient
        recipient = None

        if notify_type == NOTIFY_TYPE.TOKENOWNER and not tokenowner.is_empty():
            recipient = {
                "givenname": tokenowner.info.get("givenname"),
                "surname": tokenowner.info.get("surname"),
                "username": tokenowner.login,
                "userrealm": tokenowner.realm,
                "email": tokenowner.info.get("email"),
                "mobile": tokenowner.info.get("mobile")
            }
        elif notify_type == NOTIFY_TYPE.INTERNAL_ADMIN:
            username = handler_options.get("To "+NOTIFY_TYPE.INTERNAL_ADMIN)
            internal_admin = get_db_admin(username)
            recipient = {
                "givenname": username,
                "email": internal_admin.email if internal_admin else ""
            }
        elif notify_type == NOTIFY_TYPE.ADMIN_REALM:
            # Send emails to all the users in the specified admin realm
            admin_realm = handler_options.get("To "+NOTIFY_TYPE.ADMIN_REALM)
            ulist = get_user_list({"realm": admin_realm})
            # create a list of all user-emails, if the user has an email
            emails = [u.get("email") for u in ulist if u.get("email")]
            recipient = {
                "givenname": "admin of realm {0!s}".format(admin_realm),
                "email": emails
            }
        elif notify_type == NOTIFY_TYPE.LOGGED_IN_USER:
            # Send notification to the logged in user
            if logged_in_user.get("user") and not logged_in_user.get("realm"):
                # internal admins have no realm
                internal_admin = get_db_admin(logged_in_user.get("user"))
                if internal_admin:
                    recipient = {
                        "givenname": logged_in_user.get("user"),
                        "email": internal_admin.email if internal_admin else ""
                    }
            else:
                # Try to find the user in the specified realm
                user_obj = User(logged_in_user.get("user"),
                                logged_in_user.get("realm"))
                if user_obj:
                    recipient = {
                        "givenname": user_obj.info.get("givenname"),
                        "surname": user_obj.info.get("surname"),
                        "email": user_obj.info.get("email"),
                        "mobile": user_obj.info.get("mobile")
                    }

        elif notify_type == NOTIFY_TYPE.EMAIL:
            email = handler_options.get("To "+NOTIFY_TYPE.EMAIL, "").split(",")
            recipient = {
                "email": email
            }
        else:
            log.warning("Was not able to determine the recipient for the user "
                        "notification: {0!s}".format(handler_def))

        if recipient:
            # Collect all data
            body = handler_options.get("body") or DEFAULT_BODY
            serial = request.all_data.get("serial") or \
                     content.get("detail", {}).get("serial") or \
                     g.audit_object.audit_data.get("serial")
            registrationcode = content.get("detail", {}).get("registrationcode")
            tokentype = None
            if serial:
                tokens = get_tokens(serial=serial)
                if tokens:
                    tokentype = tokens[0].get_tokentype()
            else:
                token_objects = get_tokens(user=tokenowner)
                serial = ','.join([tok.get_serial() for tok in token_objects])

            body = body.format(
                admin=logged_in_user.get("username"),
                realm=logged_in_user.get("realm"),
                action=request.path,
                serial=serial,
                url=request.url_root,
                user=tokenowner.info.get("givenname"),
                surname=tokenowner.info.get("surname"),
                givenname=recipient.get("givenname"),
                username=tokenowner.login,
                userrealm=tokenowner.realm,
                tokentype=tokentype,
                registrationcode=registrationcode,
                recipient_givenname=recipient.get("givenname"),
                recipient_surname=recipient.get("surname")
            )

            # Send notification
            if action.lower() == "sendmail":
                emailconfig = handler_options.get("emailconfig")
                useremail = recipient.get("email")
                subject = handler_options.get("subject") or \
                          "An action was performed on your token."
                try:
                    ret = send_email_identifier(emailconfig,
                                                recipient=useremail,
                                                subject=subject, body=body)
                except Exception as exx:
                    log.error("Failed to send email: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification email to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

            elif action.lower() == "sendsms":
                smsconfig = handler_options.get("smsconfig")
                userphone = recipient.get("mobile")
                try:
                    ret = send_sms_identifier(smsconfig, userphone, body)
                except Exception as exx:
                    log.error("Failed to send sms: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification sms to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

        return ret
예제 #3
0
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = self._get_response_content(response)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})
        notify_type = handler_options.get("To", NOTIFY_TYPE.TOKENOWNER)
        try:
            logged_in_user = g.logged_in_user
        except Exception:
            logged_in_user = {}

        tokenowner = self._get_tokenowner(request)
        log.debug(u"Executing event for action {0!r}, user {1!r}, "
                  u"logged_in_user {2!r}".format(action, tokenowner,
                                                 logged_in_user))

        # Determine recipient
        recipient = None

        if notify_type == NOTIFY_TYPE.TOKENOWNER and not tokenowner.is_empty():
            recipient = {
                "givenname": tokenowner.info.get("givenname"),
                "surname": tokenowner.info.get("surname"),
                "username": tokenowner.login,
                "userrealm": tokenowner.realm,
                "email": tokenowner.info.get("email"),
                "mobile": tokenowner.info.get("mobile")
            }
        elif notify_type == NOTIFY_TYPE.INTERNAL_ADMIN:
            username = handler_options.get("To "+NOTIFY_TYPE.INTERNAL_ADMIN)
            internal_admin = get_db_admin(username)
            recipient = {
                "givenname": username,
                "email": internal_admin.email if internal_admin else ""
            }
        elif notify_type == NOTIFY_TYPE.ADMIN_REALM:
            # Send emails to all the users in the specified admin realm
            admin_realm = handler_options.get("To "+NOTIFY_TYPE.ADMIN_REALM)
            ulist = get_user_list({"realm": admin_realm})
            # create a list of all user-emails, if the user has an email
            emails = [u.get("email") for u in ulist if u.get("email")]
            recipient = {
                "givenname": "admin of realm {0!s}".format(admin_realm),
                "email": emails
            }
        elif notify_type == NOTIFY_TYPE.LOGGED_IN_USER:
            # Send notification to the logged in user
            if logged_in_user.get("username") and not logged_in_user.get(
                    "realm"):
                # internal admins have no realm
                internal_admin = get_db_admin(logged_in_user.get("username"))
                if internal_admin:
                    recipient = {
                        "givenname": logged_in_user.get("username"),
                        "email": internal_admin.email if internal_admin else ""
                    }
            else:
                # Try to find the user in the specified realm
                user_obj = User(logged_in_user.get("username"),
                                logged_in_user.get("realm"))
                if user_obj:
                    recipient = {
                        "givenname": user_obj.info.get("givenname"),
                        "surname": user_obj.info.get("surname"),
                        "email": user_obj.info.get("email"),
                        "mobile": user_obj.info.get("mobile")
                    }

        elif notify_type == NOTIFY_TYPE.EMAIL:
            email = handler_options.get("To "+NOTIFY_TYPE.EMAIL, "").split(",")
            recipient = {
                "email": email
            }
        else:
            log.warning("Was not able to determine the recipient for the user "
                        "notification: {0!s}".format(handler_def))

        if recipient:
            # Collect all data
            body = handler_options.get("body") or DEFAULT_BODY
            subject = handler_options.get("subject") or \
                      "An action was performed on your token."
            serial = request.all_data.get("serial") or \
                     content.get("detail", {}).get("serial") or \
                     g.audit_object.audit_data.get("serial")
            registrationcode = content.get("detail", {}).get("registrationcode")
            googleurl_value = content.get("detail", {}).get("googleurl",
                                                            {}).get("value")
            googleurl_img = content.get("detail", {}).get("googleurl",
                                                          {}).get("img")
            tokentype = None
            if serial:
                tokens = get_tokens(serial=serial)
                if tokens:
                    tokentype = tokens[0].get_tokentype()
            else:
                token_objects = get_tokens(user=tokenowner)
                serial = ','.join([tok.get_serial() for tok in token_objects])

            time = datetime.datetime.now().strftime("%H:%M:%S")
            date = datetime.datetime.now().strftime("%Y-%m-%d")
            tags = dict(admin=logged_in_user.get("username"),
                        realm=logged_in_user.get("realm"),
                        action=request.path,
                        serial=serial,
                        url=request.url_root,
                        user=tokenowner.info.get("givenname"),
                        surname=tokenowner.info.get("surname"),
                        givenname=recipient.get("givenname"),
                        username=tokenowner.login,
                        userrealm=tokenowner.realm,
                        tokentype=tokentype,
                        registrationcode=registrationcode,
                        recipient_givenname=recipient.get("givenname"),
                        recipient_surname=recipient.get("surname"),
                        googleurl_value=googleurl_value,
                        time=time,
                        date=date,
                        client_ip=g.client_ip,
                        ua_browser=request.user_agent.browser,
                        ua_string=request.user_agent.string)
            body = body.format(googleurl_img=googleurl_img,
                               **tags)
            subject = subject.format(**tags)
            # Send notification
            if action.lower() == "sendmail":
                emailconfig = handler_options.get("emailconfig")
                mimetype = handler_options.get("mimetype", "plain")
                useremail = recipient.get("email")
                reply_to = handler_options.get("reply_to")

                try:
                    ret = send_email_identifier(emailconfig,
                                                recipient=useremail,
                                                subject=subject, body=body,
                                                reply_to=reply_to,
                                                mimetype=mimetype)
                except Exception as exx:
                    log.error("Failed to send email: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification email to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

            elif action.lower() == "sendsms":
                smsconfig = handler_options.get("smsconfig")
                userphone = recipient.get("mobile")
                try:
                    ret = send_sms_identifier(smsconfig, userphone, body)
                except Exception as exx:
                    log.error("Failed to send sms: {0!s}".format(exx))
                    ret = False
                if ret:
                    log.info("Sent a notification sms to user {0}".format(
                        recipient))
                else:
                    log.warning("Failed to send a notification email to user "
                                "{0}".format(recipient))

        return ret