You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
5.1 KiB

  1. #!/bin/bash
  2. #Here is the script to deploy the cert to your s3 bucket.
  3. #export S3_BUCKET=acme
  4. #export S3_REGION=eu-central-1
  5. #export AWS_ACCESS_KEY_ID=exampleid
  6. #export AWS_SECRET_ACCESS_KEY=examplekey
  7. # Checks to see if awscli present
  8. # If not, use curl + aws v4 signature to upload object
  9. # Make sure your keys have access to upload objects.
  10. # Also make sure your default region is correct, otherwise, override with $S3_REGION
  11. # IMPORTANT
  12. # If you're using acme.sh on a mac, make sure you have the latest version of openssl
  13. # Upgrade easily with homebrew: brew install openssl
  14. ######## Public functions #####################
  15. #domain keyfile certfile cafile fullchain
  16. s3_deploy() {
  17. _cdomain="$1"
  18. _ckey="$2"
  19. _ccert="$3"
  20. _cca="$4"
  21. _cfullchain="$5"
  22. if [ -z "$S3_BUCKET" ] ; then
  23. _err "You haven't specified the bucket name yet."
  24. _err "Please set it via export and try again."
  25. _err "e.g. export S3_BUCKET=acme"
  26. return 1
  27. fi
  28. if ! command -v aws; then
  29. _debug "AWS CLI not installed, defaulting to curl method"
  30. _aws_cli_installed=0
  31. else
  32. _debug "AWS CLI installed, defaulting ignoring curl method"
  33. _aws_cli_installed=1
  34. fi
  35. if [ "$_aws_cli_installed" -eq "0" ] && ([ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]); then
  36. _err "AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY not set."
  37. _err "Please set them via export, or use the aws-cli."
  38. return 1
  39. fi
  40. if [ -z "$S3_REGION" ]; then
  41. S3_REGION="us-east-1"
  42. fi
  43. # Save s3 options if it's succesful (First run case)
  44. _saveaccountconf S3_BUCKET "$S3_BUCKET"
  45. _saveaccountconf S3_REGION "$S3_REGION"
  46. _debug _cdomain "$_cdomain"
  47. _debug _ckey "$_ckey"
  48. _debug _ccert "$_ccert"
  49. _debug _cca "$_cca"
  50. _debug _cfullchain "$_cfullchain"
  51. _debug S3_BUCKET "$S3_BUCKET"
  52. _debug AWS_ACCESS_KEY_ID "$AWS_ACCESS_KEY_ID"
  53. _debug AWS_SECRET_ACCESS_KEY "$AWS_SECRET_ACCESS_KEY"
  54. _info "Deploying certificate to s3 bucket: $S3_BUCKET in $S3_REGION"
  55. if [ "$_aws_cli_installed" -eq "0" ]; then
  56. _debug "deploying with curl method"
  57. else
  58. _debug "deploying with aws cli method"
  59. fi
  60. # private
  61. _deploy_to_bucket $_ckey "$_cdomain/$_cdomain.key"
  62. # public
  63. _deploy_to_bucket $_ccert "$_cdomain/$_cdomain.cer"
  64. # ca
  65. _deploy_to_bucket $_cca "$_cdomain/ca.cer"
  66. # fullchain
  67. _deploy_to_bucket $_cfullchain "$_cdomain/fullchain.cer"
  68. return 0
  69. }
  70. #################### Private functions below ##################################
  71. _deploy_to_bucket() {
  72. if [ "$_aws_cli_installed" -eq "0" ]; then
  73. _deploy_with_curl $1 $2
  74. else
  75. _deploy_with_awscli $1 $2
  76. fi
  77. }
  78. _deploy_with_awscli() {
  79. file="$1"
  80. bucket="$S3_BUCKET"
  81. prefix="$2"
  82. region="$S3_REGION"
  83. aws s3 cp "$file" s3://"$bucket"/"$prefix" --region "$region"
  84. }
  85. _deploy_with_curl() {
  86. file="${1}"
  87. bucket="${S3_BUCKET}"
  88. prefix="${2}"
  89. region="${S3_REGION}"
  90. acl="private"
  91. timestamp="$(date -u "+%Y-%m-%d %H:%M:%S")"
  92. signed_headers="date;host;x-amz-acl;x-amz-content-sha256;x-amz-date"
  93. if [[ $(uname) == "Darwin" ]]; then
  94. iso_timestamp=$(date -ujf "%Y-%m-%d %H:%M:%S" "${timestamp}" "+%Y%m%dT%H%M%SZ")
  95. date_scope=$(date -ujf "%Y-%m-%d %H:%M:%S" "${timestamp}" "+%Y%m%d")
  96. date_header=$(date -ujf "%Y-%m-%d %H:%M:%S" "${timestamp}" "+%a, %d %h %Y %T %Z")
  97. else
  98. iso_timestamp=$(date -ud "${timestamp}" "+%Y%m%dT%H%M%SZ")
  99. date_scope=$(date -ud "${timestamp}" "+%Y%m%d")
  100. date_header=$(date -ud "${timestamp}" "+%a, %d %h %Y %T %Z")
  101. fi
  102. _info "Uploading $S3_BUCKET/$prefix"
  103. curl \
  104. -T "${file}" \
  105. -H "Authorization: AWS4-HMAC-SHA256 Credential=${AWS_ACCESS_KEY_ID}/${date_scope}/${region}/s3/aws4_request,SignedHeaders=${signed_headers},Signature=$(_signature)" \
  106. -H "Date:${date_header}" \
  107. -H "x-amz-acl:${acl}" \
  108. -H "x-amz-content-sha256:$(_payload_hash)" \
  109. -H "x-amz-date:${iso_timestamp}" \
  110. "https://${bucket}.s3.${region}.amazonaws.com/${prefix}"
  111. }
  112. _payload_hash() {
  113. local output=$(shasum -ba 256 "$file")
  114. echo "${output%% *}"
  115. }
  116. _canonical_request() {
  117. echo "PUT"
  118. echo "/${prefix}"
  119. echo ""
  120. echo "date:${date_header}"
  121. echo "host:${bucket}.s3.${region}.amazonaws.com"
  122. echo "x-amz-acl:${acl}"
  123. echo "x-amz-content-sha256:$(_payload_hash)"
  124. echo "x-amz-date:${iso_timestamp}"
  125. echo ""
  126. echo "${signed_headers}"
  127. printf "$(_payload_hash)"
  128. }
  129. _canonical_request_hash() {
  130. local output=$(_canonical_request | shasum -a 256)
  131. echo "${output%% *}"
  132. }
  133. _string_to_sign() {
  134. echo "AWS4-HMAC-SHA256"
  135. echo "${iso_timestamp}"
  136. echo "${date_scope}/${region}/s3/aws4_request"
  137. printf "$(_canonical_request_hash)"
  138. }
  139. _signature_key() {
  140. local secret=$(printf "AWS4${AWS_SECRET_ACCESS_KEY?}" | _hex_key)
  141. local date_key=$(printf ${date_scope} | _hmac_sha256 "${secret}" | _hex_key)
  142. local region_key=$(printf ${region} | _hmac_sha256 "${date_key}" | _hex_key)
  143. local service_key=$(printf "s3" | _hmac_sha256 "${region_key}" | _hex_key)
  144. printf "aws4_request" | _hmac_sha256 "${service_key}" | _hex_key
  145. }
  146. _hex_key() {
  147. hexdump -ve '1/1 "%.2x"'; echo
  148. }
  149. _hmac_sha256() {
  150. local hexkey=$1
  151. openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:${hexkey}
  152. }
  153. _signature() {
  154. _string_to_sign | _hmac_sha256 $(_signature_key) | _hex_key | sed "s/^.* //"
  155. }