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?
最重要的是 Let’s Encrypt 完全免费!
经过一通研究,笔者发现可以通过调用阿里云 OpenAPI 来实现自动化更新 SSL 证书,在此记录一下使用方式。
什么是阿里云 OpenAPI
OpenAPI 是指开放应用程序编程接口(Open Application Programming Interface)的简称。阿里云 OpenAPI 为开发者提供了一系列开放的应用程序接口,使您可以通过这些应用程序接口来方便的管理云上资源、数据和服务等内容。
详见:什么是 OpenAPI
总之,我们可以通过阿里云提供的 OpenAPI,来调用阿里云上的一系列接口,从而管理对应的资源和服务。
获取 AccessKey 在一切开始之前,需要先获取到 AccessKeyId 和 AccessKeySecret。
如果你现在点击 左上角的 AccessKey
管理的话,就会发现,阿里云提示你使用 子用户 AccessKey
在这里,出于安全起见,十分建议使用子用户 AccessKey !
可以前往 子用户管理 页面进行创建。
创建用户的时候记得选上 OpenAPI 调用访问
。
详见:创建 RAM 用户
记得及时保存 AccessKey ID
和 AccessKey Secret
,关掉之后就看不见了。
创建完子用户后还需要给子用户授权。
由于目前只需要管理 CDN,因此这里只给子用户授权 CDN 相关的权限即可。
因为还需要写入域名证书,故需要拿到写入权限,不要选择 只读
权限。
如何使用 OpenAPI 管理 CDN 在调用 OpenAPI 之前,显然需要先知道这个 API 是干什么的,有哪些入参,返回值又是什么样的。
查看 API 文档 所幸,阿里云提供了完善的 API 文档。
详见:阿里云 API 文档
经过一番搜索,就可以看到需要的 API 了。
DescribeDomainCertificateInfo - 查询域名证书信息
和 SetCdnDomainSSLCertificate - 设置CDN域名证书
。一个用于查看当前域名的证书信息,另一个用于设置证书。
详见:DescribeDomainCertificateInfo- 查询域名证书信息
SetCdnDomainSSLCertificate- 设置 CDN 域名证书
查看 API 代码调用示例 点击右上方的 去调用
即可调试相关接口。
参考:DescribeDomainCertificateInfo
在输入输入参数
后,即可点击左侧的 SDK 示例
查看具体的代码。
由于笔者比较喜欢用 TypeScript,所以此处的例子是用 TypeScript 实现的。
读者朋友也可以使用自己喜欢的编程语言进行调用。
阿里云提供了包括 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 { static createClient (): Cdn20180510 { const config = new $OpenApi.Config ({ accessKeyId : process.env ['ALIBABA_CLOUD_ACCESS_KEY_ID' ], accessKeySecret : process.env ['ALIBABA_CLOUD_ACCESS_KEY_SECRET' ], }) 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 { return (await client.describeDomainCertificateInfoWithOptions (describeDomainCertificateInfoRequest, runtime)).body } catch (error) { console .error (error?.message ) console .error (error?.data ?.['Recommend' ]) } } 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 { return (await client.setCdnDomainSSLCertificateWithOptions (setCdnDomainSSLCertificateRequest, runtime)).body } catch (error) { console .error (error?.message ) console .error (error?.data ?.['Recommend' ]) } } }
这里通过设置 ALIBABA_CLOUD_ACCESS_KEY_ID
和 ALIBABA_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' dotenv.config ({ path : ['.env.local' , '.env' ] }) 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 ) { console .log (`域名 ${domainName} 的证书即将过期,正在更新中` ) const certName = `${domainName} -${dayjs().format('YYYY-MM-DD' )} ` 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 ID
和 AccessKey Secret
,以免泄露,从而造成损失。
本文作者:草梅友仁 本文地址: https://blog.cmyr.ltd/archives/46e67068.html 版权声明:转载请注明出处!