3 # OpenStack Designate API plugin
5 # This requires you to have OpenStackClient and python-desginateclient
8 # You will require Keystone V3 credentials loaded into your environment, which
9 # could be either password or v3applicationcredential type.
11 # Author: Andy Botting <andy@andybotting.com>
13 ######## Public functions #####################
15 # Usage: dns_openstack_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
19 _debug fulldomain
"$fulldomain"
20 _debug txtvalue
"$txtvalue"
22 _dns_openstack_credentials ||
return $?
23 _dns_openstack_check_setup ||
return $?
24 _dns_openstack_find_zone ||
return $?
25 _dns_openstack_get_recordset ||
return $?
26 _debug _recordset_id
"$_recordset_id"
27 if [ -n "$_recordset_id" ]; then
28 _dns_openstack_get_records ||
return $?
29 _debug _records
"$_records"
31 _dns_openstack_create_recordset ||
return $?
34 # Usage: dns_openstack_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
35 # Remove the txt record after validation.
39 _debug fulldomain
"$fulldomain"
40 _debug txtvalue
"$txtvalue"
42 _dns_openstack_credentials ||
return $?
43 _dns_openstack_check_setup ||
return $?
44 _dns_openstack_find_zone ||
return $?
45 _dns_openstack_get_recordset ||
return $?
46 _debug _recordset_id
"$_recordset_id"
47 if [ -n "$_recordset_id" ]; then
48 _dns_openstack_get_records ||
return $?
49 _debug _records
"$_records"
51 _dns_openstack_delete_recordset ||
return $?
54 #################### Private functions below ##################################
56 _dns_openstack_create_recordset
() {
58 if [ -z "$_recordset_id" ]; then
59 _info
"Creating a new recordset"
60 if ! _recordset_id
=$
(openstack recordset create
-c id
-f value
--type TXT
--record "$txtvalue" "$_zone_id" "$fulldomain."); then
61 _err
"No recordset ID found after create"
65 _info
"Updating existing recordset"
66 # Build new list of --record <rec> args for update
67 _record_args
="--record $txtvalue"
68 for _rec
in $_records; do
69 _record_args
="$_record_args --record $_rec"
71 # shellcheck disable=SC2086
72 if ! _recordset_id
=$
(openstack recordset
set -c id
-f value
$_record_args "$_zone_id" "$fulldomain."); then
73 _err
"Recordset update failed"
81 while [ "$_retry_times" -lt "$_max_retries" ]; do
82 _retry_times
=$
(_math
"$_retry_times" + 1)
83 _debug3 _retry_times
"$_retry_times"
85 _record_status
=$
(openstack recordset show
-c status
-f value
"$_zone_id" "$_recordset_id")
86 _info
"Recordset status is $_record_status"
87 if [ "$_record_status" = "ACTIVE" ]; then
89 elif [ "$_record_status" = "ERROR" ]; then
96 _err
"Recordset failed to become ACTIVE"
100 _dns_openstack_delete_recordset
() {
102 if [ "$_records" = "$txtvalue" ]; then
103 _info
"Only one record found, deleting recordset"
104 if ! openstack recordset delete
"$_zone_id" "$fulldomain." >/dev
/null
; then
105 _err
"Failed to delete recordset"
109 _info
"Found existing records, updating recordset"
110 # Build new list of --record <rec> args for update
112 for _rec
in $_records; do
113 if [ "$_rec" = "$txtvalue" ]; then
116 _record_args
="$_record_args --record $_rec"
118 # shellcheck disable=SC2086
119 if ! openstack recordset
set -c id
-f value
$_record_args "$_zone_id" "$fulldomain." >/dev
/null
; then
120 _err
"Recordset update failed"
126 _dns_openstack_get_root
() {
127 # Take the full fqdn and strip away pieces until we get an exact zone name
128 # match. For example, _acme-challenge.something.domain.com might need to go
129 # into something.domain.com or domain.com
132 while [ "$_zone_name" != "" ]; do
133 _zone_name
="$(echo "$_zone_name" | sed 's/[^.]*\.*//')"
134 echo "$_zone_list" |
while read -r id name
; do
135 if _startswith
"$_zone_name." "$name"; then
142 _dns_openstack_find_zone
() {
143 if ! _zone_list
="$(openstack zone list -c id -c name -f value)"; then
144 _err
"Can't list zones. Check your OpenStack credentials"
147 _debug _zone_list
"$_zone_list"
149 if ! _zone_id
="$(_dns_openstack_get_root "$fulldomain" "$_zone_list")"; then
150 _err
"Can't find a matching zone. Check your OpenStack credentials"
153 _debug _zone_id
"$_zone_id"
156 _dns_openstack_get_records
() {
157 if ! _records
=$
(openstack recordset show
-c records
-f value
"$_zone_id" "$fulldomain."); then
158 _err
"Failed to get records"
164 _dns_openstack_get_recordset
() {
165 if ! _recordset_id
=$
(openstack recordset list
-c id
-f value
--name "$fulldomain." "$_zone_id"); then
166 _err
"Failed to get recordset"
172 _dns_openstack_check_setup
() {
173 if ! _exists openstack
; then
174 _err
"OpenStack client not found"
179 _dns_openstack_credentials
() {
180 _debug
"Check OpenStack credentials"
182 # If we have OS_AUTH_URL already set in the environment, then assume we want
183 # to use those, otherwise use stored credentials
184 if [ -n "$OS_AUTH_URL" ]; then
185 _debug
"OS_AUTH_URL env var found, using environment"
187 _debug
"OS_AUTH_URL not found, loading stored credentials"
188 OS_AUTH_URL
="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}"
189 OS_IDENTITY_API_VERSION
="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}"
190 OS_AUTH_TYPE
="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}"
191 OS_APPLICATION_CREDENTIAL_ID
="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}"
192 OS_APPLICATION_CREDENTIAL_SECRET
="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}"
193 OS_USERNAME
="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}"
194 OS_PASSWORD
="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}"
195 OS_PROJECT_NAME
="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}"
196 OS_PROJECT_ID
="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}"
197 OS_USER_DOMAIN_NAME
="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}"
198 OS_USER_DOMAIN_ID
="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}"
199 OS_PROJECT_DOMAIN_NAME
="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}"
200 OS_PROJECT_DOMAIN_ID
="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}"
203 # Check each var and either save or clear it depending on whether its set.
204 # The helps us clear out old vars in the case where a user may want
205 # to switch between password and app creds
206 _debug
"OS_AUTH_URL" "$OS_AUTH_URL"
207 if [ -n "$OS_AUTH_URL" ]; then
209 _saveaccountconf_mutable OS_AUTH_URL
"$OS_AUTH_URL"
212 _clearaccountconf SAVED_OS_AUTH_URL
215 _debug
"OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION"
216 if [ -n "$OS_IDENTITY_API_VERSION" ]; then
217 export OS_IDENTITY_API_VERSION
218 _saveaccountconf_mutable OS_IDENTITY_API_VERSION
"$OS_IDENTITY_API_VERSION"
220 unset OS_IDENTITY_API_VERSION
221 _clearaccountconf SAVED_OS_IDENTITY_API_VERSION
224 _debug
"OS_AUTH_TYPE" "$OS_AUTH_TYPE"
225 if [ -n "$OS_AUTH_TYPE" ]; then
227 _saveaccountconf_mutable OS_AUTH_TYPE
"$OS_AUTH_TYPE"
230 _clearaccountconf SAVED_OS_AUTH_TYPE
233 _debug
"OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID"
234 if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then
235 export OS_APPLICATION_CREDENTIAL_ID
236 _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID
"$OS_APPLICATION_CREDENTIAL_ID"
238 unset OS_APPLICATION_CREDENTIAL_ID
239 _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID
242 _secure_debug
"OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET"
243 if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
244 export OS_APPLICATION_CREDENTIAL_SECRET
245 _saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET
"$OS_APPLICATION_CREDENTIAL_SECRET"
247 unset OS_APPLICATION_CREDENTIAL_SECRET
248 _clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET
251 _debug
"OS_USERNAME" "$OS_USERNAME"
252 if [ -n "$OS_USERNAME" ]; then
254 _saveaccountconf_mutable OS_USERNAME
"$OS_USERNAME"
257 _clearaccountconf SAVED_OS_USERNAME
260 _secure_debug
"OS_PASSWORD" "$OS_PASSWORD"
261 if [ -n "$OS_PASSWORD" ]; then
263 _saveaccountconf_mutable OS_PASSWORD
"$OS_PASSWORD"
266 _clearaccountconf SAVED_OS_PASSWORD
269 _debug
"OS_PROJECT_NAME" "$OS_PROJECT_NAME"
270 if [ -n "$OS_PROJECT_NAME" ]; then
271 export OS_PROJECT_NAME
272 _saveaccountconf_mutable OS_PROJECT_NAME
"$OS_PROJECT_NAME"
274 unset OS_PROJECT_NAME
275 _clearaccountconf SAVED_OS_PROJECT_NAME
278 _debug
"OS_PROJECT_ID" "$OS_PROJECT_ID"
279 if [ -n "$OS_PROJECT_ID" ]; then
281 _saveaccountconf_mutable OS_PROJECT_ID
"$OS_PROJECT_ID"
284 _clearaccountconf SAVED_OS_PROJECT_ID
287 _debug
"OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME"
288 if [ -n "$OS_USER_DOMAIN_NAME" ]; then
289 export OS_USER_DOMAIN_NAME
290 _saveaccountconf_mutable OS_USER_DOMAIN_NAME
"$OS_USER_DOMAIN_NAME"
292 unset OS_USER_DOMAIN_NAME
293 _clearaccountconf SAVED_OS_USER_DOMAIN_NAME
296 _debug
"OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID"
297 if [ -n "$OS_USER_DOMAIN_ID" ]; then
298 export OS_USER_DOMAIN_ID
299 _saveaccountconf_mutable OS_USER_DOMAIN_ID
"$OS_USER_DOMAIN_ID"
301 unset OS_USER_DOMAIN_ID
302 _clearaccountconf SAVED_OS_USER_DOMAIN_ID
305 _debug
"OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME"
306 if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then
307 export OS_PROJECT_DOMAIN_NAME
308 _saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME
"$OS_PROJECT_DOMAIN_NAME"
310 unset OS_PROJECT_DOMAIN_NAME
311 _clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME
314 _debug
"OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID"
315 if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then
316 export OS_PROJECT_DOMAIN_ID
317 _saveaccountconf_mutable OS_PROJECT_DOMAIN_ID
"$OS_PROJECT_DOMAIN_ID"
319 unset OS_PROJECT_DOMAIN_ID
320 _clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID
323 if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then
324 # Application Credential auth
325 if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] ||
[ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
326 _err
"When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID"
327 _err
"and OS_APPLICATION_CREDENTIAL_SECRET must be set."
328 _err
"Please check your credentials and try again."
333 if [ -z "$OS_USERNAME" ] ||
[ -z "$OS_PASSWORD" ]; then
334 _err
"OpenStack username or password not found."
335 _err
"Please check your credentials and try again."
339 if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then
340 _err
"When using password authentication, OS_PROJECT_NAME or"
341 _err
"OS_PROJECT_ID must be set."
342 _err
"Please check your credentials and try again."