Skip to content

Commit

Permalink
新增 证书部署到阿里云oss
Browse files Browse the repository at this point in the history
  • Loading branch information
mouday committed Jul 24, 2024
1 parent 0663eb0 commit 4b32044
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 37 deletions.
9 changes: 9 additions & 0 deletions domain_admin/api/deploy_cert_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from domain_admin.model.deploy_cert_model import DeployCertModel
from domain_admin.model.host_model import HostModel
from domain_admin.service import deploy_cert_service
from domain_admin.utils.open_api import aliyun_oss_api


def get_deploy_list_by_cert_id():
Expand Down Expand Up @@ -160,3 +161,11 @@ def handle_deploy_cert():
err = deploy_cert_service.handle_deploy_cert(deploy_cert_id)
if err:
raise err


def get_aliyun_endpoint_options():
"""
阿里云endpoint
:return:
"""
return aliyun_oss_api.ENDPOINT_OPTIONS
40 changes: 40 additions & 0 deletions domain_admin/api/issue_certificate_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,46 @@ def notify_web_hook():
return ret


def deploy_cert_to_oss():
"""
部署证书到oss
:return:
"""
issue_certificate_id = request.json['issue_certificate_id']
bucket_name = request.json['bucket_name']
endpoint = request.json.get['endpoint']
dns_id = request.json.get['dns_id']

ret = issue_certificate_service.deploy_cert_to_oss(
issue_certificate_id=issue_certificate_id,
bucket_name=bucket_name,
endpoint=endpoint,
dns_id=dns_id,
)

deploy_params = {
'endpoint': endpoint,
'bucket_name': bucket_name,
}

# 更新验证信息
IssueCertificateModel.update(
deploy_type_id=SSLDeployTypeEnum.OSS,
deploy_host_id=dns_id,
deploy_params_raw=json.dumps(deploy_params),
ssl_deploy_status=DeployStatusEnum.SUCCESS
).where(
IssueCertificateModel.id == issue_certificate_id
).execute()

# 验证成功后, check_auto_renew
issue_certificate_service.check_auto_renew(
issue_certificate_id=issue_certificate_id
)

return ret


def add_dns_domain_record():
"""
添加dns记录
Expand Down
3 changes: 3 additions & 0 deletions domain_admin/enums/ssl_deploy_type_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
@Date : 2024-06-27
"""


class SSLDeployTypeEnum(object):
"""
ssl证书部署方式
"""
SSH = 0

WEB_HOOK = 1

OSS = 2
9 changes: 9 additions & 0 deletions domain_admin/enums/version_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,12 @@ class VersionEnum(object):
Version_1633 = '1.6.33'
Version_1634 = '1.6.34'
Version_1635 = '1.6.35'

Version_1636 = '1.6.36'
Version_1637 = '1.6.37'
Version_1638 = '1.6.38'
Version_1639 = '1.6.39'
Version_1640 = '1.6.40'
Version_1641 = '1.6.41'
Version_1642 = '1.6.42'
Version_1643 = '1.6.43'
32 changes: 32 additions & 0 deletions domain_admin/migrate/history/migrate_1642_to_1643.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
"""
@File : migrate_1642_to_1643.py
@Date : 2024-07-24
cmd:
$ python domain_admin/migrate/migrate_1642_to_1643.py
"""
from __future__ import print_function, unicode_literals, absolute_import, division

from domain_admin.migrate import migrate_common
from domain_admin.model.base_model import db
from domain_admin.model.issue_certificate_model import IssueCertificateModel, DeployStatusEnum


def execute_migrate():
"""
版本升级 1.6.42 => 1.6.43
:return:
"""
migrator = migrate_common.get_migrator(db)

migrate_rows = [
# deploy_params_raw
migrator.add_column(
table=IssueCertificateModel._meta.table_name,
column_name=IssueCertificateModel.deploy_params_raw.name,
field=IssueCertificateModel.deploy_params_raw
)
]

migrate_common.try_execute_migrate(migrate_rows)
20 changes: 19 additions & 1 deletion domain_admin/migrate/migrate_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
migrate_162_to_163,
migrate_168_to_169,
migrate_1610_to_1611,
migrate_1625_to_1626, migrate_1633_to_1634, migrate_1634_to_1635)
migrate_1625_to_1626, migrate_1633_to_1634, migrate_1634_to_1635, migrate_1642_to_1643)

# 参数说明
# local_versions 本地版本
Expand Down Expand Up @@ -398,4 +398,22 @@
'migrate_func': migrate_1634_to_1635.execute_migrate,
'update_version': VersionEnum.Version_1635
},

# 2024-07-24
# 1.6.42 => 1.6.43
{
'local_versions': [
VersionEnum.Version_1635,
VersionEnum.Version_1636,
VersionEnum.Version_1637,
VersionEnum.Version_1638,
VersionEnum.Version_1639,
VersionEnum.Version_1640,
VersionEnum.Version_1641,
VersionEnum.Version_1642,
],
'migrate_func': migrate_1642_to_1643.execute_migrate,
'update_version': VersionEnum.Version_1643
},

]
12 changes: 12 additions & 0 deletions domain_admin/model/issue_certificate_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class IssueCertificateModel(BaseModel):
status = CharField(default=ValidStatus.PENDING, null=True)

# 部署方式 @since 1.6.33 可选:ssh api
# @since 1.6.43 新增 oss
deploy_type_id = IntegerField(default=SSLDeployTypeEnum.SSH)

# 部署机器
Expand All @@ -112,6 +113,10 @@ class IssueCertificateModel(BaseModel):
# 部署请求头
deploy_header_raw = TextField(default=None, null=True)

# 部署参数
# @since 1.6.43
deploy_params_raw = TextField(default=None, null=True)

# ssl证书文件部署状态
ssl_deploy_status = IntegerField(default=DeployStatusEnum.PENDING)

Expand Down Expand Up @@ -202,3 +207,10 @@ def to_dict(self):
'domain_validation_urls'
]
)

@property
def deploy_params(self):
if self.deploy_params_raw:
return json.loads(self.deploy_params_raw)
else:
return {}
2 changes: 2 additions & 0 deletions domain_admin/router/api_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
'/api/deleteCertificateByBatch': issue_certificate_api.delete_certificate_by_batch,
'/api/getAllowCommands': issue_certificate_api.get_allow_commands,
'/api/notifyWebHook': issue_certificate_api.notify_web_hook,
'/api/deployCertToOss': issue_certificate_api.deploy_cert_to_oss,
'/api/addDnsDomainRecord': issue_certificate_api.add_dns_domain_record,
'/api/updateRowAutoRenew': issue_certificate_api.update_row_auto_renew,
'/api/getIssueCertificateOptions': issue_certificate_api.get_issue_certificate_options,
Expand Down Expand Up @@ -223,6 +224,7 @@
'/api/deleteByDeployCertIds': deploy_cert_api.delete_by_deploy_cert_ids,
'/api/getDeployCertById': deploy_cert_api.get_deploy_cert_by_id,
'/api/handleDeployCert': deploy_cert_api.handle_deploy_cert,
'/api/getAliyunEndpointOptions': deploy_cert_api.get_aliyun_endpoint_options,

# DNS账户管理
'/api/addDns': dns_api.add_dns,
Expand Down
34 changes: 33 additions & 1 deletion domain_admin/service/issue_certificate_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from domain_admin.utils.acme_util.key_type_enum import KeyTypeEnum
from domain_admin.utils.cert_util import cert_common
from domain_admin.utils.flask_ext.app_exception import AppException
from domain_admin.utils.open_api import aliyun_domain_api, tencentcloud_domain_api
from domain_admin.utils.open_api import aliyun_domain_api, tencentcloud_domain_api, aliyun_oss_api
from domain_admin.utils.open_api.aliyun_domain_api import RecordTypeEnum
from domain_admin import config

Expand Down Expand Up @@ -332,6 +332,14 @@ def renew_certificate_row(row):
headers=row.deploy_header,
)

elif row.deploy_type_id == SSLDeployTypeEnum.OSS:
deploy_cert_to_oss(
issue_certificate_id=row.id,
bucket_name=row.deploy_params['bucket_name'],
endpoint=row.deploy_params['bucket_name'],
dns_id=row.deploy_host_id
)


def deploy_verify_file(host_id, verify_deploy_path, challenges):
"""
Expand Down Expand Up @@ -549,6 +557,30 @@ def deploy_ssl_by_web_hook(issue_certificate_id, url, headers):
return res.text


def deploy_cert_to_oss(issue_certificate_id, bucket_name, endpoint, dns_id):
"""
部署ssl证书到oss
"""
issue_certificate_row = IssueCertificateModel.get_by_id(issue_certificate_id)

if not issue_certificate_row:
raise AppException('证书数据不存在')

dns_row = DnsModel.get_by_id(dns_id)
if not dns_row:
raise AppException('DNS数据不存在')

aliyun_oss_api.put_bucket_cname(
access_key_id=dns_row.access_key,
access_key_secret=dns_row.secret_key,
bucket_name=bucket_name,
domain=issue_certificate_row.domains[0],
certificate=issue_certificate_row.ssl_certificate,
private_key=issue_certificate_row.ssl_certificate_key,
endpoint=endpoint,
)


def check_auto_renew(issue_certificate_id):
"""
首次申请,自动判断是否可以自动续期
Expand Down
42 changes: 42 additions & 0 deletions domain_admin/utils/open_api/aliyun_cas_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"""
@File : aliyun_api.py
@Date : 2024-07-24
"""

from alibabacloud_cas20200407 import models as cas_20200407_models
from alibabacloud_cas20200407.client import Client as cas20200407Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models


def upload_user_certificate(
access_key_id, access_key_secret,
cert_name, cert, key
):
"""
上传证书
@return: Client
@throws Exception
"""
# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
# 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html。
config = open_api_models.Config(
# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。,
access_key_id=access_key_id,
# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。,
access_key_secret=access_key_secret
)
# Endpoint 请参考 https://api.aliyun.com/product/cas
config.endpoint = 'cas.aliyuncs.com'

client = cas20200407Client(config)
upload_user_certificate_request = cas_20200407_models.UploadUserCertificateRequest(
name=cert_name,
cert=cert,
key=key,
)

runtime = util_models.RuntimeOptions()

client.upload_user_certificate_with_options(upload_user_certificate_request, runtime)
34 changes: 34 additions & 0 deletions domain_admin/utils/open_api/aliyun_cdn_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
"""
@File : aliyun_cdn_api.py
@Date : 2024-07-24
"""

from alibabacloud_cdn20180510 import models as cdn_20180510_models
from alibabacloud_cdn20180510.client import Client as Cdn20180510Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models


def set_cdn_domain_ssl_certificate(access_key_id, access_key_secret, domain_name):
# 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
# 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378659.html。
config = open_api_models.Config(
# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。,
access_key_id=access_key_id,
# 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。,
access_key_secret=access_key_secret,
)
# Endpoint 请参考 https://api.aliyun.com/product/Cdn
config.endpoint = f'cdn.aliyuncs.com'
client = Cdn20180510Client(config)

set_cdn_domain_sslcertificate_request = cdn_20180510_models.SetCdnDomainSSLCertificateRequest(
cert_type='cas',
domain_name=domain_name,
sslprotocol='on'
)
runtime = util_models.RuntimeOptions()

# 复制代码运行请自行打印 API 的返回值
client.set_cdn_domain_sslcertificate_with_options(set_cdn_domain_sslcertificate_request, runtime)
Loading

0 comments on commit 4b32044

Please sign in to comment.