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

原文地址:https://www.cnblogs.com/drewgg/p/13141196.html