Arabezar
4 years ago
51 changed files with 3643 additions and 1439 deletions
-
211.github/workflows/DNS.yml
-
116.github/workflows/LetsEncrypt.yml
-
39.github/workflows/PebbleStrict.yml
-
56.github/workflows/dockerhub.yml
-
33.github/workflows/shellcheck.yml
-
37.travis.yml
-
6Dockerfile
-
60README.md
-
724acme.sh
-
4deploy/exim4.sh
-
262deploy/openstack.sh
-
10deploy/ssh.sh
-
4deploy/synology_dsm.sh
-
67deploy/vault.sh
-
2deploy/vault_cli.sh
-
6deploy/vsftpd.sh
-
90dnsapi/dns_1984hosting.sh
-
150dnsapi/dns_anx.sh
-
12dnsapi/dns_aws.sh
-
4dnsapi/dns_azure.sh
-
6dnsapi/dns_cloudns.sh
-
6dnsapi/dns_conoha.sh
-
32dnsapi/dns_cyon.sh
-
6dnsapi/dns_dgon.sh
-
24dnsapi/dns_do.sh
-
9dnsapi/dns_duckdns.sh
-
244dnsapi/dns_dynv6.sh
-
18dnsapi/dns_freedns.sh
-
16dnsapi/dns_gandi_livedns.sh
-
12dnsapi/dns_gcloud.sh
-
4dnsapi/dns_he.sh
-
8dnsapi/dns_hetzner.sh
-
199dnsapi/dns_infomaniak.sh
-
150dnsapi/dns_kappernet.sh
-
4dnsapi/dns_misaka.sh
-
162dnsapi/dns_netlify.sh
-
2dnsapi/dns_nic.sh
-
348dnsapi/dns_openstack.sh
-
2dnsapi/dns_ovh.sh
-
39dnsapi/dns_pleskxml.sh
-
10dnsapi/dns_regru.sh
-
2dnsapi/dns_yandex.sh
@ -0,0 +1,211 @@ |
|||||
|
name: DNS |
||||
|
on: |
||||
|
push: |
||||
|
paths: |
||||
|
- 'dnsapi/*.sh' |
||||
|
- '.github/workflows/DNS.yml' |
||||
|
pull_request: |
||||
|
branches: |
||||
|
- 'dev' |
||||
|
paths: |
||||
|
- 'dnsapi/*.sh' |
||||
|
- '.github/workflows/DNS.yml' |
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
CheckToken: |
||||
|
runs-on: ubuntu-latest |
||||
|
outputs: |
||||
|
hasToken: ${{ steps.step_one.outputs.hasToken }} |
||||
|
steps: |
||||
|
- name: Set the value |
||||
|
id: step_one |
||||
|
run: | |
||||
|
if [ "${{secrets.TokenName1}}" ] ; then |
||||
|
echo "::set-output name=hasToken::true" |
||||
|
else |
||||
|
echo "::set-output name=hasToken::false" |
||||
|
fi |
||||
|
- name: Check the value |
||||
|
run: echo ${{ steps.step_one.outputs.hasToken }} |
||||
|
|
||||
|
Fail: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: CheckToken |
||||
|
if: "contains(needs.CheckToken.outputs.hasToken, 'false')" |
||||
|
steps: |
||||
|
- name: "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
||||
|
run: | |
||||
|
echo "Read this: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Test" |
||||
|
if [ "${{github.actor}}" != "Neilpang" ]; then |
||||
|
false |
||||
|
fi |
||||
|
|
||||
|
Docker: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: CheckToken |
||||
|
if: "contains(needs.CheckToken.outputs.hasToken, 'true')" |
||||
|
env: |
||||
|
TEST_DNS : ${{ secrets.TEST_DNS }} |
||||
|
TestingDomain: ${{ secrets.TestingDomain }} |
||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} |
||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} |
||||
|
CASE: le_test_dnsapi |
||||
|
TEST_LOCAL: 1 |
||||
|
DEBUG: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Set env file |
||||
|
run: | |
||||
|
cd ../acmetest |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
echo "${{ secrets.TokenName1}}=${{ secrets.TokenValue1}}" >> env.list |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
echo "${{ secrets.TokenName2}}=${{ secrets.TokenValue2}}" >> env.list |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
echo "${{ secrets.TokenName3}}=${{ secrets.TokenValue3}}" >> env.list |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
echo "${{ secrets.TokenName4}}=${{ secrets.TokenValue4}}" >> env.list |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
echo "${{ secrets.TokenName5}}=${{ secrets.TokenValue5}}" >> env.list |
||||
|
fi |
||||
|
echo "TEST_DNS_NO_WILDCARD" >> env.list |
||||
|
echo "TEST_DNS_SLEEP" >> env.list |
||||
|
- name: Run acmetest |
||||
|
run: cd ../acmetest && ./rundocker.sh testall |
||||
|
|
||||
|
MacOS: |
||||
|
runs-on: macos-latest |
||||
|
needs: Docker |
||||
|
env: |
||||
|
TEST_DNS : ${{ secrets.TEST_DNS }} |
||||
|
TestingDomain: ${{ secrets.TestingDomain }} |
||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} |
||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} |
||||
|
CASE: le_test_dnsapi |
||||
|
TEST_LOCAL: 1 |
||||
|
DEBUG: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install tools |
||||
|
run: brew install socat |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
Windows: |
||||
|
runs-on: windows-latest |
||||
|
needs: MacOS |
||||
|
env: |
||||
|
TEST_DNS : ${{ secrets.TEST_DNS }} |
||||
|
TestingDomain: ${{ secrets.TestingDomain }} |
||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} |
||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} |
||||
|
CASE: le_test_dnsapi |
||||
|
TEST_LOCAL: 1 |
||||
|
DEBUG: 1 |
||||
|
steps: |
||||
|
- name: Set git to use LF |
||||
|
run: | |
||||
|
git config --global core.autocrlf false |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install cygwin base packages with chocolatey |
||||
|
run: | |
||||
|
choco config get cacheLocation |
||||
|
choco install --no-progress cygwin |
||||
|
shell: cmd |
||||
|
- name: Install cygwin additional packages |
||||
|
run: | |
||||
|
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git |
||||
|
shell: cmd |
||||
|
- name: Set ENV |
||||
|
run: | |
||||
|
echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
shell: bash |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
FreeBSD: |
||||
|
runs-on: macos-latest |
||||
|
needs: Windows |
||||
|
env: |
||||
|
TEST_DNS : ${{ secrets.TEST_DNS }} |
||||
|
TestingDomain: ${{ secrets.TestingDomain }} |
||||
|
TEST_DNS_NO_WILDCARD: ${{ secrets.TEST_DNS_NO_WILDCARD }} |
||||
|
TEST_DNS_SLEEP: ${{ secrets.TEST_DNS_SLEEP }} |
||||
|
CASE: le_test_dnsapi |
||||
|
TEST_LOCAL: 1 |
||||
|
DEBUG: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/freebsd-vm@v0.0.7 |
||||
|
with: |
||||
|
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' |
||||
|
prepare: pkg install -y socat curl |
||||
|
usesh: true |
||||
|
run: | |
||||
|
if [ "${{ secrets.TokenName1}}" ] ; then |
||||
|
export ${{ secrets.TokenName1}}=${{ secrets.TokenValue1}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName2}}" ] ; then |
||||
|
export ${{ secrets.TokenName2}}=${{ secrets.TokenValue2}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName3}}" ] ; then |
||||
|
export ${{ secrets.TokenName3}}=${{ secrets.TokenValue3}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName4}}" ] ; then |
||||
|
export ${{ secrets.TokenName4}}=${{ secrets.TokenValue4}} |
||||
|
fi |
||||
|
if [ "${{ secrets.TokenName5}}" ] ; then |
||||
|
export ${{ secrets.TokenName5}}=${{ secrets.TokenValue5}} |
||||
|
fi |
||||
|
cd ../acmetest |
||||
|
./letest.sh |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,116 @@ |
|||||
|
name: LetsEncrypt |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
|
||||
|
|
||||
|
jobs: |
||||
|
CheckToken: |
||||
|
runs-on: ubuntu-latest |
||||
|
outputs: |
||||
|
hasToken: ${{ steps.step_one.outputs.hasToken }} |
||||
|
env: |
||||
|
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} |
||||
|
steps: |
||||
|
- name: Set the value |
||||
|
id: step_one |
||||
|
run: | |
||||
|
if [ "$NGROK_TOKEN" ] ; then |
||||
|
echo "::set-output name=hasToken::true" |
||||
|
else |
||||
|
echo "::set-output name=hasToken::false" |
||||
|
fi |
||||
|
- name: Check the value |
||||
|
run: echo ${{ steps.step_one.outputs.hasToken }} |
||||
|
|
||||
|
Ubuntu: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: CheckToken |
||||
|
if: "contains(needs.CheckToken.outputs.hasToken, 'true')" |
||||
|
env: |
||||
|
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} |
||||
|
TEST_LOCAL: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install tools |
||||
|
run: sudo apt-get install -y socat |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
run: cd ../acmetest && sudo --preserve-env ./letest.sh |
||||
|
|
||||
|
MacOS: |
||||
|
runs-on: macos-latest |
||||
|
needs: Ubuntu |
||||
|
env: |
||||
|
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} |
||||
|
TEST_LOCAL: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install tools |
||||
|
run: brew install socat |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
run: cd ../acmetest && sudo --preserve-env ./letest.sh |
||||
|
|
||||
|
Windows: |
||||
|
runs-on: windows-latest |
||||
|
needs: MacOS |
||||
|
env: |
||||
|
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} |
||||
|
TEST_LOCAL: 1 |
||||
|
#The 80 port is used by Windows server, we have to use a custom port, ngrok will also use this port. |
||||
|
Le_HTTPPort: 8888 |
||||
|
steps: |
||||
|
- name: Set git to use LF |
||||
|
run: | |
||||
|
git config --global core.autocrlf false |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install cygwin base packages with chocolatey |
||||
|
run: | |
||||
|
choco config get cacheLocation |
||||
|
choco install --no-progress cygwin |
||||
|
shell: cmd |
||||
|
- name: Install cygwin additional packages |
||||
|
run: | |
||||
|
C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -s http://mirrors.kernel.org/sourceware/cygwin/ -P socat,curl,cron,unzip,git |
||||
|
shell: cmd |
||||
|
- name: Set ENV |
||||
|
run: | |
||||
|
echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin' |
||||
|
- name: Clone acmetest |
||||
|
shell: cmd |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
shell: cmd |
||||
|
run: cd ../acmetest && bash.exe -c ./letest.sh |
||||
|
|
||||
|
FreeBSD: |
||||
|
runs-on: macos-latest |
||||
|
needs: Windows |
||||
|
env: |
||||
|
NGROK_TOKEN : ${{ secrets.NGROK_TOKEN }} |
||||
|
TEST_LOCAL: 1 |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- uses: vmactions/freebsd-vm@v0.0.7 |
||||
|
with: |
||||
|
envs: 'NGROK_TOKEN TEST_LOCAL' |
||||
|
prepare: pkg install -y socat curl |
||||
|
usesh: true |
||||
|
run: | |
||||
|
cd ../acmetest && ./letest.sh |
||||
|
|
@ -0,0 +1,39 @@ |
|||||
|
name: PebbleStrict |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
|
||||
|
jobs: |
||||
|
PebbleStrict: |
||||
|
runs-on: ubuntu-latest |
||||
|
env: |
||||
|
TestingDomain: example.com |
||||
|
TestingAltDomains: www.example.com |
||||
|
ACME_DIRECTORY: https://localhost:14000/dir |
||||
|
HTTPS_INSECURE: 1 |
||||
|
Le_HTTPPort: 5002 |
||||
|
TEST_LOCAL: 1 |
||||
|
TEST_CA: "Pebble Intermediate CA" |
||||
|
|
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install tools |
||||
|
run: sudo apt-get install -y socat |
||||
|
- name: Run Pebble |
||||
|
run: cd .. && curl https://raw.githubusercontent.com/letsencrypt/pebble/master/docker-compose.yml >docker-compose.yml && docker-compose up -d |
||||
|
- name: Set up Pebble |
||||
|
run: curl --request POST --data '{"ip":"10.30.50.1"}' http://localhost:8055/set-default-ipv4 |
||||
|
- name: Clone acmetest |
||||
|
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ |
||||
|
- name: Run acmetest |
||||
|
run: cd ../acmetest && ./letest.sh |
@ -0,0 +1,33 @@ |
|||||
|
name: Shellcheck |
||||
|
on: |
||||
|
push: |
||||
|
branches: |
||||
|
- '*' |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
pull_request: |
||||
|
branches: |
||||
|
- dev |
||||
|
paths: |
||||
|
- '**.sh' |
||||
|
- '**.yml' |
||||
|
|
||||
|
jobs: |
||||
|
ShellCheck: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install Shellcheck |
||||
|
run: sudo apt-get install -y shellcheck |
||||
|
- name: DoShellcheck |
||||
|
run: shellcheck -V && shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" |
||||
|
|
||||
|
shfmt: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- uses: actions/checkout@v2 |
||||
|
- name: Install shfmt |
||||
|
run: curl -sSL https://github.com/mvdan/sh/releases/download/v3.1.2/shfmt_v3.1.2_linux_amd64 -o ~/shfmt && chmod +x ~/shfmt |
||||
|
- name: shfmt |
||||
|
run: ~/shfmt -l -w -i 2 . ; git diff --exit-code && echo "shfmt OK" |
@ -1,37 +0,0 @@ |
|||||
language: shell |
|
||||
dist: trusty |
|
||||
|
|
||||
os: |
|
||||
- linux |
|
||||
- osx |
|
||||
|
|
||||
services: |
|
||||
- docker |
|
||||
|
|
||||
env: |
|
||||
global: |
|
||||
- SHFMT_URL=https://github.com/mvdan/sh/releases/download/v0.4.0/shfmt_v0.4.0_linux_amd64 |
|
||||
|
|
||||
|
|
||||
install: |
|
||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then |
|
||||
brew update && brew install socat; |
|
||||
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH" ; |
|
||||
fi |
|
||||
|
|
||||
script: |
|
||||
- echo "NGROK_TOKEN=$(echo "$NGROK_TOKEN" | wc -c)" |
|
||||
- command -V openssl && openssl version |
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then curl -sSL $SHFMT_URL -o ~/shfmt && chmod +x ~/shfmt && ~/shfmt -l -w -i 2 . ; fi |
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then git diff --exit-code && echo "shfmt OK" ; fi |
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -V ; fi |
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then shellcheck -e SC2181 **/*.sh && echo "shellcheck OK" ; fi |
|
||||
- cd .. |
|
||||
- git clone --depth 1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ && cd acmetest |
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ./rundocker.sh testplat ubuntu:latest ; fi |
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$NGROK_TOKEN" ]; then sudo TEST_LOCAL="$TEST_LOCAL" NGROK_TOKEN="$NGROK_TOKEN" ACME_OPENSSL_BIN="$ACME_OPENSSL_BIN" ./letest.sh ; fi |
|
||||
|
|
||||
matrix: |
|
||||
fast_finish: true |
|
||||
|
|
||||
|
|
724
acme.sh
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,262 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# OpenStack Barbican deploy hook |
||||
|
# |
||||
|
# This requires you to have OpenStackClient and python-barbicanclient |
||||
|
# installed. |
||||
|
# |
||||
|
# You will require Keystone V3 credentials loaded into your environment, which |
||||
|
# could be either password or v3applicationcredential type. |
||||
|
# |
||||
|
# Author: Andy Botting <andy@andybotting.com> |
||||
|
|
||||
|
openstack_deploy() { |
||||
|
_cdomain="$1" |
||||
|
_ckey="$2" |
||||
|
_ccert="$3" |
||||
|
_cca="$4" |
||||
|
_cfullchain="$5" |
||||
|
|
||||
|
_debug _cdomain "$_cdomain" |
||||
|
_debug _ckey "$_ckey" |
||||
|
_debug _ccert "$_ccert" |
||||
|
_debug _cca "$_cca" |
||||
|
_debug _cfullchain "$_cfullchain" |
||||
|
|
||||
|
if ! _exists openstack; then |
||||
|
_err "OpenStack client not found" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_openstack_credentials || return $? |
||||
|
|
||||
|
_info "Generate import pkcs12" |
||||
|
_import_pkcs12="$(_mktemp)" |
||||
|
if ! _openstack_to_pkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca"; then |
||||
|
_err "Error creating pkcs12 certificate" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _import_pkcs12 "$_import_pkcs12" |
||||
|
_base64_pkcs12=$(_base64 "multiline" <"$_import_pkcs12") |
||||
|
|
||||
|
secretHrefs=$(_openstack_get_secrets) |
||||
|
_debug secretHrefs "$secretHrefs" |
||||
|
_openstack_store_secret || return $? |
||||
|
|
||||
|
if [ -n "$secretHrefs" ]; then |
||||
|
_info "Cleaning up existing secret" |
||||
|
_openstack_delete_secrets || return $? |
||||
|
fi |
||||
|
|
||||
|
_info "Certificate successfully deployed" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_openstack_store_secret() { |
||||
|
if ! openstack secret store --name "$_cdomain." -t 'application/octet-stream' -e base64 --payload "$_base64_pkcs12"; then |
||||
|
_err "Failed to create OpenStack secret" |
||||
|
return 1 |
||||
|
fi |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
_openstack_delete_secrets() { |
||||
|
echo "$secretHrefs" | while read -r secretHref; do |
||||
|
_info "Deleting old secret $secretHref" |
||||
|
if ! openstack secret delete "$secretHref"; then |
||||
|
_err "Failed to delete OpenStack secret" |
||||
|
return 1 |
||||
|
fi |
||||
|
done |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
_openstack_get_secrets() { |
||||
|
if ! secretHrefs=$(openstack secret list -f value --name "$_cdomain." | cut -d' ' -f1); then |
||||
|
_err "Failed to list secrets" |
||||
|
return 1 |
||||
|
fi |
||||
|
echo "$secretHrefs" |
||||
|
} |
||||
|
|
||||
|
_openstack_to_pkcs() { |
||||
|
# The existing _toPkcs command can't allow an empty password, due to sh |
||||
|
# -z test, so copied here and forcing the empty password. |
||||
|
_cpfx="$1" |
||||
|
_ckey="$2" |
||||
|
_ccert="$3" |
||||
|
_cca="$4" |
||||
|
|
||||
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:" |
||||
|
} |
||||
|
|
||||
|
_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 |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Here is a script to deploy cert to hashicorp vault using curl |
||||
|
# (https://www.vaultproject.io/) |
||||
|
# |
||||
|
# it requires following environment variables: |
||||
|
# |
||||
|
# VAULT_PREFIX - this contains the prefix path in vault |
||||
|
# VAULT_ADDR - vault requires this to find your vault server |
||||
|
# |
||||
|
# additionally, you need to ensure that VAULT_TOKEN is avialable |
||||
|
# to access the vault server |
||||
|
|
||||
|
#returns 0 means success, otherwise error. |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#domain keyfile certfile cafile fullchain |
||||
|
vault_deploy() { |
||||
|
|
||||
|
_cdomain="$1" |
||||
|
_ckey="$2" |
||||
|
_ccert="$3" |
||||
|
_cca="$4" |
||||
|
_cfullchain="$5" |
||||
|
|
||||
|
_debug _cdomain "$_cdomain" |
||||
|
_debug _ckey "$_ckey" |
||||
|
_debug _ccert "$_ccert" |
||||
|
_debug _cca "$_cca" |
||||
|
_debug _cfullchain "$_cfullchain" |
||||
|
|
||||
|
# validate required env vars |
||||
|
_getdeployconf VAULT_PREFIX |
||||
|
if [ -z "$VAULT_PREFIX" ]; then |
||||
|
_err "VAULT_PREFIX needs to be defined (contains prefix path in vault)" |
||||
|
return 1 |
||||
|
fi |
||||
|
_savedeployconf VAULT_PREFIX "$VAULT_PREFIX" |
||||
|
|
||||
|
_getdeployconf VAULT_ADDR |
||||
|
if [ -z "$VAULT_ADDR" ]; then |
||||
|
_err "VAULT_ADDR needs to be defined (contains vault connection address)" |
||||
|
return 1 |
||||
|
fi |
||||
|
_savedeployconf VAULT_ADDR "$VAULT_ADDR" |
||||
|
|
||||
|
# JSON does not allow multiline strings. |
||||
|
# So replacing new-lines with "\n" here |
||||
|
_ckey=$(sed -z 's/\n/\\n/g' <"$2") |
||||
|
_ccert=$(sed -z 's/\n/\\n/g' <"$3") |
||||
|
_cca=$(sed -z 's/\n/\\n/g' <"$4") |
||||
|
_cfullchain=$(sed -z 's/\n/\\n/g' <"$5") |
||||
|
|
||||
|
URL="$VAULT_ADDR/v1/$VAULT_PREFIX/$_cdomain" |
||||
|
export _H1="X-Vault-Token: $VAULT_TOKEN" |
||||
|
|
||||
|
if [ -n "$FABIO" ]; then |
||||
|
_post "{\"cert\": \"$_cfullchain\", \"key\": \"$_ckey\"}" "$URL" |
||||
|
else |
||||
|
_post "{\"value\": \"$_ccert\"}" "$URL/cert.pem" |
||||
|
_post "{\"value\": \"$_ckey\"}" "$URL/cert.key" |
||||
|
_post "{\"value\": \"$_cca\"}" "$URL/chain.pem" |
||||
|
_post "{\"value\": \"$_cfullchain\"}" "$URL/fullchain.pem" |
||||
|
fi |
||||
|
|
||||
|
} |
@ -0,0 +1,150 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# Anexia CloudDNS acme.sh hook |
||||
|
# Author: MA |
||||
|
|
||||
|
#ANX_Token="xxxx" |
||||
|
|
||||
|
ANX_API='https://engine.anexia-it.com/api/clouddns/v1' |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
dns_anx_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_info "Using ANX CDNS API" |
||||
|
|
||||
|
ANX_Token="${ANX_Token:-$(_readaccountconf_mutable ANX_Token)}" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
if [ "$ANX_Token" ]; then |
||||
|
_saveaccountconf_mutable ANX_Token "$ANX_Token" |
||||
|
else |
||||
|
_err "You didn't specify a ANEXIA Engine API token." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug "First detect the root zone" |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
# Always add records, wildcard need two records with the same name |
||||
|
_anx_rest POST "zone.json/${_domain}/records" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"rdata\":\"$txtvalue\"}" |
||||
|
if _contains "$response" "$txtvalue"; then |
||||
|
return 0 |
||||
|
else |
||||
|
return 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
dns_anx_rm() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
_info "Using ANX CDNS API" |
||||
|
|
||||
|
ANX_Token="${ANX_Token:-$(_readaccountconf_mutable ANX_Token)}" |
||||
|
|
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
_debug "First detect the root zone" |
||||
|
if ! _get_root "$fulldomain"; then |
||||
|
_err "invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_get_record_id |
||||
|
|
||||
|
if _is_uuid "$_record_id"; then |
||||
|
if ! _anx_rest DELETE "zone.json/${_domain}/records/$_record_id"; then |
||||
|
_err "Delete record" |
||||
|
return 1 |
||||
|
fi |
||||
|
else |
||||
|
_info "No record found." |
||||
|
fi |
||||
|
echo "$response" | tr -d " " | grep \"status\":\"OK\" >/dev/null |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_is_uuid() { |
||||
|
pattern='^\{?[A-Z0-9a-z]{8}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{4}-[A-Z0-9a-z]{12}\}?$' |
||||
|
if echo "$1" | _egrep_o "$pattern" >/dev/null; then |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_get_record_id() { |
||||
|
_debug subdomain "$_sub_domain" |
||||
|
_debug domain "$_domain" |
||||
|
|
||||
|
if _anx_rest GET "zone.json/${_domain}/records?name=$_sub_domain&type=TXT"; then |
||||
|
_debug response "$response" |
||||
|
if _contains "$response" "\"name\":\"$_sub_domain\"" >/dev/null; then |
||||
|
_record_id=$(printf "%s\n" "$response" | _egrep_o "\[.\"identifier\":\"[^\"]*\"" | head -n 1 | cut -d : -f 2 | tr -d \") |
||||
|
else |
||||
|
_record_id='' |
||||
|
fi |
||||
|
else |
||||
|
_err "Search existing record" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
_anx_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
export _H2="Authorization: Token $ANX_Token" |
||||
|
|
||||
|
if [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "${ANX_API}/$ep" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "${ANX_API}/$ep")" |
||||
|
fi |
||||
|
|
||||
|
# shellcheck disable=SC2181 |
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug response "$response" |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
|
||||
|
_anx_rest GET "zone.json" |
||||
|
|
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug h "$h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"name\":\"$h\""; then |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
|
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
@ -0,0 +1,199 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
############################################################################### |
||||
|
# Infomaniak API integration |
||||
|
# |
||||
|
# To use this API you need visit the API dashboard of your account |
||||
|
# once logged into https://manager.infomaniak.com add /api/dashboard to the URL |
||||
|
# |
||||
|
# Please report bugs to |
||||
|
# https://github.com/acmesh-official/acme.sh/issues/3188 |
||||
|
# |
||||
|
# Note: the URL looks like this: |
||||
|
# https://manager.infomaniak.com/v3/<account_id>/api/dashboard |
||||
|
# Then generate a token with the scope Domain |
||||
|
# this is given as an environment variable INFOMANIAK_API_TOKEN |
||||
|
############################################################################### |
||||
|
|
||||
|
# base variables |
||||
|
|
||||
|
DEFAULT_INFOMANIAK_API_URL="https://api.infomaniak.com" |
||||
|
DEFAULT_INFOMANIAK_TTL=300 |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_infomaniak_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_infomaniak_add() { |
||||
|
|
||||
|
INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" |
||||
|
INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" |
||||
|
INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_API_TOKEN" ]; then |
||||
|
INFOMANIAK_API_TOKEN="" |
||||
|
_err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_API_URL" ]; then |
||||
|
INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_TTL" ]; then |
||||
|
INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" |
||||
|
fi |
||||
|
|
||||
|
#save the token to the account conf file. |
||||
|
_saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" |
||||
|
|
||||
|
if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then |
||||
|
_saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" |
||||
|
fi |
||||
|
|
||||
|
if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then |
||||
|
_saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" |
||||
|
fi |
||||
|
|
||||
|
export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" |
||||
|
export _H2="Content-Type: application/json" |
||||
|
|
||||
|
fulldomain="$1" |
||||
|
txtvalue="$2" |
||||
|
|
||||
|
_info "Infomaniak DNS API" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
fqdn=${fulldomain#_acme-challenge.} |
||||
|
|
||||
|
# guess which base domain to add record to |
||||
|
zone_and_id=$(_find_zone "$fqdn") |
||||
|
if [ -z "$zone_and_id" ]; then |
||||
|
_err "cannot find zone to modify" |
||||
|
return 1 |
||||
|
fi |
||||
|
zone=${zone_and_id% *} |
||||
|
domain_id=${zone_and_id#* } |
||||
|
|
||||
|
# extract first part of domain |
||||
|
key=${fulldomain%.$zone} |
||||
|
|
||||
|
_debug "zone:$zone id:$domain_id key:$key" |
||||
|
|
||||
|
# payload |
||||
|
data="{\"type\": \"TXT\", \"source\": \"$key\", \"target\": \"$txtvalue\", \"ttl\": $INFOMANIAK_TTL}" |
||||
|
|
||||
|
# API call |
||||
|
response=$(_post "$data" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record") |
||||
|
if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then |
||||
|
_info "Record added" |
||||
|
_debug "Response: $response" |
||||
|
return 0 |
||||
|
fi |
||||
|
_err "could not create record" |
||||
|
_debug "Response: $response" |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#Usage: fulldomain txtvalue |
||||
|
#Remove the txt record after validation. |
||||
|
dns_infomaniak_rm() { |
||||
|
|
||||
|
INFOMANIAK_API_TOKEN="${INFOMANIAK_API_TOKEN:-$(_readaccountconf_mutable INFOMANIAK_API_TOKEN)}" |
||||
|
INFOMANIAK_API_URL="${INFOMANIAK_API_URL:-$(_readaccountconf_mutable INFOMANIAK_API_URL)}" |
||||
|
INFOMANIAK_TTL="${INFOMANIAK_TTL:-$(_readaccountconf_mutable INFOMANIAK_TTL)}" |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_API_TOKEN" ]; then |
||||
|
INFOMANIAK_API_TOKEN="" |
||||
|
_err "Please provide a valid Infomaniak API token in variable INFOMANIAK_API_TOKEN" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_API_URL" ]; then |
||||
|
INFOMANIAK_API_URL="$DEFAULT_INFOMANIAK_API_URL" |
||||
|
fi |
||||
|
|
||||
|
if [ -z "$INFOMANIAK_TTL" ]; then |
||||
|
INFOMANIAK_TTL="$DEFAULT_INFOMANIAK_TTL" |
||||
|
fi |
||||
|
|
||||
|
#save the token to the account conf file. |
||||
|
_saveaccountconf_mutable INFOMANIAK_API_TOKEN "$INFOMANIAK_API_TOKEN" |
||||
|
|
||||
|
if [ "$INFOMANIAK_API_URL" != "$DEFAULT_INFOMANIAK_API_URL" ]; then |
||||
|
_saveaccountconf_mutable INFOMANIAK_API_URL "$INFOMANIAK_API_URL" |
||||
|
fi |
||||
|
|
||||
|
if [ "$INFOMANIAK_TTL" != "$DEFAULT_INFOMANIAK_TTL" ]; then |
||||
|
_saveaccountconf_mutable INFOMANIAK_TTL "$INFOMANIAK_TTL" |
||||
|
fi |
||||
|
|
||||
|
export _H1="Authorization: Bearer $INFOMANIAK_API_TOKEN" |
||||
|
export _H2="ContentType: application/json" |
||||
|
|
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
_info "Infomaniak DNS API" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
fqdn=${fulldomain#_acme-challenge.} |
||||
|
|
||||
|
# guess which base domain to add record to |
||||
|
zone_and_id=$(_find_zone "$fqdn") |
||||
|
if [ -z "$zone_and_id" ]; then |
||||
|
_err "cannot find zone to modify" |
||||
|
return 1 |
||||
|
fi |
||||
|
zone=${zone_and_id% *} |
||||
|
domain_id=${zone_and_id#* } |
||||
|
|
||||
|
# extract first part of domain |
||||
|
key=${fulldomain%.$zone} |
||||
|
|
||||
|
_debug "zone:$zone id:$domain_id key:$key" |
||||
|
|
||||
|
# find previous record |
||||
|
# shellcheck disable=SC1004 |
||||
|
record_id=$(_get "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record" | sed 's/.*"data":\[\(.*\)\]}/\1/; s/},{/}\ |
||||
|
{/g' | sed -n 's/.*"id":"*\([0-9]*\)"*.*"source_idn":"'"$fulldomain"'".*"target_idn":"'"$txtvalue"'".*/\1/p') |
||||
|
if [ -z "$record_id" ]; then |
||||
|
_err "could not find record to delete" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug "record_id: $record_id" |
||||
|
|
||||
|
# API call |
||||
|
response=$(_post "" "${INFOMANIAK_API_URL}/1/domain/$domain_id/dns/record/$record_id" "" DELETE) |
||||
|
if [ -n "$response" ] && echo "$response" | _contains '"result":"success"'; then |
||||
|
_info "Record deleted" |
||||
|
return 0 |
||||
|
fi |
||||
|
_err "could not delete record" |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_get_domain_id() { |
||||
|
domain="$1" |
||||
|
|
||||
|
# shellcheck disable=SC1004 |
||||
|
_get "${INFOMANIAK_API_URL}/1/product?service_name=domain&customer_name=$domain" | sed 's/.*"data":\[{\(.*\)}\]}/\1/; s/,/\ |
||||
|
/g' | sed -n 's/^"id":\(.*\)/\1/p' |
||||
|
} |
||||
|
|
||||
|
_find_zone() { |
||||
|
zone="$1" |
||||
|
|
||||
|
# find domain in list, removing . parts sequentialy |
||||
|
while _contains "$zone" '\.'; do |
||||
|
_debug "testing $zone" |
||||
|
id=$(_get_domain_id "$zone") |
||||
|
if [ -n "$id" ]; then |
||||
|
echo "$zone $id" |
||||
|
return |
||||
|
fi |
||||
|
zone=${zone#*.} |
||||
|
done |
||||
|
} |
@ -0,0 +1,150 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# kapper.net domain api |
||||
|
# for further questions please contact: support@kapper.net |
||||
|
# please report issues here: https://github.com/acmesh-official/acme.sh/issues/2977 |
||||
|
|
||||
|
#KAPPERNETDNS_Key="yourKAPPERNETapikey" |
||||
|
#KAPPERNETDNS_Secret="yourKAPPERNETapisecret" |
||||
|
|
||||
|
KAPPERNETDNS_Api="https://dnspanel.kapper.net/API/1.2?APIKey=$KAPPERNETDNS_Key&APISecret=$KAPPERNETDNS_Secret" |
||||
|
|
||||
|
############################################################################### |
||||
|
# called with |
||||
|
# fullhostname: something.example.com |
||||
|
# txtvalue: someacmegenerated string |
||||
|
dns_kappernet_add() { |
||||
|
fullhostname=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}" |
||||
|
KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}" |
||||
|
|
||||
|
if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then |
||||
|
KAPPERNETDNS_Key="" |
||||
|
KAPPERNETDNS_Secret="" |
||||
|
_err "Please specify your kapper.net api key and secret." |
||||
|
_err "If you have not received yours - send your mail to" |
||||
|
_err "support@kapper.net to get your key and secret." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#store the api key and email to the account conf file. |
||||
|
_saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key" |
||||
|
_saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" |
||||
|
_debug "Checking Domain ..." |
||||
|
if ! _get_root "$fullhostname"; then |
||||
|
_err "invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug _sub_domain "SUBDOMAIN: $_sub_domain" |
||||
|
_debug _domain "DOMAIN: $_domain" |
||||
|
|
||||
|
_info "Trying to add TXT DNS Record" |
||||
|
data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" |
||||
|
if _kappernet_api GET "action=new&subject=$_domain&data=$data"; then |
||||
|
|
||||
|
if _contains "$response" "{\"OK\":true"; then |
||||
|
_info "Waiting 120 seconds for DNS to spread the new record" |
||||
|
_sleep 120 |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Error creating a TXT DNS Record: $fullhostname TXT $txtvalue" |
||||
|
_err "Error Message: $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Failed creating TXT Record" |
||||
|
} |
||||
|
|
||||
|
############################################################################### |
||||
|
# called with |
||||
|
# fullhostname: something.example.com |
||||
|
dns_kappernet_rm() { |
||||
|
fullhostname=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
KAPPERNETDNS_Key="${KAPPERNETDNS_Key:-$(_readaccountconf_mutable KAPPERNETDNS_Key)}" |
||||
|
KAPPERNETDNS_Secret="${KAPPERNETDNS_Secret:-$(_readaccountconf_mutable KAPPERNETDNS_Secret)}" |
||||
|
|
||||
|
if [ -z "$KAPPERNETDNS_Key" ] || [ -z "$KAPPERNETDNS_Secret" ]; then |
||||
|
KAPPERNETDNS_Key="" |
||||
|
KAPPERNETDNS_Secret="" |
||||
|
_err "Please specify your kapper.net api key and secret." |
||||
|
_err "If you have not received yours - send your mail to" |
||||
|
_err "support@kapper.net to get your key and secret." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
#store the api key and email to the account conf file. |
||||
|
_saveaccountconf_mutable KAPPERNETDNS_Key "$KAPPERNETDNS_Key" |
||||
|
_saveaccountconf_mutable KAPPERNETDNS_Secret "$KAPPERNETDNS_Secret" |
||||
|
|
||||
|
_info "Trying to remove the TXT Record: $fullhostname containing $txtvalue" |
||||
|
data="%7B%22name%22%3A%22$fullhostname%22%2C%22type%22%3A%22TXT%22%2C%22content%22%3A%22$txtvalue%22%2C%22ttl%22%3A%223600%22%2C%22prio%22%3A%22%22%7D" |
||||
|
if _kappernet_api GET "action=del&subject=$fullhostname&data=$data"; then |
||||
|
if _contains "$response" "{\"OK\":true"; then |
||||
|
return 0 |
||||
|
else |
||||
|
_err "Error deleting DNS Record: $fullhostname containing $txtvalue" |
||||
|
_err "Problem: $response" |
||||
|
return 1 |
||||
|
fi |
||||
|
fi |
||||
|
_err "Problem deleting TXT DNS record" |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
# called with hostname |
||||
|
# e.g._acme-challenge.www.domain.com returns |
||||
|
# _sub_domain=_acme-challenge.www |
||||
|
# _domain=domain.com |
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
i=2 |
||||
|
p=1 |
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
return 1 |
||||
|
fi |
||||
|
if ! _kappernet_api GET "action=list&subject=$h"; then |
||||
|
return 1 |
||||
|
fi |
||||
|
if _contains "$response" '"OK":false'; then |
||||
|
_debug "$h not found" |
||||
|
else |
||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) |
||||
|
_domain="$h" |
||||
|
return 0 |
||||
|
fi |
||||
|
p="$i" |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
################################################################################ |
||||
|
# calls the kapper.net DNS Panel API |
||||
|
# with |
||||
|
# method |
||||
|
# param |
||||
|
_kappernet_api() { |
||||
|
method=$1 |
||||
|
param="$2" |
||||
|
|
||||
|
_debug param "PARAMETER=$param" |
||||
|
url="$KAPPERNETDNS_Api&$param" |
||||
|
_debug url "URL=$url" |
||||
|
|
||||
|
if [ "$method" = "GET" ]; then |
||||
|
response="$(_get "$url")" |
||||
|
else |
||||
|
_err "Unsupported method" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,162 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
#NETLIFY_ACCESS_TOKEN="xxxx" |
||||
|
|
||||
|
NETLIFY_HOST="api.netlify.com/api/v1/" |
||||
|
NETLIFY_URL="https://$NETLIFY_HOST" |
||||
|
|
||||
|
######## Public functions ##################### |
||||
|
|
||||
|
#Usage: dns_myapi_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
dns_netlify_add() { |
||||
|
fulldomain=$1 |
||||
|
txtvalue=$2 |
||||
|
|
||||
|
NETLIFY_ACCESS_TOKEN="${NETLIFY_ACCESS_TOKEN:-$(_readaccountconf_mutable NETLIFY_ACCESS_TOKEN)}" |
||||
|
|
||||
|
if [ -z "$NETLIFY_ACCESS_TOKEN" ]; then |
||||
|
NETLIFY_ACCESS_TOKEN="" |
||||
|
_err "Please specify your Netlify Access Token and try again." |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_info "Using Netlify" |
||||
|
_debug fulldomain "$fulldomain" |
||||
|
_debug txtvalue "$txtvalue" |
||||
|
|
||||
|
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN" |
||||
|
|
||||
|
if ! _get_root "$fulldomain" "$accesstoken"; then |
||||
|
_err "invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug _domain_id "$_domain_id" |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
dnsRecordURI="dns_zones/$_domain_id/dns_records" |
||||
|
|
||||
|
body="{\"type\":\"TXT\", \"hostname\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"ttl\":\"10\"}" |
||||
|
|
||||
|
_netlify_rest POST "$dnsRecordURI" "$body" "$NETLIFY_ACCESS_TOKEN" |
||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" |
||||
|
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then |
||||
|
_info "validation value added" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "error adding validation value ($_code)" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_err "Not fully implemented!" |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#Usage: dns_myapi_rm _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" |
||||
|
#Remove the txt record after validation. |
||||
|
dns_netlify_rm() { |
||||
|
_info "Using Netlify" |
||||
|
txtdomain="$1" |
||||
|
txt="$2" |
||||
|
_debug txtdomain "$txtdomain" |
||||
|
_debug txt "$txt" |
||||
|
|
||||
|
_saveaccountconf_mutable NETLIFY_ACCESS_TOKEN "$NETLIFY_ACCESS_TOKEN" |
||||
|
|
||||
|
if ! _get_root "$txtdomain" "$accesstoken"; then |
||||
|
_err "invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
_debug _domain_id "$_domain_id" |
||||
|
_debug _sub_domain "$_sub_domain" |
||||
|
_debug _domain "$_domain" |
||||
|
|
||||
|
dnsRecordURI="dns_zones/$_domain_id/dns_records" |
||||
|
|
||||
|
_netlify_rest GET "$dnsRecordURI" "" "$NETLIFY_ACCESS_TOKEN" |
||||
|
|
||||
|
_record_id=$(echo "$response" | _egrep_o "\"type\":\"TXT\",[^\}]*\"value\":\"$txt\"" | head -n 1 | _egrep_o "\"id\":\"[^\"\}]*\"" | cut -d : -f 2 | tr -d \") |
||||
|
_debug _record_id "$_record_id" |
||||
|
if [ "$_record_id" ]; then |
||||
|
_netlify_rest DELETE "$dnsRecordURI/$_record_id" "" "$NETLIFY_ACCESS_TOKEN" |
||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" |
||||
|
if [ "$_code" = "200" ] || [ "$_code" = '204' ]; then |
||||
|
_info "validation value removed" |
||||
|
return 0 |
||||
|
else |
||||
|
_err "error removing validation value ($_code)" |
||||
|
return 1 |
||||
|
fi |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
#################### Private functions below ################################## |
||||
|
|
||||
|
_get_root() { |
||||
|
domain=$1 |
||||
|
accesstoken=$2 |
||||
|
i=1 |
||||
|
p=1 |
||||
|
|
||||
|
_netlify_rest GET "dns_zones" "" "$accesstoken" |
||||
|
|
||||
|
while true; do |
||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100) |
||||
|
_debug2 "Checking domain: $h" |
||||
|
if [ -z "$h" ]; then |
||||
|
#not valid |
||||
|
_err "Invalid domain" |
||||
|
return 1 |
||||
|
fi |
||||
|
|
||||
|
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then |
||||
|
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \") |
||||
|
if [ "$_domain_id" ]; then |
||||
|
if [ "$i" = 1 ]; then |
||||
|
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias |
||||
|
_sub_domain="@" |
||||
|
else |
||||
|
_sub_domain=$(echo "$domain" | cut -d . -f 1-$p) |
||||
|
fi |
||||
|
_domain=$h |
||||
|
return 0 |
||||
|
fi |
||||
|
return 1 |
||||
|
fi |
||||
|
p=$i |
||||
|
i=$(_math "$i" + 1) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
_netlify_rest() { |
||||
|
m=$1 |
||||
|
ep="$2" |
||||
|
data="$3" |
||||
|
_debug "$ep" |
||||
|
|
||||
|
token_trimmed=$(echo "$NETLIFY_ACCESS_TOKEN" | tr -d '"') |
||||
|
|
||||
|
export _H1="Content-Type: application/json" |
||||
|
export _H2="Authorization: Bearer $token_trimmed" |
||||
|
|
||||
|
: >"$HTTP_HEADER" |
||||
|
|
||||
|
if [ "$m" != "GET" ]; then |
||||
|
_debug data "$data" |
||||
|
response="$(_post "$data" "$NETLIFY_URL$ep" "" "$m")" |
||||
|
else |
||||
|
response="$(_get "$NETLIFY_URL$ep")" |
||||
|
fi |
||||
|
|
||||
|
if [ "$?" != "0" ]; then |
||||
|
_err "error $ep" |
||||
|
return 1 |
||||
|
fi |
||||
|
_debug2 response "$response" |
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,348 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
|
||||
|
# OpenStack Designate API plugin |
||||
|
# |
||||
|
# This requires you to have OpenStackClient and python-desginateclient |
||||
|
# installed. |
||||
|
# |
||||
|
# You will require Keystone V3 credentials loaded into your environment, which |
||||
|
# could be either password or v3applicationcredential type. |
||||
|
# |
||||
|
# 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 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue