Init commit
This commit is contained in:
commit
40a1679bda
|
@ -0,0 +1,12 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -0,0 +1,3 @@
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
.DS_Store
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
for c in openssl curl python3; do
|
||||||
|
if ! command -v ${c} > /dev/null; then
|
||||||
|
echo "${c}: command not found"
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
_AliAccessKeyId=$(printenv AliAccessKeyId)
|
||||||
|
_AliAccessKeySecret=$(printenv AliAccessKeySecret)
|
||||||
|
_Format=JSON
|
||||||
|
_SignatureMethod=HMAC-SHA1
|
||||||
|
_SignatureVersion=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=(
|
||||||
|
"Format"
|
||||||
|
"AccessKeyId"
|
||||||
|
"SignatureMethod"
|
||||||
|
"Timestamp"
|
||||||
|
"SignatureVersion"
|
||||||
|
"SignatureNonce"
|
||||||
|
"Version"
|
||||||
|
"Action"
|
||||||
|
)
|
||||||
|
# 公共查询参数值
|
||||||
|
local _ali_common_value=(
|
||||||
|
"$_Format"
|
||||||
|
"$_AliAccessKeyId"
|
||||||
|
"$_SignatureMethod"
|
||||||
|
"$(_ali_sign_timestamp)"
|
||||||
|
"$_SignatureVersion"
|
||||||
|
"$(_ali_sign_nonce)"
|
||||||
|
"$3"
|
||||||
|
"$4"
|
||||||
|
)
|
||||||
|
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[*]}"
|
||||||
|
read -r -a _ali_value <<< "${_ali_common_value[*]} ${_ali_custom_value[*]}"
|
||||||
|
local _http_host=$1 _http_method=$2
|
||||||
|
local _query_str=""
|
||||||
|
local _key _value
|
||||||
|
for (( i = 0; i < ${#_ali_key[@]}; ++i )); do
|
||||||
|
_key=${_ali_key[$i]}
|
||||||
|
_value=${_ali_value[$i]}
|
||||||
|
[[ $(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 _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 $?)
|
||||||
|
cat "$_curl_out" && echo
|
||||||
|
rm -f "$_curl_out"
|
||||||
|
[[ ${_result_code} -eq 200 ]] && return 0 || return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_ali_sign() {
|
||||||
|
local _http_method _str _query_str _sign_str
|
||||||
|
_http_method=$1
|
||||||
|
_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_sign_nonce() {
|
||||||
|
date "+%s%N"
|
||||||
|
}
|
||||||
|
|
||||||
|
_urlencode() {
|
||||||
|
echo -n "$1" | python3 -c "$_urlencode_pycode"
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019-2020 Zhong Lufan
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,65 @@
|
||||||
|
Aliyun OpenAPI Shell SDK
|
||||||
|
--
|
||||||
|
# 介绍
|
||||||
|
|
||||||
|
这是一个非官方的阿里云 OpenAPI Shell SDK,目的是方便 Shell 脚本直接调用阿里云 OpenAPI,主要是实现了自动计算签名。
|
||||||
|
|
||||||
|
虽然阿里云官方有 [AliyunCLI](https://github.com/aliyun/aliyun-cli),可以方便的在 Shell 环境下调用阿里云 OpenAPI。不过某些 API (比如 SSL 证书) 它并不支持,所以我就想写一个可能是最好用的 Shell SDK。
|
||||||
|
|
||||||
|
这个 SDK 理论上支持所有阿里云 RPC OpenAPI,RESTful OpenAPI 暂不支持,因为我暂时没用到,以后可能会考虑支持。
|
||||||
|
|
||||||
|
# 依赖
|
||||||
|
|
||||||
|
SDK 主要依赖于 `curl`, `openssl`, `python3`
|
||||||
|
|
||||||
|
其中 `python3` 用于 `urlencode`,因为纯 Shell 实现的 `urlencode` 可用性较低,索性就直接调用 Python 实现,内部的 Python 代码不兼容 Python2,只能运行于 Python3。
|
||||||
|
|
||||||
|
# 使用
|
||||||
|
|
||||||
|
使用起来非常简单,只需要在你的 Shell 脚本顶部导出`AliAccessKeyId` 和 `AliAccessKeySecret` 环境变量,然后引用 `AliyunOpenAPI.sh` 即可。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# 务必使用 export 导出
|
||||||
|
export AliAccessKeyId="<AliAccessKeyId>" # 此处替换为你的阿里云 AliAccessKeyId
|
||||||
|
export AliAccessKeySecret="<AliAccessKeySecret>" # 此处替换为你的阿里云 AliAccessKeySecret
|
||||||
|
|
||||||
|
. AliyunOpenAPI.sh
|
||||||
|
|
||||||
|
# 自定义 GET 参数的键值顺序要一一对应,而且不能包含空格。
|
||||||
|
# 自定义值支持自定义函数,如果你需要包含空格或者读取文件等操作,可以声明一个自定义函数,然后按照此格式填写:函数名(),就比如下面这样。
|
||||||
|
# SDK 在处理值的时候会自动执行自定义函数,但是如果自定义函数不存在则会导致获取值失败。
|
||||||
|
|
||||||
|
get_show_size() {
|
||||||
|
echo 50
|
||||||
|
}
|
||||||
|
|
||||||
|
# 自定义 GET 参数的键
|
||||||
|
ali_custom_key=(
|
||||||
|
"CurrentPage"
|
||||||
|
"ShowSize"
|
||||||
|
)
|
||||||
|
# 自定义 GET 参数的值
|
||||||
|
ali_custom_value=(
|
||||||
|
"1"
|
||||||
|
"get_show_size()"
|
||||||
|
)
|
||||||
|
# 获取阿里云 SSL 证书列表
|
||||||
|
# aliapi_rpc 的函数签名如下
|
||||||
|
# aliapi_rpc <host> <http_method> <api_version> <api_action> <api_custom_key[]> <api_custom_value[]>
|
||||||
|
aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DescribeUserCertificateList" "${ali_custom_key[*]}" "${ali_custom_value[*]}"
|
||||||
|
# 可以通过 $? 是否等于 0 来判断是否执行成功(HTTP CODE == 200)
|
||||||
|
# 执行成功返回 JSON 格式的结果,执行失败返回 HTTP CODE 或 curl 的退出代码。
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
# 执行成功
|
||||||
|
else
|
||||||
|
# 执行失败
|
||||||
|
fi
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
更多使用方法可以参考 `example` 下的示例
|
||||||
|
|
||||||
|
如果你有好的示例,欢迎提交 [PR](https://github.com/Hill-98/aliyun-openapi-shell-sdk/pulls)
|
||||||
|
|
||||||
|
如果你有问题 / BUG 要反馈,也欢迎提交 [Issue](https://github.com/Hill-98/aliyun-openapi-shell-sdk/issues)
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# 可用于 acme.sh 的 renewHook 脚本,可以自动更新阿里云 SSL 证书并更新对应 CDN 域名,然后删除对应域名旧的证书。
|
||||||
|
# 每次 API 的执行都会检测是否失败,如果失败,会中断脚本执行并返回自定义错误代码
|
||||||
|
|
||||||
|
# acme.sh 导出的环境变量
|
||||||
|
ENV_NAME=(
|
||||||
|
"CERT_PATH"
|
||||||
|
"CERT_KEY_PATH"
|
||||||
|
"CA_CERT_PATH"
|
||||||
|
"CERT_FULLCHAIN_PATH"
|
||||||
|
"Le_Domain"
|
||||||
|
)
|
||||||
|
# 检查环境变量是否存在
|
||||||
|
for value in "${ENV_NAME[@]}" ; do
|
||||||
|
printenv "$value" > /dev/null || exit 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# 获取证书自定义函数
|
||||||
|
get_cert() {
|
||||||
|
sed -e "/^$/d" "$(printenv CERT_FULLCHAIN_PATH)" # 使用 sed 删除掉证书文件的空行
|
||||||
|
}
|
||||||
|
# 获取密钥自定义函数
|
||||||
|
get_key() {
|
||||||
|
cat "$(printenv CERT_KEY_PATH)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 导出 AliAccessKeyId 和 AliAccessKeySecret
|
||||||
|
export AliAccessKeyId="<AliAccessKeyId>"
|
||||||
|
export AliAccessKeySecret="<AliAccessKeySecret>"
|
||||||
|
|
||||||
|
DOMAIN=$(printenv Le_Domain)
|
||||||
|
CERT_NAME="${DOMAIN}-$(date +%s)" # 证书名称
|
||||||
|
# 需要更新证书的 CDN 域名列表
|
||||||
|
DOMAIN_LIST=(
|
||||||
|
"example.example.com"
|
||||||
|
)
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. ../AliyunOpenAPI.sh
|
||||||
|
|
||||||
|
ali_custom_name=(
|
||||||
|
"CurrentPage"
|
||||||
|
"ShowSize"
|
||||||
|
)
|
||||||
|
# 获取第一页的 50 个结果,如果你的证书列表条目较多,可以考虑增加获取数量。
|
||||||
|
ali_custom_value=(
|
||||||
|
"1"
|
||||||
|
"50"
|
||||||
|
)
|
||||||
|
# 获取证书列表
|
||||||
|
result=$(aliapi_rpc "cas.aliyuncs.com" "GET" "2018-07-13" "DescribeUserCertificateList" "${ali_custom_name[*]}" "${ali_custom_value[*]}" || exit 101)
|
||||||
|
# 使用 jq 处理返回的 JSON 数据并提取出匹配当前证书域名的证书列表的 ID,用于稍后的删除旧证书操作。
|
||||||
|
cert_list=$(echo "$result" | jq -cr ".CertificateList|map(select(.common == \"${DOMAIN}\"))|map(.id)|.[]")
|
||||||
|
ali_custom_name=(
|
||||||
|
"Cert"
|
||||||
|
"Key"
|
||||||
|
"Name"
|
||||||
|
)
|
||||||
|
# 使用自定义函数获取证书和密钥,保证内容可以被安全的传递过去
|
||||||
|
ali_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
|
||||||
|
# 设置 CDN 域名列表使用新的证书
|
||||||
|
for domain in "${DOMAIN_LIST[@]}"; do
|
||||||
|
ali_custom_name=(
|
||||||
|
"DomainName"
|
||||||
|
"ServerCertificateStatus"
|
||||||
|
"CertName"
|
||||||
|
"CertType"
|
||||||
|
)
|
||||||
|
ali_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"
|
||||||
|
done
|
||||||
|
# 删除旧的证书
|
||||||
|
for id in ${cert_list}; do
|
||||||
|
ali_custom_name=(
|
||||||
|
"CertId"
|
||||||
|
)
|
||||||
|
ali_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"
|
||||||
|
done
|
Loading…
Reference in New Issue