]> git.proxmox.com Git - proxmox-acme.git/commitdiff
move DNS plugin schema to separate JSON based file
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 5 May 2021 12:07:35 +0000 (14:07 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 5 May 2021 12:32:15 +0000 (14:32 +0200)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/Makefile
src/PVE/ACME/DNSChallenge.pm
src/dns-challenge-schema.README [new file with mode: 0644]
src/dns-challenge-schema.json [new file with mode: 0644]
src/test/verify-dnsapi-plugins-in-schema.pl

index 27418d0453bc6ad8b54ade84786ec4bb32c7d442..16166fecf3fd2c0ee4037cf60000ec1366ed65e6 100644 (file)
@@ -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
index ce66f3c5edd6ef016dad6560055634e36b8c8790..9b2897001145c070f5e34a5e56295dfe4a5b32d8 100644 (file)
@@ -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 (file)
index 0000000..1de1cd1
--- /dev/null
@@ -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 (file)
index 0000000..559077f
--- /dev/null
@@ -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" : {}
+}
index 3f1377eb8a6d5810511c1aa5039292a3b9f607ee..a9628612bd67951080628b734bca7dfd146ea44b 100755 (executable)
@@ -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) {