RSS Impact 是一个支持 Hook 的 RSS 订阅工具,
支持推送通知、Webhook 、下载、BitTorrent、AI 大模型 等多种形式的 Hook。

0%

2024-06-09 如何通过阿里云 OpenAPI 管理 CDN

2024-06-09 如何通过阿里云 OpenAPI 管理 CDN

前言

前不久,阿里云通知笔者 CDN 的 SSL 证书快到期了,于是笔者就打算新申请一张 1 年的 SSL 证书。

【变更】关于免费证书服务策略调整通知

对于免费领取的 SSL 证书,签发后的证书有效期统一变更为 3 个月

结果发现,现在免费的证书只有 3 个月了,跟 Let’s Encrypt 提供的 90 天免费证书一样了。

既然如此,为什么不直接使用 Let’s Encrypt 提供的免费证书呢?

在之前,由于 Let’s Encrypt 只提供最长 90 天的免费证书,为了省点事,选择了阿里云的 1 年期免费证书。

关于 Let’s Encrypt 为什么只提供 90 天的免费证书,详见:Why ninety-day lifetimes for certificates?

image-20240609202714928

最重要的是 Let’s Encrypt 完全免费!

经过一通研究,笔者发现可以通过调用阿里云 OpenAPI 来实现自动化更新 SSL 证书,在此记录一下使用方式。

什么是阿里云 OpenAPI

OpenAPI 是指开放应用程序编程接口(Open Application Programming Interface)的简称。阿里云 OpenAPI 为开发者提供了一系列开放的应用程序接口,使您可以通过这些应用程序接口来方便的管理云上资源、数据和服务等内容。

详见:什么是 OpenAPI

总之,我们可以通过阿里云提供的 OpenAPI,来调用阿里云上的一系列接口,从而管理对应的资源和服务。

获取 AccessKey

在一切开始之前,需要先获取到 AccessKeyId 和 AccessKeySecret。

如果你现在点击 左上角的 AccessKey 管理的话,就会发现,阿里云提示你使用 子用户 AccessKey

image-20240609204527843

image-20240609204621782

在这里,出于安全起见,十分建议使用子用户 AccessKey

可以前往 子用户管理 页面进行创建。

创建用户的时候记得选上 OpenAPI 调用访问

image-20240609204949690

详见:创建 RAM 用户

记得及时保存 AccessKey IDAccessKey Secret,关掉之后就看不见了。

image-20240609205501826

创建完子用户后还需要给子用户授权。

由于目前只需要管理 CDN,因此这里只给子用户授权 CDN 相关的权限即可。

因为还需要写入域名证书,故需要拿到写入权限,不要选择 只读 权限。

image-20240609205048058

如何使用 OpenAPI 管理 CDN

在调用 OpenAPI 之前,显然需要先知道这个 API 是干什么的,有哪些入参,返回值又是什么样的。

查看 API 文档

所幸,阿里云提供了完善的 API 文档。

详见:阿里云 API 文档

经过一番搜索,就可以看到需要的 API 了。

DescribeDomainCertificateInfo - 查询域名证书信息SetCdnDomainSSLCertificate - 设置CDN域名证书。一个用于查看当前域名的证书信息,另一个用于设置证书。

image-20240609205819013

详见:DescribeDomainCertificateInfo- 查询域名证书信息

SetCdnDomainSSLCertificate- 设置 CDN 域名证书

查看 API 代码调用示例

点击右上方的 去调用 即可调试相关接口。

参考:DescribeDomainCertificateInfo

在输入输入参数后,即可点击左侧的 SDK 示例查看具体的代码。

image-20240609205944808

由于笔者比较喜欢用 TypeScript,所以此处的例子是用 TypeScript 实现的。

读者朋友也可以使用自己喜欢的编程语言进行调用。

image-20240609210238588

阿里云提供了包括 Java、TypeScript、Go、PHP、Python 等多种语言的 SDK,可以选一个喜欢的进行使用。

基于同样的原理,也可以获取到 SetCdnDomainSSLCertificate 的代码逻辑。

封装 API 调用

参考阿里云给出的例子后,稍加改动,就得到了以下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import Cdn20180510, * as $Cdn20180510 from '@alicloud/cdn20180510'
import * as $OpenApi from '@alicloud/openapi-client'
import * as $Util from '@alicloud/tea-util'

export default class Client {

/**
* 使用AK&SK初始化账号Client
* @return Client
* @throws Exception
*/
static createClient(): Cdn20180510 {
// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
// 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html。
const config = new $OpenApi.Config({
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
accessKeyId: process.env['ALIBABA_CLOUD_ACCESS_KEY_ID'],
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
accessKeySecret: process.env['ALIBABA_CLOUD_ACCESS_KEY_SECRET'],
})
// Endpoint 请参考 https://api.aliyun.com/product/Cdn
config.endpoint = 'cdn.aliyuncs.com'
return new Cdn20180510(config)
}

// 查询域名的证书
static async describeDomainCertificateInfoWithOptions(domainName: string) {
const client = Client.createClient()
const describeDomainCertificateInfoRequest = new $Cdn20180510.DescribeDomainCertificateInfoRequest({
domainName,
})
const runtime = new $Util.RuntimeOptions({})
try {
// 复制代码运行请自行打印 API 的返回值
return (await client.describeDomainCertificateInfoWithOptions(describeDomainCertificateInfoRequest, runtime)).body
} catch (error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message
console.error(error?.message)
// 诊断地址
console.error(error?.data?.['Recommend'])

}
}
/**
* 设置域名证书
*
* @author CaoMeiYouRen
* @date 2024-05-22
* @static
* @param domainName 域名
* @param certName 证书名称
* @param SSLPub 证书内容
* @param SSLPri 私钥内容
*/
static async setCdnDomainSSLCertificateWithOptions(domainName: string, certName: string, SSLPub: string, SSLPri: string) {
const client = Client.createClient()
const setCdnDomainSSLCertificateRequest = new $Cdn20180510.SetCdnDomainSSLCertificateRequest({
domainName,
certName,
certType: 'upload',
SSLProtocol: 'on',
SSLPub,
SSLPri,
})
const runtime = new $Util.RuntimeOptions({})
try {
// 复制代码运行请自行打印 API 的返回值
return (await client.setCdnDomainSSLCertificateWithOptions(setCdnDomainSSLCertificateRequest, runtime)).body
} catch (error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
console.error(error?.message)
// 诊断地址
console.error(error?.data?.['Recommend'])
}
}

}

这里通过设置 ALIBABA_CLOUD_ACCESS_KEY_IDALIBABA_CLOUD_ACCESS_KEY_SECRET 两个环境变量来进行调用 API,相对安全。

如果需要更安全的方式,可以考虑通过 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378664.html。

实现自动更新 SSL 证书逻辑

最后,再添加一些判断逻辑进去,就是实现了自动更新 SSL 证书,这里是在过期时间小于 31 天的时候就更新证书。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import path from 'path'
import dotenv from 'dotenv'
import dayjs from 'dayjs'
import fs from 'fs-extra'
import CdnClient from './apis/cdn' // './apis/cdn' 文件就是上面的示例。

dotenv.config({ path: ['.env.local', '.env'] })

// 更新 CDN 证书
async function updateCdnCertificate(domainName: string) {
// 域名证书位置
const CDN_SSL_DIR_PATH = process.env.CDN_SSL_DIR_PATH
const certificateInfo = await CdnClient.describeDomainCertificateInfoWithOptions(domainName)

const days = dayjs(certificateInfo.certInfos.certInfo[0].certExpireTime).diff(dayjs(), 'days')
console.log(`域名 ${domainName} 还有 ${days} 天过期`)

if (days < 31) { // 如果小于 31 天,更新证书
console.log(`域名 ${domainName} 的证书即将过期,正在更新中`)
const certName = `${domainName}-${dayjs().format('YYYY-MM-DD')}`
// 此处假定是 Let’s Encrypt 提供的域名证书,公钥是 fullchain.pem,私钥是 privkey.pem。其他类型的证书也类似
const SSLPub = await fs.readFile(path.join(CDN_SSL_DIR_PATH, 'fullchain.pem'), 'utf-8')
const SSLPri = await fs.readFile(path.join(CDN_SSL_DIR_PATH, 'privkey.pem'), 'utf-8')
const certificateResponseBody = await CdnClient.setCdnDomainSSLCertificateWithOptions(domainName, certName, SSLPub, SSLPri)
console.log(JSON.stringify(certificateResponseBody))
console.log
return
}
console.log(`域名 ${domainName} 的证书还未过期,跳过更新`)
}

updateDcdnCertificate('example.com')

最后,把这份代码设置为定时任务,每天执行一遍,即可实现自动更新 SSL 证书!

总结

除了更新 CDN 证书外,阿里云 OpenAPI 自然也可以更新 DCDN 域名证书、管理 DNS 解析、管理图床、管理 WAF 等。

总之,只要是阿里云上提供的服务,基本上都能通过阿里云 OpenAPI 来管理。对自动化来说,是极大的利好。

不过,需要注意的是,也要保管好 AccessKey IDAccessKey Secret,以免泄露,从而造成损失。

本文作者:草梅友仁
本文地址: https://blog.cmyr.ltd/archives/46e67068.html
版权声明:转载请注明出处!

坚持原创技术分享,您的支持将鼓励我继续创作!