mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-05-08 22:12:44 +00:00
- Adds support for signing custom headers - Adds support for Amazon Certificate Manager calls - Place in a lib for use with DNS and deploy plugins
198 lines
4.8 KiB
Bash
198 lines
4.8 KiB
Bash
#!/usr/bin/env sh
|
|
|
|
# usage: _aws <svc> <svcargs...>
|
|
#
|
|
# services:
|
|
#
|
|
# ACM: _aws acm <rpc> <region> [json]
|
|
# _aws acm ListCertificates us-east-1 '{"MaxItems": 2}'
|
|
|
|
_aws() {
|
|
_svc="$1" # _args=...
|
|
shift
|
|
if ! _aws_auth; then
|
|
return 255
|
|
fi
|
|
n="$(printf '\nn')" n="${n%n}"
|
|
"_aws_svc_$_svc" "$@"
|
|
}
|
|
|
|
# private
|
|
|
|
# services
|
|
|
|
_aws_svc_acm() {
|
|
_rpc="$1" _region="$2" _json="$3"
|
|
|
|
_empty='{}'
|
|
_rpc="x-amz-target:CertificateManager.$_rpc"
|
|
_type='content-type:application/x-amz-json-1.1'
|
|
|
|
_aws_wrap '"__type":' \
|
|
POST "acm.$_region.amazonaws.com" '/' '' "$_region/acm" \
|
|
"$_rpc$n$_type" "${_json:-$_empty}"
|
|
}
|
|
|
|
# core
|
|
|
|
_aws_wrap() {
|
|
_check="$1" # _args=...
|
|
shift
|
|
_resp="$(_aws_req4 "$@")"
|
|
_ret="$?"
|
|
_debug2 _resp "$_resp"
|
|
if [ "$_ret" -eq 0 ] && _contains "$_resp" "$_check"; then
|
|
_err "Response error: $_resp"
|
|
return 1
|
|
fi
|
|
printf %s "$_resp"
|
|
return "$_ret"
|
|
}
|
|
|
|
_aws_req4() {
|
|
_verb="$1" _host="$2" _path="$3" _query="$4" _svc="$5" _hdrs="$6" _data="$7"
|
|
|
|
_debug _verb "$_verb"
|
|
_debug _host "$_host"
|
|
_debug _path "$_path"
|
|
_debug _query "$_query"
|
|
_debug _svc "$_svc"
|
|
_debug _hdrs "$_hdrs"
|
|
_debug _data "$_data"
|
|
|
|
_date="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
_debug2 _date "$_date"
|
|
|
|
_hdrs="host:$_host${n}x-amz-date:$_date$n$_hdrs"
|
|
if [ "$AWS_SESSION_TOKEN" ]; then
|
|
_hdrs="$_hdrs${n}x-amz-security-token:$AWS_SESSION_TOKEN"
|
|
fi
|
|
_hdrs="$(printf %s "$_hdrs" | sort | sed '/^$/d')$n"
|
|
_debug2 _hdrs "$_hdrs"
|
|
|
|
_keys="$(
|
|
printf %s "$_hdrs" | while read -r _hdr; do
|
|
printf '%s\n' "${_hdr%%:*}"
|
|
done | paste -sd ';'
|
|
)"
|
|
_debug2 _keys "$_keys"
|
|
|
|
_scope="$(printf %s "$_date" | cut -c 1-8)/$_svc/aws4_request"
|
|
_debug2 _scope "$_scope"
|
|
|
|
_hash='sha256'
|
|
_debug3 _hash "$_hash"
|
|
_algo='AWS4-HMAC-SHA256'
|
|
_debug3 _algo "$_algo"
|
|
|
|
_bdy="$(printf %s "$_data" | _digest "$_hash" hex)"
|
|
_debug2 _bdy "$_bdy"
|
|
_req="$_verb$n$_path$n$_query$n$_hdrs$n$_keys$n$_bdy"
|
|
_debug2 _req "$_req"
|
|
_req="$(printf %s "$_req" | _digest "$_hash" hex)"
|
|
_debug2 _req "$_req"
|
|
_str="$_algo$n$_date$n$_scope$n$_req"
|
|
_debug2 _str "$_str"
|
|
|
|
_sig="$(printf %s "AWS4$AWS_SECRET_ACCESS_KEY" | _hex_dump | tr -d ' ')"
|
|
_secure_debug2 _sig "$_sig"
|
|
for _step in $(printf %s "$_scope" | tr '/' ' ') "$_str"; do
|
|
_debug2 _step "$_step"
|
|
_sig="$(printf %s "$_step" | _hmac "$_hash" "$_sig" hex)"
|
|
_debug2 _sig "$_sig"
|
|
done
|
|
|
|
_cred="$AWS_ACCESS_KEY_ID/$_scope"
|
|
_auth="$_algo Credential=$_cred, SignedHeaders=$_keys, Signature=$_sig"
|
|
_debug2 _auth "$_auth"
|
|
|
|
_url="https://$_host$_path"
|
|
if [ "$_query" ]; then
|
|
_url="$_url?$_query"
|
|
fi
|
|
|
|
unset i
|
|
while read -r _line; do
|
|
i=$((i + 1))
|
|
eval "_H$i=\"\$_line\"; _debug2 _H$i \"\$_H$i\""
|
|
done <<-END
|
|
authorization:$_auth
|
|
$_hdrs
|
|
END
|
|
|
|
case "$(printf %s "$_verb" | tr '[:upper:]' '[:lower:]')" in
|
|
get) _get "$_url" ;;
|
|
post) _post "$_data" "$_url" ;;
|
|
*) _err '_aws only supports get and post' ;;
|
|
esac
|
|
}
|
|
|
|
# credentials
|
|
|
|
_aws_auth() {
|
|
_aws_auth_environment || _aws_auth_container_role || _aws_auth_instance_role
|
|
}
|
|
|
|
_aws_auth_environment() {
|
|
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-$(_readaccountconf_mutable AWS_ACCESS_KEY_ID)}"
|
|
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-$(_readaccountconf_mutable AWS_SECRET_ACCESS_KEY)}"
|
|
if [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then
|
|
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
|
|
return 1
|
|
fi
|
|
if [ -z "$_aws_using_role" ]; then
|
|
_saveaccountconf_mutable AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
|
|
_saveaccountconf_mutable AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
|
|
fi
|
|
}
|
|
|
|
_aws_auth_container_role() {
|
|
# automatically set if running inside ECS
|
|
if [ -z "$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" ]; then
|
|
_debug 'no ECS environment variable detected'
|
|
return 1
|
|
fi
|
|
_aws_auth_metadata "169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
|
|
}
|
|
|
|
_aws_auth_instance_role() {
|
|
_url='http://169.254.169.254/latest/meta-data/iam/security-credentials/'
|
|
_debug _url "$_url"
|
|
_aws_role=$(_get "$_url" '' 1)
|
|
if [ "$?" -gt 0 ]; then
|
|
_debug 'unable to fetch IAM role from instance metadata'
|
|
return 1
|
|
fi
|
|
_debug _aws_role "$_aws_role"
|
|
_aws_auth_metadata "$_url$_aws_role"
|
|
}
|
|
|
|
_aws_auth_metadata() {
|
|
_url="$1"
|
|
|
|
_aws_creds="$(
|
|
_get "$_url" "" 1 |
|
|
_normalizeJson |
|
|
tr '{,}' '\n' |
|
|
while read -r _line; do
|
|
_key="$(printf %s "${_line%%:*}" | tr -d '"')" _value="${_line#*:}"
|
|
_debug3 _key "$_key"
|
|
_secure_debug3 _value "$_value"
|
|
case "$_key" in
|
|
AccessKeyId) printf '%s\n' "AWS_ACCESS_KEY_ID=$_value" ;;
|
|
SecretAccessKey) printf '%s\n' "AWS_SECRET_ACCESS_KEY=$_value" ;;
|
|
Token) printf '%s\n' "AWS_SESSION_TOKEN=$_value" ;;
|
|
esac
|
|
done |
|
|
paste -sd' ' -
|
|
)"
|
|
_secure_debug _aws_creds "$_aws_creds"
|
|
|
|
if [ -z "$_aws_creds" ]; then
|
|
return 1
|
|
fi
|
|
|
|
eval "$_aws_creds"
|
|
_aws_using_role=true
|
|
}
|