diff --git a/fir_ser/api/utils/app/iossignapi.py b/fir_ser/api/utils/app/iossignapi.py
index f8d6329..3a61e62 100644
--- a/fir_ser/api/utils/app/iossignapi.py
+++ b/fir_ser/api/utils/app/iossignapi.py
@@ -111,6 +111,13 @@ class ResignApp(object):
# script_path=os.path.join(SUPER_SIGN_ROOT,'scripts','apple_api.rb')
self.cmd = "isign -c '%s' -k '%s' " % (self.app_dev_pem, self.my_local_key)
+ @staticmethod
+ def sign_mobileconfig(mobilconfig_path, sign_mobilconfig_path, ssl_pem_path, ssl_key_path):
+ cmd = "openssl smime -sign -in %s -out %s -signer %s " \
+ "-inkey %s -certfile %s -outform der -nodetach " % (
+ mobilconfig_path, sign_mobilconfig_path, ssl_pem_path, ssl_key_path, ssl_pem_path)
+ return exec_shell(cmd)
+
def sign(self, new_profile, org_ipa, new_ipa):
self.cmd = self.cmd + " -p '%s' -o '%s' '%s'" % (new_profile, new_ipa, org_ipa)
result = exec_shell(self.cmd)
diff --git a/fir_ser/api/utils/app/supersignutils.py b/fir_ser/api/utils/app/supersignutils.py
index 0c70c05..2f74bd9 100644
--- a/fir_ser/api/utils/app/supersignutils.py
+++ b/fir_ser/api/utils/app/supersignutils.py
@@ -5,7 +5,7 @@
# date: 2020/3/6
import uuid, xmltodict, os, re, logging
-from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN
+from fir_ser.settings import SUPER_SIGN_ROOT, MEDIA_ROOT, SERVER_DOMAIN, MOBILECONFIG_SIGN_SSL
from api.utils.app.iossignapi import AppDeveloperApi, ResignApp
from api.models import APPSuperSignUsedInfo, AppUDID, AppIOSDeveloperInfo, AppReleaseInfo, Apps, APPToDeveloper, \
UDIDsyncDeveloper
@@ -32,8 +32,45 @@ def udid_bytes_to_dict(xml_stream):
return new_uuid_info
-def make_udid_mobileconfig(udid_url, PayloadOrganization, PayloadUUID=uuid.uuid1(), PayloadDescription='本文件仅用来获取设备ID',
- PayloadDisplayName='查询设备UDID'):
+def make_sign_udid_mobileconfig(udid_url, PayloadOrganization, appname):
+ if MOBILECONFIG_SIGN_SSL.get("open"):
+ ssl_key_path = MOBILECONFIG_SIGN_SSL.get("ssl_key_path", None)
+ ssl_pem_path = MOBILECONFIG_SIGN_SSL.get("ssl_pem_path", None)
+
+ if ssl_key_path and ssl_pem_path and os.path.isfile(ssl_key_path) and os.path.isfile(ssl_pem_path):
+ mobileconfig_tmp_dir = os.path.join(SUPER_SIGN_ROOT, 'tmp', 'mobileconfig')
+ if not os.path.exists(mobileconfig_tmp_dir):
+ os.makedirs(mobileconfig_tmp_dir)
+
+ mobileconfig_filename = PayloadOrganization + str(uuid.uuid1())
+ mobilconfig_path = os.path.join(mobileconfig_tmp_dir, mobileconfig_filename)
+
+ sign_mobilconfig_path = os.path.join(mobileconfig_tmp_dir, 'sign_' + mobileconfig_filename)
+ with open(mobilconfig_path, "w") as f:
+ f.write(make_udid_mobileconfig(udid_url, PayloadOrganization, appname))
+
+ status, result = ResignApp.sign_mobileconfig(mobilconfig_path, sign_mobilconfig_path, ssl_pem_path,
+ ssl_key_path)
+ if status:
+ mobileconfig_body = open(sign_mobilconfig_path, 'rb')
+ else:
+ logger.error(
+ "%s %s sign_mobileconfig failed ERROR:%s" % (PayloadOrganization, appname, result.get("err_info")))
+ return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
+
+ return mobileconfig_body
+
+ else:
+ logger.error("sign_mobileconfig %s or %s is not exists" % (ssl_key_path, ssl_pem_path))
+ return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
+
+ else:
+ return make_udid_mobileconfig(udid_url, PayloadOrganization, appname)
+
+
+def make_udid_mobileconfig(udid_url, PayloadOrganization, appname, PayloadUUID=uuid.uuid1(),
+ PayloadDescription='该文件仅用来获取设备ID,帮助用户安装授权',
+ PayloadDisplayName='设备安装授权'):
#
mobileconfig = '''
@@ -68,7 +105,8 @@ def make_udid_mobileconfig(udid_url, PayloadOrganization, PayloadUUID=uuid.uuid1
PayloadType
Profile Service
-''' % (udid_url, PayloadOrganization, PayloadDisplayName, PayloadUUID, PayloadOrganization, PayloadDescription)
+''' % (udid_url, PayloadOrganization, appname + " -- " + PayloadDisplayName, PayloadUUID, PayloadOrganization,
+ PayloadDescription)
return mobileconfig
diff --git a/fir_ser/api/utils/crontab/run.py b/fir_ser/api/utils/crontab/run.py
index 3bdd623..89b8ee8 100644
--- a/fir_ser/api/utils/crontab/run.py
+++ b/fir_ser/api/utils/crontab/run.py
@@ -7,7 +7,8 @@
from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job
from fir_ser.settings import SYNC_CACHE_TO_DATABASE
-from api.utils.crontab.sync_cache import sync_download_times, auto_clean_upload_tmp_file, auto_delete_job_log
+from api.utils.crontab.sync_cache import sync_download_times, auto_clean_upload_tmp_file, auto_delete_job_log, \
+ auto_delete_tmp_file
import logging
logger = logging.getLogger(__file__)
@@ -40,11 +41,15 @@ try:
# @register_job(scheduler, 'cron', day_of_week='mon-fri', hour='9', minute='30', second='10',id='task_time')
@register_job(scheduler, "interval", seconds=SYNC_CACHE_TO_DATABASE.get("auto_clean_tmp_file_times"))
def auto_clean_upload_tmp_file_job():
- # 这里写你要执行的任务
auto_clean_upload_tmp_file()
auto_delete_job_log()
+ @register_job(scheduler, "interval", seconds=SYNC_CACHE_TO_DATABASE.get("auto_clean_local_tmp_file_times"))
+ def auto_delete_tmp_file_job():
+ auto_delete_tmp_file()
+
+
register_events(scheduler)
scheduler.start()
except Exception as e:
diff --git a/fir_ser/api/utils/crontab/sync_cache.py b/fir_ser/api/utils/crontab/sync_cache.py
index 8b20e2c..e93a505 100644
--- a/fir_ser/api/utils/crontab/sync_cache.py
+++ b/fir_ser/api/utils/crontab/sync_cache.py
@@ -7,8 +7,8 @@
from api.models import Apps, UserInfo
from api.utils.storage.storage import Storage
from django.core.cache import cache
-from fir_ser.settings import CACHE_KEY_TEMPLATE, SYNC_CACHE_TO_DATABASE
-import time
+from fir_ser.settings import CACHE_KEY_TEMPLATE, SYNC_CACHE_TO_DATABASE, SUPER_SIGN_ROOT
+import time, os
from django_apscheduler.models import DjangoJobExecution
import logging
@@ -65,3 +65,17 @@ def auto_delete_job_log():
count = DjangoJobExecution.objects.count()
if count > need_count:
DjangoJobExecution.objects.filter(id__lte=max_id - need_count).delete()
+
+
+def auto_delete_tmp_file():
+ mobileconfig_tmp_dir = os.path.join(SUPER_SIGN_ROOT, 'tmp', 'mobileconfig')
+ for root, dirs, files in os.walk(mobileconfig_tmp_dir, topdown=False):
+ now_time = time.time()
+ for name in files:
+ file_path = os.path.join(root, name)
+ st_mtime = os.stat(file_path).st_mtime
+ if now_time - st_mtime > SYNC_CACHE_TO_DATABASE.get('clean_local_tmp_file_from_mtime', 30 * 60):
+ try:
+ os.remove(file_path)
+ except Exception as e:
+ logger.error("auto_delete_tmp_file %s Failed . Exception %s" % (file_path, e))
diff --git a/fir_ser/api/views/download.py b/fir_ser/api/views/download.py
index 3dc49bd..c845e6f 100644
--- a/fir_ser/api/views/download.py
+++ b/fir_ser/api/views/download.py
@@ -10,7 +10,7 @@ from fir_ser import settings
from api.utils.TokenManager import DownloadToken
from api.utils.app.randomstrings import make_random_uuid
from api.utils.app.apputils import make_resigned
-from api.utils.app.supersignutils import make_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain
+from api.utils.app.supersignutils import make_sign_udid_mobileconfig, get_post_udid_url, get_redirect_server_domain
from api.utils.storage.storage import Storage
from api.utils.storage.caches import get_app_instance_by_cache, get_download_url_by_cache, set_app_download_by_cache, \
del_cache_response_by_short
@@ -69,7 +69,7 @@ class DownloadView(APIView):
if release_obj:
bundle_id = release_obj.app_id.bundle_id
udid_url = get_post_udid_url(request, release_obj.app_id.short)
- ios_udid_mobileconfig = make_udid_mobileconfig(udid_url, bundle_id)
+ ios_udid_mobileconfig = make_sign_udid_mobileconfig(udid_url, bundle_id, release_obj.app_id.name)
response = FileResponse(ios_udid_mobileconfig)
response['Content-Type'] = "application/x-apple-aspen-config"
response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() + '.mobileconfig'
diff --git a/fir_ser/fir_ser/settings.py b/fir_ser/fir_ser/settings.py
index 57e190f..bda612c 100644
--- a/fir_ser/fir_ser/settings.py
+++ b/fir_ser/fir_ser/settings.py
@@ -230,8 +230,10 @@ FILE_UPLOAD_TMP_KEY = ".tmp"
SYNC_CACHE_TO_DATABASE = {
'download_times': 10, # 下载次数同步时间
'auto_clean_tmp_file_times': 60 * 30, # 定时清理上传失误生成的临时文件
- 'auto_clean_apscheduler_log': 100000, # 定时清理定时任务执行的日志,该参数为日志保留的数量
+ 'auto_clean_local_tmp_file_times': 60 * 30, # 定时清理临时文件,现在包含超级签名描述临时文件
'try_login_times': 5, # 当天登录失败次数,超过该失败次数,锁定24小时
+ 'auto_clean_apscheduler_log': 100000, # 定时清理定时任务执行的日志,该日志存在数据库中,该参数为日志保留的数量
+ 'clean_local_tmp_file_from_mtime': 60 * 60, # 清理最后一次修改时间超过限制时间的临时文件,单位秒
}
SERVER_DOMAIN = {
@@ -244,6 +246,13 @@ SERVER_DOMAIN = {
'FILE_UPLOAD_DOMAIN': 'https://fly.harmonygames.cn', # 本地文件上传域名,使用本地存储必须配置
}
+MOBILECONFIG_SIGN_SSL = {
+ # 描述文件是否签名,默认是关闭状态;如果开启,并且ssl_key_path 和 ssl_pem_path 正常,则使用填写的ssl进行签名,否则默认不签名
+ 'open': False,
+ 'ssl_key_path': '/data/cert/fly.harmonygames.cn.key',
+ 'ssl_pem_path': '/data/cert/fly.harmonygames.cn.pem'
+}
+
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"