This commit is contained in:
Zhong Lufan 2019-12-31 23:36:16 +08:00
parent 052bbe6dd0
commit 5151206472
No known key found for this signature in database
GPG Key ID: 30191289A9BD0B15
3 changed files with 58 additions and 51 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
* text=auto
*.sh text eol=lf

View File

@ -8,16 +8,16 @@ done
_AliAccessKeyId=$(printenv AliAccessKeyId)
_AliAccessKeySecret=$(printenv AliAccessKeySecret)
_Format=JSON
_SignatureMethod=HMAC-SHA1
_SignatureVersion=1.0
_ali_format_rpc=JSON
_ali_signature_method=HMAC-SHA1
_ali_signature_version=1.0
_urlencode_pycode="from sys import stdin;from urllib.parse import quote;print(quote(stdin.read(), '-_.~'))"
# aliapi_rpc <host> <http_method> <api_version> <api_action> <api_custom_key[]> <api_custom_value[]>
aliapi_rpc() {
[[ $# -lt 6 ]] && return 66
# 公共查询参数键
local _ali_common_key=(
local _api_common_key=(
"Format"
"AccessKeyId"
"SignatureMethod"
@ -29,20 +29,22 @@ aliapi_rpc() {
)
# 公共查询参数值
local _ali_common_value=(
"$_Format"
"$_ali_format_rpc"
"$_AliAccessKeyId"
"$_SignatureMethod"
"$(_ali_sign_timestamp)"
"$_SignatureVersion"
"$(_ali_sign_nonce)"
"$_ali_signature_method"
"$(_ali_timestamp_rpc)"
"$_ali_signature_version"
"$(_ali_signature_nonce)"
"$3"
"$4"
)
local _ali_custom_key=() _ali_custom_value=() # 自定义查询参数键值
# 自定义查询参数键值
local _ali_custom_key=() _ali_custom_value=()
read -r -a _ali_custom_key <<< "$5"
read -r -a _ali_custom_value <<< "$6"
local _ali_key=() _ali_value=() # 合并查询键值
read -r -a _ali_key <<< "${_ali_common_key[*]} ${_ali_custom_key[*]}"
# 合并查询键值
local _ali_key=() _ali_value=()
read -r -a _ali_key <<< "${_api_common_key[*]} ${_ali_custom_key[*]}"
read -r -a _ali_value <<< "${_ali_common_value[*]} ${_ali_custom_value[*]}"
local _http_host=$1 _http_method=$2
local _query_str=""
@ -50,13 +52,14 @@ aliapi_rpc() {
for (( i = 0; i < ${#_ali_key[@]}; ++i )); do
_key=${_ali_key[$i]}
_value=${_ali_value[$i]}
[[ $(grep -E "^.+\(\)$" <<< "$_value") == "$_value" ]] && _value=$(${_value//()/}) # 参数值如果是以 () 结束,代表需要执行命令获取值。
# 参数值如果是以 () 结束,代表需要执行命令获取值。
[[ $(grep -E "^.+\(\)$" <<< "$_value") == "$_value" ]] && _value=$(${_value//()/})
_value=$(_urlencode "$_value")
_query_str+="$_key=$_value&"
done
local _ali_signature
_ali_signature=$(_ali_sign "$_http_method" "$_query_str")
_query_str+="Signature=$(_urlencode "$_ali_signature")"
local _ali_signature_value
_ali_signature_value=$(_ali_signature_rpc "$_http_method" "$_query_str")
_query_str+="Signature=$(_urlencode "$_ali_signature_value")"
local _curl_out _result_code _http_url="https://${_http_host}/?${_query_str}"
_curl_out=$(mktemp)
_result_code=$(curl -L -s -X "$_http_method" -o "$_curl_out" --write-out "%{http_code}" "$_http_url" || echo $?)
@ -65,20 +68,20 @@ aliapi_rpc() {
[[ ${_result_code} -eq 200 ]] && return 0 || return 1
}
_ali_sign() {
local _http_method _str _query_str _sign_str
_http_method=$1
_ali_signature_rpc() {
local _http_method=$1 _str _query_str _sign_str
_str=$(echo -n "$2" | tr "&" "\n" | sort)
_query_str=$(echo -n "$_str" | tr "\n" "&")
_sign_str="${_http_method}&$(_urlencode "/")&$(_urlencode "$_query_str")"
echo -n "$_sign_str" | openssl sha1 -hmac "${_AliAccessKeySecret}&" -binary | openssl base64 -e
}
_ali_sign_timestamp() {
TZ="UTC" date "+%FT%TZ"
_ali_timestamp_rpc() {
# ISO8601 UTC
date -u +%FT%TZ
}
_ali_sign_nonce() {
_ali_signature_nonce() {
date "+%s%N"
}

View File

@ -1,13 +1,19 @@
#!/usr/bin/env bash
# https://help.aliyun.com/document_detail/126507.html
# https://help.aliyun.com/document_detail/106661.html
# CAS https://help.aliyun.com/document_detail/126507.html
# CDN https://help.aliyun.com/document_detail/106661.html
# 可用于 acme.sh 的 renewHook 脚本,可以自动更新阿里云 SSL 证书并更新对应 CDN 域名,然后删除对应域名的证书。
# 每次 API 执行都会检测是否失败,如果失败,会中断脚本执行并返回自定义错误代码
# 可配合 acme.sh 使用的 renewHook 脚本:自动将新证书上传至阿里云并更新对应 CDN 域名,然后删除对应域名的证书。
# 每次 API 执行都会检测是否失败,如果失败,会中断脚本执行并返回自定义错误代码
# acme.sh 导出的环境变量
ENV_NAME=(
# 导出 AliAccessKeyId 和 AliAccessKeySecret
export AliAccessKeyId="<AliAccessKeyId>"
export AliAccessKeySecret="<AliAccessKeySecret>"
# shellcheck disable=SC1091
. ../AliyunOpenAPI.sh
# acme.sh 执行 renewHook 时导出的环境变量列表
ACME_ENV_LIST=(
"CERT_PATH"
"CERT_KEY_PATH"
"CA_CERT_PATH"
@ -15,81 +21,77 @@ ENV_NAME=(
"Le_Domain"
)
# 检查环境变量是否存在
for value in "${ENV_NAME[@]}" ; do
for value in "${ACME_ENV_LIST[@]}" ; do
printenv "$value" > /dev/null || exit 1
done
# 获取证书自定义函数
get_cert() {
sed -e "/^$/d" "$(printenv CERT_FULLCHAIN_PATH)" # 使用 sed 删除掉证书文件的空行
# 使用 sed 删除掉证书文件的空行
sed -e "/^$/d" "$(printenv CERT_FULLCHAIN_PATH)"
}
# 获取密钥自定义函数
get_key() {
cat "$(printenv CERT_KEY_PATH)"
}
# 导出 AliAccessKeyId 和 AliAccessKeySecret
export AliAccessKeyId="<AliAccessKeyId>"
export AliAccessKeySecret="<AliAccessKeySecret>"
DOMAIN=$(printenv Le_Domain)
CERT_NAME="${DOMAIN}-$(date +%s)" # 证书名称
# 证书名称
CERT_NAME="${DOMAIN}-$(date +%s)"
# 需要更新证书的 CDN 域名列表
DOMAIN_LIST=(
"example.example.com"
)
# shellcheck disable=SC1091
. ../AliyunOpenAPI.sh
ali_custom_name=(
api_custom_key=(
"CurrentPage"
"ShowSize"
)
# 获取第一页的 50 个结果,如果你的证书列表条目较多,可以考虑增加获取数量。
ali_custom_value=(
api_custom_value=(
"1"
"50"
)
# 获取证书列表
result=$(aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DescribeUserCertificateList" "${ali_custom_name[*]}" "${ali_custom_value[*]}" || exit 101)
result=$(aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DescribeUserCertificateList" "${api_custom_key[*]}" "${api_custom_value[*]}" || exit 101)
# 使用 jq 处理返回的 JSON 数据并提取出匹配当前证书域名的证书列表的 ID用于稍后的删除旧证书操作。
cert_list=$(echo "$result" | jq -cr ".CertificateList|map(select(.common == \"${DOMAIN}\"))|map(.id)|.[]")
ali_custom_name=(
api_custom_key=(
"Cert"
"Key"
"Name"
)
# 使用自定义函数获取证书和密钥,保证内容可以被安全的传递过去
ali_custom_value=(
# 使用自定义函数获取证书和密钥,保证内容可以被完整的传递。
api_custom_value=(
"get_cert()"
"get_key()"
"$CERT_NAME"
)
# 上传新的证书
aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "CreateUserCertificate" "${ali_custom_name[*]}" "${ali_custom_value[*]}" || exit 102
aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "CreateUserCertificate" "${api_custom_key[*]}" "${api_custom_value[*]}" || exit 102
# 设置 CDN 域名列表使用新的证书
for domain in "${DOMAIN_LIST[@]}"; do
ali_custom_name=(
api_custom_key=(
"DomainName"
"ServerCertificateStatus"
"CertName"
"CertType"
)
ali_custom_value=(
api_custom_value=(
"$domain"
"on"
"$CERT_NAME"
"cas"
)
aliapi_rpc "cdn.aliyuncs.com" "GET" "2018-05-10" "SetDomainServerCertificate" "${ali_custom_name[*]}" "${ali_custom_value[*]}" || _exit 103 "Set cdn domain cert fail: $domain"
aliapi_rpc "cdn.aliyuncs.com" "GET" "2018-05-10" "SetDomainServerCertificate" "${api_custom_key[*]}" "${api_custom_value[*]}" || exit 103
done
# 删除旧的证书
for id in ${cert_list}; do
ali_custom_name=(
api_custom_key=(
"CertId"
)
ali_custom_value=(
api_custom_value=(
"$id"
)
aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DeleteUserCertificate" "${ali_custom_name[*]}" "${ali_custom_value[*]}" || _exit 104 "Delete old cert fail: $id"
aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DeleteUserCertificate" "${api_custom_key[*]}" "${api_custom_value[*]}" || exit 104
done