diff --git a/.gitignore b/.gitignore index caf3a5a..6450dca 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ settings.py cert.db test.py +cert/ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 2d222ba..a509bb3 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,35 @@ # CDN Cert 自动将 Let's encrypt 续签后的证书推送到阿里云 CDN +## v2 更新日志 +更新于 2019 年 7 月 8 日 + +1. 支持多 RAM 账号。 + + 即当您有多个网站存在于同一个服务器上,且多个网站部署CDN时使用的不是同一阿里云账号时, + CDN Cert 可以向多个阿里云账号推送续签后的证书。 + +2. **完全迁移至 Python 3.7** + ### 工作原理 -定期对比存储在本机的证书与上一次推送成功的证书的 MD5 +定期[1]对比存储在本机的证书与上一次推送成功的证书的 MD5 如有差异则将新证书推送到 CDN 使用 SQLite3 做为数据库,并支持阿里云邮件推送服务,如有更新可以将推送结果发送到您的邮箱。 -### 使用方法 +## 配置环境 1. 准备 ``` -git clone https://github.com/0xJacky/cdn_cert.git -pip install aliyun-python-sdk-cdn sqlalchemy +git clone https://github.com/0xJacky/cdn_cert.git "CDN Cert" +pip3 install -r requirements.txt ``` 2. 配置 将 `settings-template.py` 复制一份并命名为 `settings.py` -打开 `settings.py` 进行配置 - -运行 `python update.py -a` 添加需要自动续期的域名到数据库 +打开 `settings.py` 配置 Let's encrypt 证书目录,邮件发送账户等,在 `settings-simple.py` +中,我提供了基于 certbot 和 acme.sh 管理证书的配置模板,请根据需求进行注释或解除注释 ##### 2018.6.7 更新日志(important!) @@ -32,73 +41,40 @@ pip install aliyun-python-sdk-cdn sqlalchemy 例如,使用 acme.sh 管理证书的用户,生成的私钥名称与域名相同,则应该设置为 `PrivkeyName = '{{ domain_name }}.key'` - -3. 参数 - -``` -$python update.py -h -usage: update.py [-h] [-f] [-o ONLY] [-a] [-d] [-ls] - -CDN_Cert - Automatically push the new certificates to CDN - -optional arguments: - -h, --help show this help message and exit - -f, --force force update - -o ONLY, --only ONLY update only, use it after -f/-force - -a, --add add domain name to database - -d, --delete remove domain name from database - -ls, --list print all the domain names from database - - -e.g. -$python update.py -Domain: jackyu.cn -Result: Push success -RequestId: D40F6BC4-6418-43B1-8E31-8BBB548AB3E2 - -Domain: beta.uozi.org -Result: Push success -RequestId: 9BF6A271-38CC-45F4-8DA0-48022DB742A3 - - -邮件发送成功! -$python update.py -f -Domain: jackyu.cn -Result: Push success -RequestId: D40F6BC4-6418-43B1-8E31-8BBB548AB3E2 - -Domain: beta.uozi.org -Result: Push success -RequestId: 9BF6A271-38CC-45F4-8DA0-48022DB742A3 - - -邮件发送成功! - -$python update.py -f -o ipsw.pw -Domain: ipsw.pw -Result: Push success -RequestId: AE15AC6F-5D71-4732-A6A6-02863057B202 - - -$python update.py -ls -CDN Cert -- Domain List ------------------------ -apt.uozi.org -jackyu.cn -ipsw.pw ------------------------ - -$python update.py -a -Plase input the domain name, use ',' to split. -ojbk.me -Execute successfully. - -$python update.py -d -Plase input a domain name to delete. -beta.uozi.org -Execute successfully. -``` -4. 定时配置 +## 使用方法 + +1. 用法 `-h/ --help` + ``` + python3 cdncert.py -h + usage: cdncert.py [-h] [-f] [-o ONLY] [-a {domain,user}] [-d {domain,user}] + [-ls {domains,users}] [-v] + + CDN Cert - Automatically push the new certificates to CDN + + optional arguments: + -h, --help show this help message and exit + -f, --force force update + -o ONLY, --only ONLY update only, use it after -f/--force + -a {domain,user}, --add {domain,user} + add [domain/user] to database + -d {domain,user}, --delete {domain,user} + delete [domain/user] from database + -ls {domains,users}, --list {domains,users} + print all [domains/users] from database + -v, --verbosity increase output verbosity + + ``` +2. 添加用户信息 `-a user` +3. 添加域名信息 `-a domain` +4. 删除用户 `-d user` +5. 删除域名 `-d domain` +6. 列出所有域名/用户 `-ls users/domains` +7. 开发模式 `-v` +8. 强制更新 `-f` +9. 推送成功的邮件模板 + + +9. 定时配置 ``` crontab -e # 每天 3:30 执行 @@ -106,7 +82,7 @@ crontab -e ``` ### LICENSE 版权声明 -Copyright © 2017 0xJacky +Copyright © 2017 - 2019 0xJacky The program is distributed under the terms of the GNU Affero General Public License. diff --git a/cdncert.py b/cdncert.py new file mode 100644 index 0000000..dae6313 --- /dev/null +++ b/cdncert.py @@ -0,0 +1,42 @@ +#!/usr/bin/python +# -*- coding:utf-8 -*- +# +# Copyright (c) 2017 0xJacky +# +# !请先使用 pip install aliyun-python-sdk-cdn 安装 sdk! + +import argparse +from core import Core +from database import Database + +parser = argparse.ArgumentParser(description='CDN Cert - Automatically push the new certificates to CDN') +parser.add_argument('-f', '--force', action="store_true", help='force update') +parser.add_argument('-o', '--only', action="store", default=None, help='update only, use it after -f/--force') +parser.add_argument('-a', '--add', action="store", choices=['domain', 'user'], help='add [domain/user] to database') +parser.add_argument('-d', '--delete', action="store", choices=['domain', 'user'], help='delete [domain/user] from database') +parser.add_argument('-ls', '--list', action="store", choices=['domains', 'users'], help='print all [domains/users] from database') +parser.add_argument("-v", "--verbosity", action="store_true", help="increase output verbosity") +args = parser.parse_args() + +Core = Core() +db = Database(args.verbosity) + +if args.force: + Core.do(force=True, only=args.only) +elif args.add: + if args.add == 'user': + Core.add_user() + elif args.add == 'domain': + Core.add_domain() +elif args.delete: + if args.delete == 'user': + Core.delete_user() + elif args.delete == 'domain': + Core.delete_domain() +elif args.list: + if args.list == 'users': + Core.get_all_user() + elif args.list == 'domains': + Core.get_all_domain() +else: + Core.do() diff --git a/core.py b/core.py new file mode 100644 index 0000000..67c2aef --- /dev/null +++ b/core.py @@ -0,0 +1,171 @@ +#!/usr/bin/python +# -*- coding:utf-8 -*- +import datetime +import os +import hashlib +import json +import settings +from aliyunsdkcore.client import AcsClient +from aliyunsdkcdn.request.v20180510.SetDomainServerCertificateRequest import SetDomainServerCertificateRequest +from prettytable import PrettyTable +from database import Database +from mail import Mail + +db = Database() +mail = Mail() + + +class Core: + def __init__(self): + pass + + # 执行操作 + def do(self, force=False, only=''): + queue = () + if only: + if db.has_domain(only): + queue = (only,) + else: + exit('\033[1;31mNo record of this domain.\nPlease add this domain before the operation.\033[0m') + + else: + domains = db.get_all_domain() + for domain in domains: + queue = (domain.domain, ) + self.push(force=force, queue=queue) + + # 获取文件 md5 + # 返回: 字符串 + @staticmethod + def md5sum(path): + file = open(path, 'rb') + return hashlib.md5(file.read()).hexdigest() + + def add_user(self): + name = input('Please input the user name\n') + + if db.has_user(name): + exit('\033[1;31mUser %s already exists.\033[0m' % name) + + access_key_id = input('Please input the Access Key ID\n') + access_key_secret = input('Please input the Access Key Secret\n') + db.add_user(name, access_key_id, access_key_secret) + + def add_domain(self): + domain = input('Please input your domain here\n') + + if db.has_domain(domain): + exit('\033[1;31mDomain %s already exists\033[0m' % domain) + + self.get_all_user() + user = input('Please input a user name from the table above.\n') + + if db.has_user(user) is not True: + exit('\033[1;31mNo record of %s.\033[0m' % user) + + db.add_domain(domain, user) + + @staticmethod + def get_all_domain(): + print('--------------------------------') + print('Here are your domains list') + domains = db.get_all_domain() + table = PrettyTable(['Domain', 'User']) + for domain in domains: + table.add_row([domain.domain, domain.user]) + print(table) + print('--------------------------------') + + @staticmethod + def get_all_user(): + print('--------------------------------') + print('Here are your users list') + users = db.get_all_user() + table = PrettyTable(['User', 'Access Key ID']) + for user in users: + table.add_row([user.name, user.access_key_id]) + print(table) + print('--------------------------------') + + def update_domain(self): + self.get_all_domain() + domain = input('Please input a domain from the table above.\n') + + if db.has_domain(domain) is not True: + exit('\033[1;31mNo record of this domain.\033[0m') + + self.get_all_user() + user = input('Please input a user name from the table above.\n') + + if db.has_user(user) is not True: + exit('\033[1;31mNo record of this user.\033[0m') + + db.update_domain(domain, user=user) + + def delete_domain(self): + self.get_all_domain() + domain = input('Please input a domain to delete from the table above.\n') + + if db.has_domain(domain) is not True: + exit('\033[1;31mNo record of this domain.\033[0m') + + sure = input('Are you sure to delete this domain: [y/n]') + + if sure == 'y': + db.delete_domain(domain) + + def delete_user(self): + self.get_all_user() + user = input('Please input a user to delete from the table above.\n') + + if db.has_user(user) is not True: + exit('\033[1;31mNo record of this user.\033[0m') + + sure = input('Are you sure to delete this user: [y/n]') + if sure == 'y': + db.delete_user(user) + + # 处理推送 + def push(self, force, queue=()): + msg = {} + for domain in queue: + PrivateKeyPath = os.path.join(settings.LiveCert, domain, + settings.PrivkeyName.replace('{{ domain_name }}', domain)) # 私钥路径 + info = db.get_domain(domain) + user = db.get_user(info.user) + store_md5 = info.md5 + currect_md5 = self.md5sum(PrivateKeyPath) + if not currect_md5 == store_md5 or force is True: + try: + client = AcsClient(user.access_key_id, user.access_key_secret, 'cn-hangzhou') + ServerCertificatePath = os.path.join(settings.LiveCert, domain, + settings.ServerCertificateName) # 安全证书路径 + ServerCertificate = open(ServerCertificatePath, 'r').read() + PrivateKey = open(PrivateKeyPath, 'r').read() + CertName = domain + '_' + datetime.datetime.now().strftime("%Y%m%d_%H%M%S") # 证书名称 + + request = SetDomainServerCertificateRequest() + request.set_accept_format('json') + request.set_DomainName(domain) + request.set_ServerCertificateStatus("on") + request.set_CertName(CertName) + request.set_ServerCertificate(ServerCertificate) + request.set_PrivateKey(PrivateKey) + request.set_CertType("upload") # 上传证书 + request.set_ForceSet("1") # 忽略证书同名检测 + response = client.do_action_with_exception(request) + RequestId = json.loads(response.decode('utf-8'))['RequestId'] + result = "Push successfully\nRequestId: " + str(RequestId) + + db.update_domain(domain, currect_md5) + except Exception as e: + result = e.get_error_code() if hasattr(e, 'get_error_code') else e + msg[domain] = result + if msg: + content = "" + for k, v in msg.items(): + content += 'Domain: ' + k + '\nResult: ' + str(v) + "\n\n" + print(content) + mail.send('[CDN Cert] 证书推送结果', content) + else: + print("Already up-to-date.") diff --git a/database.py b/database.py index f11b14a..2218d29 100644 --- a/database.py +++ b/database.py @@ -1,102 +1,101 @@ #!/usr/bin/python # -*- coding:utf-8 -*- -from sqlalchemy import * +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import create_engine, Table, Column, String, Integer, MetaData +from sqlalchemy.orm import sessionmaker from settings import DB_PATH -class DB: - def __init__(self): - self.db = create_engine('sqlite:///'+DB_PATH) - self.db.echo = False - self.conn = self.db.connect() - self.metadata = MetaData(self.db) - if not self.db.dialect.has_table(self.db, 'cert_data'): - self.init() - self.data = Table('cert_data', - self.metadata, - autoload=True) - - - def query(self, sql): - self.c.execute(sql) - self.con.commit() - - def add(self): - i = self.data.insert() - domain = raw_input('Plase input the domain name, use \',\' to split.\n') - d = () - if ',' in domain: - domain_list = domain.split(',') - for k in domain_list: - t = {} - t['domain'] = k - t['md5'] = '' - d = d + (t,) - else: - t = {} - t['domain'] = domain - t['md5'] = '' - d = d + (t,) +engine = create_engine('sqlite:///' + DB_PATH) +db = declarative_base() + + +class Domain(db): + __tablename__ = "domain" + id = Column(Integer, primary_key=True) + domain = Column(String(255)) + md5 = Column(String(32)) + user = Column(Integer) + + +class User(db): + __tablename__ = "user" + id = Column(Integer, primary_key=True) + name = Column(String(255)) + access_key_id = Column(String(16)) + access_key_secret = Column(String(32)) + + +class Database(object): + def __init__(self, verbosity = False): + engine.echo = verbosity + db.metadata.create_all(engine) + self.sessionmaker = sessionmaker(bind=engine) + self.session = self.sessionmaker() + + def add_user(self, name, access_key_id, access_key_secret): try: - i.execute(d) - print("Execute successfully.") + self.session.add(User(name=name, access_key_id=access_key_id, access_key_secret=access_key_secret)) + self.session.commit() + print("\033[1;32mUser %s added successfully\033[0m" % name) except Exception: print(Exception) - def update(self, domain, md5): - query = self.data.update().where(self.data.c.domain == domain).values({'md5': md5}) - self.conn.execute(query) - - def delete(self): - domain = raw_input('Plase input a domain name to delete.\n') - query = self.data.delete().where(self.data.c.domain == domain) + def add_domain(self, domain, user): try: - self.conn.execute(query) - print("Execute successfully.") + self.session.add(Domain(domain=domain, user=user)) + self.session.commit() + print("\033[1;32mDomain %s added successfully\033[0m" % domain) except Exception: print(Exception) - def fetchone(self, domain): - query = self.data.select().where(self.data.c.domain == domain) - return self.conn.execute(query).fetchone() - - def fetchall(self): - s = self.data.select() - r = s.execute() - output = () - for f in r.fetchall(): - output = output + (f[0],) - return output - - def domainlist(self): - s = self.data.select() - r = s.execute() - print("CDN Cert -- Domain List") - print("-----------------------") - for f in r.fetchall(): - print(f[0]) - print("-----------------------") - - def intable(self, domain): - if self.fetchone(domain=domain): + def get_domain(self, domain): + return self.session.query(Domain).filter(Domain.domain == domain).first() + + def get_all_domain(self): + return self.session.query(Domain).all() + + def has_domain(self, domain): + domain = self.get_domain(domain) + if domain is not None: return True - else: - return False - - def init(self): - table = ( - ('cert_data', - ( - Column('domain', String(255), unique=True), - Column('md5', String(32)), - ), - ), - ) - metadata = MetaData(self.db) - - for name, columns in table: - try: - c_table = Table(name, metadata, autoload=True) - except: - c_table = apply(Table, (name, metadata) + columns) - c_table.create() - print('Database has been initialized') + return False + + def has_user(self, user): + user = self.get_user(user) + if user is not None: + return True + return False + + def get_user(self, name): + return self.session.query(User).filter(User.name == name).first() + + def get_all_user(self): + return self.session.query(User).all() + + def update_domain(self, domain, md5, user=None): + try: + domain = self.session.query(Domain).filter(Domain.domain == domain).first() + domain.md5 = md5 + if user is not None: + domain.user = user + print("\033[1;32mDomain %s updated successfully\033[0m" % domain) + self.session.commit() + except Exception: + print(Exception) + + def delete_domain(self, domain): + self.session.query(Domain).filter(Domain.domain == domain).delete() + self.session.commit() + print("\033[1;32mDomain %s deleted successfully\033[0m" % domain) + + def delete_user(self, name): + try: + self.session.query(User).filter(User.name == name).delete() + self.session.commit() + print("\033[1;32mUser %s deleted successfully\033[0m" % name) + except Exception: + print(Exception) + + + + diff --git a/process.py b/process.py deleted file mode 100644 index 016313b..0000000 --- a/process.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- -import datetime -import os -import collections -import hashlib -import json -import settings -from database import DB -from mail import Mail -from aliyunsdkcore import client -from aliyunsdkcdn.request.v20141111 import SetDomainServerCertificateRequest - -db = DB() -mail = Mail() - -class Process: - def __init__(self): - pass - - # 执行操作 - def do(self, force=False, only=''): - queue = () - if only: - if db.intable(only): - queue = (only,) - else: - exit('No record of this domain name.') - else: - queue = db.fetchall() - self.push(force=force, queue=queue) - - # 获取文件 md5 - # 返回: 字符串 - def md5sum(self, path): - file = open(path, 'rb') - return hashlib.md5(file.read()).hexdigest() - - # 处理推送 - def push(self, force, queue=()): - msg = {} - for d in queue: - PrivateKey_path = os.path.join(settings.LiveCert, d, settings.PrivkeyName.replace('{{ domain_name }}', d)) # 私钥路径 - store_md5 = db.fetchone(d)[1] - currect_md5 = self.md5sum(PrivateKey_path) - if not currect_md5 == store_md5 or force == True: - try: - self.Client = client.AcsClient(settings.AccessKeyId, settings.AccessKeySecret, 'cn-hangzhou') - self.request = SetDomainServerCertificateRequest.SetDomainServerCertificateRequest() - self.request.set_accept_format('json') - CertName = d + '_' + datetime.datetime.now().strftime("%Y%m%d_%H%M%S") # 证书名称,默认域名+日期时间 - ServerCertificate_path = os.path.join(settings.LiveCert, d, settings.ServerCertificateName) # 安全证书路径 - self.request.set_DomainName(d) - self.request.set_CertName(CertName) - self.request.set_ServerCertificateStatus('on') - ServerCertificate = open(ServerCertificate_path, 'r').read() - ServerCertificate = open(ServerCertificate_path, 'r').read() - PrivateKey = open(PrivateKey_path, 'r').read() - self.request.set_ServerCertificate(ServerCertificate) - self.request.set_PrivateKey(PrivateKey) - RequestId = json.loads(self.Client.do_action_with_exception(self.request).decode('utf-8'))['RequestId'] - result = "Push success\nRequestId: "+ str(RequestId) - db.update(d, currect_md5) - except Exception as e: - result = e.get_error_code() if hasattr(e, 'get_error_code') else e - msg[d] = result - if msg: - content = "" - for k,v in msg.items(): - content += 'Domain: ' + k + '\nResult: ' + str(v) + "\n\n" - print(content) - mail.send('[CDN Cert] 证书推送结果', content) - else: - print("Already up-to-date.") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..88f9e05 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,58 @@ +aliyun-python-sdk-cdn==3.0.8 +aliyun-python-sdk-core-v3==2.13.3 +asn1crypto==0.24.0 +atomicwrites==1.1.5 +attrs==18.1.0 +beautifulsoup4==4.6.0 +bs4==0.0.1 +certifi==2018.4.16 +cffi==1.11.5 +chardet==3.0.4 +configparser==3.5.0 +cryptography==2.3 +cssselect==1.0.3 +et-xmlfile==1.0.1 +feedparser==5.2.1 +get==1.0.3 +html5lib==1.0.1 +idna==2.7 +itchat==1.3.10 +jdcal==1.4 +jmespath==0.9.4 +k==0.0.1 +lxml==4.2.3 +more-itertools==4.2.0 +mutagen==1.42.0 +openpyxl==2.6.0 +parse==1.8.4 +pathlib==1.0.1 +pdfminer.six==20170720 +pdfminer3k==1.3.1 +pluggy==0.6.0 +ply==3.11 +post==1.0.2 +prettytable==0.7.2 +public==1.0.3 +py==1.5.4 +pycparser==2.18 +pycryptodome==3.6.6 +pyExcelerator==0.6.4.1 +PyMySQL==0.9.2 +PyParse==1.1.7 +pypng==0.0.19 +PyQRCode==1.2.1 +pyquery==1.4.0 +pytest==3.6.4 +python-dateutil==2.7.3 +query-string==1.0.2 +request==1.0.2 +requests==2.20.0 +six==1.11.0 +SQLAlchemy==1.3.5 +urllib3==1.23 +webencodings==0.5.1 +workbook==1.1 +xlrd==1.2.0 +XlsxWriter==1.1.3 +xlutils==2.0.0 +xlwt==1.3.0 diff --git a/screenshots/2019-07-08-11.39.31.png b/screenshots/2019-07-08-11.39.31.png new file mode 100644 index 0000000..59295d1 Binary files /dev/null and b/screenshots/2019-07-08-11.39.31.png differ diff --git a/screenshots/2019-07-08-11.39.50.png b/screenshots/2019-07-08-11.39.50.png new file mode 100644 index 0000000..7b7a182 Binary files /dev/null and b/screenshots/2019-07-08-11.39.50.png differ diff --git a/screenshots/2019-07-08-11.40.30.png b/screenshots/2019-07-08-11.40.30.png new file mode 100644 index 0000000..68a6b83 Binary files /dev/null and b/screenshots/2019-07-08-11.40.30.png differ diff --git a/screenshots/2019-07-08-11.40.46.png b/screenshots/2019-07-08-11.40.46.png new file mode 100644 index 0000000..22b16fc Binary files /dev/null and b/screenshots/2019-07-08-11.40.46.png differ diff --git a/screenshots/2019-07-08-11.41.02.png b/screenshots/2019-07-08-11.41.02.png new file mode 100644 index 0000000..a22be5e Binary files /dev/null and b/screenshots/2019-07-08-11.41.02.png differ diff --git a/screenshots/2019-07-08-11.41.24.png b/screenshots/2019-07-08-11.41.24.png new file mode 100644 index 0000000..70a1d75 Binary files /dev/null and b/screenshots/2019-07-08-11.41.24.png differ diff --git a/screenshots/2019-07-08-11.41.40.png b/screenshots/2019-07-08-11.41.40.png new file mode 100644 index 0000000..0ba7790 Binary files /dev/null and b/screenshots/2019-07-08-11.41.40.png differ diff --git a/screenshots/2019-07-08-11.41.52.png b/screenshots/2019-07-08-11.41.52.png new file mode 100644 index 0000000..2860dd7 Binary files /dev/null and b/screenshots/2019-07-08-11.41.52.png differ diff --git a/screenshots/2019-07-08-11.43.50.png b/screenshots/2019-07-08-11.43.50.png new file mode 100644 index 0000000..f325889 Binary files /dev/null and b/screenshots/2019-07-08-11.43.50.png differ diff --git a/settings-template.py b/settings-template.py index e6d8ca3..5f77670 100644 --- a/settings-template.py +++ b/settings-template.py @@ -1,11 +1,11 @@ #!/usr/bin/python # -*- coding:utf-8 -*- import os -## 配置开始 -# 访问 https://ak-console.aliyun.com/index#/accesskey 获取 -AccessKeyId = '' -AccessKeySecret = '' +# 数据存储地址 +ABS_PATH = os.path.split(os.path.realpath(__file__))[0] +DB_PATH = os.path.join(ABS_PATH, 'cert.db') +## 配置开始 # Let's encrypt 证书目录,一般情况下无需修改 # LetsencryptPath = os.path.join('/usr/local/nginx/conf') # LiveCert = os.path.join(LetsencryptPath, 'ssl') @@ -21,10 +21,6 @@ # ServerCertificateName = 'fullchain.cer' # PrivkeyName = '{{ domain_name }}.key' -# 数据存储地址 -ABS_PATH = os.path.split(os.path.realpath(__file__))[0] -DB_PATH = os.path.join(ABS_PATH, 'cert.db') - # 邮件反馈设置 - 阿里云邮件推送服务 Host = 'smtpdm.aliyun.com' Port = '465' diff --git a/update.py b/update.py deleted file mode 100644 index 44fbf96..0000000 --- a/update.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python -# -*- coding:utf-8 -*- -# -# Copyright (c) 2017 0xJacky -# -# !请先使用 pip install aliyun-python-sdk-cdn 安装 sdk! - -import argparse -from process import Process -from database import DB - -Process = Process() -db = DB() - -parser = argparse.ArgumentParser(description='CDN_Cert - Automatically push the new certificates to CDN') -parser.add_argument('-f', '--force', action="store_true", help='force update') -parser.add_argument('-o', '--only', action="store", default=None, help='update only, use it after -f/-force') -parser.add_argument('-a', '--add', action="store_true", help='add domain name to database') -parser.add_argument('-d', '--delete', action="store_true", help='remove domain name from database') -parser.add_argument('-ls', '--list', action="store_true", help='print all the domain names from database') -args = parser.parse_args() - -if args.force: - Process.do(force=True, only=args.only) -elif args.add: - db.add() -elif args.delete: - db.delete() -elif args.list: - db.domainlist() -else: - Process.do()