分析七牛云接口利用腾讯云API开发一个基于Python脚本命令行的域名HTTPS证书申请工具
前言
需要回顾前面几天的几篇文章的代码:
前面已经对七牛云的证书申请的接口进行了分析,完成了整个证书申请流程,其中在七牛云申请免费HTTPS证书的中间需要给域名添加一个DNS解析证明域名归属也根据腾讯云的API文档完成了,今天就来整合这几个接口。
流程整理
首选需要一些必备的账号(腾讯云账户secretId,secretKey,七牛云账号密码),必备的域名,Chrome seleium环境,下面用一个简单的流程图来表示:
未签发
返回检查
已签发
seleium登录七牛云获取cookie
申请证书
完善证书申请信息
腾讯云DNS解析
检查证书状态,是否可下载?
否
是
设置压缩包密码
下载
解压
展示
代码
前面所有功能我都封装成了一个个函数,接着就需要把他们组合成一起,主要是对上面的流程进行函数整合,为了方便展示,我就把所有的代码放在一起展示:
# coding=UTF-8
import requests
import json, time, os, zipfile, sys
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.dnspod.v20210323 import dnspod_client, models
user_name = '********@*****.com'
password = '*****'
pwd = '1'
chorme_options = Options()
chorme_options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=chorme_options) # 初始化Chrome驱动
driver.implicitly_wait(20)
headers = {
'authority': 'portal.qiniu.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
'content-type': 'application/json',
'accept': '*/*',
'origin': 'https://portal.qiniu.com',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://portal.qiniu.com/certificate/apply',
'accept-language': 'zh,zh-CN;q=0.9',
}
def set_dns(domain, record_type, value, sub_domain):
try:
# 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
# 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
cred = credential.Credential("**************", "**********")
# 实例化一个http选项,可选的,没有特殊需求可以跳过
httpProfile = HttpProfile()
httpProfile.endpoint = "dnspod.tencentcloudapi.com"
# 实例化一个client选项,可选的,没有特殊需求可以跳过
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
# 实例化要请求产品的client对象,clientProfile是可选的
client = dnspod_client.DnspodClient(cred, "", clientProfile)
# 实例化一个请求对象,每个接口都会对应一个request对象
req = models.CreateRecordRequest()
params = {
"Domain": domain,
"RecordType": record_type,
"RecordLine": "默认",
"Value": value,
"SubDomain": sub_domain
}
req.from_json_string(json.dumps(params))
# 返回的resp是一个CreateRecordResponse的实例,与请求对象对应
resp = client.CreateRecord(req)
# 输出json格式的字符串回包
print(resp.to_json_string())
return True
except TencentCloudSDKException as err:
print(err)
return False
def create_ssl(common_name, cookie):
data = '{"product_short_name":"TrustAsiaTLSC1","years":1,"limit":0,"wildcard_limit":-1,"product_type":"single"}'
response = requests.post('https://portal.qiniu.com/api/certificate/v1/sslorder/prepare', headers=headers, cookies=cookie,
data=data)
res = json.loads(response.text)
order_id = res['data']['order_id']
data = {
'common_name': common_name,
'org_addressLine1': '***************',
'org_city': '深圳市',
'org_region': '广东',
'org_country': 'CN',
'org_postalCode': '430000',
'org_organization_name': '***********',
'org_division': '技术部',
'org_phone': '027-******',
'admin_firstName': '*',
'admin_lastName': '**',
'admin_phone': '**********',
'admin_email': '******@**.com',
'orderid': order_id,
'auth_method': 'DNS',
'admin_title': '*******',
'dns_names': '',
'cert_name': common_name,
'encrypt': 'RSA',
'toBeDeployedDomains': [],
}
response = requests.post('https://portal.qiniu.com/api/certificate/v1/sslorder/create', headers=headers,
cookies=cookie, json=data)
time.sleep(2)
response = requests.get('https://portal.qiniu.com/api/certificate/v1/sslorder/' + order_id, headers=headers,
cookies=cookie)
res = response.json()
print("证书申请成功,域名为:" + common_name + " TXT记录名:" + res['data']['auth_array'][0]['AuthKey'] + " TXT记录值:" +
res['data']['auth_array'][0]['AuthValue'])
return {'AuthKey': res['data']['auth_array'][0]['AuthKey'],
'AuthValue': res['data']['auth_array'][0]['AuthValue'],
'order_id': order_id} # 返回记录值
def check_status(order_id, cookie):
response = requests.get('https://portal.qiniu.com/api/certificate/v1/sslorder/' + order_id, headers=headers,
cookies=cookie)
res = response.json()
if res['data']['certID'] == '':
return ''
else:
return res['data']['certID']
def download_data(cookie, cert_id, pwd):
url = 'https://portal.qiniu.com/api/certificate/v1/ssl/download?certid=' + cert_id + '&type=PEM_Nginx' \
'&key_store_pwd=' + pwd
response = requests.get(url, headers=headers, cookies=cookie)
save_path = os.getcwd() + '/cert/' + cert_id + '.zip'
with open(save_path, 'ab') as f:
f.write(response.content)
f.flush()
print(save_path + " 下载完成!")
def decode_package(cert_id, pwd):
unzip_path = os.getcwd() + '\cert\' + cert_id
zip_file = zipfile.ZipFile(os.getcwd() + '\cert\' + cert_id + '.zip')
if not os.path.exists(unzip_path):
os.makedirs(unzip_path)
zip_list = zip_file.namelist() # 得到压缩包里所有文件
for i in zip_list:
zip_file.extract(i, unzip_path, pwd.encode('utf-8')) # 解压到的目标文件夹
zip_file.close()
os.remove(os.getcwd() + '\cert\' + cert_id + '.zip') # 删掉压缩包
def get_cookie():
driver.get(url='https://sso.qiniu.com/') # 直接访问登录页
user_input = driver.find_element(By.ID, 'email') # 获取用户名输入框
user_input.send_keys(user_name) # 输入用户名
password_input = driver.find_element(By.ID, 'password') # 获取密码框
password_input.send_keys(password) # 输入密码
driver.find_element(By.ID, 'login-button').click() # 登录
try:
WebDriverWait(driver, 60).until(EC.visibility_of_element_located(
(By.CLASS_NAME, "user-plane-entry"))) # 等待网页跳转,超时等待60秒
except:
print('登陆超时,失败') # 等待超过了60
# driver.quit()
cookie = driver.get_cookies() # 获取cookie 此时是键值对
return cookie
def read_file(domain, cet_id):
with open(os.getcwd() + '\cert\' + cet_id + '\' + domain + '.crt', 'r') as f1:
print(f1.read())
with open(os.getcwd() + '\cert\' + cet_id + '\' + domain + '.crt', 'r') as f2:
print(f2.read())
if __name__ == '__main__':
common_name = sys.argv[1] # 读取完整需要申请证书的域名
cookie = get_cookie()
qiniu_cookie = {}
# 从列表取出字典,从字典获取name和对应的value,再添加到cookies字典中
for cookie_dic in cookie:
qiniu_cookie[cookie_dic['name']] = cookie_dic['value'] # 列表转字典
dns_info = create_ssl(common_name, qiniu_cookie)
domain_name = common_name.replace(common_name.split('.')[0]+'.', '') # 去掉二级域名前缀 符合腾讯云API要求
sub_domain = dns_info['AuthKey'].split('.')[0] + '.' + dns_info['AuthKey'].split('.')[1] # 子域名参数处理 为了符合腾讯云API要求
set_dns(domain_name, 'CNAME', dns_info['AuthValue'], sub_domain)
count = 0
cert_id = ''
while True:
time.sleep(60)
cert_id = check_status(dns_info['order_id'], qiniu_cookie)
if cert_id != '':
print('已签发')
break
print('还未签发')
count += 1
if count == 60:
print('检查超时,请手动检查')
quit()
download_data(qiniu_cookie, cert_id, pwd) # 下载证书压缩包
decode_package(cert_id, pwd) # 解压压缩包
read_file(common_name, cert_id) # 展示证书内容
运行效果如:
总结
敏感的信息都通过*号替换还有水印遮盖了~
短短两百行代码今天调试了很久,终于把整个流程走通了,花了很多精力,主要是要处理腾讯云API请求格式,文件的处理这里,还有一些参数的共用处理。非常完美,基本上5分钟以内自动地就可以申请一个证书,几乎不会出什么问题,有点繁琐的就是需要一个seleium驱动谷歌浏览器的环境,有机会再用到它再仔细研究登录接口。
转载自:https://juejin.cn/post/7132503603817742367