• iOS企业证书开发的APP证书过期时间监控


    大家都知道iOS的企业证书开发的APP,证书都是一年有效期,满一年得新建证书重新打包,否则无法继续使用。

    我们一个企业账号下有几十个APP,一个个去看也很麻烦~~搞个监控呗!!!

    写个脚本放Jenkins上定时跑就行,跑完发布邮件:

    1.邮件包含信息:APP名称,APP相关的bundle id、证书名称、签名时间、团队id,过期时间,以及剩余有效的月数。

    common_mail.py: 发布邮件,邮件发送网上多,自己找,不累述

    copy_ipa_monitor.py: 把打好的ipa复制到指定的目录,这个目录给监控的扫描用

    date_month.py: 专门计算月份差,Python没有直接计算月份差的模块,自己写,考虑下各种条件计算

    ipa_monitor.py: 获取ipa的有效时间以及ipa包里描述文件里的有效时间

    ipa_monitor_html.py: 生成邮件发送的html模版

    贴代码:

      1 ## ipa_monitor.py
      2 # coding = utf-8
      3 # 读取配置证书
      4 
      5 import os
      6 import time
      7 import shutil
      8 import datetime
      9 from pkg_common.cmd import common_run_cmd as cmd
     10 from pkg_common.handle_file import find_file as find
     11 from pkg_common.ipa_monitor import common_mail as mail
     12 from pkg_common.ipa_monitor import ipa_monitor_html as html
     13 
     14 
     15 to_find_path = '/Users/Work/package/ipa_monitor'
     16 
     17 
     18 # 获取证书时间一些命令 
     19 codesign_cmd = 'codesign -d --extract-certificates Payload/*.app'
     20 openssl_cmd = 'openssl x509 -inform DER -in codesign0 -noout -nameopt -oneline -dates'
     21 codesign_get_cmd = 'codesign -dv --verbose=4 Payload/*.app'
     22 mobile_provision_cmd = 'more Payload/Runner.app/embedded.mobileprovision'
     23 
     24 
     25 def get_ipa_time():
     26     f, f_l = find.find_file("'*.ipa'", to_find_path)
     27     all_dic = []
     28     for i in f_l:
     29         dic = {}
     30         dir_name = os.path.dirname(i)
     31         app_name = dir_name.split('/')[-1]
     32         dic['app_name'] = app_name
     33         base_name = os.path.basename(i)
     34         un_zip_cmd = 'unzip -q %s' % base_name
     35         # 解压ipa文件
     36         cmd.run_cmd(un_zip_cmd, dir_name)
     37         time.sleep(2)
     38         cmd.run_commands(codesign_cmd, dir_name)
     39         time.sleep(2)
     40         not_time = cmd.run_commands(openssl_cmd, dir_name)[1]
     41         not_after, not_stamp = deal_gmt(not_time.split('\n')[1].split('=')[1])
     42         f, f_l = find.find_file("'*.mobileprovision'", dir_name)
     43         ipa_no_time = ''
     44         ipa_no_stamp = 0
     45         # 获取描述文件里的过期时间,这里解码格式一定要用ISO-8859-1
     46         with open(f_l[0], 'r', encoding='ISO-8859-1') as f_w:
     47             lines = f_w.readlines()
     48             for index, l in enumerate(lines):
     49                 if 'ExpirationDate' in l:
     50                     ipa_no_time = lines[index+1].split('>')[1].split('<')[0]
     51                     ipa_no_time, ipa_no_stamp = deal_utc(ipa_no_time)
     52                     break
     53         if not_stamp <= ipa_no_stamp:
     54             expired_time = not_after
     55         else:
     56             expired_time = ipa_no_time
     57         dic['expired_time'] = expired_time
     58         pro_info = cmd.run_commands(codesign_get_cmd, dir_name)[1].split('\n')
     59         delete_file(dir_name)
     60 
     61         for x in pro_info:
     62             if 'Identifier' == x.split('=')[0]:
     63                 dic['Identifier'] = x.split('=')[1]
     64             if 'Authority' in x:
     65                 if 'Authority' not in dic:
     66                     dic['Authority'] = x.split('=')[1]
     67             if 'Signed Time' in x:
     68                 dic['Signed_time'] = x.split('=')[1]
     69             if 'TeamIdentifier' in x:
     70                 dic['TeamIdentifier'] = x.split('=')[1]
     71         all_dic.append(dic)
     72     return all_dic
     73 
     74 
     75 def deal_gmt(gmt_time):
     76     """
     77     GMT时间转换
     78     :param gmt_time:
     79     :return:
     80     """
     81     gmt_format = '%b %d %H:%M:%S %Y GMT'
     82     # GMT时间与北京时间相差8小时
     83     sta_time = datetime.datetime.strptime(gmt_time, gmt_format) + datetime.timedelta(hours=8)
     84     time_array = time.strptime(str(sta_time), "%Y-%m-%d %H:%M:%S")
     85     time_stamp = int(time.mktime(time_array))
     86     return sta_time, time_stamp
     87 
     88 
     89 def deal_utc(utc_time):
     90     utc_format = "%Y-%m-%dT%H:%M:%SZ"
     91     sta_time = datetime.datetime.strptime(utc_time, utc_format) + datetime.timedelta(hours=8)
     92     time_array = time.strptime(str(sta_time), "%Y-%m-%d %H:%M:%S")
     93     time_stamp = int(time.mktime(time_array))
     94     return sta_time, time_stamp
     95 
     96 
     97 def delete_file(dir_name):
     98     """
     99     删除多余文件
    100     :param dir_name:
    101     :return:
    102     """
    103     os.remove(dir_name + '/codesign0')
    104     os.remove(dir_name + '/codesign1')
    105     os.remove(dir_name + '/codesign2')
    106     shutil.rmtree(dir_name + '/Payload')
    107 
    108 
    109 if __name__ == '__main__':
    110     ipa_info = get_ipa_time()
    111     subject, html = html.deal_html(ipa_info)
    112     try:
    113         if mail.cs_mail_send(subject, html, 'c'):
    114             print('Send success')
    115         else:
    116             print('Send failure')
    117     except Exception as e:
    118         raise e
    119         
    ## date_month.py
    
    import datetime
    import calendar as c
    
    
    def cal_months(start_date, end_date):
    
        # 计算两个日期相隔月差
        try:
            same_month_date = datetime.date(end_date.year, end_date.month, start_date.day)
        except Exception as e:
            print(e)
            same_month_date = datetime.date(end_date.year, end_date.month, c.monthrange(end_date.year, end_date.month)[1])
        decimal_month = 0.0
        if same_month_date > end_date:
            try:
                pre_date = datetime.date(end_date.year, end_date.month - 1, start_date.day)
            except Exception as e:
                print(e)
                pre_date = datetime.date(end_date.year, end_date.month - 1, c.monthrange(end_date.year, end_date.month - 1)[1])
            curr_month_days = (same_month_date - pre_date).days
            hold_months = (pre_date.year - start_date.year) * 12 + pre_date.month - start_date.month
            decimal_month = round((end_date - pre_date).days / curr_month_days, 1)
    
        elif same_month_date < end_date:
            try:
                next_month_date = datetime.date(end_date.year, end_date.month + 1, start_date.day)
            except Exception as e:
                print(e)
                next_month_date = datetime.date(end_date.year, end_date.month + 1, c.monthrange(end_date.year, end_date.month + 1)[1])
            curr_month_days = (next_month_date - same_month_date).days
            hold_months = (same_month_date.year - start_date.year) * 12 + same_month_date.month - start_date.month
            decimal_month = round((end_date - same_month_date).days / curr_month_days, 1)
    
        else:
            hold_months = (end_date.year - start_date.year) * 12 + end_date.month - start_date.month
    
        return hold_months + decimal_month
    ## ipa_monitor_html.py
    # coding = utf-8
    # ipa过期时间监控
    
    import datetime
    from pkg_common.ipa_monitor import date_month as dm
    
    
    # 处理html
    def deal_html(data):
        tl = deal_tl(data)
        subject = '企业证书iOS应用过期时间监控'
        html = """
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>企业证书iOS应用过期时间监控</title>
            <body>
            <div id="container">
             <center>
            <strong>汇总时间: """ + str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + """</strong>
            <p><strong></strong></p>
            <div id="content">
             <table border="1" cellpadding="2" style="border-collapse:collapse;margin-top:10px">
             <tr>
               <td colspan="4" align="center" height="35px"><font size="4"><strong>只针对企业证书打包的应用</strong>[<font color="red">有效期小于3月的红色加粗显示</font>]</font></td> 
             </tr>
             <tr height="28px" bgcolor="#f0f8ff">
              <td width="120" align="center"><font size="3"><strong>应用名称</strong></font></td>
              <td width="520" align="center"><font size="3"><strong>APP参数</strong></font></td>
              <td width="180" align="center"><font size="3"><strong>过期时间</strong></font></td>
              <td width="80" align="center"><font size="3"><strong>剩余月数</strong></font></td>
             </tr>              
            """ + tl + """
            </tr>
            </table>
            <p><font size="3" ><center>--------------------<strong><a href="http://chandao.thecover.cn/">汇总数据源于测试监控系统</a></strong>--------------------</center></font>
            </center>
            </div>
            </div>
            </div>
            </body>
            </html>
                  """
        return subject, html
    
    
    def deal_tl(data):
    
        tl_a = ''
        for i in data:
    
            dt1 = i['expired_time'].date()
            dt2 = datetime.date.today()
            dt = dm.cal_months(dt2, dt1)
    
            a = """
            <tr>
                <td rowspan="4" align="center"> %s </td>
                <td align="left"> Identifier:%s</td> 
                <td rowspan="4" align="center"> %s</td>
            """ % (i['app_name'], i['Identifier'], i['expired_time'])
    
            if dt > 3:
                b = """ <td rowspan="4" align="center"> %s</td> """ % dt
            else:
                b = """ <td rowspan="4" align="center"> <strong><font color="red"> %s </font></strong></td> """ % dt
    
            c = """
            </tr>
            <tr>
                <td align="left"> Authority:%s</td>
            </tr>
            <tr>
                <td align="left"> Signed_time:%s </td>
            </tr>
            <tr>
                <td align="left"> TeamIdentifier:%s </td>
            </tr>
            <tr>
                <td colspan="4" align="center" height="0px" bgcolor="#a9a9a9"><font size="4"> </td>
            </tr>
            """ % (i['Authority'], i['Signed_time'], i['TeamIdentifier'])
    
            tl_a = tl_a + a + b + c
    
        return tl_a

    其他py文件很简单,就不贴了,若遇到问题,可留言交流~~

    本文来自博客园,作者:drewgg,转载请注明原文链接:https://www.cnblogs.com/drewgg/p/13141196.html

  • 相关阅读:
    为什么需要Docker?
    shiro原理
    java面对对象
    mysql面试题
    spring boot +thymeleaf+ mybatis
    mysql语句级sql
    spring boot+spring cloud面试笔记
    Docker-compose配置
    Docker compose命令的使用
    Dockerfile操作命令说明
  • 原文地址:https://www.cnblogs.com/drewgg/p/13141196.html
Copyright © 2020-2023  润新知