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.

348 lines
11 KiB

  1. #!/usr/bin/env sh
  2. # OpenStack Designate API plugin
  3. #
  4. # This requires you to have OpenStackClient and python-desginateclient
  5. # installed.
  6. #
  7. # You will require Keystone V3 credentials loaded into your environment, which
  8. # could be either password or v3applicationcredential type.
  9. #
  10. # Author: Andy Botting <andy@andybotting.com>
  11. ######## Public functions #####################
  12. # Usage: dns_openstack_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  13. dns_openstack_add() {
  14. fulldomain=$1
  15. txtvalue=$2
  16. _debug fulldomain "$fulldomain"
  17. _debug txtvalue "$txtvalue"
  18. _dns_openstack_credentials || return $?
  19. _dns_openstack_check_setup || return $?
  20. _dns_openstack_find_zone || return $?
  21. _dns_openstack_get_recordset || return $?
  22. _debug _recordset_id "$_recordset_id"
  23. if [ -n "$_recordset_id" ]; then
  24. _dns_openstack_get_records || return $?
  25. _debug _records "$_records"
  26. fi
  27. _dns_openstack_create_recordset || return $?
  28. }
  29. # Usage: dns_openstack_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
  30. # Remove the txt record after validation.
  31. dns_openstack_rm() {
  32. fulldomain=$1
  33. txtvalue=$2
  34. _debug fulldomain "$fulldomain"
  35. _debug txtvalue "$txtvalue"
  36. _dns_openstack_credentials || return $?
  37. _dns_openstack_check_setup || return $?
  38. _dns_openstack_find_zone || return $?
  39. _dns_openstack_get_recordset || return $?
  40. _debug _recordset_id "$_recordset_id"
  41. if [ -n "$_recordset_id" ]; then
  42. _dns_openstack_get_records || return $?
  43. _debug _records "$_records"
  44. fi
  45. _dns_openstack_delete_recordset || return $?
  46. }
  47. #################### Private functions below ##################################
  48. _dns_openstack_create_recordset() {
  49. if [ -z "$_recordset_id" ]; then
  50. _info "Creating a new recordset"
  51. if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record="$txtvalue" "$_zone_id" "$fulldomain."); then
  52. _err "No recordset ID found after create"
  53. return 1
  54. fi
  55. else
  56. _info "Updating existing recordset"
  57. # Build new list of --record=<rec> args for update
  58. _record_args="--record=$txtvalue"
  59. for _rec in $_records; do
  60. _record_args="$_record_args --record=$_rec"
  61. done
  62. # shellcheck disable=SC2086
  63. if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
  64. _err "Recordset update failed"
  65. return 1
  66. fi
  67. fi
  68. _max_retries=60
  69. _sleep_sec=5
  70. _retry_times=0
  71. while [ "$_retry_times" -lt "$_max_retries" ]; do
  72. _retry_times=$(_math "$_retry_times" + 1)
  73. _debug3 _retry_times "$_retry_times"
  74. _record_status=$(openstack recordset show -c status -f value "$_zone_id" "$_recordset_id")
  75. _info "Recordset status is $_record_status"
  76. if [ "$_record_status" = "ACTIVE" ]; then
  77. return 0
  78. elif [ "$_record_status" = "ERROR" ]; then
  79. return 1
  80. else
  81. _sleep $_sleep_sec
  82. fi
  83. done
  84. _err "Recordset failed to become ACTIVE"
  85. return 1
  86. }
  87. _dns_openstack_delete_recordset() {
  88. if [ "$_records" = "$txtvalue" ]; then
  89. _info "Only one record found, deleting recordset"
  90. if ! openstack recordset delete "$_zone_id" "$fulldomain." >/dev/null; then
  91. _err "Failed to delete recordset"
  92. return 1
  93. fi
  94. else
  95. _info "Found existing records, updating recordset"
  96. # Build new list of --record=<rec> args for update
  97. _record_args=""
  98. for _rec in $_records; do
  99. if [ "$_rec" = "$txtvalue" ]; then
  100. continue
  101. fi
  102. _record_args="$_record_args --record=$_rec"
  103. done
  104. # shellcheck disable=SC2086
  105. if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
  106. _err "Recordset update failed"
  107. return 1
  108. fi
  109. fi
  110. }
  111. _dns_openstack_get_root() {
  112. # Take the full fqdn and strip away pieces until we get an exact zone name
  113. # match. For example, _acme-challenge.something.domain.com might need to go
  114. # into something.domain.com or domain.com
  115. _zone_name=$1
  116. _zone_list=$2
  117. while [ "$_zone_name" != "" ]; do
  118. _zone_name="$(echo "$_zone_name" | sed 's/[^.]*\.*//')"
  119. echo "$_zone_list" | while read -r id name; do
  120. if _startswith "$_zone_name." "$name"; then
  121. echo "$id"
  122. fi
  123. done
  124. done | _head_n 1
  125. }
  126. _dns_openstack_find_zone() {
  127. if ! _zone_list="$(openstack zone list -c id -c name -f value)"; then
  128. _err "Can't list zones. Check your OpenStack credentials"
  129. return 1
  130. fi
  131. _debug _zone_list "$_zone_list"
  132. if ! _zone_id="$(_dns_openstack_get_root "$fulldomain" "$_zone_list")"; then
  133. _err "Can't find a matching zone. Check your OpenStack credentials"
  134. return 1
  135. fi
  136. _debug _zone_id "$_zone_id"
  137. }
  138. _dns_openstack_get_records() {
  139. if ! _records=$(openstack recordset show -c records -f value "$_zone_id" "$fulldomain."); then
  140. _err "Failed to get records"
  141. return 1
  142. fi
  143. return 0
  144. }
  145. _dns_openstack_get_recordset() {
  146. if ! _recordset_id=$(openstack recordset list -c id -f value --name "$fulldomain." "$_zone_id"); then
  147. _err "Failed to get recordset"
  148. return 1
  149. fi
  150. return 0
  151. }
  152. _dns_openstack_check_setup() {
  153. if ! _exists openstack; then
  154. _err "OpenStack client not found"
  155. return 1
  156. fi
  157. }
  158. _dns_openstack_credentials() {
  159. _debug "Check OpenStack credentials"
  160. # If we have OS_AUTH_URL already set in the environment, then assume we want
  161. # to use those, otherwise use stored credentials
  162. if [ -n "$OS_AUTH_URL" ]; then
  163. _debug "OS_AUTH_URL env var found, using environment"
  164. else
  165. _debug "OS_AUTH_URL not found, loading stored credentials"
  166. OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}"
  167. OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}"
  168. OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}"
  169. OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}"
  170. OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}"
  171. OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}"
  172. OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}"
  173. OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}"
  174. OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}"
  175. OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}"
  176. OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}"
  177. OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}"
  178. OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}"
  179. fi
  180. # Check each var and either save or clear it depending on whether its set.
  181. # The helps us clear out old vars in the case where a user may want
  182. # to switch between password and app creds
  183. _debug "OS_AUTH_URL" "$OS_AUTH_URL"
  184. if [ -n "$OS_AUTH_URL" ]; then
  185. export OS_AUTH_URL
  186. _saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL"
  187. else
  188. unset OS_AUTH_URL
  189. _clearaccountconf SAVED_OS_AUTH_URL
  190. fi
  191. _debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION"
  192. if [ -n "$OS_IDENTITY_API_VERSION" ]; then
  193. export OS_IDENTITY_API_VERSION
  194. _saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION"
  195. else
  196. unset OS_IDENTITY_API_VERSION
  197. _clearaccountconf SAVED_OS_IDENTITY_API_VERSION
  198. fi
  199. _debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE"
  200. if [ -n "$OS_AUTH_TYPE" ]; then
  201. export OS_AUTH_TYPE
  202. _saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE"
  203. else
  204. unset OS_AUTH_TYPE
  205. _clearaccountconf SAVED_OS_AUTH_TYPE
  206. fi
  207. _debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID"
  208. if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then
  209. export OS_APPLICATION_CREDENTIAL_ID
  210. _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID"
  211. else
  212. unset OS_APPLICATION_CREDENTIAL_ID
  213. _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID
  214. fi
  215. _secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET"
  216. if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
  217. export OS_APPLICATION_CREDENTIAL_SECRET
  218. _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET"
  219. else
  220. unset OS_APPLICATION_CREDENTIAL_SECRET
  221. _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET
  222. fi
  223. _debug "OS_USERNAME" "$OS_USERNAME"
  224. if [ -n "$OS_USERNAME" ]; then
  225. export OS_USERNAME
  226. _saveaccountconf_mutable OS_USERNAME "$OS_USERNAME"
  227. else
  228. unset OS_USERNAME
  229. _clearaccountconf SAVED_OS_USERNAME
  230. fi
  231. _secure_debug "OS_PASSWORD" "$OS_PASSWORD"
  232. if [ -n "$OS_PASSWORD" ]; then
  233. export OS_PASSWORD
  234. _saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD"
  235. else
  236. unset OS_PASSWORD
  237. _clearaccountconf SAVED_OS_PASSWORD
  238. fi
  239. _debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME"
  240. if [ -n "$OS_PROJECT_NAME" ]; then
  241. export OS_PROJECT_NAME
  242. _saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME"
  243. else
  244. unset OS_PROJECT_NAME
  245. _clearaccountconf SAVED_OS_PROJECT_NAME
  246. fi
  247. _debug "OS_PROJECT_ID" "$OS_PROJECT_ID"
  248. if [ -n "$OS_PROJECT_ID" ]; then
  249. export OS_PROJECT_ID
  250. _saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID"
  251. else
  252. unset OS_PROJECT_ID
  253. _clearaccountconf SAVED_OS_PROJECT_ID
  254. fi
  255. _debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME"
  256. if [ -n "$OS_USER_DOMAIN_NAME" ]; then
  257. export OS_USER_DOMAIN_NAME
  258. _saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME"
  259. else
  260. unset OS_USER_DOMAIN_NAME
  261. _clearaccountconf SAVED_OS_USER_DOMAIN_NAME
  262. fi
  263. _debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID"
  264. if [ -n "$OS_USER_DOMAIN_ID" ]; then
  265. export OS_USER_DOMAIN_ID
  266. _saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID"
  267. else
  268. unset OS_USER_DOMAIN_ID
  269. _clearaccountconf SAVED_OS_USER_DOMAIN_ID
  270. fi
  271. _debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME"
  272. if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then
  273. export OS_PROJECT_DOMAIN_NAME
  274. _saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME"
  275. else
  276. unset OS_PROJECT_DOMAIN_NAME
  277. _clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME
  278. fi
  279. _debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID"
  280. if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then
  281. export OS_PROJECT_DOMAIN_ID
  282. _saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID"
  283. else
  284. unset OS_PROJECT_DOMAIN_ID
  285. _clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID
  286. fi
  287. if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then
  288. # Application Credential auth
  289. if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
  290. _err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID"
  291. _err "and OS_APPLICATION_CREDENTIAL_SECRET must be set."
  292. _err "Please check your credentials and try again."
  293. return 1
  294. fi
  295. else
  296. # Password auth
  297. if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then
  298. _err "OpenStack username or password not found."
  299. _err "Please check your credentials and try again."
  300. return 1
  301. fi
  302. if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then
  303. _err "When using password authentication, OS_PROJECT_NAME or"
  304. _err "OS_PROJECT_ID must be set."
  305. _err "Please check your credentials and try again."
  306. return 1
  307. fi
  308. fi
  309. return 0
  310. }