From: Thomas Lamprecht Date: Wed, 5 May 2021 12:07:35 +0000 (+0200) Subject: move DNS plugin schema to separate JSON based file X-Git-Url: https://git.proxmox.com/?p=proxmox-acme.git;a=commitdiff_plain;h=4195bf0a9a4fe7ea7a838df3b8dd1a44036d9930 move DNS plugin schema to separate JSON based file Signed-off-by: Thomas Lamprecht --- diff --git a/src/Makefile b/src/Makefile index 27418d0..16166fe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -137,6 +137,7 @@ all: .PHONY: install install: install -D -m 0744 proxmox-acme ${DESTDIR}${ACMEDIR}/proxmox-acme + install -D -m 0644 dns-challenge-schema.json ${DESTDIR}${ACMEDIR}/dns-challenge-schema.json for f in ${ACME_SOURCES}; do install -D -m 0644 acme.sh/$$f ${DESTDIR}${ACMEDIR}/$$f; done install -d -m 0755 ${DESTDIR}${PERLDIR}/PVE install -d -m 0755 ${DESTDIR}${PERLDIR}/PVE/ACME diff --git a/src/PVE/ACME/DNSChallenge.pm b/src/PVE/ACME/DNSChallenge.pm index ce66f3c..9b28970 100644 --- a/src/PVE/ACME/DNSChallenge.pm +++ b/src/PVE/ACME/DNSChallenge.pm @@ -4,6 +4,8 @@ use strict; use warnings; use Digest::SHA qw(sha256); +use JSON; + use PVE::Tools; use PVE::ACME; @@ -20,356 +22,8 @@ sub type { return 'dns'; } -# describe the data schema of the supported plugins, e.g.: -# 'dnsprovider' => { -# name => 'Full name of Plugin', -# fields => { -# 'FOO_API_KEY' => { -# description => "The API key", -# default => "none", -# optional => 1, -# type => 'string', -# }, -# # ... -# }, -# }, -my $plugins = { - '1984hosting' => {}, - 'acmedns' => { - name => 'acme-dns', - fields => { - 'ACMEDNS_UPDATE_URL' => { - description => 'The API update endpoint', - type => 'string', - }, - 'ACMEDNS_USERNAME' => { - description => 'The acme-dns user', - type => 'string', - }, - 'ACMEDNS_PASSWORD' => { - description => 'The acme-dns password', - type => 'string', - }, - 'ACMEDNS_SUBDOMAIN' => { - description => 'The subdomain you got from acme-dns registration', - type => 'string', - }, - }, - }, - 'acmeproxy' => {}, - 'active24' => { - name => 'Active24', - fields => { - 'ACTIVE24_Token' => { - description => "The API key", - type => 'string', - }, - }, - }, - 'ad' => { - name => 'Alwaysdata', - fields => { - 'AD_API_KEY' => { - description => "The API key", - type => 'string', - }, - }, - }, - 'ali' => { - name => 'Alibaba Cloud DNS', - fields => { - 'Ali_API' => { - description => 'The API endpoint', - default => "https://alidns.aliyuncs.com/", - type => 'string', - optional => 1, - }, - 'Ali_Key' => { - description => 'The API Key', - type => 'string', - }, - 'Ali_Secret' => { - description => 'The API Secret', - type => 'string', - }, - }, - }, - 'anx' => {}, - 'arvan' => {}, - 'aurora' => { - name => 'AuroraDNS', - fields => { - 'AURORA_Key' => { - description => 'The API Key', - type => 'string', - }, - 'AURORA_Secret' => { - description => 'The API Secret', - type => 'string', - }, - }, - }, - 'autodns' => {}, - 'aws' => { - name => 'Amazon Route53 (AWS)', - fields => { - 'AWS_ACCESS_KEY_ID' => { - name => 'ACCESS_KEY_ID', - description => 'The AWS access-key ID', - type => 'string', - }, - 'AWS_SECRET_ACCESS_KEY' => { - name => 'SECRET_ACCESS_KEY', - description => 'The AWS access-key secret', - type => 'string', - }, - }, - }, - 'azure' => {}, - 'cf' => { - name => 'Cloudflare Managed DNS', - description => 'Either provide global account key and email, or CF API token and Account ID.', - fields => { - 'CF_Key' => { - description => 'The Cloudflare Global API Key', - type => 'string', - }, - 'CF_Email' => { - description => 'The Cloudflare Account EMail-Address', - type => 'string', - }, - 'CF_Token' => { - description => 'The new Cloudflare API Token', - type => 'string', - }, - 'CF_Account_ID' => { - description => 'The new Cloudflare API Account ID', - type => 'string', - }, - 'CF_Zone_ID' => { - description => 'For Zone restricted API Token', - type => 'string', - }, - }, - }, - 'clouddns' => {}, - 'cloudns' => {}, - 'cn' => {}, - 'conoha' => {}, - 'constellix' => {}, - 'cx' => {}, - 'cyon' => {}, - 'da' => {}, - 'ddnss' => {}, - 'desec' => {}, - 'df' => {}, - 'dgon' => { - name => 'DigitalOcean DNS', - fields => { - 'DO_API_KEY' => { - description => 'The DigitalOcean API Key', - type => 'string', - }, - }, - }, - 'dnsimple' => {}, - 'do' => {}, - 'doapi' => {}, - 'domeneshop' => {}, - 'dp' => {}, - 'dpi' => {}, - 'dreamhost' => {}, - 'duckdns' => {}, - 'durabledns' => {}, - 'dyn' => {}, - 'dynu' => {}, - 'dynv6' => {}, - 'easydns' => {}, - 'edgedns' => {}, - 'euserv' => {}, - 'exoscale' => {}, - 'freedns' => {}, - 'gandi_livedns' => {}, - 'gcloud' => {}, - 'gd' => { - name => 'GoDaddy', - fields => { - 'GD_Key' => { - description => 'The GoDaddy API Key', - type => 'string', - }, - 'GD_Secret' => { - description => 'The GoDaddy API Secret', - type => 'string', - }, - }, - }, - 'gdnsdk' => {}, - 'he' => {}, - 'hetzner' => {}, - 'hexonet' => {}, - 'hostingde' => {}, - 'huaweicloud' => {}, - 'infoblox' => {}, - 'infomaniak' => {}, - 'internetbs' => {}, - 'inwx' => { - name => 'INWX', - fields => { - 'INWX_User' => { - description => 'The INWX username', - type => 'string', - }, - 'INWX_Password' => { - description => 'The INWX password', - type => 'string', - }, - }, - }, - 'ionos' => {}, - 'ispconfig' => {}, - 'jd' => {}, - 'joker' => {}, - 'kappernet' => { - name => 'kapper.net', - fields => { - 'KAPPERNETDNS_Key' => { - description => 'Your kapper.net API key', - type => 'string', - }, - 'KAPPERNETDNS_Secret' => { - description => 'Your kapper.net API secret', - type => 'string', - }, - }, - }, - 'kas' => {}, - 'kinghost' => {}, - 'knot' => {}, - 'leaseweb' => {}, - 'lexicon' => {}, - 'linode' => {}, - 'linode_v4' => {}, - 'loopia' => {}, - 'lua' => {}, - 'maradns' => {}, - 'me' => {}, - 'miab' => {}, - 'misaka' => {}, - 'myapi' => {}, - 'mydevil' => {}, - 'mydnsjp' => {}, - 'namecheap' => {}, - 'namecom' => {}, - 'namesilo' => {}, - 'nederhost' => {}, - 'neodigit' => {}, - 'netcup' => {}, - 'netlify' => {}, - 'nic' => {}, - 'njalla' => {}, - 'nm' => {}, - 'nsd' => {}, - 'nsone' => {}, - 'nsupdate' => {}, - 'nw' => {}, - 'one' => {}, - 'online' => {}, - 'openprovider' => {}, - 'openstack' => {}, - 'opnsense' => {}, - 'ovh' => { - name => 'OVH', - fields => { - 'OVH_END_POINT' => { - description => "The OVH endpoint", - default => "ovh-eu", - optional => 1, - type => 'string', - }, - 'OVH_AK' => { - description => "The application key.", - type => 'string', - }, - 'OVH_AS' => { - description => "The application secret.", - type => 'string', - }, - 'OVH_CK' => { - description => "The consumer key.", - optional => 1, - type => 'string', - }, - }, - }, - 'pdns' => { - name => 'PowerDNS server', - fields => { - 'PDNS_Url' => { - description => "The PowerDNS API endpoint.", - type => 'string', - }, - 'PDNS_ServerId'=> { - type => 'string', - }, - 'PDNS_Token'=> { - type => 'string', - }, - 'PDNS_Ttl'=> { - type => 'integer', - }, - }, - }, - 'pleskxml' => {}, - 'pointhq' => {}, - 'porkbun' => { - name => 'Porkbun', - fields => { - 'PORKBUN_API_KEY' => { - description => 'The API Key', - type => 'string', - }, - 'PORKBUN_SECRET_API_KEY' => { - description => 'The API Secret', - type => 'string', - }, - }, - }, - 'rackcorp' => {}, - 'rackspace' => {}, - 'rcode0' => {}, - 'regru' => {}, - 'scaleway' => {}, - 'schlundtech' => {}, - 'selectel' => {}, - 'servercow' => {}, - 'simply' => {}, - 'tele3' => {}, - 'transip' => {}, - 'ultra' => {}, - 'unoeuro' => {}, - 'variomedia' => {}, - 'vscale' => {}, - 'vultr' => {}, - 'world4you' => { - name => 'World4You', - fields => { - 'WORLD4YOU_USERNAME' => { - description => "The World4You customer id or package id", - type => 'string', - }, - 'WORLD4YOU_PASSWORD' => { - description => "The World4You password", - type => 'string', - }, - }, - }, - 'websupport' => {}, - 'yandex' => {}, - 'zilore' => {}, - 'zone' => {}, - 'zonomi' => {}, -}; +my $DNS_API_CHALLENGE_SCHEMA_FN = '/usr/share/proxmox-acme/dns-challenge-schema.json'; +my $plugins = from_json(PVE::Tools::file_get_contents($DNS_API_CHALLENGE_SCHEMA_FN)); sub get_supported_plugins { return $plugins; diff --git a/src/dns-challenge-schema.README b/src/dns-challenge-schema.README new file mode 100644 index 0000000..1de1cd1 --- /dev/null +++ b/src/dns-challenge-schema.README @@ -0,0 +1,44 @@ +Introduction +------------ + +Promxox projects (PVE, PMG, PBS) all support ACME with DNS challenges. +As there are many DNS providers we re-use the plugins for the great [acme.sh] +project. + +As a user interface needs to know which plugins there are supported we need to +provide at least the list of known ones. +But, we extend that and return a full JSON-Schema oriented Object Schema, so +that any user-interface can use that to show UX hints and create the respective +inputs for each plugin. + +Note, we do not define a full schema for all plugins, but accept patches for +adding one. See the [developer-documentation] about how to do so. + +We use JSON as format as we need this schema in both, perl and rust based +projects. + +Schema Example +-------------- + +A entry describing the data schema of a supported plugin could look like: + +``` +'dnsprovider' => { + name => 'Full name of Plugin', + fields => { + 'FOO_API_KEY' => { + description => "The API key", + default => "none", + optional => 1, + type => 'string', + }, + ... + }, +}, +``` + +References +---------- + +[acme.sh]: https://acme.sh/ +[developer-documentation]: https://pve.proxmox.com/wiki/Developer_Documentation diff --git a/src/dns-challenge-schema.json b/src/dns-challenge-schema.json new file mode 100644 index 0000000..559077f --- /dev/null +++ b/src/dns-challenge-schema.json @@ -0,0 +1,337 @@ +{ + "1984hosting" : {}, + "acmedns" : { + "fields" : { + "ACMEDNS_PASSWORD" : { + "description" : "The acme-dns password", + "type" : "string" + }, + "ACMEDNS_SUBDOMAIN" : { + "description" : "The subdomain you got from acme-dns registration", + "type" : "string" + }, + "ACMEDNS_UPDATE_URL" : { + "description" : "The API update endpoint", + "type" : "string" + }, + "ACMEDNS_USERNAME" : { + "description" : "The acme-dns user", + "type" : "string" + } + }, + "name" : "acme-dns" + }, + "acmeproxy" : {}, + "active24" : { + "fields" : { + "ACTIVE24_Token" : { + "description" : "The API key", + "type" : "string" + } + }, + "name" : "Active24" + }, + "ad" : { + "fields" : { + "AD_API_KEY" : { + "description" : "The API key", + "type" : "string" + } + }, + "name" : "Alwaysdata" + }, + "ali" : { + "fields" : { + "Ali_API" : { + "default" : "https://alidns.aliyuncs.com/", + "description" : "The API endpoint", + "optional" : 1, + "type" : "string" + }, + "Ali_Key" : { + "description" : "The API Key", + "type" : "string" + }, + "Ali_Secret" : { + "description" : "The API Secret", + "type" : "string" + } + }, + "name" : "Alibaba Cloud DNS" + }, + "anx" : {}, + "arvan" : {}, + "aurora" : { + "fields" : { + "AURORA_Key" : { + "description" : "The API Key", + "type" : "string" + }, + "AURORA_Secret" : { + "description" : "The API Secret", + "type" : "string" + } + }, + "name" : "AuroraDNS" + }, + "autodns" : {}, + "aws" : { + "fields" : { + "AWS_ACCESS_KEY_ID" : { + "description" : "The AWS access-key ID", + "name" : "ACCESS_KEY_ID", + "type" : "string" + }, + "AWS_SECRET_ACCESS_KEY" : { + "description" : "The AWS access-key secret", + "name" : "SECRET_ACCESS_KEY", + "type" : "string" + } + }, + "name" : "Amazon Route53 (AWS)" + }, + "azure" : {}, + "cf" : { + "description" : "Either provide global account key and email, or CF API token and Account ID.", + "fields" : { + "CF_Account_ID" : { + "description" : "The new Cloudflare API Account ID", + "type" : "string" + }, + "CF_Email" : { + "description" : "The Cloudflare Account EMail-Address", + "type" : "string" + }, + "CF_Key" : { + "description" : "The Cloudflare Global API Key", + "type" : "string" + }, + "CF_Token" : { + "description" : "The new Cloudflare API Token", + "type" : "string" + }, + "CF_Zone_ID" : { + "description" : "For Zone restricted API Token", + "type" : "string" + } + }, + "name" : "Cloudflare Managed DNS" + }, + "clouddns" : {}, + "cloudns" : {}, + "cn" : {}, + "conoha" : {}, + "constellix" : {}, + "cx" : {}, + "cyon" : {}, + "da" : {}, + "ddnss" : {}, + "desec" : {}, + "df" : {}, + "dgon" : { + "fields" : { + "DO_API_KEY" : { + "description" : "The DigitalOcean API Key", + "type" : "string" + } + }, + "name" : "DigitalOcean DNS" + }, + "dnsimple" : {}, + "do" : {}, + "doapi" : {}, + "domeneshop" : {}, + "dp" : {}, + "dpi" : {}, + "dreamhost" : {}, + "duckdns" : {}, + "durabledns" : {}, + "dyn" : {}, + "dynu" : {}, + "dynv6" : {}, + "easydns" : {}, + "edgedns" : {}, + "euserv" : {}, + "exoscale" : {}, + "freedns" : {}, + "gandi_livedns" : {}, + "gcloud" : {}, + "gd" : { + "fields" : { + "GD_Key" : { + "description" : "The GoDaddy API Key", + "type" : "string" + }, + "GD_Secret" : { + "description" : "The GoDaddy API Secret", + "type" : "string" + } + }, + "name" : "GoDaddy" + }, + "gdnsdk" : {}, + "he" : {}, + "hetzner" : {}, + "hexonet" : {}, + "hostingde" : {}, + "huaweicloud" : {}, + "infoblox" : {}, + "infomaniak" : {}, + "internetbs" : {}, + "inwx" : { + "fields" : { + "INWX_Password" : { + "description" : "The INWX password", + "type" : "string" + }, + "INWX_User" : { + "description" : "The INWX username", + "type" : "string" + } + }, + "name" : "INWX" + }, + "ionos" : {}, + "ispconfig" : {}, + "jd" : {}, + "joker" : {}, + "kappernet" : { + "fields" : { + "KAPPERNETDNS_Key" : { + "description" : "Your kapper.net API key", + "type" : "string" + }, + "KAPPERNETDNS_Secret" : { + "description" : "Your kapper.net API secret", + "type" : "string" + } + }, + "name" : "kapper.net" + }, + "kas" : {}, + "kinghost" : {}, + "knot" : {}, + "leaseweb" : {}, + "lexicon" : {}, + "linode" : {}, + "linode_v4" : {}, + "loopia" : {}, + "lua" : {}, + "maradns" : {}, + "me" : {}, + "miab" : {}, + "misaka" : {}, + "myapi" : {}, + "mydevil" : {}, + "mydnsjp" : {}, + "namecheap" : {}, + "namecom" : {}, + "namesilo" : {}, + "nederhost" : {}, + "neodigit" : {}, + "netcup" : {}, + "netlify" : {}, + "nic" : {}, + "njalla" : {}, + "nm" : {}, + "nsd" : {}, + "nsone" : {}, + "nsupdate" : {}, + "nw" : {}, + "one" : {}, + "online" : {}, + "openprovider" : {}, + "openstack" : {}, + "opnsense" : {}, + "ovh" : { + "fields" : { + "OVH_AK" : { + "description" : "The application key.", + "type" : "string" + }, + "OVH_AS" : { + "description" : "The application secret.", + "type" : "string" + }, + "OVH_CK" : { + "description" : "The consumer key.", + "optional" : 1, + "type" : "string" + }, + "OVH_END_POINT" : { + "default" : "ovh-eu", + "description" : "The OVH endpoint", + "optional" : 1, + "type" : "string" + } + }, + "name" : "OVH" + }, + "pdns" : { + "fields" : { + "PDNS_ServerId" : { + "type" : "string" + }, + "PDNS_Token" : { + "type" : "string" + }, + "PDNS_Ttl" : { + "type" : "integer" + }, + "PDNS_Url" : { + "description" : "The PowerDNS API endpoint.", + "type" : "string" + } + }, + "name" : "PowerDNS server" + }, + "pleskxml" : {}, + "pointhq" : {}, + "porkbun" : { + "fields" : { + "PORKBUN_API_KEY" : { + "description" : "The API Key", + "type" : "string" + }, + "PORKBUN_SECRET_API_KEY" : { + "description" : "The API Secret", + "type" : "string" + } + }, + "name" : "Porkbun" + }, + "rackcorp" : {}, + "rackspace" : {}, + "rcode0" : {}, + "regru" : {}, + "scaleway" : {}, + "schlundtech" : {}, + "selectel" : {}, + "servercow" : {}, + "simply" : {}, + "tele3" : {}, + "transip" : {}, + "ultra" : {}, + "unoeuro" : {}, + "variomedia" : {}, + "vscale" : {}, + "vultr" : {}, + "websupport" : {}, + "world4you" : { + "fields" : { + "WORLD4YOU_PASSWORD" : { + "description" : "The World4You password", + "type" : "string" + }, + "WORLD4YOU_USERNAME" : { + "description" : "The World4You customer id or package id", + "type" : "string" + } + }, + "name" : "World4You" + }, + "yandex" : {}, + "zilore" : {}, + "zone" : {}, + "zonomi" : {} +} diff --git a/src/test/verify-dnsapi-plugins-in-schema.pl b/src/test/verify-dnsapi-plugins-in-schema.pl index 3f1377e..a962861 100755 --- a/src/test/verify-dnsapi-plugins-in-schema.pl +++ b/src/test/verify-dnsapi-plugins-in-schema.pl @@ -5,8 +5,9 @@ use warnings; use lib '../'; -use PVE::Tools qw(dir_glob_foreach); -use PVE::ACME::DNSChallenge; +use JSON; + +use PVE::Tools qw(dir_glob_foreach file_get_contents); my $dnsapi_path = '../acme.sh/dnsapi'; @@ -18,9 +19,10 @@ dir_glob_foreach($dnsapi_path, qr/dns_(\S+)\.sh/, sub { push @$acmesh_plugins, $provider; }); -my $ok = 1; -my $defined_plugins = PVE::ACME::DNSChallenge::get_supported_plugins(); +my $DNS_API_CHALLENGE_SCHEMA_FN = '../dns-challenge-schema.json'; +my $defined_plugins = from_json(PVE::Tools::file_get_contents($DNS_API_CHALLENGE_SCHEMA_FN)); +my $ok = 1; # first check for missing ones, delete from hash so we can easily see if a plug got removed/renamed my $printed_missing = 0; for my $provider (sort @$acmesh_plugins) {