Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Acme.Sh
Commits
0ec9b982
Unverified
Commit
0ec9b982
authored
Nov 22, 2016
by
Armando Lüscher
Browse files
Add DNS API for cyon.ch
parent
cd9c3a79
Changes
1
Hide whitespace changes
Inline
Side-by-side
dnsapi/dns_cyon.sh
0 → 100644
View file @
0ec9b982
#!/usr/bin/env sh
########
# Custom cyon.ch DNS API for use with [acme.sh](https://github.com/Neilpang/acme.sh)
#
# Usage: acme.sh --issue --dns dns_cyon -d www.domain.com
#
# Dependencies:
# -------------
# - jq (get it here: https://stedolan.github.io/jq/download)
# - oathtool (When using 2 Factor Authentication)
#
# Author: Armando Lüscher <armando@noplanman.ch>
########
########
# Define cyon.ch login credentials:
#
# Either set them here: (uncomment these lines)
#
# cyon_username='your_cyon_username'
# cyon_password='your_cyon_password'
# cyon_otp_secret='your_otp_secret' # Only required if using 2FA
#
# ...or export them as environment variables in your shell:
#
# $ export cyon_username='your_cyon_username'
# $ export cyon_password='your_cyon_password'
# $ export cyon_otp_secret='your_otp_secret' # Only required if using 2FA
#
# *Note:*
# After the first run, the credentials are saved in the "account.conf"
# file, so any hard-coded or environment variables can then be removed.
########
dns_cyon_add
()
{
if
!
_exists jq
;
then
_fail
"Please install jq to use cyon.ch DNS API."
fi
_load_credentials
_load_parameters
"
$@
"
_info_header
"add"
_login
_domain_env
_add_txt
_cleanup
return
0
}
dns_cyon_rm
()
{
_load_credentials
_load_parameters
"
$@
"
_info_header
"delete"
_login
_domain_env
_delete_txt
_cleanup
return
0
}
#########################
### PRIVATE FUNCTIONS ###
#########################
_load_credentials
()
{
# Convert loaded password to/from base64 as needed.
if
[
"
${
cyon_password_b64
}
"
]
;
then
cyon_password
=
"
$(
echo
"
${
cyon_password_b64
}
"
| _dbase64
)
"
elif
[
"
${
cyon_password
}
"
]
;
then
cyon_password_b64
=
"
$(
echo
"
${
cyon_password
}
"
| _base64
)
"
fi
if
[
-z
"
${
cyon_username
}
"
]
||
[
-z
"
${
cyon_password
}
"
]
;
then
_err
""
_err
"You haven't set your cyon.ch login credentials yet."
_err
"Please set the required cyon environment variables."
_err
""
exit
1
fi
# Save the login credentials to the account.conf file.
_debug
"Save credentials to account.conf"
_saveaccountconf cyon_username
"
${
cyon_username
}
"
_saveaccountconf cyon_password_b64
"
$cyon_password_b64
"
if
[
!
-z
"
${
cyon_otp_secret
}
"
]
;
then
_saveaccountconf cyon_otp_secret
"
$cyon_otp_secret
"
fi
}
_is_idn
()
{
_idn_temp
=
$(
printf
"%s"
"
$1
"
|
tr
-d
"[0-9a-zA-Z.,-]"
)
_idn_temp2
=
"
$(
printf
"%s"
"
$1
"
|
grep
-o
"xn--"
)
"
[
"
$_idn_temp
"
]
||
[
"
$_idn_temp2
"
]
}
_load_parameters
()
{
# Read the required parameters to add the TXT entry.
fulldomain
=
"
$(
echo
"
$1
"
|
tr
'[:upper:]'
'[:lower:]'
)
"
fulldomain_idn
=
"
${
fulldomain
}
"
# Special case for IDNs, as cyon needs a domain environment change,
# which uses the "pretty" instead of the punycode version.
if
_is_idn
"
$1
"
;
then
if
!
_exists idn
;
then
_fail
"Please install idn to process IDN names."
fi
fulldomain
=
"
$(
idn
-u
"
${
fulldomain
}
"
)
"
fulldomain_idn
=
"
$(
idn
-a
"
${
fulldomain
}
"
)
"
fi
_debug fulldomain
"
$fulldomain
"
_debug fulldomain_idn
"
$fulldomain_idn
"
txtvalue
=
"
$2
"
_debug txtvalue
"
$txtvalue
"
# Cookiejar required for login session, as cyon.ch has no official API (yet).
cookiejar
=
$(
tempfile
)
_debug cookiejar
"
$cookiejar
"
}
_info_header
()
{
if
[
"
$1
"
=
"add"
]
;
then
_info
""
_info
"+---------------------------------------------+"
_info
"| Adding DNS TXT entry to your cyon.ch domain |"
_info
"+---------------------------------------------+"
_info
""
_info
" * Full Domain:
${
fulldomain
}
"
_info
" * TXT Value:
${
txtvalue
}
"
_info
" * Cookie Jar:
${
cookiejar
}
"
_info
""
elif
[
"
$1
"
=
"delete"
]
;
then
_info
""
_info
"+-------------------------------------------------+"
_info
"| Deleting DNS TXT entry from your cyon.ch domain |"
_info
"+-------------------------------------------------+"
_info
""
_info
" * Full Domain:
${
fulldomain
}
"
_info
" * Cookie Jar:
${
cookiejar
}
"
_info
""
fi
}
_login
()
{
_info
" - Logging in..."
login_response
=
$(
curl
\
"https://my.cyon.ch/auth/index/dologin-async"
\
-s
\
-c
"
${
cookiejar
}
"
\
-H
"X-Requested-With: XMLHttpRequest"
\
--data-urlencode
"username=
${
cyon_username
}
"
\
--data-urlencode
"password=
${
cyon_password
}
"
\
--data-urlencode
"pathname=/"
)
_debug login_response
"
${
login_response
}
"
# Bail if login fails.
if
[
"
$(
echo
"
${
login_response
}
"
| jq
-r
'.onSuccess'
)
"
!=
"success"
]
;
then
_fail
"
$(
echo
"
${
login_response
}
"
| jq
-r
'.message'
)
"
fi
_info
" success"
# NECESSARY!! Load the main page after login, before the OTP check.
curl
"https://my.cyon.ch/"
-s
--compressed
-b
"
${
cookiejar
}
"
>
/dev/null
# todo: instead of just checking if the env variable is defined, check if we actually need to do a 2FA auth request.
# 2FA authentication with OTP?
if
[
!
-z
"
${
cyon_otp_secret
}
"
]
;
then
_info
" - Authorising with OTP code..."
if
!
_exists oathtool
;
then
_fail
"Please install oathtool to use 2 Factor Authentication."
fi
# Get OTP code with the defined secret.
otp_code
=
$(
oathtool
--base32
--totp
"
${
cyon_otp_secret
}
"
2>/dev/null
)
otp_response
=
$(
curl
\
"https://my.cyon.ch/auth/multi-factor/domultifactorauth-async"
\
-s
\
--compressed
\
-b
"
${
cookiejar
}
"
\
-c
"
${
cookiejar
}
"
\
-H
"X-Requested-With: XMLHttpRequest"
\
-d
"totpcode=
${
otp_code
}
&pathname=%2F&rememberme=0"
)
_debug otp_response
"
${
otp_response
}
"
# Bail if OTP authentication fails.
if
[
"
$(
echo
"
${
otp_response
}
"
| jq
-r
'.onSuccess'
)
"
!=
"success"
]
;
then
_fail
"
$(
echo
"
${
otp_response
}
"
| jq
-r
'.message'
)
"
fi
_info
" success"
fi
_info
""
}
_domain_env
()
{
_info
" - Changing domain environment..."
# Get the "example.com" part of the full domain name.
domain_env
=
$(
echo
"
${
fulldomain
}
"
|
sed
-E
-e
's/.*\.(.*\..*)$/\1/'
)
_debug
"Changing domain environment to
${
domain_env
}
"
domain_env_response
=
$(
curl
\
"https://my.cyon.ch/user/environment/setdomain/d/
${
domain_env
}
/gik/domain%3A
${
domain_env
}
"
\
-s
\
--compressed
\
-b
"
${
cookiejar
}
"
\
-H
"X-Requested-With: XMLHttpRequest"
)
_debug domain_env_response
"
${
domain_env_response
}
"
_check_2fa_miss
"
${
domain_env_response
}
"
domain_env_success
=
$(
echo
"
${
domain_env_response
}
"
| jq
-r
'.authenticated'
)
# Bail if domain environment change fails.
if
[
"
${
domain_env_success
}
"
!=
"true"
]
;
then
_fail
"
$(
echo
"
${
domain_env_response
}
"
| jq
-r
'.message'
)
"
fi
_info
" success"
_info
""
}
_add_txt
()
{
_info
" - Adding DNS TXT entry..."
addtxt_response
=
$(
curl
\
"https://my.cyon.ch/domain/dnseditor/add-record-async"
\
-s
\
--compressed
\
-b
"
${
cookiejar
}
"
\
-H
"X-Requested-With: XMLHttpRequest"
\
-d
"zone=
${
fulldomain_idn
}
.&ttl=900&type=TXT&value=
${
txtvalue
}
"
)
_debug addtxt_response
"
${
addtxt_response
}
"
_check_2fa_miss
"
${
addtxt_response
}
"
addtxt_message
=
$(
echo
"
${
addtxt_response
}
"
| jq
-r
'.message'
)
addtxt_status
=
$(
echo
"
${
addtxt_response
}
"
| jq
-r
'.status'
)
# Bail if adding TXT entry fails.
if
[
"
${
addtxt_status
}
"
!=
"true"
]
;
then
if
[
"
${
addtxt_status
}
"
=
"null"
]
;
then
addtxt_message
=
$(
echo
"
${
addtxt_response
}
"
| jq
-r
'.error.message'
)
fi
_fail
"
${
addtxt_message
}
"
fi
_info
" success"
_info
""
}
_delete_txt
()
{
_info
" - Deleting DNS TXT entry..."
list_txt_response
=
$(
curl
\
"https://my.cyon.ch/domain/dnseditor/list-async"
\
-s
\
-b
"
${
cookiejar
}
"
\
--compressed
\
-H
"X-Requested-With: XMLHttpRequest"
)
_debug list_txt_response
"
${
list_txt_response
}
"
_check_2fa_miss
"
${
list_txt_response
}
"
# Find and delete all acme challenge entries for the $fulldomain.
_dns_entries
=
$(
echo
"
$list_txt_response
"
| jq
-r
--arg
fulldomain_idn
"
${
fulldomain_idn
}
."
'
.rows[] |
label $out|
if .[0] != $fulldomain_idn then
break $out
else
.[4]|
capture("data-hash=\"(?<hash>[^\"]*)\" data-identifier=\"(?<identifier>[^\"]*)\"";"g")|
.hash + " " + .identifier
end'
)
_dns_entries_cnt
=
$(
echo
"
${
_dns_entries
}
"
|
wc
-l
|
grep
-o
'\d'
)
_info
" (entries found:
${
_dns_entries_cnt
}
)"
_dns_entry_num
=
0
echo
"
${
_dns_entries
}
"
|
while
read
-r
_hash _identifier
do
((
_dns_entry_num++
))
delete_txt_response
=
$(
curl
\
"https://my.cyon.ch/domain/dnseditor/delete-record-async"
\
-s
\
--compressed
\
-b
"
${
cookiejar
}
"
\
-H
"X-Requested-With: XMLHttpRequest"
\
--data-urlencode
"hash=
${
_hash
}
"
\
--data-urlencode
"identifier=
${
_identifier
}
"
)
_debug delete_txt_response
"
${
delete_txt_response
}
"
_check_2fa_miss
"
${
delete_txt_response
}
"
delete_txt_message
=
$(
echo
"
${
delete_txt_response
}
"
| jq
-r
'.message'
)
delete_txt_status
=
$(
echo
"
${
delete_txt_response
}
"
| jq
-r
'.status'
)
# Skip if deleting TXT entry fails.
if
[
"
${
delete_txt_status
}
"
!=
"true"
]
;
then
if
[
"
${
delete_txt_status
}
"
=
"null"
]
;
then
delete_txt_message
=
$(
echo
"
${
delete_txt_response
}
"
| jq
-r
'.error.message'
)
fi
_err
" [
${
_dns_entry_num
}
/
${
_dns_entries_cnt
}
]
${
delete_txt_message
}
(
${
_identifier
}
)"
else
_info
" [
${
_dns_entry_num
}
/
${
_dns_entries_cnt
}
] success (
${
_identifier
}
)"
fi
done
_info
" done"
_info
""
}
_check_2fa_miss
()
{
# Did we miss the 2FA?
if
[[
"
$1
"
=
~
"multi_factor_form"
]]
;
then
_fail
" Missed OTP authentication!"
fi
}
_fail
()
{
_err
"
$1
"
_err
""
_cleanup
exit
1
}
_cleanup
()
{
_info
" - Cleanup."
_debug
"Remove cookie jar:
${
cookiejar
}
"
rm
"
${
cookiejar
}
"
2>/dev/null
_info
""
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment