update_route53_v1.sh 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/bin/sh
  2. # Distributed under the terms of the GNU General Public License (GPL) version 2.0
  3. # based on Yuval Adam's route53.sh found at https://github.com/yuvadm/route53-ddns/blob/master/route53.sh
  4. # 2017 Max Berger <max at berger dot name>
  5. [ -z "${CURL_SSL}" ] && write_log 14 "Amazon AWS Route53 communication require cURL with SSL support. Please install"
  6. [ -z "{$username}" ] && write_log 14 "Service section not configured correctly! Missing key as 'username'"
  7. [ -z "${password}" ] && write_log 14 "Service section not configured correctly! Missing secret as 'password'"
  8. [ -z "${domain}" ] && write_log 14 "Service section not configured correctly! Missing zone id as 'domain'"
  9. ENDPOINT="route53.amazonaws.com"
  10. RECORD_TTL=300
  11. RECORD_NAME="${lookup_host}."
  12. [ ${use_ipv6} -eq 0 ] && RECORD_TYPE="A"
  13. [ ${use_ipv6} -eq 1 ] && RECORD_TYPE="AAAA"
  14. RECORD_VALUE="${LOCAL_IP}"
  15. HOSTED_ZONE_ID="${domain}"
  16. API_PATH="/2013-04-01/hostedzone/${HOSTED_ZONE_ID}/rrset/"
  17. AWS_ACCESS_KEY_ID="${username}"
  18. AWS_SECRET_ACCESS_KEY="${password}"
  19. AWS_REGION='us-east-1'
  20. AWS_SERVICE='route53'
  21. hash() {
  22. msg="$1"
  23. echo -en "${msg}" | openssl dgst -sha256 | sed 's/^.* //'
  24. }
  25. sign_plain() {
  26. # Sign message using a plaintext key
  27. key="$1"
  28. msg="$2"
  29. echo -en "${msg}" | openssl dgst -hex -sha256 -hmac "${key}" | sed 's/^.* //'
  30. }
  31. sign() {
  32. # Sign message using a hex formatted key
  33. key="$1"
  34. msg="$2"
  35. echo -en "${msg}" | openssl dgst -hex -sha256 -mac HMAC -macopt "hexkey:${key}" | sed 's/^.* //'
  36. }
  37. request_body="<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
  38. <ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2013-04-01/\"> \
  39. <ChangeBatch> \
  40. <Changes> \
  41. <Change> \
  42. <Action>UPSERT</Action> \
  43. <ResourceRecordSet> \
  44. <Name>${RECORD_NAME}</Name> \
  45. <Type>${RECORD_TYPE}</Type> \
  46. <TTL>${RECORD_TTL}</TTL> \
  47. <ResourceRecords> \
  48. <ResourceRecord> \
  49. <Value>${RECORD_VALUE}</Value> \
  50. </ResourceRecord> \
  51. </ResourceRecords> \
  52. </ResourceRecordSet> \
  53. </Change> \
  54. </Changes> \
  55. </ChangeBatch> \
  56. </ChangeResourceRecordSetsRequest>"
  57. fulldate="$(date --utc +%Y%m%dT%H%M%SZ)"
  58. shortdate="$(date --utc +%Y%m%d)"
  59. signed_headers="host;x-amz-date"
  60. request_hash="$(hash "${request_body}")"
  61. canonical_request="POST\n${API_PATH}\n\nhost:route53.amazonaws.com\nx-amz-date:${fulldate}\n\n${signed_headers}\n${request_hash}"
  62. date_key="$(sign_plain "AWS4${AWS_SECRET_ACCESS_KEY}" "${shortdate}")"
  63. region_key="$(sign "${date_key}" ${AWS_REGION})"
  64. service_key="$(sign "${region_key}" ${AWS_SERVICE})"
  65. signing_key="$(sign "${service_key}" aws4_request)"
  66. credential="${shortdate}/${AWS_REGION}/${AWS_SERVICE}/aws4_request"
  67. sigmsg="AWS4-HMAC-SHA256\n${fulldate}\n${credential}\n$(hash "${canonical_request}")"
  68. signature="$(sign "${signing_key}" "${sigmsg}")"
  69. authorization="AWS4-HMAC-SHA256 Credential=${AWS_ACCESS_KEY_ID}/${credential}, SignedHeaders=${signed_headers}, Signature=${signature}"
  70. ANSWER="$(flock /tmp/$(basename -s .sh "$0").lock curl \
  71. -X "POST" \
  72. -H "Host: route53.amazonaws.com" \
  73. -H "X-Amz-Date: ${fulldate}" \
  74. -H "Authorization: ${authorization}" \
  75. -H "Content-Type: text/xml" \
  76. -d "$request_body" \
  77. "https://${ENDPOINT}${API_PATH}")"
  78. write_log 7 "${ANSWER}"
  79. echo "${ANSWER}" | grep -F "Error" >/dev/null && return 1
  80. echo "${ANSWER}" | grep -F "ChangeInfo" >/dev/null && return 0
  81. return 2