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.

265 lines
6.4 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. #!/usr/bin/env sh
  2. #OPNsense Bind API
  3. #https://docs.opnsense.org/development/api.html
  4. #
  5. #OPNs_Host="opnsense.example.com"
  6. #OPNs_Port="443"
  7. #OPNs_Key="qocfU9RSbt8vTIBcnW8bPqCrpfAHMDvj5OzadE7Str+rbjyCyk7u6yMrSCHtBXabgDDXx/dY0POUp7ZA"
  8. #OPNs_Token="pZEQ+3ce8dDlfBBdg3N8EpqpF5I1MhFqdxX06le6Gl8YzyQvYCfCzNaFX9O9+IOSyAs7X71fwdRiZ+Lv"
  9. #OPNs_Api_Insecure=0 # Set 1 for insecure and 0 for secure -> difference is whether ssl cert is checked for validity (0) or whether it is just accepted (1)
  10. ######## Public functions #####################
  11. #Usage: add _acme-challenge.www.domain.com "123456789ABCDEF0000000000000000000000000000000000000"
  12. #fulldomain
  13. #txtvalue
  14. dns_opnsense_add() {
  15. fulldomain=$1
  16. txtvalue=$2
  17. _opns_check_auth || return 1
  18. if ! set_record "$fulldomain" "$txtvalue"; then
  19. return 1
  20. fi
  21. return 0
  22. }
  23. #fulldomain
  24. dns_opnsense_rm() {
  25. fulldomain=$1
  26. txtvalue=$2
  27. _opns_check_auth || return 1
  28. if ! rm_record "$fulldomain" "$txtvalue"; then
  29. return 1
  30. fi
  31. return 0
  32. }
  33. set_record() {
  34. _info "Adding record"
  35. fulldomain=$1
  36. new_challenge=$2
  37. _debug "Detect root zone"
  38. if ! _get_root "$fulldomain"; then
  39. _err "invalid domain"
  40. return 1
  41. fi
  42. _debug _domain "$_domain"
  43. _debug _host "$_host"
  44. _debug _domainid "$_domainid"
  45. _return_str=""
  46. _record_string=""
  47. _build_record_string "$_domainid" "$_host" "$new_challenge"
  48. _uuid=""
  49. if _existingchallenge "$_domain" "$_host" "$new_challenge"; then
  50. # Update
  51. if _opns_rest "POST" "/record/setRecord/${_uuid}" "$_record_string"; then
  52. _return_str="$response"
  53. else
  54. return 1
  55. fi
  56. else
  57. #create
  58. if _opns_rest "POST" "/record/addRecord" "$_record_string"; then
  59. _return_str="$response"
  60. else
  61. return 1
  62. fi
  63. fi
  64. if echo "$_return_str" | _egrep_o "\"result\":\"saved\"" >/dev/null; then
  65. _opns_rest "POST" "/service/reconfigure" "{}"
  66. _debug "Record created"
  67. else
  68. _err "Error createing record $_record_string"
  69. return 1
  70. fi
  71. return 0
  72. }
  73. rm_record() {
  74. _info "Remove record"
  75. fulldomain=$1
  76. new_challenge="$2"
  77. _debug "Detect root zone"
  78. if ! _get_root "$fulldomain"; then
  79. _err "invalid domain"
  80. return 1
  81. fi
  82. _debug _domain "$_domain"
  83. _debug _host "$_host"
  84. _debug _domainid "$_domainid"
  85. _uuid=""
  86. if _existingchallenge "$_domain" "$_host" "$new_challenge"; then
  87. # Delete
  88. if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then
  89. if echo "$_return_str" | _egrep_o "\"result\":\"deleted\"" >/dev/null; then
  90. _opns_rest "POST" "/service/reconfigure" "{}"
  91. _debug "Record deleted"
  92. else
  93. _err "Error delteting record $fulldomain"
  94. return 1
  95. fi
  96. else
  97. _err "Error delteting record $fulldomain"
  98. return 1
  99. fi
  100. else
  101. _info "Record not found, nothing to remove"
  102. fi
  103. return 0
  104. }
  105. #################### Private functions below ##################################
  106. #_acme-challenge.www.domain.com
  107. #returns
  108. # _domainid=domid
  109. #_domain=domain.com
  110. _get_root() {
  111. domain=$1
  112. i=2
  113. p=1
  114. if _opns_rest "GET" "/domain/get"; then
  115. _domain_response="$response"
  116. else
  117. return 1
  118. fi
  119. while true; do
  120. h=$(printf "%s" "$domain" | cut -d . -f $i-100)
  121. if [ -z "$h" ]; then
  122. #not valid
  123. return 1
  124. fi
  125. _debug h "$h"
  126. id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":\"[^\"]*\",\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
  127. if [ -n "$id" ]; then
  128. _debug id "$id"
  129. _host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
  130. _domain="${h}"
  131. _domainid="${id}"
  132. return 0
  133. fi
  134. p=$i
  135. i=$(_math $i + 1)
  136. done
  137. _debug "$domain not found"
  138. return 1
  139. }
  140. _opns_rest() {
  141. method=$1
  142. ep=$2
  143. data=$3
  144. #Percent encode user and token
  145. key=$(echo "$OPNs_Key" | tr -d "\n\r" | _url_encode)
  146. token=$(echo "$OPNs_Token" | tr -d "\n\r" | _url_encode)
  147. opnsense_url="https://${key}:${token}@${OPNs_Host}:${OPNs_Port}/api/bind${ep}"
  148. export _H1="Content-Type: application/json"
  149. if [ ! "$method" = "GET" ]; then
  150. _debug data "$data"
  151. export _H1="Content-Type: application/json"
  152. response="$(_post "$data" "$opnsense_url" "" "$method")"
  153. else
  154. export _H1=""
  155. response="$(_get "$opnsense_url")"
  156. fi
  157. if [ "$?" != "0" ]; then
  158. _err "error $ep"
  159. return 1
  160. fi
  161. _debug2 response "$response"
  162. return 0
  163. }
  164. _build_record_string() {
  165. _record_string="{\"record\":{\"enabled\":\"1\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"}}"
  166. }
  167. _existingchallenge() {
  168. if _opns_rest "GET" "/record/searchRecord"; then
  169. _record_response="$response"
  170. else
  171. return 1
  172. fi
  173. _uuid=""
  174. _uuid=$(echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2)
  175. if [ -n "$_uuid" ]; then
  176. _debug uuid "$_uuid"
  177. return 0
  178. fi
  179. _debug "${2}.$1{1} record not found"
  180. return 1
  181. }
  182. _opns_check_auth() {
  183. OPNs_Host="${OPNs_Host:-$(_readaccountconf_mutable OPNs_Host)}"
  184. OPNs_Port="${OPNs_Port:-$(_readaccountconf_mutable OPNs_Port)}"
  185. OPNs_Key="${OPNs_Key:-$(_readaccountconf_mutable OPNs_Key)}"
  186. OPNs_Token="${OPNs_Token:-$(_readaccountconf_mutable OPNs_Token)}"
  187. OPNs_Api_Insecure="${OPNs_Api_Insecure:-$(_readaccountconf_mutable OPNs_Api_Insecure)}"
  188. if [ -z "$OPNs_Host" ]; then
  189. OPNs_Host="localhost"
  190. _err "You don't specify OPNsense address."
  191. return 1
  192. else
  193. _saveaccountconf_mutable OPNs_Host "$OPNs_Host"
  194. fi
  195. if [ -z "$OPNs_Port" ]; then
  196. OPNs_Port="443"
  197. else
  198. _saveaccountconf_mutable OPNs_Port "$OPNs_Port"
  199. fi
  200. if [ -z "$OPNs_Api_Insecure" ]; then
  201. OPNs_Api_Insecure="0"
  202. else
  203. #save the api addr and key to the account conf file.
  204. _saveaccountconf_mutable OPNs_Api_Insecure "$OPNs_Api_Insecure"
  205. fi
  206. export HTTPS_INSECURE="${OPNs_Api_Insecure}"
  207. if [ -z "$OPNs_Key" ]; then
  208. OPNs_Key=""
  209. _err "You don't specify OPNsense api key id."
  210. _err "Please set you OPNs_Key and try again."
  211. return 1
  212. else
  213. _saveaccountconf_mutable OPNs_Key "$OPNs_Key"
  214. fi
  215. if [ -z "$OPNs_Token" ]; then
  216. OPNs_Token=""
  217. _err "You don't specify OPNsense token."
  218. _err "Please create you OPNs_Token and try again."
  219. return 1
  220. else
  221. _saveaccountconf_mutable OPNs_Token "$OPNs_Token"
  222. fi
  223. if ! _opns_rest "GET" "/general/get"; then
  224. _err "Can't Access OPNsense"
  225. return 1
  226. fi
  227. return 0
  228. }