IDM 用户帐号过期提醒

芯片设计环境通常有比较严格的安全管理,用户帐号过期后就不能登录环境,影响用户工作。为减少影响,应该提前向用户发送提醒,及时更新密码。

方案设计

通过IDM REST API接口获取所有帐号信息,根据以下条件过滤,筛选出即将过期帐号和已过期帐号。

  1. 帐号类型为正式员工(employee)和实习生(intern)

  2. 帐号没有在需要忽略的清单中

  3. 帐号过期日期相对于今天的间隔时间在指定间隔时间内

筛选出需要通知的帐号列表以后,遍历列表,如果帐号与公司人事系统不一致,使用公司人事系统帐号,最后记录日志并发送飞书提醒给用户。

示例代码:

#!/opt/miniconda3/bin/python
##########################################
## Author: shuguangbo
##########################################import os
import re
import datetime
import sys
import traceback
import time
import yaml
import logging
import logging.config
import re
import urllib3
import requests
import jsonimport ipahttpurllib3.disable_warnings()def parseConfig(cfname=None):appConf = Nonetry:if cfname is None or not os.path.exists(cfname) :cfname = os.path.join(os.environ['CONF_DIR'] if 'CONF_DIR' in os.environ else os.path.dirname(__file__), os.path.basename(__file__).split('.')[0] + ".yml")with open(cfname, 'r') as fd :appConf = yaml.load(fd, Loader=yaml.FullLoader)except Exception as e:logging.error("Read configuration failed! Error:{}".format(str(e)))sys.exit(1)reqParams = {'IDM':['IDM_URL', 'IDM_USER', 'IDM_PASS'], 'NOTICE': ['ADMINS', 'NOTICE_DATES', 'TMPDIR', 'TOKEN', 'LARKURL'],'LOGGERCONFIG':['formatters', 'handlers', 'root']}missingParams = {key: set(reqParams[key]) - set(appConf[key].keys()) for key in reqParams.keys() if len(set(reqParams[key]) - set(appConf[key].keys()))}if len(missingParams):logging.error('Missing parameters: {}'.format(missingParams))sys.exit(1)appConf['IDM']['IDM_PASS'] = appConf['IDM']['IDM_PASS']if len(appConf['NOTICE']['NOTICE_DATES']) < 1:logging.error('Empty notice dates!')sys.exit(4)if 'NOTIFY_ADMIN_ONLY' not in appConf['NOTICE']:appConf['NOTICE']['NOTIFY_ADMIN_ONLY'] = Falsereturn appConfclass accountExpiryChecker():def __init__(self, config):self._config = configself._idmClient = self._createIDMClient()self._expiryList = []def _createIDMClient(self):idm = Noneconnected = Falsetry:admin_receivers = ' '.join(self._config['NOTICE']['ADMINS'])user = self._config['IDM']['IDM_USER']   password = self._config['IDM']['IDM_PASS']urlList = self._config['IDM']['IDM_URL'] if isinstance(self._config['IDM']['IDM_URL'], list) else [self._config['IDM']['IDM_URL']]for url in urlList:try:idm = ipahttp.ipa(url)ret = idm.login(user, password)if ret.status_code != 200:logging.error("Login IDM %s failed, error:%s."%(url, ret.text))time.sleep(5)continueelse:connected = Truebreakexcept Exception as e:logging.error("Login IDM {} failed. Error: {}, Stack: {}".format(url, str(e), traceback.format_exc()))continueif connected:logging.info("Login IDM succeeded.")else:logging.error("Failed to loging IDM. Exit!")exit(2)except Exception as e:logging.error("Login IDM failed. Error: {}".format(str(e), traceback.format_exc()))exit(2)return idmdef _checkExpiry(self):ipa = self._idmClientusers = ipa.user_find()expiryList = []maxExpiryDay = max([abs(item) for item in self._config['NOTICE']['NOTICE_DATES']])logging.info('Total {} accounts. Max expiry notice day is {}'.format(len(users['result']['result']), maxExpiryDay))for user in users['result']['result']:name = user['uid'][0]cname = user['displayname'][0] if 'displayname' in user else '-'atype = user['employeetype'][0] if 'employeetype' in user else '-'ts = user['krbpasswordexpiration'][0] if 'krbpasswordexpiration' in user else '-'status = user['nsaccountlock']if cname == '-' or atype == '-' or ts == '-' or status:continueif atype not in ['employee', 'intern']:continueif name in self._config['NOTICE']['IGNORED_ACCOUNTS']:continueexpiry = datetime.datetime.strptime(ts[0:8], '%Y%m%d').date()delta = (expiry - datetime.date.today()).daysif delta > maxExpiryDay:continuedata = {'cname':cname, 'name':name, 'expiry':expiry.strftime('%Y-%m-%d'), 'delta': delta}expiryList.append(data)logging.debug('{}'.format(data))self._expiryList = expiryListdef _notifyExpiry(self):logging.info(f"Notify admin only {self._config['NOTICE']['NOTIFY_ADMIN_ONLY']}")gqtx = '用户 {} 帐号 {} 密码有效期至 {},将在 {} 天后过期。请及时更新密码。'gqtz = '用户 {} 帐号 {} 密码有效期至 {},已过期 {} 天。请及时更新密码。'gqdt = '用户 {} 帐号 {} 密码有效期至 {},在今天过期。请及时更新密码。'msg = ''for expiry in self._expiryList:delta = expiry['delta']if delta in self._config['NOTICE']['NOTICE_DATES']:user = self._config['NOTICE']['SPECIAL_ACCOUNTS'].get(expiry['name'])user = user if user else expiry['name']receiver = ' '.join(self._config['NOTICE']['ADMINS'])if not self._config['NOTICE']['NOTIFY_ADMIN_ONLY']:receiver += ' ' + userif expiry['delta'] > 0:msg = gqtx.format(expiry['cname'], expiry['name'], expiry['expiry'], expiry['delta'])reminder = f"将在 {expiry['delta']} 天后过期"elif expiry['delta'] == 0:msg = gqdt.format(expiry['cname'], expiry['name'], expiry['expiry'])reminder = "在今天过期"else:msg = gqtz.format(expiry['cname'], expiry['name'], expiry['expiry'], abs(expiry['delta']))reminder = f"已过期 {abs(expiry['delta'])} 天"logger.info(msg)data = {'user':expiry['cname'], 'account':expiry['name'], 'expiry':expiry['expiry'], 'reminder':reminder}if len(receiver):self._sendLark(data, receiver)def _sendLark(self, message, receivers):try:session = requests.Session()larkURL = self._config['NOTICE']['LARKURL']header = {'Content-Type':'application/json', 'Authorization':self._config['NOTICE']['TOKEN']}data = {}data['trigger_key'] = '帐号密码过期提醒'data['instance'] = messagedata['notice'] = receivers if type(receivers) == list else receivers.split()result = session.post(larkURL, headers=header, data=json.dumps(data), verify=False)if result.status_code == 200:logging.info('Send message succeeded.')else:logging.error(f"Send message failed. Error: {result.text}")except Exception as e:logging.error(f"Send message failed. Error: {str(e)}, Stack: {traceback.format_exc()}")def run(self):self._checkExpiry()self._notifyExpiry()if __name__ == "__main__":config = parseConfig()logging.config.dictConfig(config['LOGGERCONFIG'])logger = logging.getLogger(os.path.basename(__file__))exipryChecker = accountExpiryChecker(config)exipryChecker.run()

通过设置配置文件中的参数 NOTICE_DATES 控制发送通知的频率,下面的配置为提前15、7、4、2、1天和当天,以及过期后1、2、4、7、14、21天后发送通知。

NOTICE_DATES: [15, 7, 4, 2, 1, 0, -1, -2, -4, -7, -14, -21, -28, -35]

可能通过 crontab 或 Jenkins 每天运行一次即可。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/617972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win11下载Hbuliderx 安装闪退解决教程+安装包分享

在官网下载 目录 在官网下载 出现闪退 下载失败 2.2. 最终在百度网盘里下载了历史版本 2.3. 然后解压文件 2.4. 双击打开 2.5. 安装成功 出现闪退 下载失败 结果下载失败&#xff0c;一下子弹出的下载框就会闪退 2.2. 最终在百度网盘里下载了历史版本 下载的网盘链接: …

黑马苍穹外卖学习Day5

文章目录 Redis学习Redis简介准备工作Redis常用数据类型介绍各数据类型的特点Redis常用命令字符串操作命令哈希操作命令列表操作命令集合操作命令有序集合操作命令通用操作命令 在Java中操作Redis导入Spring Data Redis坐标配置Redis数据源编写配置类&#xff0c;创建RedisTemp…

Scipy 中级教程——图像处理

Python Scipy 中级教程&#xff1a;图像处理 Scipy 的图像处理模块提供了许多功能&#xff0c;用于读取、处理和分析图像。在本篇博客中&#xff0c;我们将深入介绍 Scipy 中的图像处理功能&#xff0c;并通过实例演示如何应用这些工具。 1. 读取和显示图像 首先&#xff0c…

linux多进程基础(2):僵尸进程以及解决方法wait()函数(大白话解释)

在我的linux多线程多进程基础专栏中,已和大家一起分享了僵尸线程.在这一篇文章中我将分享僵尸进程以及解决方法wait()函数. 1.僵尸进程 什么是僵尸进程呢?用最通俗易懂的话来说就是子进程执行结束的时候其父进程并没有及时回收该子进程导致成为僵尸进程.如果僵尸进程数量较多…

【模型评估 06】超参数调优

对于很多算法工程师来说&#xff0c;超参数调优是一件非常头疼的事情。除了根据经验设定所谓的“合理值”之外&#xff0c;一般很难找到合理的方法去寻找超参数的最优取值。而与此同时&#xff0c;超参数对于模型效果的影响又至关重要。有没有一些可行的办法去进行超参数的调优…

10分钟快速搭建个人博客、文档网站!

本文来分享 8 个现代化前端工具&#xff0c;帮你快速生成个人博客、文档网站&#xff01; VitePress VitePress 是一款静态站点生成器&#xff0c;专为构建快速、以内容为中心的网站而设计。简而言之&#xff0c;VitePress 获取用 Markdown 编写的源内容&#xff0c;为其应用…

前端面试 -- vue系列

Vue系列 1. vue理解&#xff1a;2. SPA&#xff08;单页面应用理解&#xff09;3. vue实例挂载的过程4. v-for和v-if优先级5. SPA首屏加载速度慢的原因和解决办法6. Vue中给对象添加新属性界面不刷新&#xff08;直接给对象添加属性&#xff09;7. vue组件之间的通信方式有哪些…

python24.1.13for循环

对列表、字典、字符串等进行迭代 range

Legion R7000 2021(82JW)原装出厂Win10/WIN11系统预装OEM系统镜像

LENOVO联想拯救者R7000 2021款(82JW)笔记本电脑原厂Windows10/11系统 链接&#xff1a;https://pan.baidu.com/s/1m_Ql5qu6tnw62PbpvXB0hQ?pwd6ek4 提取码&#xff1a;6ek4 原装出厂系统自带所有驱动、出厂主题壁纸、系统属性专属联机支持标志、系统属性专属联想的LOGO标…

Linux期末总复习( 详解 )

文章目录 一、选择题二、填空题三、简答题四、操作题 一、选择题 1.在创建Linux分区时&#xff0c;一定要创建&#xff08; D &#xff09;两个分区 A. FAT/NTFS  B. FAT/SWAP  C. NTFS/SWAP  D.SWAP/根分区 2.在Red Hat Linux 9 中&#xff0c;系统默认的&#xf…

88.乐理基础-记号篇-反复记号(二)D.C.、D.S.、Fine、Coda

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;87.乐理基础-记号篇-反复记号&#xff08;一&#xff09;反复、跳房子-CSDN博客 下图红色左括号框起来的东西&#xff0c;它们都相对比较抽象一点&#xff0c;这几个词都是意大利语 首先D.C.这个标记&#xff0c;然…

7 - MySQL主从同步|主从同步模式

MySQL主从同步&#xff5c;主从同步模式 MySQL主从同步主从同步介绍主从同步工作过程主从同步结构模式配置主从同步一主一从同步结构一主多从同步结构主从从同步结构主主同步结构 主从同步模式主从同步结构模式复制模式 MySQL主从同步 主从同步介绍 存储数据的服务结构 主服务…

高效便捷的远程管理利器——Royal TSX for Mac软件介绍

Royal TSX for Mac是一款功能强大、操作便捷的远程管理软件。无论是远程桌面、SSH、VNC、Telnet还是FTP&#xff0c;用户都可以通过Royal TSX轻松地远程连接和管理各种服务器、计算机和网络设备。 Royal TSX for Mac提供了直观的界面和丰富的功能&#xff0c;让用户能够快速便…

事关年终奖,速看!年终奖应该如何设定结构,提高激励性?

随着2024年的临近&#xff0c;员工们对于年终奖的发放满怀期待&#xff0c;而企业管理者则又到了大费周章的时候。年终奖的发放方式、内容以及金额&#xff0c;成为困扰每个管理者的难题。为什么年终奖发放后&#xff0c;大家的积极性没有得到提高&#xff1f;该激励的没激励到…

聊聊PowerJob的TimingStrategyHandler

序 本文主要研究一下PowerJob的TimingStrategyHandler TimingStrategyHandler tech/powerjob/server/core/scheduler/auxiliary/TimingStrategyHandler.java public interface TimingStrategyHandler {/*** 校验表达式** param timeExpression 时间表达式*/void validate(S…

ITSS申报条件以及评审方式

01、四级申报基本条件&#xff1a; &#xff08;1&#xff09;具有独立法人地位&#xff1b; &#xff08;2&#xff09;已按照《运维服务能力成熟度》四级特征和关键指标建立了运维服务能力体系&#xff0c;且已有效运行三个月以上&#xff1b; &#xff08;3&#xff09;能…

Spring Boot - Application Events 的发布顺序_ApplicationReadyEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

Hades-C2:一款功能强大的纯Python命令控制服务器

关于Hades-C2 Hades-C2是一款功能强大的命令控制服务器&#xff0c;该工具基于纯Python开发&#xff0c;可以帮助广大研究人员快速实现命令控制基础设施的搭建。 当前版本的Hades-C2可以用作安全分析研究或CTF比赛&#xff0c;但功能并不完善&#xff0c;目前该项目仍在积极开…

Java之Stream类

1.介绍 &#xff08;1&#xff09;Stream流 配合Lambda表达式&#xff0c;简化集合和数组的操作 &#xff08;2&#xff09;Stream流思想 流水线思想 2.获取Stream流对象 &#xff08;1&#xff09;集合获取流Stream流对象 使用Collection接口中的默认方法Stream<T> s…

Python学习之路-综合练习:学生管理系统

Python学习之路-综合练习:学生管理系统 目前已经学习了变量、流程控制、函数、模块&#xff0c;可以利用已学习的知识开发一个学生管理系统 项目需求 系统有首页介绍页面与功能菜单系统功能由查询、显示、修改与删除功能可以使用数字选择不同的功能学生信息需要记录&#xf…