acme.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. 'use strict';
  2. 'require form';
  3. 'require fs';
  4. 'require uci';
  5. 'require view';
  6. return view.extend({
  7. load: function() {
  8. return L.resolveDefault(fs.list('/etc/ssl/acme/'), []).then(function(entries) {
  9. var certs = [];
  10. for (var i = 0; i < entries.length; i++) {
  11. if (entries[i].type == 'file' && entries[i].name.match(/\.key$/)) {
  12. certs.push(entries[i]);
  13. }
  14. }
  15. return certs;
  16. });
  17. },
  18. render: function (certs) {
  19. let wikiUrl = 'https://github.com/acmesh-official/acme.sh/wiki/';
  20. var wikiInstructionUrl = wikiUrl + 'dnsapi';
  21. let m, s, o;
  22. m = new form.Map("acme", _("ACME certificates"),
  23. _("This configures ACME (Letsencrypt) automatic certificate installation. " +
  24. "Simply fill out this to have the router configured with Letsencrypt-issued " +
  25. "certificates for the web interface. " +
  26. "Note that the domain names in the certificate must already be configured to " +
  27. "point at the router's public IP address. " +
  28. "Once configured, issuing certificates can take a while. " +
  29. "Check the logs for progress and any errors.") + '<br/>' +
  30. _("Cert files are stored in") + ' <em>/etc/ssl/acme<em>'
  31. );
  32. s = m.section(form.TypedSection, "acme", _("ACME global config"));
  33. s.anonymous = true;
  34. o = s.option(form.Value, "account_email", _("Account email"),
  35. _('Email address to associate with account key.') + '<br/>' +
  36. _('If a certificate wasn\'t renewed in time then you\'ll receive a notice at 20 days before expiry.')
  37. )
  38. o.rmempty = false;
  39. o.datatype = "minlength(1)";
  40. o = s.option(form.Flag, "debug", _("Enable debug logging"));
  41. o.rmempty = false;
  42. s = m.section(form.GridSection, "cert", _("Certificate config"))
  43. s.anonymous = false;
  44. s.addremove = true;
  45. s.nodescriptions = true;
  46. o = s.tab("general", _("General Settings"));
  47. o = s.tab('challenge_webroot', _('Webroot Challenge Validation'));
  48. o = s.tab('challenge_dns', _('DNS Challenge Validation'));
  49. o = s.tab("advanced", _('Advanced Settings'));
  50. o = s.taboption('general', form.Flag, "enabled", _("Enabled"));
  51. o.rmempty = false;
  52. o = s.taboption('general', form.DynamicList, "domains", _("Domain names"),
  53. _("Domain names to include in the certificate. " +
  54. "The first name will be the subject name, subsequent names will be alt names. " +
  55. "Note that all domain names must point at the router in the global DNS."));
  56. o.datatype = "list(string)";
  57. o = s.taboption('general', form.ListValue, 'validation_method', _('Validation method'),
  58. _("Standalone mode will use the built-in webserver of acme.sh to issue a certificate. " +
  59. "Webroot mode will use an existing webserver to issue a certificate. " +
  60. "DNS mode will allow you to use the DNS API of your DNS provider to issue a certificate."));
  61. o.value("standalone", _("Standalone"));
  62. o.value("webroot", _("Webroot"));
  63. o.value("dns", _("DNS"));
  64. o.default = 'webroot';
  65. o = s.taboption('challenge_webroot', form.Value, 'webroot', _('Webroot directory'),
  66. _("Webserver root directory. Set this to the webserver " +
  67. "document root to run Acme in webroot mode. The web " +
  68. "server must be accessible from the internet on port 80.") + '<br/>' +
  69. _("Default") + " <em>/var/run/acme/challenge/</em>"
  70. );
  71. o.optional = true;
  72. o.depends("validation_method", "webroot");
  73. o.modalonly = true;
  74. o = s.taboption('challenge_dns', form.ListValue, 'dns', _('DNS API'),
  75. _("To use DNS mode to issue certificates, set this to the name of a DNS API supported by acme.sh. " +
  76. "See https://github.com/acmesh-official/acme.sh/wiki/dnsapi for the list of available APIs. " +
  77. "In DNS mode, the domain name does not have to resolve to the router IP. " +
  78. "DNS mode is also the only mode that supports wildcard certificates. " +
  79. "Using this mode requires the acme-dnsapi package to be installed."));
  80. o.depends("validation_method", "dns");
  81. // List of supported DNS API. Names are same as file names in acme.sh for easier search.
  82. // May be outdated but not changed too often.
  83. o.value('', '')
  84. o.value('dns_acmedns', 'ACME DNS API github.com/joohoi/acme-dns');
  85. o.value('dns_acmeproxy', 'ACME Proxy github.com/mdbraber/acmeproxy');
  86. o.value('dns_1984hosting', '1984.is');
  87. o.value('dns_active24', 'Active24.com');
  88. o.value('dns_ad', 'Alwaysdata.com');
  89. o.value('dns_ali', 'Alibaba Cloud Aliyun.com');
  90. o.value('dns_anx', 'Anexia.com');
  91. o.value('dns_arvan', 'ArvanCloud.ir');
  92. o.value('dns_aurora', 'AuroraDNS.eu');
  93. o.value('dns_autodns', 'autoDNS (InternetX)');
  94. o.value('dns_aws', 'Amazon AWS Route53');
  95. o.value('dns_azion', 'Azion.com');
  96. o.value('dns_azure', 'Azure');
  97. o.value('dns_bunny', 'Bunny.net');
  98. o.value('dns_cf', 'CloudFlare.com');
  99. o.value('dns_clouddns', 'CloudDNS vshosting.cz');
  100. o.value('dns_cloudns', 'ClouDNS.net');
  101. o.value('dns_cn', 'Core-Networks.de');
  102. o.value('dns_conoha', 'ConoHa.io');
  103. o.value('dns_constellix', 'constellix.com');
  104. o.value('dns_cpanel', 'CPanel');
  105. o.value('dns_curanet', 'curanet.dk scannet.dk wannafind.dk dandomain.dk');
  106. o.value('dns_cyon', 'cayon.ch');
  107. o.value('dns_da', 'DirectAdmin Panel');
  108. o.value('dns_ddnss', 'DDNSS.de');
  109. o.value('dns_desec', 'deSEC.io');
  110. o.value('dns_df', 'DynDnsFree.de');
  111. o.value('dns_dgon', 'DigitalOcean.com');
  112. o.value('dns_dnshome', 'dnsHome.de');
  113. o.value('dns_dnsimple', 'DNSimple.com');
  114. o.value('dns_dnsservices', 'dns.services');
  115. o.value('dns_doapi', 'Domain-Offensive do.de');
  116. o.value('dns_domeneshop', 'DomeneShop.no');
  117. o.value('dns_dp', 'DNSPod.cn');
  118. o.value('dns_dpi', 'DNSPod.com');
  119. o.value('dns_dreamhost', 'DreamHost.com');
  120. o.value('dns_duckdns', 'DuckDNS.org');
  121. o.value('dns_durabledns', 'DurableDNS.com');
  122. o.value('dns_dyn', 'Dyn.com');
  123. o.value('dns_dynu', 'Dynu.com');
  124. o.value('dns_dynv6', 'DynV6.com');
  125. o.value('dns_easydns', 'EasyDNS.net');
  126. o.value('dns_edgedns', 'Akamai Edge DNS');
  127. o.value('dns_euserv', 'euserv.eu');
  128. o.value('dns_exoscale', 'Exoscale.com');
  129. o.value('dns_fornex', 'fornex.com');
  130. o.value('dns_freedns', 'FreeDNS.afraid.org');
  131. o.value('dns_gandi_livedns', 'LiveDNS.Gandi.net');
  132. // o.value('dns_gcloud', 'Google Cloud gcloud client');
  133. o.value('dns_gcore', 'Gcore.com');
  134. o.value('dns_gd', 'GoDaddy.com');
  135. o.value('dns_geoscaling', 'Geoscaling.com');
  136. o.value('dns_googledomains', 'Google Domains');
  137. o.value('dns_he', 'he.net');
  138. o.value('dns_hetzner', 'Hetzner.com');
  139. o.value('dns_hexonet', 'Hexonet.net');
  140. o.value('dns_hostingde', 'Hosting.de');
  141. o.value('dns_huaweicloud', 'MyHuaweiCloud.com');
  142. o.value('dns_infoblox', 'Infoblox');
  143. o.value('dns_infomaniak', 'InfoManiak.com');
  144. o.value('dns_internetbs', 'InternetBS.net');
  145. o.value('dns_inwx', 'inwx.de');
  146. o.value('dns_ionos', 'IONOS.com');
  147. o.value('dns_ipv64', 'ipv64.net');
  148. o.value('dns_ispconfig', 'ISPConfig Server');
  149. o.value('dns_jd', 'JDCloud.com');
  150. o.value('dns_joker', 'Joker.com');
  151. o.value('dns_kappernet', 'kapper.net');
  152. o.value('dns_kas', 'kasserver.com');
  153. o.value('dns_kinghost', 'KingHost.net');
  154. o.value('dns_la', 'dns.la');
  155. o.value('dns_leaseweb', 'leaseweb.com');
  156. // o.value('dns_lexicon', 'Lexicon client');
  157. o.value('dns_linode_v4', 'Linode.com');
  158. o.value('dns_loopia', 'Loopia.se');
  159. o.value('dns_lua', 'LuaDNS.com');
  160. // o.value('dns_maradns', 'MaraDNS Server zone file');
  161. o.value('dns_me', 'DNSMadeEasy.com');
  162. // o.value('dns_miab', 'Mail-in-a-Box Server API');
  163. o.value('dns_misaka', 'misaka.io');
  164. o.value('dns_mydevil', 'MyDevil.net');
  165. o.value('dns_mydnsjp', 'MyDNS.JP');
  166. o.value('dns_mythic_beasts', 'Mythic-Beasts.com');
  167. o.value('dns_namecheap', 'NameCheap.com');
  168. o.value('dns_namecom', 'Name.com');
  169. o.value('dns_namesilo', 'NameSilo.com');
  170. o.value('dns_nanelo', 'Nanelo.com');
  171. o.value('dns_nederhost', 'NederHost.nl');
  172. o.value('dns_neodigit', 'Neodigit.net');
  173. o.value('dns_netcup', 'netcup.eu netcup.de');
  174. o.value('dns_netlify', 'Netlify.com');
  175. o.value('dns_nic', 'nic.ru');
  176. o.value('dns_njalla', 'Njalla njal.la');
  177. o.value('dns_nm', 'NameMaster.de');
  178. // o.value('dns_nsd', 'NSD Server zone file');
  179. o.value('dns_nsone', 'NS1 nsone.net');
  180. o.value('dns_nsupdate', 'nsupdate (RFC2136) Server');
  181. o.value('dns_nw', 'Nexcess.net');
  182. o.value('dns_oci', 'Oracle Cloud Infrastructure (OCI)');
  183. o.value('dns_one', 'one.com');
  184. o.value('dns_online', 'online.net');
  185. o.value('dns_openprovider', 'OpenProvider.com');
  186. // o.value('dns_openstack', 'OpenStack Client');
  187. o.value('dns_opnsense', 'OPNsense Bind API');
  188. o.value('dns_ovh', 'OVH ovh.com ovhcloud.com kimsufi.com soyoustart.com');
  189. o.value('dns_pdns', 'PowerDNS Server');
  190. o.value('dns_pleskxml', 'plesk.com XML API');
  191. o.value('dns_pointhq', 'PointDNS pointhq.com');
  192. o.value('dns_porkbun', 'Porkbun.com');
  193. o.value('dns_rackcorp', 'RackCorp.com');
  194. o.value('dns_rackspace', 'RackSpace rackspacecloud.com');
  195. o.value('dns_rage4', 'rage4.com');
  196. o.value('dns_rcode0', 'Rcode0 rcodezero.at');
  197. o.value('dns_regru', 'Reg.ru');
  198. o.value('dns_scaleway', 'Scaleway.com');
  199. o.value('dns_schlundtech', 'Schlundtech.de');
  200. o.value('dns_selectel', 'Selectel.ru');
  201. o.value('dns_selfhost', 'selfhost.de');
  202. o.value('dns_servercow', 'servercow.de');
  203. o.value('dns_simply', 'Simply.com');
  204. o.value('dns_tele3', 'tele3.cz');
  205. o.value('dns_transip', 'transip.nl');
  206. o.value('dns_udr', 'ud-reselling.com');
  207. o.value('dns_ultra', 'UltraDNS.com');
  208. o.value('dns_variomedia', 'variomedia.de');
  209. o.value('dns_veesp', 'veesp.com');
  210. o.value('dns_vercel', 'Vercel.com');
  211. o.value('dns_vscale', 'vscale.io');
  212. o.value('dns_vultr', 'vultr.com');
  213. o.value('dns_websupport', 'websupport.sk');
  214. o.value('dns_world4you', 'World4You.com');
  215. o.value('dns_yandex', 'Yandex DNS dns.yandex.ru');
  216. o.value('dns_yc', 'Yandex Cloud cloud.yandex.net');
  217. o.value('dns_zilore', 'zilore.com');
  218. o.value('dns_zone', 'Zone.ee');
  219. o.value('dns_zonomi', 'Zonomi.com');
  220. o.modalonly = true;
  221. o.onchange = L.bind(_handleCheckService, o, s);
  222. o = s.taboption('challenge_dns', form.DummyValue, '_wiki_url', _('See instructions'), '');
  223. o.rawhtml = true;
  224. o.default = '<a id="wikiInstructionUrl" href="%s" target="_blank" rel="noreferrer">Acme Wiki DNS API</a>'
  225. .format(wikiInstructionUrl);
  226. o.depends('validation_method', 'dns');
  227. o.modalonly = true;
  228. _addDnsProviderField(s, 'dns_1984hosting', 'One984HOSTING_Username', '1984.is Username', '');
  229. _addDnsProviderField(s, 'dns_1984hosting', 'One984HOSTING_Password', '1984.is Password', '');
  230. _addDnsProviderField(s, 'dns_acmedns', 'ACMEDNS_BASE_URL', 'ACMEDNS URL', '');
  231. _addDnsProviderField(s, 'dns_acmedns', 'ACMEDNS_USERNAME', 'ACMEDNS User', '');
  232. _addDnsProviderField(s, 'dns_acmedns', 'ACMEDNS_PASSWORD', 'ACMEDNS Password', '');
  233. _addDnsProviderField(s, 'dns_acmedns', 'ACMEDNS_SUBDOMAIN', 'ACMEDNS Subdomain', '');
  234. _addDnsProviderField(s, 'dns_ali', 'Ali_Key', 'Ali Key', '');
  235. _addDnsProviderField(s, 'dns_ali', 'Ali_Secret', 'Ali Secret', '');
  236. _addDnsProviderField(s, 'dns_aws', 'AWS_ACCESS_KEY_ID', 'AWS access key id', '');
  237. _addDnsProviderField(s, 'dns_aws', 'AWS_SECRET_ACCESS_KEY', 'AWS secret access key', '');
  238. _addDnsProviderField(s, 'dns_azure', 'AZUREDNS_SUBSCRIPTIONID', 'Azure Subscription ID', '');
  239. _addDnsProviderField(s, 'dns_azure', 'AZUREDNS_TENANTID', 'Azure Tenant ID', '');
  240. _addDnsProviderField(s, 'dns_azure', 'AZUREDNS_APPID', 'Azure App ID', '');
  241. _addDnsProviderField(s, 'dns_azure', 'AZUREDNS_CLIENTSECRET', 'Azure Client Secret', '');
  242. _addDnsProviderField(s, 'dns_bunny', 'BUNNY_API_KEY', 'Bunny API Key', '');
  243. _addDnsProviderField(s, 'dns_cf', 'CF_Key', 'CF Key', '');
  244. _addDnsProviderField(s, 'dns_cf', 'CF_Email', 'CF Email', '');
  245. _addDnsProviderField(s, 'dns_cf', 'CF_Token', 'CF Token', '');
  246. _addDnsProviderField(s, 'dns_cf', 'CF_Account_ID', 'CF Account ID', '');
  247. _addDnsProviderField(s, 'dns_cf', 'CF_Zone_ID', 'CF Zone ID', '');
  248. _addDnsProviderField(s, 'dns_ddnss', 'DDNSS_Token', 'DDNSS.de Token', '');
  249. _addDnsProviderField(s, 'dns_desec', 'DEDYN_TOKEN', 'deSEC.io Token', '');
  250. _addDnsProviderField(s, 'dns_duckdns', 'DuckDNS_Token', 'DuckDNS Token',
  251. _('Open <a href="https://www.duckdns.org/">DuckDNS</a> and copy a token here')
  252. );
  253. _addDnsProviderField(s, 'dns_dynv6', 'DYNV6_TOKEN', 'DynV6 Token', '');
  254. _addDnsProviderField(s, 'dns_dnsimple', 'DNSimple_OAUTH_TOKEN', 'DNSimple OAuth TOKEN', '');
  255. _addDnsProviderField(s, 'dns_dgon', 'DO_API_KEY', 'Digital Ocean API Key', '');
  256. _addDnsProviderField(s, 'dns_dreamhost', 'DH_API_KEY', 'DreamHost.com API Key', '');
  257. _addDnsProviderField(s, 'dns_df', 'DF_user', 'DynDnsFree.de Username', '');
  258. _addDnsProviderField(s, 'dns_df', 'DF_password', 'DynDnsFree.de Password', '');
  259. _addDnsProviderField(s, 'dns_gandi_livedns', 'GANDI_LIVEDNS_KEY', 'Gandi LiveDNS Key', '');
  260. _addDnsProviderField(s, 'dns_gcore', 'GCORE_Key', 'GCore Key', '');
  261. _addDnsProviderField(s, 'dns_gd', 'GD_Key', 'GoDaddy.com Key', '');
  262. _addDnsProviderField(s, 'dns_gd', 'GD_Secret', 'GoDaddy.com Secret', '');
  263. _addDnsProviderField(s, 'dns_geoscaling', 'GEOSCALING_Username', 'Geoscaling.com Username',
  264. _('This is usually NOT an email address')
  265. );
  266. _addDnsProviderField(s, 'dns_geoscaling', 'GEOSCALING_Password', 'Geoscaling.com Password', '');
  267. _addDnsProviderField(s, 'dns_googledomains', 'GOOGLEDOMAINS_ACCESS_TOKEN', 'Google Domains Access Token', '');
  268. _addDnsProviderField(s, 'dns_googledomains', 'GOOGLEDOMAINS_ZONE', 'Google Domains Zone', '');
  269. _addDnsProviderField(s, 'dns_he', 'HE_Username', 'dns.he.net Username', '');
  270. _addDnsProviderField(s, 'dns_he', 'HE_Password', 'dns.he.net Password', '');
  271. _addDnsProviderField(s, 'dns_hetzner', 'HETZNER_Token', 'Hetzner Token', '');
  272. _addDnsProviderField(s, 'dns_he', 'dns_hexonet', 'Hexonet.net Login', 'username!roleId');
  273. _addDnsProviderField(s, 'dns_he', 'dns_hexonet', 'Hexonet.net Password', '');
  274. _addDnsProviderField(s, 'dns_huaweicloud', 'HUAWEICLOUD_Username', 'MyHuaweiCloud.com Username', '');
  275. _addDnsProviderField(s, 'dns_huaweicloud', 'HUAWEICLOUD_Password', 'MyHuaweiCloud.com Password', '');
  276. _addDnsProviderField(s, 'dns_huaweicloud', 'HUAWEICLOUD_DomainName', 'MyHuaweiCloud.com Domain Name', '');
  277. _addDnsProviderField(s, 'dns_infomaniak', 'INFOMANIAK_API_TOKEN', 'InfoManiak Token', '');
  278. _addDnsProviderField(s, 'dns_ipv64', 'IPv64_Token', 'ipv64.net Token', '');
  279. _addDnsProviderField(s, 'dns_jd', 'JD_ACCESS_KEY_ID', 'JDCloud.com Access Key ID', '');
  280. _addDnsProviderField(s, 'dns_jd', 'JD_ACCESS_KEY_SECRET', 'JDCloud.com Access Key Secret', '');
  281. _addDnsProviderField(s, 'dns_jd', 'JD_REGION', 'JDCloud.com Region', 'cn-north-1');
  282. _addDnsProviderField(s, 'dns_joker', 'JOKER_USERNAME', 'Joker.com User', '');
  283. _addDnsProviderField(s, 'dns_joker', 'JOKER_PASSWORD', 'Joker.com Password', '');
  284. _addDnsProviderField(s, 'dns_freedns', 'FREEDNS_User', 'FreeDNS User', '');
  285. _addDnsProviderField(s, 'dns_freedns', 'FREEDNS_Password', 'FreeDNS Password', '');
  286. _addDnsProviderField(s, 'dns_la', 'LA_Id', 'dns.la Id', '');
  287. _addDnsProviderField(s, 'dns_la', 'LA_Key', 'dns.la Key', '');
  288. _addDnsProviderField(s, 'dns_linodev4', 'LINODE_V4_API_KEY', 'Linode API Key', '');
  289. _addDnsProviderField(s, 'dns_loopia', 'LOOPIA_User', 'Loopia User', '');
  290. _addDnsProviderField(s, 'dns_loopia', 'LOOPIA_Password', 'Loopia Password', '');
  291. _addDnsProviderField(s, 'dns_lua', 'LUA_Email', 'luadns.com email', '');
  292. _addDnsProviderField(s, 'dns_lua', 'LUA_Key', 'luadns.com Key', '');
  293. _addDnsProviderField(s, 'dns_mydnsjp', 'MYDNSJP_MasterID', 'MyDNS.jp MasterID', '');
  294. _addDnsProviderField(s, 'dns_mydnsjp', 'MYDNSJP_Password', 'MyDNS.jp Password', '');
  295. _addDnsProviderField(s, 'dns_me', 'ME_Key', 'DNSMadeEasy Key', '');
  296. _addDnsProviderField(s, 'dns_me', 'ME_Secret', 'DNSMadeEasy Secret', '');
  297. _addDnsProviderField(s, 'dns_namecom', 'Namecom_Username', 'Name.com Username', '');
  298. _addDnsProviderField(s, 'dns_namecom', 'Namecom_Token', 'Name.com Token', '');
  299. _addDnsProviderField(s, 'dns_namecheap', 'NAMECHEAP_API_KEY', 'NameCheap API Key', '');
  300. _addDnsProviderField(s, 'dns_namecheap', 'NAMECHEAP_USERNAME', 'NameCheap User', '');
  301. _addDnsProviderField(s, 'dns_namecheap', 'NAMECHEAP_SOURCEIP', 'NameCheap Source IP', '');
  302. _addDnsProviderField(s, 'dns_nic', 'NIC_ClientID', 'Nic.ru ClientID', '');
  303. _addDnsProviderField(s, 'dns_nic', 'NIC_ClientSecret', 'Nic.ru ClientSecret', '');
  304. _addDnsProviderField(s, 'dns_nic', 'NIC_Username', 'Nic.ru Username', '');
  305. _addDnsProviderField(s, 'dns_nic', 'NIC_Password', 'Nic.ru Password', '');
  306. _addDnsProviderField(s, 'dns_netlify', 'NETLIFY_ACCESS_TOKEN', 'Netlify Access Token', '');
  307. _addDnsProviderField(s, 'dns_nsone', 'NS1_Key', 'nsone.net Key', '');
  308. _addDnsProviderField(s, 'dns_nsupdate', 'NSUPDATE_SERVER', 'nsupdate server address', '');
  309. _addDnsProviderField(s, 'dns_nsupdate', 'NSUPDATE_SERVER_PORT', 'nsupdate server port', '');
  310. _addDnsProviderField(s, 'dns_nsupdate', 'NSUPDATE_KEY', 'nsupdate key file path', '');
  311. _addDnsProviderField(s, 'dns_nsupdate', 'NSUPDATE_ZONE', 'nsupdate zone', '');
  312. _addDnsProviderField(s, 'dns_nsupdate', 'OCI_CLI_TENANCY', 'OCI Tenancy',
  313. _('OCID of tenancy that contains the target DNS zone')
  314. );
  315. _addDnsProviderField(s, 'dns_nsupdate', 'OCI_CLI_USER', 'OCI User',
  316. _('OCID of user with permission to add/remove records from zones')
  317. );
  318. _addDnsProviderField(s, 'dns_nsupdate', 'OCI_CLI_REGION', 'OCI Region',
  319. _('Should point to the tenancy home region')
  320. );
  321. _addDnsProviderField(s, 'dns_nsupdate', 'OCI_CLI_KEY_FILE', 'OCI Key file',
  322. _('Path to private API signing key file in PEM format')
  323. );
  324. _addDnsProviderField(s, 'dns_nsupdate', 'OCI_CLI_KEY', 'OCI Key',
  325. _('The private API signing key in PEM format')
  326. );
  327. _addDnsProviderField(s, 'dns_ovh', 'OVH_AK', 'OVH Application Key', '');
  328. _addDnsProviderField(s, 'dns_ovh', 'OVH_AS', 'OVH Application Secret', '');
  329. _addDnsProviderField(s, 'dns_ovh', 'OVH_CK', 'OVH Consumer Key', '');
  330. _addDnsProviderField(s, 'dns_ovh', 'OVH_END_POINT', 'OVH Region/Endpoint',
  331. 'ovh-eu, ovh-us, ovh-ca, kimsufi-eu, kimsufi-ca, soyoustart-eu, soyoustart-ca'
  332. );
  333. _addDnsProviderField(s, 'dns_pdns', 'PDNS_Url', 'PDNS API URL', '');
  334. _addDnsProviderField(s, 'dns_pdns', 'PDNS_ServerId', 'PDNS Server ID', '');
  335. _addDnsProviderField(s, 'dns_pdns', 'PDNS_Token', 'PDNS Token', '');
  336. _addDnsProviderField(s, 'dns_pdns', 'PDNS_Ttl', 'PDNS Default TTL', '60');
  337. _addDnsProviderField(s, 'dns_porkbun', 'PORKBUN_API_KEY', 'Porkbun API Key', '');
  338. _addDnsProviderField(s, 'dns_porkbun', 'PORKBUN_SECRET_API_KEY', 'Porkbun API Secret', '');
  339. _addDnsProviderField(s, 'dns_rackspace', 'RACKSPACE_Apikey', 'RackSpace API Key', '');
  340. _addDnsProviderField(s, 'dns_rackspace', 'RACKSPACE_Username', 'Porkbun Username', '');
  341. _addDnsProviderField(s, 'dns_regru', 'REGRU_API_Username', 'reg.ru Username', '');
  342. _addDnsProviderField(s, 'dns_regru', 'REGRU_API_Password', 'reg.ru Password', '');
  343. _addDnsProviderField(s, 'dns_selectel', 'SL_Key', 'Selectel API Key', '');
  344. _addDnsProviderField(s, 'dns_selfhost', 'SELFHOSTDNS_USERNAME', 'SelfHost.de Username', '');
  345. _addDnsProviderField(s, 'dns_selfhost', 'SELFHOSTDNS_PASSWORD', 'SelfHost.de Password', '');
  346. _addDnsProviderField(s, 'dns_selfhost', 'SELFHOSTDNS_MAP', 'SelfHost.de Domains map',
  347. _('E.g. <code>_acme-challenge.example.com:12345:98765 alias.example.com:11111</code>')
  348. );
  349. _addDnsProviderField(s, 'dns_simply', 'SIMPLY_AccountName', 'Simply.com account name', '');
  350. _addDnsProviderField(s, 'dns_simply', 'SIMPLY_ApiKey', 'Simply.com API Key', '');
  351. _addDnsProviderField(s, 'dns_tele3', 'TELE3_Key', 'tele3.cz API Key', '');
  352. _addDnsProviderField(s, 'dns_tele3', 'TELE3_Secret', 'tele3.cz API Secret', '');
  353. _addDnsProviderField(s, 'dns_vultr', 'VULTR_API_KEY', 'Vultr API Secret', '');
  354. _addDnsProviderField(s, 'dns_vscale', 'VSCALE_API_KEY', 'vscale.io API Key', '');
  355. _addDnsProviderField(s, 'dns_yandex', 'PDD_Token', 'Yandex DNS API Token', '');
  356. _addDnsProviderField(s, 'dns_yandex', 'PDD_Token', 'Yandex DNS API Token', '');
  357. _addDnsProviderField(s, 'dns_yc', 'YC_Zone_ID', 'Yandex Cloud: DNS Zone ID', '');
  358. _addDnsProviderField(s, 'dns_yc', 'YC_Folder_ID', 'Yandex Cloud: YC Folder ID', '');
  359. _addDnsProviderField(s, 'dns_yc', 'YC_SA_ID', 'Yandex Cloud: Service Account ID', '');
  360. _addDnsProviderField(s, 'dns_yc', 'YC_SA_Key_ID', 'Yandex Cloud: Service Account IAM Key ID', '');
  361. _addDnsProviderField(s, 'dns_yc', 'YC_SA_Key_File_Path', 'Yandex Cloud: Path to private key', '');
  362. _addDnsProviderField(s, 'dns_yc', 'YC_SA_Key_File_PEM_b64', 'Yandex Cloud: PEM of private key',
  363. _('Base64 content of private key. Use instead of YC_SA_Key_File_Path')
  364. );
  365. _addDnsProviderField(s, 'dns_zilore', 'Zilore_Key', 'Zilore API Key', '');
  366. _addDnsProviderField(s, 'dns_zone', 'ZONE_Username', 'Zone.ee Username', '');
  367. _addDnsProviderField(s, 'dns_zone', 'ZONE_Key', 'Zone.ee API Key', '');
  368. _addDnsProviderField(s, 'dns_zonomi', 'ZM_Key', 'Zonomi.com API Key', '');
  369. o = s.taboption('challenge_dns', form.DynamicList, 'credentials', _('DNS API credentials'),
  370. _("The credentials for the DNS API mode selected above. " +
  371. "See https://github.com/acmesh-official/acme.sh/wiki/dnsapi for the format of credentials required by each API. " +
  372. "Add multiple entries here in KEY=VAL shell variable format to supply multiple credential variables."))
  373. o.datatype = "list(string)";
  374. o.depends("validation_method", "dns");
  375. o.modalonly = true;
  376. o = s.taboption('challenge_dns', form.Value, 'calias', _('Challenge Alias'),
  377. _("The challenge alias to use for ALL domains. " +
  378. "See https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode for the details of this process. " +
  379. "LUCI only supports one challenge alias per certificate."));
  380. o.depends("validation_method", "dns");
  381. o.modalonly = true;
  382. o = s.taboption('challenge_dns', form.Value, 'dalias', _('Domain Alias'),
  383. _("The domain alias to use for ALL domains. " +
  384. "See https://github.com/acmesh-official/acme.sh/wiki/DNS-alias-mode for the details of this process. " +
  385. "LUCI only supports one challenge domain per certificate."));
  386. o.depends("validation_method", "dns");
  387. o.modalonly = true;
  388. o = s.taboption('advanced', form.Flag, 'staging', _('Use staging server'),
  389. _(
  390. 'Get certificate from the Letsencrypt staging server ' +
  391. '(use for testing; the certificate won\'t be valid).'
  392. )
  393. );
  394. o.rmempty = false;
  395. o.modalonly = true;
  396. o = s.taboption('advanced', form.ListValue, 'key_type', _('Key type'),
  397. _('Key size (and type) for the generated certificate.')
  398. );
  399. o.value('rsa2048', _('RSA 2048 bits'));
  400. o.value('rsa3072', _('RSA 3072 bits'));
  401. o.value('rsa4096', _('RSA 4096 bits'));
  402. o.value('ec256', _('ECC 256 bits'));
  403. o.value('ec384', _('ECC 384 bits'));
  404. o.rmempty = false;
  405. o.optional = true;
  406. o.modalonly = true;
  407. o.cfgvalue = function(section_id) {
  408. var keylength = uci.get('acme', section_id, 'keylength');
  409. if (keylength) {
  410. // migrate the old keylength to a new keytype
  411. switch (keylength) {
  412. case '2048': return 'rsa2048';
  413. case '3072': return 'rsa3072';
  414. case '4096': return 'rsa4096';
  415. case 'ec-256': return 'ec256';
  416. case 'ec-384': return 'ec384';
  417. default: return ''; // bad value
  418. }
  419. }
  420. return this.super('cfgvalue', arguments);
  421. };
  422. o.write = function(section_id, value) {
  423. // remove old keylength
  424. uci.unset('acme', section_id, 'keylength');
  425. uci.set('acme', section_id, 'key_type', value);
  426. };
  427. o = s.taboption('advanced', form.Value, "acme_server", _("ACME server URL"),
  428. _('Use a custom CA instead of Let\'s Encrypt.') + ' ' + _('Custom ACME server directory URL.'));
  429. o.depends("staging", "0");
  430. o.placeholder = "https://api.buypass.com/acme/directory";
  431. o.optional = true;
  432. o.modalonly = true;
  433. o = s.taboption('advanced', form.Value, 'days', _('Days until renewal'));
  434. o.optional = true;
  435. o.placeholder = 90;
  436. o.datatype = 'uinteger';
  437. o.modalonly = true;
  438. s = m.section(form.GridSection, '_certificates');
  439. s.render = L.bind(_renderCerts, this, certs);
  440. return m.render();
  441. }
  442. })
  443. function _addDnsProviderField(s, provider, env, title, desc) {
  444. let o = s.taboption('challenge_dns', form.Value, '_' + env, _(title),
  445. _(desc));
  446. o.depends('dns', provider);
  447. o.modalonly = true;
  448. o.cfgvalue = function (section_id, stored_val) {
  449. var creds = this.map.data.get(this.map.config, section_id, 'credentials');
  450. return _extractParamValue(creds, env);
  451. };
  452. o.write = function (section_id, value) {
  453. this.map.data.set('acme', section_id, 'credentials', [env + '="' + value + '"']);
  454. };
  455. return o;
  456. }
  457. /**
  458. * @param {string[]} paramsKeyVals
  459. * @param {string} paramName
  460. * @returns {string}
  461. */
  462. function _extractParamValue(paramsKeyVals, paramName) {
  463. if (!paramsKeyVals) {
  464. return '';
  465. }
  466. for (let i = 0; i < paramsKeyVals.length; i++) {
  467. var paramKeyVal = paramsKeyVals[i];
  468. var parts = paramKeyVal.split('=');
  469. if (parts.lenght < 2) {
  470. continue;
  471. }
  472. var name = parts[0];
  473. var val = parts[1];
  474. if (name == paramName) {
  475. // unquote
  476. return val.substring(0, val.length-1).substring(1);
  477. }
  478. }
  479. return '';
  480. }
  481. function _handleCheckService(c, event, curVal, newVal) {
  482. document.getElementById('wikiInstructionUrl').href = 'https://github.com/acmesh-official/acme.sh/wiki/dnsapi#' + newVal;
  483. }
  484. function _renderCerts(certs) {
  485. var table = E('table', {'class': 'table cbi-section-table', 'id': 'certificates_table'}, [
  486. E('tr', {'class': 'tr table-titles'}, [
  487. E('th', {'class': 'th'}, _('Main Domain')),
  488. E('th', {'class': 'th'}, _('Private Key')),
  489. E('th', {'class': 'th'}, _('Public Certificate')),
  490. E('th', {'class': 'th'}, _('Issued on')),
  491. ])
  492. ]);
  493. var rows = certs.map(function (cert) {
  494. let domain = cert.name.substring(0, cert.name.length - 4);
  495. let issueDate = new Date(cert.mtime * 1000).toLocaleDateString();
  496. return [
  497. domain,
  498. '/etc/ssl/acme/' + domain + '.key',
  499. '/etc/ssl/acme/' + domain + '.fullchain.crt',
  500. issueDate,
  501. ];
  502. });
  503. cbi_update_table(table, rows);
  504. return E('div', {'class': 'cbi-section cbi-tblsection'}, [
  505. E('h3', _('Certificates')), table]);
  506. }