mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-05-01 20:26:27 +00:00
Ubiquiti removed keytool (and java) from recent releases of Unifi OS. This moves from keytool to openssl's native pkcs12. Tested on Unifi Dream Machine which runs Unifi OS and a built-in Unifi controller. Also added backup of existing files prior to change in case anything goes wrong, and update system configuration with compatible ciphers.
356 lines
12 KiB
Bash
Executable File
356 lines
12 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# shellcheck disable=SC2034
|
|
dns_openstack_info='OpenStack Designate API
|
|
Depends on OpenStackClient and python-desginateclient.
|
|
You will require Keystone V3 credentials loaded into your environment,
|
|
which could be either password or v3 application credential type.
|
|
Site: docs.openstack.org/api-ref/dns/
|
|
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_openstack
|
|
Options:
|
|
OS_AUTH_URL Auth URL. E.g. "https://keystone.example.com:5000/"
|
|
OS_USERNAME Username
|
|
OS_PASSWORD Password
|
|
OS_PROJECT_NAME Project name
|
|
OS_PROJECT_DOMAIN_NAME Project domain name. E.g. "Default"
|
|
OS_USER_DOMAIN_NAME User domain name. E.g. "Default"
|
|
Issues: github.com/acmesh-official/acme.sh/issues/3054
|
|
Author: Andy Botting <andy@andybotting.com>
|
|
'
|
|
|
|
######## Public functions #####################
|
|
|
|
# Usage: dns_openstack_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
|
dns_openstack_add() {
|
|
fulldomain=$1
|
|
txtvalue=$2
|
|
_debug fulldomain "$fulldomain"
|
|
_debug txtvalue "$txtvalue"
|
|
|
|
_dns_openstack_credentials || return $?
|
|
_dns_openstack_check_setup || return $?
|
|
_dns_openstack_find_zone || return $?
|
|
_dns_openstack_get_recordset || return $?
|
|
_debug _recordset_id "$_recordset_id"
|
|
if [ -n "$_recordset_id" ]; then
|
|
_dns_openstack_get_records || return $?
|
|
_debug _records "$_records"
|
|
fi
|
|
_dns_openstack_create_recordset || return $?
|
|
}
|
|
|
|
# Usage: dns_openstack_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
|
# Remove the txt record after validation.
|
|
dns_openstack_rm() {
|
|
fulldomain=$1
|
|
txtvalue=$2
|
|
_debug fulldomain "$fulldomain"
|
|
_debug txtvalue "$txtvalue"
|
|
|
|
_dns_openstack_credentials || return $?
|
|
_dns_openstack_check_setup || return $?
|
|
_dns_openstack_find_zone || return $?
|
|
_dns_openstack_get_recordset || return $?
|
|
_debug _recordset_id "$_recordset_id"
|
|
if [ -n "$_recordset_id" ]; then
|
|
_dns_openstack_get_records || return $?
|
|
_debug _records "$_records"
|
|
fi
|
|
_dns_openstack_delete_recordset || return $?
|
|
}
|
|
|
|
#################### Private functions below ##################################
|
|
|
|
_dns_openstack_create_recordset() {
|
|
|
|
if [ -z "$_recordset_id" ]; then
|
|
_info "Creating a new recordset"
|
|
if ! _recordset_id=$(openstack recordset create -c id -f value --type TXT --record="$txtvalue" "$_zone_id" "$fulldomain."); then
|
|
_err "No recordset ID found after create"
|
|
return 1
|
|
fi
|
|
else
|
|
_info "Updating existing recordset"
|
|
# Build new list of --record=<rec> args for update
|
|
_record_args="--record=$txtvalue"
|
|
for _rec in $_records; do
|
|
_record_args="$_record_args --record=$_rec"
|
|
done
|
|
# shellcheck disable=SC2086
|
|
if ! _recordset_id=$(openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain."); then
|
|
_err "Recordset update failed"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
_max_retries=60
|
|
_sleep_sec=5
|
|
_retry_times=0
|
|
while [ "$_retry_times" -lt "$_max_retries" ]; do
|
|
_retry_times=$(_math "$_retry_times" + 1)
|
|
_debug3 _retry_times "$_retry_times"
|
|
|
|
_record_status=$(openstack recordset show -c status -f value "$_zone_id" "$_recordset_id")
|
|
_info "Recordset status is $_record_status"
|
|
if [ "$_record_status" = "ACTIVE" ]; then
|
|
return 0
|
|
elif [ "$_record_status" = "ERROR" ]; then
|
|
return 1
|
|
else
|
|
_sleep $_sleep_sec
|
|
fi
|
|
done
|
|
|
|
_err "Recordset failed to become ACTIVE"
|
|
return 1
|
|
}
|
|
|
|
_dns_openstack_delete_recordset() {
|
|
|
|
if [ "$_records" = "$txtvalue" ]; then
|
|
_info "Only one record found, deleting recordset"
|
|
if ! openstack recordset delete "$_zone_id" "$fulldomain." >/dev/null; then
|
|
_err "Failed to delete recordset"
|
|
return 1
|
|
fi
|
|
else
|
|
_info "Found existing records, updating recordset"
|
|
# Build new list of --record=<rec> args for update
|
|
_record_args=""
|
|
for _rec in $_records; do
|
|
if [ "$_rec" = "$txtvalue" ]; then
|
|
continue
|
|
fi
|
|
_record_args="$_record_args --record=$_rec"
|
|
done
|
|
# shellcheck disable=SC2086
|
|
if ! openstack recordset set -c id -f value $_record_args "$_zone_id" "$fulldomain." >/dev/null; then
|
|
_err "Recordset update failed"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
_dns_openstack_get_root() {
|
|
# Take the full fqdn and strip away pieces until we get an exact zone name
|
|
# match. For example, _acme-challenge.something.domain.com might need to go
|
|
# into something.domain.com or domain.com
|
|
_zone_name=$1
|
|
_zone_list=$2
|
|
while [ "$_zone_name" != "" ]; do
|
|
_zone_name="$(echo "$_zone_name" | sed 's/[^.]*\.*//')"
|
|
echo "$_zone_list" | while read -r id name; do
|
|
if _startswith "$_zone_name." "$name"; then
|
|
echo "$id"
|
|
fi
|
|
done
|
|
done | _head_n 1
|
|
}
|
|
|
|
_dns_openstack_find_zone() {
|
|
if ! _zone_list="$(openstack zone list -c id -c name -f value)"; then
|
|
_err "Can't list zones. Check your OpenStack credentials"
|
|
return 1
|
|
fi
|
|
_debug _zone_list "$_zone_list"
|
|
|
|
if ! _zone_id="$(_dns_openstack_get_root "$fulldomain" "$_zone_list")"; then
|
|
_err "Can't find a matching zone. Check your OpenStack credentials"
|
|
return 1
|
|
fi
|
|
_debug _zone_id "$_zone_id"
|
|
}
|
|
|
|
_dns_openstack_get_records() {
|
|
if ! _records=$(openstack recordset show -c records -f value "$_zone_id" "$fulldomain."); then
|
|
_err "Failed to get records"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
_dns_openstack_get_recordset() {
|
|
if ! _recordset_id=$(openstack recordset list -c id -f value --name "$fulldomain." "$_zone_id"); then
|
|
_err "Failed to get recordset"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
_dns_openstack_check_setup() {
|
|
if ! _exists openstack; then
|
|
_err "OpenStack client not found"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
_dns_openstack_credentials() {
|
|
_debug "Check OpenStack credentials"
|
|
|
|
# If we have OS_AUTH_URL already set in the environment, then assume we want
|
|
# to use those, otherwise use stored credentials
|
|
if [ -n "$OS_AUTH_URL" ]; then
|
|
_debug "OS_AUTH_URL env var found, using environment"
|
|
else
|
|
_debug "OS_AUTH_URL not found, loading stored credentials"
|
|
OS_AUTH_URL="${OS_AUTH_URL:-$(_readaccountconf_mutable OS_AUTH_URL)}"
|
|
OS_IDENTITY_API_VERSION="${OS_IDENTITY_API_VERSION:-$(_readaccountconf_mutable OS_IDENTITY_API_VERSION)}"
|
|
OS_AUTH_TYPE="${OS_AUTH_TYPE:-$(_readaccountconf_mutable OS_AUTH_TYPE)}"
|
|
OS_APPLICATION_CREDENTIAL_ID="${OS_APPLICATION_CREDENTIAL_ID:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID)}"
|
|
OS_APPLICATION_CREDENTIAL_SECRET="${OS_APPLICATION_CREDENTIAL_SECRET:-$(_readaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET)}"
|
|
OS_USERNAME="${OS_USERNAME:-$(_readaccountconf_mutable OS_USERNAME)}"
|
|
OS_PASSWORD="${OS_PASSWORD:-$(_readaccountconf_mutable OS_PASSWORD)}"
|
|
OS_PROJECT_NAME="${OS_PROJECT_NAME:-$(_readaccountconf_mutable OS_PROJECT_NAME)}"
|
|
OS_PROJECT_ID="${OS_PROJECT_ID:-$(_readaccountconf_mutable OS_PROJECT_ID)}"
|
|
OS_USER_DOMAIN_NAME="${OS_USER_DOMAIN_NAME:-$(_readaccountconf_mutable OS_USER_DOMAIN_NAME)}"
|
|
OS_USER_DOMAIN_ID="${OS_USER_DOMAIN_ID:-$(_readaccountconf_mutable OS_USER_DOMAIN_ID)}"
|
|
OS_PROJECT_DOMAIN_NAME="${OS_PROJECT_DOMAIN_NAME:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_NAME)}"
|
|
OS_PROJECT_DOMAIN_ID="${OS_PROJECT_DOMAIN_ID:-$(_readaccountconf_mutable OS_PROJECT_DOMAIN_ID)}"
|
|
fi
|
|
|
|
# Check each var and either save or clear it depending on whether its set.
|
|
# The helps us clear out old vars in the case where a user may want
|
|
# to switch between password and app creds
|
|
_debug "OS_AUTH_URL" "$OS_AUTH_URL"
|
|
if [ -n "$OS_AUTH_URL" ]; then
|
|
export OS_AUTH_URL
|
|
_saveaccountconf_mutable OS_AUTH_URL "$OS_AUTH_URL"
|
|
else
|
|
unset OS_AUTH_URL
|
|
_clearaccountconf SAVED_OS_AUTH_URL
|
|
fi
|
|
|
|
_debug "OS_IDENTITY_API_VERSION" "$OS_IDENTITY_API_VERSION"
|
|
if [ -n "$OS_IDENTITY_API_VERSION" ]; then
|
|
export OS_IDENTITY_API_VERSION
|
|
_saveaccountconf_mutable OS_IDENTITY_API_VERSION "$OS_IDENTITY_API_VERSION"
|
|
else
|
|
unset OS_IDENTITY_API_VERSION
|
|
_clearaccountconf SAVED_OS_IDENTITY_API_VERSION
|
|
fi
|
|
|
|
_debug "OS_AUTH_TYPE" "$OS_AUTH_TYPE"
|
|
if [ -n "$OS_AUTH_TYPE" ]; then
|
|
export OS_AUTH_TYPE
|
|
_saveaccountconf_mutable OS_AUTH_TYPE "$OS_AUTH_TYPE"
|
|
else
|
|
unset OS_AUTH_TYPE
|
|
_clearaccountconf SAVED_OS_AUTH_TYPE
|
|
fi
|
|
|
|
_debug "OS_APPLICATION_CREDENTIAL_ID" "$OS_APPLICATION_CREDENTIAL_ID"
|
|
if [ -n "$OS_APPLICATION_CREDENTIAL_ID" ]; then
|
|
export OS_APPLICATION_CREDENTIAL_ID
|
|
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_ID "$OS_APPLICATION_CREDENTIAL_ID"
|
|
else
|
|
unset OS_APPLICATION_CREDENTIAL_ID
|
|
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_ID
|
|
fi
|
|
|
|
_secure_debug "OS_APPLICATION_CREDENTIAL_SECRET" "$OS_APPLICATION_CREDENTIAL_SECRET"
|
|
if [ -n "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
|
|
export OS_APPLICATION_CREDENTIAL_SECRET
|
|
_saveaccountconf_mutable OS_APPLICATION_CREDENTIAL_SECRET "$OS_APPLICATION_CREDENTIAL_SECRET"
|
|
else
|
|
unset OS_APPLICATION_CREDENTIAL_SECRET
|
|
_clearaccountconf SAVED_OS_APPLICATION_CREDENTIAL_SECRET
|
|
fi
|
|
|
|
_debug "OS_USERNAME" "$OS_USERNAME"
|
|
if [ -n "$OS_USERNAME" ]; then
|
|
export OS_USERNAME
|
|
_saveaccountconf_mutable OS_USERNAME "$OS_USERNAME"
|
|
else
|
|
unset OS_USERNAME
|
|
_clearaccountconf SAVED_OS_USERNAME
|
|
fi
|
|
|
|
_secure_debug "OS_PASSWORD" "$OS_PASSWORD"
|
|
if [ -n "$OS_PASSWORD" ]; then
|
|
export OS_PASSWORD
|
|
_saveaccountconf_mutable OS_PASSWORD "$OS_PASSWORD"
|
|
else
|
|
unset OS_PASSWORD
|
|
_clearaccountconf SAVED_OS_PASSWORD
|
|
fi
|
|
|
|
_debug "OS_PROJECT_NAME" "$OS_PROJECT_NAME"
|
|
if [ -n "$OS_PROJECT_NAME" ]; then
|
|
export OS_PROJECT_NAME
|
|
_saveaccountconf_mutable OS_PROJECT_NAME "$OS_PROJECT_NAME"
|
|
else
|
|
unset OS_PROJECT_NAME
|
|
_clearaccountconf SAVED_OS_PROJECT_NAME
|
|
fi
|
|
|
|
_debug "OS_PROJECT_ID" "$OS_PROJECT_ID"
|
|
if [ -n "$OS_PROJECT_ID" ]; then
|
|
export OS_PROJECT_ID
|
|
_saveaccountconf_mutable OS_PROJECT_ID "$OS_PROJECT_ID"
|
|
else
|
|
unset OS_PROJECT_ID
|
|
_clearaccountconf SAVED_OS_PROJECT_ID
|
|
fi
|
|
|
|
_debug "OS_USER_DOMAIN_NAME" "$OS_USER_DOMAIN_NAME"
|
|
if [ -n "$OS_USER_DOMAIN_NAME" ]; then
|
|
export OS_USER_DOMAIN_NAME
|
|
_saveaccountconf_mutable OS_USER_DOMAIN_NAME "$OS_USER_DOMAIN_NAME"
|
|
else
|
|
unset OS_USER_DOMAIN_NAME
|
|
_clearaccountconf SAVED_OS_USER_DOMAIN_NAME
|
|
fi
|
|
|
|
_debug "OS_USER_DOMAIN_ID" "$OS_USER_DOMAIN_ID"
|
|
if [ -n "$OS_USER_DOMAIN_ID" ]; then
|
|
export OS_USER_DOMAIN_ID
|
|
_saveaccountconf_mutable OS_USER_DOMAIN_ID "$OS_USER_DOMAIN_ID"
|
|
else
|
|
unset OS_USER_DOMAIN_ID
|
|
_clearaccountconf SAVED_OS_USER_DOMAIN_ID
|
|
fi
|
|
|
|
_debug "OS_PROJECT_DOMAIN_NAME" "$OS_PROJECT_DOMAIN_NAME"
|
|
if [ -n "$OS_PROJECT_DOMAIN_NAME" ]; then
|
|
export OS_PROJECT_DOMAIN_NAME
|
|
_saveaccountconf_mutable OS_PROJECT_DOMAIN_NAME "$OS_PROJECT_DOMAIN_NAME"
|
|
else
|
|
unset OS_PROJECT_DOMAIN_NAME
|
|
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_NAME
|
|
fi
|
|
|
|
_debug "OS_PROJECT_DOMAIN_ID" "$OS_PROJECT_DOMAIN_ID"
|
|
if [ -n "$OS_PROJECT_DOMAIN_ID" ]; then
|
|
export OS_PROJECT_DOMAIN_ID
|
|
_saveaccountconf_mutable OS_PROJECT_DOMAIN_ID "$OS_PROJECT_DOMAIN_ID"
|
|
else
|
|
unset OS_PROJECT_DOMAIN_ID
|
|
_clearaccountconf SAVED_OS_PROJECT_DOMAIN_ID
|
|
fi
|
|
|
|
if [ "$OS_AUTH_TYPE" = "v3applicationcredential" ]; then
|
|
# Application Credential auth
|
|
if [ -z "$OS_APPLICATION_CREDENTIAL_ID" ] || [ -z "$OS_APPLICATION_CREDENTIAL_SECRET" ]; then
|
|
_err "When using OpenStack application credentials, OS_APPLICATION_CREDENTIAL_ID"
|
|
_err "and OS_APPLICATION_CREDENTIAL_SECRET must be set."
|
|
_err "Please check your credentials and try again."
|
|
return 1
|
|
fi
|
|
else
|
|
# Password auth
|
|
if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ]; then
|
|
_err "OpenStack username or password not found."
|
|
_err "Please check your credentials and try again."
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "$OS_PROJECT_NAME" ] && [ -z "$OS_PROJECT_ID" ]; then
|
|
_err "When using password authentication, OS_PROJECT_NAME or"
|
|
_err "OS_PROJECT_ID must be set."
|
|
_err "Please check your credentials and try again."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|