大家都知道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文件很简单,就不贴了,若遇到问题,可留言交流~~

iOS企业证书开发的APP证书过期时间监控的更多相关文章

  1. 安卓和ios的app证书过期的相关问题汇总

    一,ios的APP的发布流程请见:ios的APP的发布流程 http://www.jianshu.com/p/b1b77d804254 这篇文章写得很好很全面 二,app证书过期了怎么办: IOS的情 ...

  2. XE6 & IOS开发之免证书真机调试(1):颁发属于自己的App签名证书(有图有真相)

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 1.自己给自己颁发证书, ...

  3. IOS开发创建开发证书及发布App应用(二)——创建证书

    2. 创建证书 证书分为两种,一种是开发者证书,主要是用来真机调试的 另一种就是发布证书,就是用来发布应用的, 最好是两种都要下载,不然编译时候可能报错,我猜想可能苹果怕你没用真机调试 创建证书分为两 ...

  4. IOS开发创建开发证书及发布App应用(一)——流程说明

    之前在自己做的博客网站上面发布了这个系列的文章,当时还是不错的,帮助了很多跟我一样的新手朋友,不过由于服务器出现问题,丢失了一年了,现在终于找到了,所以发到博客园给大家共享一下,也是为我自己做个参考 ...

  5. 【iOS开发】企业版证书($299)In-House方式发布指南 (转)

    一.明确几个概念 1.企业版IDP:即iOS Development Enterprise Program.注意是$299/Year那种,并不是$99/Year的那种. 2.In House:是只企业 ...

  6. 关于iOS开发的各种证书

    关于iOS开发的各种证书 最近在接推送服务的时候,被各种证书弄得不亦晕乎,这里记录一下一些基本的证书作用: 1. App IDs appID分明确的和通配的两种,如果要使用推送功能,只能用明确的. 2 ...

  7. iOS开发-- 开发环境,证书和授权文件

    一.成员介绍 1.    Certification(证书)证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种:1)    Developer Certification(开发证书)安装在电脑 ...

  8. IOS 开发环境,证书和授权文件等详解

    (转自:http://blog.csdn.net/gtncwy/article/details/8617788) 一.成员介绍1.    Certification(证书)证书是对电脑开发资格的认证, ...

  9. ios 企业证书 ipa 重新签名发布

    提示:暂时不能用了,企业证书滥用 ios 企业证书 ipa 重新签名发布 1. 应用场景 当前有一个 未用企业证书签名的 ipa 文件,默认是不可以直接安装到设备上的:我们需要用企业版证书签名: 当前 ...

  10. iOS开发HTTPS实现之信任SSL证书和自签名证书

    iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...

随机推荐

  1. Java开发者的Python快速进修指南:掌握T检验

    前言 T检验是一种用于比较两个独立样本均值差异的统计方法.它通过计算T值和P值来判断样本之间是否存在显著性差异.通常情况下,我们会有两组数据,例如一组实验组和一组对照组. T检验的原假设是两组样本的均 ...

  2. ansible 自动化运维(2)

    回到顶部 Ansible playbook 简介 playbook 是 ansible 用于配置,部署,和管理被控节点的剧本. 通过 playbook 的详细描述,执行其中的一系列 tasks ,可以 ...

  3. MES集成警报灯系统,Http远程控制系统设计

    核心功能设计 警报灯实机演示:https://www.bilibili.com/video/BV1294y1M7f3?p=2 接受服务器发送http·post请求远程控制警报灯,可接入MES等系统. ...

  4. python 音频通道分离的源码实现

    一 前记 作为一个音频工程师,仅仅依靠鼠标点击,没有一些自己的小工具的话,肯定是不合格的了. 最近用到了一个音频通道分离的功能,这里就用python敲击了一下,这里做个备忘吧,给有需求的小伙伴抛砖引玉 ...

  5. WebView开源库终极方案

    目录介绍 01.前沿说明 1.1 案例展示效果 1.2 该库功能和优势 1.3 相关类介绍说明 1.4 WebView知识点 02.如何使用 2.1 如何引入 2.2 最简单使用 2.3 常用api ...

  6. View之invalidate,requestLayout,postInvalidate

    目录介绍 01.invalidate,requestLayout,postInvalidate区别 02.invalidate深入分析 03.postInvalidate深入分析 04.request ...

  7. 记录--uni-app实现京东canvas拍照识图功能

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 最近公司出了一个新的功能模块(如下图),大提上可以描述为实现拍照完上传图片,拖动四方框拍照完成上传功能,大体样子如下图.但是我找遍了 dc ...

  8. 性能测试系列:Jmeter使用记录

    jmeter配置环境变量vi /etc/profileexport PATH=$PATH:/tmp/jmeter/apache-jmeter-5.4.1/binsource /etc/profile ...

  9. 【Spring注解驱动开发】@PostConstruct与@PreDestroy源码的执行过程

    写在前面 在前面的<[String注解驱动开发]你真的了解@PostConstruct注解和@PreDestroy注解吗?>一文中,我们简单的介绍了@PostConstruct注解与@Pr ...

  10. SpringBoot2使用hikari报 Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl

    SpringBoot2配置文件有变化,需要更改配置 #datasource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spri ...