1
0

acme.html 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- Notes: This should be open in its original path-->
  5. <link rel="stylesheet" href="../script/semantic/semantic.min.css">
  6. <script src="../script/jquery-3.6.0.min.js"></script>
  7. <script src="../script/semantic/semantic.min.js"></script>
  8. <style>
  9. .disabled.table{
  10. opacity: 0.5;
  11. pointer-events: none;
  12. }
  13. .expiredDomain{
  14. color: rgb(238, 31, 31);
  15. }
  16. .validDomain{
  17. color: rgb(49, 192, 113);
  18. }
  19. </style>
  20. </head>
  21. <body>
  22. <br>
  23. <div class="ui container">
  24. <div class="ui header">
  25. <div class="content">
  26. Certificates Auto Renew Settings
  27. <div class="sub header">Fetch and renew your certificates with Automated Certificate Management Environment (ACME) protocol</div>
  28. </div>
  29. </div>
  30. <div class="ui basic segment">
  31. <p style="float: right; color: #21ba45; display:none;" id="enableToggleSucc"><i class="green checkmark icon"></i> Setting Updated</p>
  32. <div class="ui toggle checkbox">
  33. <input type="checkbox" id="enableCertAutoRenew">
  34. <label>Enable Certificate Auto Renew</label>
  35. </div>
  36. <br>
  37. <h3>ACME Email</h3>
  38. <p>Email is required by many CAs for renewing via ACME protocol</p>
  39. <div class="ui fluid action input">
  40. <input id="caRegisterEmail" type="text" placeholder="[email protected]">
  41. <button class="ui icon basic button" onclick="saveEmailToConfig(this);">
  42. <i class="blue save icon"></i>
  43. </button>
  44. </div>
  45. <small>If you don't want to share your private email address, you can also fill in an email address that point to a mailbox not exists on your domain.</small>
  46. </div>
  47. <div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
  48. <div class="ui accordion advanceSettings">
  49. <div class="title">
  50. <i class="dropdown icon"></i>
  51. Advance Renew Policy
  52. </div>
  53. <div class="content">
  54. <p>Renew all certificates with ACME supported CAs</p>
  55. <div class="ui toggle checkbox">
  56. <input type="checkbox" id="renewAllSupported" onchange="setAutoRenewIfCASupportMode(this.checked);">
  57. <label>Renew All Certs</label>
  58. </div><br>
  59. <button id="renewNowBtn" onclick="renewNow();" class="ui basic right floated button" style="margin-top: -2em;"><i class="yellow refresh icon"></i> Renew Now</button>
  60. <div class="ui horizontal divider"> OR </div>
  61. <p>Select the certificates to automatic renew in the list below</p>
  62. <table id="domainCertFileTable" class="ui very compact unstackable basic disabled table">
  63. <thead>
  64. <tr>
  65. <th>Domain Name</th>
  66. <th>Match Rule</th>
  67. <th>Auto-Renew</th>
  68. </tr>
  69. </thead>
  70. <tbody id="domainTableBody"></tbody>
  71. </table>
  72. <small><i class="ui red info circle icon"></i> Domain in red are expired</small><br>
  73. <div class="ui yellow message">
  74. Certificate Renew only works on the certification authority (CA) supported by Zoraxy. Check Zoraxy wiki for more information on supported list of CAs.
  75. </div>
  76. <button class="ui basic right floated button" onclick="saveAutoRenewPolicy();"><i class="blue save icon"></i> Save Changes</button>
  77. <button id="renewSelectedButton" onclick="renewNow();" class="ui basic right floated disabled button"><i class="yellow refresh icon"></i> Renew Selected</button>
  78. <br><br>
  79. </div>
  80. </div>
  81. </div>
  82. <div class="ui divider"></div>
  83. <h3>Generate New Certificate</h3>
  84. <p>Enter a new / existing domain(s) to request new certificate(s)</p>
  85. <div class="ui form">
  86. <div class="field">
  87. <label>Domain(s)</label>
  88. <input id="domainsInput" type="text" placeholder="example.com" onkeyup="checkIfInputDomainIsMultiple();">
  89. <small>If you have more than one domain in a single certificate, enter the domains separated by commas (e.g. s1.dev.example.com,s2.dev.example.com)</small>
  90. </div>
  91. <div class="field multiDomainOnly" style="display:none;">
  92. <label>Matching Rule</label>
  93. <input id="filenameInput" type="text" placeholder="Enter filename (no file extension)">
  94. <small>Matching rule to let Zoraxy pick which certificate to use (Also be used as filename). Usually is the longest common suffix of the entered addresses. (e.g. dev.example.com)</small>
  95. </div>
  96. <div class="field multiDomainOnly" style="display:none;">
  97. <button class="ui basic fluid button" onclick="autoDetectMatchingRules();">Auto Detect Matching Rule</button>
  98. </div>
  99. <div class="field">
  100. <label>Certificate Authority (CA)</label>
  101. <div class="ui selection dropdown" id="ca">
  102. <input type="hidden" name="ca">
  103. <i class="dropdown icon"></i>
  104. <div class="default text">Let's Encrypt</div>
  105. <div class="menu">
  106. <div class="item" data-value="Let's Encrypt">Let's Encrypt</div>
  107. <div class="item" data-value="Buypass">Buypass</div>
  108. <div class="item" data-value="ZeroSSL">ZeroSSL</div>
  109. <div class="item" data-value="Custom ACME Server">Custom ACME Server</div>
  110. <!-- <div class="item" data-value="Google">Google</div> -->
  111. </div>
  112. </div>
  113. </div>
  114. <div class="field" id="dnsChallenge">
  115. <div class="ui checkbox">
  116. <input type="checkbox" id="useDnsChallenge" onchange="toggleDnsChallenge()">
  117. <label>Use a DNS Challenge<br>
  118. </div>
  119. </div>
  120. <div class="field dnsChallengeOnly" style="display:none;">
  121. <label>DNS Provider</label>
  122. <div class="ui selection dropdown" id="dnsProvider">
  123. <input type="hidden" name="dnsProvider">
  124. <i class="dropdown icon"></i>
  125. <div class="default text">Please Choose...</div>
  126. <div class="menu">
  127. <!-- List of supported DNS providers with acme-lego 4.16 -->
  128. <!-- The file proivders-scraper-util.js can be used to generate the list of providers -->
  129. <div class="item" data-value="edgedns">Akamai EdgeDNS</div>
  130. <div class="item" data-value="alidns">Alibaba Cloud DNS</div>
  131. <div class="item" data-value="allinkl">all-inkl</div>
  132. <div class="item" data-value="lightsail">Amazon Lightsail</div>
  133. <div class="item" data-value="route53">Amazon Route 53</div>
  134. <div class="item" data-value="arvancloud">ArvanCloud</div>
  135. <div class="item" data-value="auroradns">Aurora DNS</div>
  136. <div class="item" data-value="autodns">Autodns</div>
  137. <div class="item" data-value="azure">Azure (deprecated)</div>
  138. <div class="item" data-value="azuredns">Azure DNS</div>
  139. <div class="item" data-value="bindman">Bindman</div>
  140. <div class="item" data-value="bluecat">Bluecat</div>
  141. <div class="item" data-value="brandit">Brandit</div>
  142. <div class="item" data-value="bunny">Bunny</div>
  143. <div class="item" data-value="checkdomain">Checkdomain</div>
  144. <div class="item" data-value="civo">Civo</div>
  145. <div class="item" data-value="cloudru">Cloud.ru</div>
  146. <div class="item" data-value="clouddns">CloudDNS</div>
  147. <div class="item" data-value="cloudflare">Cloudflare</div>
  148. <div class="item" data-value="cloudns">ClouDNS</div>
  149. <div class="item" data-value="cloudxns">CloudXNS</div>
  150. <div class="item" data-value="conoha">ConoHa</div>
  151. <div class="item" data-value="constellix">Constellix</div>
  152. <div class="item" data-value="cpanel">CPanel/WHM</div>
  153. <div class="item" data-value="derak">Derak Cloud</div>
  154. <div class="item" data-value="desec">deSEC.io</div>
  155. <div class="item" data-value="designate">Designate DNSaaS for Openstack</div>
  156. <div class="item" data-value="digitalocean">Digital Ocean</div>
  157. <div class="item" data-value="dnsmadeeasy">DNS Made Easy</div>
  158. <div class="item" data-value="dnshomede">dnsHome.de</div>
  159. <div class="item" data-value="dnsimple">DNSimple</div>
  160. <div class="item" data-value="dnspod">DNSPod (deprecated)</div>
  161. <div class="item" data-value="dode">Domain Offensive (do.de)</div>
  162. <div class="item" data-value="domeneshop">Domeneshop</div>
  163. <div class="item" data-value="dreamhost">DreamHost</div>
  164. <div class="item" data-value="duckdns">Duck DNS</div>
  165. <div class="item" data-value="dyn">Dyn</div>
  166. <div class="item" data-value="dynu">Dynu</div>
  167. <div class="item" data-value="easydns">EasyDNS</div>
  168. <div class="item" data-value="efficientip">Efficient IP</div>
  169. <div class="item" data-value="epik">Epik</div>
  170. <div class="item" data-value="exoscale">Exoscale</div>
  171. <div class="item" data-value="exec">External program</div>
  172. <div class="item" data-value="freemyip">freemyip.com</div>
  173. <div class="item" data-value="gcore">G-Core</div>
  174. <div class="item" data-value="gandi">Gandi</div>
  175. <div class="item" data-value="gandiv5">Gandi Live DNS (v5)</div>
  176. <div class="item" data-value="glesys">Glesys</div>
  177. <div class="item" data-value="godaddy">Go Daddy</div>
  178. <div class="item" data-value="gcloud">Google Cloud</div>
  179. <div class="item" data-value="googledomains">Google Domains</div>
  180. <div class="item" data-value="hetzner">Hetzner</div>
  181. <div class="item" data-value="hostingde">Hosting.de</div>
  182. <div class="item" data-value="hosttech">Hosttech</div>
  183. <div class="item" data-value="httpreq">HTTP request</div>
  184. <div class="item" data-value="httpnet">http.net</div>
  185. <div class="item" data-value="hurricane">Hurricane Electric DNS</div>
  186. <div class="item" data-value="hyperone">HyperOne</div>
  187. <div class="item" data-value="ibmcloud">IBM Cloud (SoftLayer)</div>
  188. <div class="item" data-value="iijdpf">IIJ DNS Platform Service</div>
  189. <div class="item" data-value="infoblox">Infoblox</div>
  190. <div class="item" data-value="infomaniak">Infomaniak</div>
  191. <div class="item" data-value="iij">Internet Initiative Japan</div>
  192. <div class="item" data-value="internetbs">Internet.bs</div>
  193. <div class="item" data-value="inwx">INWX</div>
  194. <div class="item" data-value="ionos">Ionos</div>
  195. <div class="item" data-value="ipv64">IPv64</div>
  196. <div class="item" data-value="iwantmyname">iwantmyname</div>
  197. <div class="item" data-value="joker">Joker</div>
  198. <div class="item" data-value="acme-dns">Joohoi's ACME-DNS</div>
  199. <div class="item" data-value="liara">Liara</div>
  200. <div class="item" data-value="linode">Linode (v4)</div>
  201. <div class="item" data-value="liquidweb">Liquid Web</div>
  202. <div class="item" data-value="loopia">Loopia</div>
  203. <div class="item" data-value="luadns">LuaDNS</div>
  204. <div class="item" data-value="mailinabox">Mail-in-a-Box</div>
  205. <div class="item" data-value="metaname">Metaname</div>
  206. <div class="item" data-value="mydnsjp">MyDNS.jp</div>
  207. <div class="item" data-value="mythicbeasts">MythicBeasts</div>
  208. <div class="item" data-value="namedotcom">Name.com</div>
  209. <div class="item" data-value="namecheap">Namecheap</div>
  210. <div class="item" data-value="namesilo">Namesilo</div>
  211. <div class="item" data-value="nearlyfreespeech">NearlyFreeSpeech.NET</div>
  212. <div class="item" data-value="netcup">Netcup</div>
  213. <div class="item" data-value="netlify">Netlify</div>
  214. <div class="item" data-value="nicmanager">Nicmanager</div>
  215. <div class="item" data-value="nifcloud">NIFCloud</div>
  216. <div class="item" data-value="njalla">Njalla</div>
  217. <div class="item" data-value="nodion">Nodion</div>
  218. <div class="item" data-value="ns1">NS1</div>
  219. <div class="item" data-value="otc">Open Telekom Cloud</div>
  220. <div class="item" data-value="oraclecloud">Oracle Cloud</div>
  221. <div class="item" data-value="ovh">OVH</div>
  222. <div class="item" data-value="plesk">plesk.com</div>
  223. <div class="item" data-value="porkbun">Porkbun</div>
  224. <div class="item" data-value="pdns">PowerDNS</div>
  225. <div class="item" data-value="rackspace">Rackspace</div>
  226. <div class="item" data-value="rcodezero">RcodeZero</div>
  227. <div class="item" data-value="regru">reg.ru</div>
  228. <div class="item" data-value="rfc2136">RFC2136</div>
  229. <div class="item" data-value="rimuhosting">RimuHosting</div>
  230. <div class="item" data-value="sakuracloud">Sakura Cloud</div>
  231. <div class="item" data-value="scaleway">Scaleway</div>
  232. <div class="item" data-value="selectel">Selectel</div>
  233. <div class="item" data-value="servercow">Servercow</div>
  234. <div class="item" data-value="shellrent">Shellrent</div>
  235. <div class="item" data-value="simply">Simply.com</div>
  236. <div class="item" data-value="sonic">Sonic</div>
  237. <div class="item" data-value="stackpath">Stackpath</div>
  238. <div class="item" data-value="tencentcloud">Tencent Cloud DNS</div>
  239. <div class="item" data-value="transip">TransIP</div>
  240. <div class="item" data-value="safedns">UKFast SafeDNS</div>
  241. <div class="item" data-value="ultradns">Ultradns</div>
  242. <div class="item" data-value="variomedia">Variomedia</div>
  243. <div class="item" data-value="vegadns">VegaDNS</div>
  244. <div class="item" data-value="vercel">Vercel</div>
  245. <div class="item" data-value="versio">Versio.[nl|eu|uk]</div>
  246. <div class="item" data-value="vinyldns">VinylDNS</div>
  247. <div class="item" data-value="vkcloud">VK Cloud</div>
  248. <div class="item" data-value="vscale">Vscale</div>
  249. <div class="item" data-value="vultr">Vultr</div>
  250. <div class="item" data-value="webnames">Webnames</div>
  251. <div class="item" data-value="websupport">Websupport</div>
  252. <div class="item" data-value="wedos">WEDOS</div>
  253. <div class="item" data-value="yandex360">Yandex 360</div>
  254. <div class="item" data-value="yandexcloud">Yandex Cloud</div>
  255. <div class="item" data-value="yandex">Yandex PDD</div>
  256. <div class="item" data-value="zoneee">Zone.ee</div>
  257. <div class="item" data-value="zonomi">Zonomi</div>
  258. </div>
  259. </div>
  260. </div>
  261. <div class="field dnsChallengeOnly" style="display:none;">
  262. <label>Credentials File Content</label>
  263. <textarea id="dnsCredentials" placeholder=""></textarea>
  264. <small>For more information on the supported DNS Providers and their attirbutes look <a href="https://go-acme.github.io/lego/dns/" target="_blank">here</a>! </small>
  265. <div class="ui negative message">
  266. <i class="icon exclamation triangle"></i>
  267. These credentials will be stored as plaintext in the database and in environment variables!
  268. </div>
  269. </div>
  270. <div class="field" id="caInput" style="display:none;">
  271. <label>ACME Server URL</label>
  272. <input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
  273. </div>
  274. <div class="field" id="kidInput" style="display:none;">
  275. <label>EAB Credentials (KID) for current provider</label>
  276. <input id="eab_kid" type="text" placeholder="Leave this field blank to keep the current configuration">
  277. </div>
  278. <div class="field" id="hmacInput" style="display:none;">
  279. <label>EAB HMAC Key for current provider</label>
  280. <input id="eab_hmac" type="text" placeholder="Leave this field blank to keep the current configuration">
  281. </div>
  282. <div class="field" id="skipTLS" style="display:none;">
  283. <div class="ui checkbox">
  284. <input type="checkbox" id="skipTLSCheckbox">
  285. <label>Ignore TLS/SSL Verification Error<br><small>E.g. self-signed, expired certificate (Not Recommended)</small></label>
  286. </div>
  287. </div>
  288. <button id="obtainButton" class="ui basic button" type="submit"><i class="yellow refresh icon"></i> Get Certificate</button>
  289. </div>
  290. <div class="ui divider"></div>
  291. <small>First time setting up HTTPS?<br>Try out our <a href="../tools/https.html" target="_blank">wizard</a></small>
  292. <button class="ui basic button" style="float: right;" onclick="parent.hideSideWrapper();"><i class="remove icon"></i> Cancel</button>
  293. <br><br><br><br>
  294. </div>
  295. <script>
  296. let expiredDomains = [];
  297. let enableTrigerOnChangeEvent = true;
  298. $(".accordion").accordion();
  299. $(".dropdown").dropdown();
  300. $(".checkbox").checkbox();
  301. function setAutoRenewIfCASupportMode(useAutoMode = true){
  302. if (useAutoMode){
  303. $("#domainCertFileTable").addClass("disabled");
  304. $("#renewNowBtn").removeClass("disabled");
  305. $("#renewSelectedButton").addClass("disabled");
  306. }else{
  307. $("#domainCertFileTable").removeClass("disabled");
  308. $("#renewNowBtn").addClass("disabled");
  309. $("#renewSelectedButton").removeClass("disabled");
  310. }
  311. }
  312. function initRenewerConfigFromFile(){
  313. //Set the renew switch state
  314. $.get("/api/acme/autoRenew/enable", function(data){
  315. if (data == true){
  316. $("#enableCertAutoRenew").parent().checkbox("set checked");
  317. }
  318. $("#enableCertAutoRenew").on("change", function(){
  319. if (!enableTrigerOnChangeEvent){
  320. return;
  321. }
  322. toggleAutoRenew();
  323. })
  324. });
  325. //Load the email from server side
  326. $.get("/api/acme/autoRenew/email", function(data){
  327. if (data != "" && data != undefined && data != null){
  328. $("#caRegisterEmail").val(data);
  329. }
  330. });
  331. //Load the domain selection options
  332. $.get("/api/acme/autoRenew/renewPolicy", function(data){
  333. if (data == true){
  334. $("#renewAllSupported").parent().checkbox("set checked");
  335. }else{
  336. $("#renewAllSupported").parent().checkbox("set unchecked");
  337. }
  338. });
  339. }
  340. initRenewerConfigFromFile();
  341. function saveEmailToConfig(btn){
  342. $.ajax({
  343. url: "/api/acme/autoRenew/email",
  344. data: {set: $("#caRegisterEmail").val()},
  345. success: function(data){
  346. if (data.error != undefined){
  347. parent.msgbox(data.error, false, 5000);
  348. }else{
  349. parent.msgbox("Email updated");
  350. $(btn).html(`<i class="green check icon"></i>`);
  351. $(btn).addClass("disabled");
  352. setTimeout(function(){
  353. $(btn).html(`<i class="blue save icon"></i>`);
  354. $(btn).removeClass("disabled");
  355. }, 3000);
  356. }
  357. }
  358. });
  359. }
  360. function toggleAutoRenew(){
  361. var enabled = $("#enableCertAutoRenew").parent().checkbox("is checked");
  362. $.post("/api/acme/autoRenew/enable?enable=" + enabled, function(data){
  363. if (data.error){
  364. parent.msgbox(data.error, false, 5000);
  365. if (enabled){
  366. enableTrigerOnChangeEvent = false;
  367. $("#enableCertAutoRenew").parent().checkbox("set unchecked");
  368. enableTrigerOnChangeEvent = true;
  369. }
  370. if (parent && parent.setACMEEnableStates){
  371. parent.setACMEEnableStates(!enabled);
  372. }
  373. }else{
  374. $("#enableToggleSucc").stop().finish().fadeIn("fast").delay(3000).fadeOut("fast");
  375. if (parent && parent.setACMEEnableStates){
  376. parent.setACMEEnableStates(enabled);
  377. }
  378. }
  379. });
  380. }
  381. //Render the domains table that exists in this zoraxy host
  382. function renderDomainTable(domainFileList) {
  383. // Get the table body element
  384. var tableBody = $('#domainTableBody');
  385. // Clear the table body
  386. tableBody.empty();
  387. // Iterate over the domain names
  388. var counter = 0;
  389. for (const [srcfile, domains] of Object.entries(domainFileList)) {
  390. // Create a table row
  391. var row = $('<tr>');
  392. // Create the domain name cell
  393. var domainClass = "validDomain";
  394. for (var i = 0; i < domains.length; i++){
  395. let thisDomain = domains[i];
  396. if (expiredDomains.includes(thisDomain)){
  397. domainClass = "expiredDomain";
  398. }
  399. }
  400. var domainCell = $('<td class="' + domainClass +'">').html(domains.join("<br>"));
  401. row.append(domainCell);
  402. var srcFileCell = $('<td>').text(srcfile);
  403. row.append(srcFileCell);
  404. // Create the auto-renew checkbox cell
  405. let domainsEncoded = encodeURIComponent(JSON.stringify(domains));
  406. var checkboxCell = $(`<td domain="${domainsEncoded}" srcfile="${srcfile}">`);
  407. var checkbox = $(`<input name="${srcfile}">`).attr('type', 'checkbox');
  408. checkboxCell.append(checkbox);
  409. row.append(checkboxCell);
  410. // Add the row to the table body
  411. tableBody.append(row);
  412. counter++;
  413. }
  414. if (Object.keys(domainFileList).length == 0){
  415. //No certificate in this system
  416. tableBody.append(`<tr>
  417. <td colspan="3"><i class="ui green circle check icon"></i> No certificate in use</td>
  418. </tr>`);
  419. }
  420. }
  421. //Initiate domain table. If you needs to update the expired domain as well
  422. //call from initDomainFileList() instead
  423. function initDomainTable(){
  424. $.get("/api/cert/listdomains?compact=true", function(data){
  425. if (data.error != undefined){
  426. parent.msgbox(data.error, false);
  427. }else{
  428. renderDomainTable(data);
  429. }
  430. initAutoRenewPolicy();
  431. })
  432. }
  433. function initDomainFileList() {
  434. $.ajax({
  435. url: "/api/acme/listExpiredDomains",
  436. method: "GET",
  437. success: function(response) {
  438. // Render domain table
  439. expiredDomains = response.domain;
  440. initDomainTable();
  441. //renderDomainTable(response.domain);
  442. },
  443. error: function(error) {
  444. console.log("Failed to fetch expired domains:", error);
  445. }
  446. });
  447. }
  448. initDomainFileList();
  449. // Button click event handler for obtaining certificate
  450. $("#obtainButton").click(function() {
  451. $("#obtainButton").addClass("loading").addClass("disabled");
  452. updateCertificateEAB();
  453. updateCertificateDNS();
  454. obtainCertificate();
  455. });
  456. $("input[name=ca]").on('change', function() {
  457. if(this.value == "Custom ACME Server") {
  458. $("#caInput").show();
  459. $("#kidInput").show();
  460. $("#hmacInput").show();
  461. $("#skipTLS").show();
  462. $("#dnsChallenge").hide();
  463. } else if (this.value == "ZeroSSL") {
  464. $("#kidInput").show();
  465. $("#hmacInput").show();
  466. $("#dnsChallenge").hide();
  467. } else if (this.value == "Buypass") {
  468. $("#kidInput").show();
  469. $("#hmacInput").show();
  470. $("#dnsChallenge").hide()
  471. }else {
  472. $("#caInput").hide();
  473. $("#skipTLS").hide();
  474. $("#kidInput").hide();
  475. $("#hmacInput").hide();
  476. $("#dnsChallenge").show();
  477. }
  478. })
  479. $("input[name=dnsProvider]").on('change', function() {
  480. // The file proivders-scraper-util.js can be used to generate the list of providers
  481. switch(this.value){
  482. case "edgedns":
  483. $("#dnsCredentials").val("AKAMAI_ACCESS_TOKEN=\nAKAMAI_CLIENT_SECRET=\nAKAMAI_CLIENT_TOKEN=\nAKAMAI_EDGERC=\nAKAMAI_EDGERC_SECTION=\nAKAMAI_HOST=");
  484. break;
  485. case "alidns":
  486. $("#dnsCredentials").val("ALICLOUD_ACCESS_KEY=\nALICLOUD_RAM_ROLE=\nALICLOUD_SECRET_KEY=\nALICLOUD_SECURITY_TOKEN=");
  487. break;
  488. case "allinkl":
  489. $("#dnsCredentials").val("ALL_INKL_LOGIN=\nALL_INKL_PASSWORD=");
  490. break;
  491. case "lightsail":
  492. $("#dnsCredentials").val("AWS_ACCESS_KEY_ID=\nAWS_ACCESS_KEY_ID_FILE=\nAWS_SHARED_CREDENTIALS_FILE=\nAWS_SECRET_ACCESS_KEY=\nAWS_SECRET_ACCESS_KEY_FILE=\nAWS_SHARED_CREDENTIALS_FILE=\nDNS_ZONE=");
  493. break;
  494. case "route53":
  495. $("#dnsCredentials").val("AWS_ACCESS_KEY_ID=\nAWS_ACCESS_KEY_ID_FILE=\nAWS_SHARED_CREDENTIALS_FILE=\nAWS_ASSUME_ROLE_ARN=\nAWS_ASSUME_ROLE_ARN_FILE=\nAWS_EXTERNAL_ID=\nAWS_EXTERNAL_ID_FILE=\nAWS_HOSTED_ZONE_ID=\nAWS_PROFILE=\nAWS_PROFILE_FILE=\nAWS_REGION=\nAWS_REGION_FILE=\nAWS_SDK_LOAD_CONFIG=\nAWS_SDK_LOAD_CONFIG_FILE=\nAWS_SECRET_ACCESS_KEY=\nAWS_SECRET_ACCESS_KEY_FILE=\nAWS_SHARED_CREDENTIALS_FILE=");
  496. break;
  497. case "arvancloud":
  498. $("#dnsCredentials").val("ARVANCLOUD_API_KEY=");
  499. break;
  500. case "auroradns":
  501. $("#dnsCredentials").val("AURORA_API_KEY=\nAURORA_SECRET=");
  502. break;
  503. case "autodns":
  504. $("#dnsCredentials").val("AUTODNS_API_PASSWORD=\nAUTODNS_API_USER=");
  505. break;
  506. case "azure":
  507. $("#dnsCredentials").val("AZURE_CLIENT_ID=\nAZURE_CLIENT_SECRET=\nAZURE_ENVIRONMENT=\nAZURE_RESOURCE_GROUP=\nAZURE_SUBSCRIPTION_ID=\nAZURE_TENANT_ID=\ninstance metadata service=");
  508. break;
  509. case "azuredns":
  510. $("#dnsCredentials").val("AZURE_CLIENT_CERTIFICATE_PATH=\nAZURE_CLIENT_ID=\nAZURE_CLIENT_SECRET=\nAZURE_TENANT_ID=");
  511. break;
  512. case "bindman":
  513. $("#dnsCredentials").val("BINDMAN_MANAGER_ADDRESS=");
  514. break;
  515. case "bluecat":
  516. $("#dnsCredentials").val("BLUECAT_CONFIG_NAME=\nBLUECAT_DNS_VIEW=\nBLUECAT_PASSWORD=\nBLUECAT_SERVER_URL=\nBLUECAT_USER_NAME=");
  517. break;
  518. case "brandit":
  519. $("#dnsCredentials").val("BRANDIT_API_KEY=\nBRANDIT_API_USERNAME=");
  520. break;
  521. case "bunny":
  522. $("#dnsCredentials").val("BUNNY_API_KEY=");
  523. break;
  524. case "checkdomain":
  525. $("#dnsCredentials").val("CHECKDOMAIN_TOKEN=");
  526. break;
  527. case "civo":
  528. $("#dnsCredentials").val("CIVO_TOKEN=");
  529. break;
  530. case "cloudru":
  531. $("#dnsCredentials").val("CLOUDRU_KEY_ID=\nCLOUDRU_SECRET=\nCLOUDRU_SERVICE_INSTANCE_ID=");
  532. break;
  533. case "clouddns":
  534. $("#dnsCredentials").val("CLOUDDNS_CLIENT_ID=\nCLOUDDNS_EMAIL=\nCLOUDDNS_PASSWORD=");
  535. break;
  536. case "cloudflare":
  537. $("#dnsCredentials").val("CF_API_EMAIL=\nCF_API_KEY=\nCF_DNS_API_TOKEN=\nCF_ZONE_API_TOKEN=\nCLOUDFLARE_API_KEY=\nCLOUDFLARE_DNS_API_TOKEN=\nCLOUDFLARE_EMAIL=\nCLOUDFLARE_ZONE_API_TOKEN=");
  538. break;
  539. case "cloudns":
  540. $("#dnsCredentials").val("CLOUDNS_AUTH_ID=\nCLOUDNS_AUTH_PASSWORD=");
  541. break;
  542. case "cloudxns":
  543. $("#dnsCredentials").val("CLOUDXNS_API_KEY=\nCLOUDXNS_SECRET_KEY=");
  544. break;
  545. case "conoha":
  546. $("#dnsCredentials").val("CONOHA_API_PASSWORD=\nCONOHA_API_USERNAME=\nCONOHA_TENANT_ID=");
  547. break;
  548. case "constellix":
  549. $("#dnsCredentials").val("CONSTELLIX_API_KEY=\nCONSTELLIX_SECRET_KEY=");
  550. break;
  551. case "cpanel":
  552. $("#dnsCredentials").val("CPANEL_BASE_URL=\nCPANEL_TOKEN=\nCPANEL_USERNAME=");
  553. break;
  554. case "derak":
  555. $("#dnsCredentials").val("DERAK_API_KEY=");
  556. break;
  557. case "desec":
  558. $("#dnsCredentials").val("DESEC_TOKEN=");
  559. break;
  560. case "designate":
  561. $("#dnsCredentials").val("OS_APPLICATION_CREDENTIAL_ID=\nOS_APPLICATION_CREDENTIAL_NAME=\nOS_APPLICATION_CREDENTIAL_SECRET=\nOS_AUTH_URL=\nOS_PASSWORD=\nOS_PROJECT_NAME=\nOS_REGION_NAME=\nOS_USERNAME=\nOS_USER_ID=");
  562. break;
  563. case "digitalocean":
  564. $("#dnsCredentials").val("DO_AUTH_TOKEN=");
  565. break;
  566. case "dnsmadeeasy":
  567. $("#dnsCredentials").val("DNSMADEEASY_API_KEY=\nDNSMADEEASY_API_SECRET=");
  568. break;
  569. case "dnshomede":
  570. $("#dnsCredentials").val("DNSHOMEDE_CREDENTIALS=");
  571. break;
  572. case "dnsimple":
  573. $("#dnsCredentials").val("DNSIMPLE_OAUTH_TOKEN=");
  574. break;
  575. case "dnspod":
  576. $("#dnsCredentials").val("DNSPOD_API_KEY=");
  577. break;
  578. case "dode":
  579. $("#dnsCredentials").val("DODE_TOKEN=");
  580. break;
  581. case "domeneshop":
  582. $("#dnsCredentials").val("DOMENESHOP_API_SECRET=\nDOMENESHOP_API_TOKEN=");
  583. break;
  584. case "dreamhost":
  585. $("#dnsCredentials").val("DREAMHOST_API_KEY=");
  586. break;
  587. case "duckdns":
  588. $("#dnsCredentials").val("DUCKDNS_TOKEN=");
  589. break;
  590. case "dyn":
  591. $("#dnsCredentials").val("DYN_CUSTOMER_NAME=\nDYN_PASSWORD=\nDYN_USER_NAME=");
  592. break;
  593. case "dynu":
  594. $("#dnsCredentials").val("DYNU_API_KEY=");
  595. break;
  596. case "easydns":
  597. $("#dnsCredentials").val("EASYDNS_KEY=\nEASYDNS_TOKEN=");
  598. break;
  599. case "efficientip":
  600. $("#dnsCredentials").val("EFFICIENTIP_DNS_NAME=\nEFFICIENTIP_HOSTNAME=\nEFFICIENTIP_PASSWORD=\nEFFICIENTIP_USERNAME=");
  601. break;
  602. case "epik":
  603. $("#dnsCredentials").val("EPIK_SIGNATURE=");
  604. break;
  605. case "exoscale":
  606. $("#dnsCredentials").val("EXOSCALE_API_KEY=\nEXOSCALE_API_SECRET=");
  607. break;
  608. case "exec":
  609. $("#dnsCredentials").val("EXEC_MODE=\nRAW=\nEXEC_PATH=");
  610. break;
  611. case "freemyip":
  612. $("#dnsCredentials").val("FREEMYIP_TOKEN=");
  613. break;
  614. case "gcore":
  615. $("#dnsCredentials").val("GCORE_PERMANENT_API_TOKEN=");
  616. break;
  617. case "gandi":
  618. $("#dnsCredentials").val("GANDI_API_KEY=");
  619. break;
  620. case "gandiv5":
  621. $("#dnsCredentials").val("GANDIV5_API_KEY=\nGANDIV5_PERSONAL_ACCESS_TOKEN=");
  622. break;
  623. case "glesys":
  624. $("#dnsCredentials").val("GLESYS_API_KEY=\nGLESYS_API_USER=");
  625. break;
  626. case "godaddy":
  627. $("#dnsCredentials").val("GODADDY_API_KEY=\nGODADDY_API_SECRET=");
  628. break;
  629. case "gcloud":
  630. $("#dnsCredentials").val("Application Default Credentials=\nGCE_PROJECT=\nGCE_SERVICE_ACCOUNT=\nGCE_SERVICE_ACCOUNT_FILE=");
  631. break;
  632. case "googledomains":
  633. $("#dnsCredentials").val("GOOGLE_DOMAINS_ACCESS_TOKEN=");
  634. break;
  635. case "hetzner":
  636. $("#dnsCredentials").val("HETZNER_API_KEY=");
  637. break;
  638. case "hostingde":
  639. $("#dnsCredentials").val("HOSTINGDE_API_KEY=");
  640. break;
  641. case "hosttech":
  642. $("#dnsCredentials").val("HOSTTECH_API_KEY=\nHOSTTECH_PASSWORD=");
  643. break;
  644. case "httpreq":
  645. $("#dnsCredentials").val("HTTPREQ_ENDPOINT=\nHTTPREQ_MODE=\nRAW=");
  646. break;
  647. case "httpnet":
  648. $("#dnsCredentials").val("HTTPNET_API_KEY=");
  649. break;
  650. case "hurricane":
  651. $("#dnsCredentials").val("HURRICANE_TOKENS=");
  652. break;
  653. case "hyperone":
  654. $("#dnsCredentials").val("HYPERONE_API_URL=\nHYPERONE_LOCATION_ID=\nHYPERONE_PASSPORT_LOCATION=\nHYPERONE_POLLING_INTERVAL=\nHYPERONE_PROPAGATION_TIMEOUT=\nHYPERONE_TTL=");
  655. break;
  656. case "ibmcloud":
  657. $("#dnsCredentials").val("SOFTLAYER_API_KEY=\nSOFTLAYER_USERNAME=");
  658. break;
  659. case "iijdpf":
  660. $("#dnsCredentials").val("IIJ_DPF_API_TOKEN=\nIIJ_DPF_DPM_SERVICE_CODE=");
  661. break;
  662. case "infoblox":
  663. $("#dnsCredentials").val("INFOBLOX_HOST=\nINFOBLOX_PASSWORD=\nINFOBLOX_USERNAME=");
  664. break;
  665. case "infomaniak":
  666. $("#dnsCredentials").val("INFOMANIAK_ACCESS_TOKEN=");
  667. break;
  668. case "iij":
  669. $("#dnsCredentials").val("IIJ_API_ACCESS_KEY=\nIIJ_API_SECRET_KEY=\nIIJ_DO_SERVICE_CODE=");
  670. break;
  671. case "internetbs":
  672. $("#dnsCredentials").val("INTERNET_BS_API_KEY=\nINTERNET_BS_PASSWORD=");
  673. break;
  674. case "inwx":
  675. $("#dnsCredentials").val("INWX_PASSWORD=\nINWX_USERNAME=");
  676. break;
  677. case "ionos":
  678. $("#dnsCredentials").val("IONOS_API_KEY=\n&lt;prefix&gt;.&lt;secret&gt;=");
  679. break;
  680. case "ipv64":
  681. $("#dnsCredentials").val("IPV64_API_KEY=");
  682. break;
  683. case "iwantmyname":
  684. $("#dnsCredentials").val("IWANTMYNAME_PASSWORD=\nIWANTMYNAME_USERNAME=");
  685. break;
  686. case "joker":
  687. $("#dnsCredentials").val("JOKER_API_KEY=\nJOKER_API_MODE=\nJOKER_PASSWORD=\nJOKER_USERNAME=");
  688. break;
  689. case "acme-dns":
  690. $("#dnsCredentials").val("ACME_DNS_API_BASE=\nACME_DNS_STORAGE_PATH=");
  691. break;
  692. case "liara":
  693. $("#dnsCredentials").val("LIARA_API_KEY=");
  694. break;
  695. case "linode":
  696. $("#dnsCredentials").val("LINODE_TOKEN=");
  697. break;
  698. case "liquidweb":
  699. $("#dnsCredentials").val("LWAPI_PASSWORD=\nLWAPI_USERNAME=");
  700. break;
  701. case "loopia":
  702. $("#dnsCredentials").val("LOOPIA_API_PASSWORD=\nLOOPIA_API_USER=");
  703. break;
  704. case "luadns":
  705. $("#dnsCredentials").val("LUADNS_API_TOKEN=\nLUADNS_API_USERNAME=");
  706. break;
  707. case "mailinabox":
  708. $("#dnsCredentials").val("MAILINABOX_BASE_URL=\nMAILINABOX_EMAIL=\nMAILINABOX_PASSWORD=");
  709. break;
  710. case "metaname":
  711. $("#dnsCredentials").val("METANAME_ACCOUNT_REFERENCE=\nMETANAME_API_KEY=");
  712. break;
  713. case "mydnsjp":
  714. $("#dnsCredentials").val("MYDNSJP_MASTER_ID=\nMYDNSJP_PASSWORD=");
  715. break;
  716. case "mythicbeasts":
  717. $("#dnsCredentials").val("MYTHICBEASTS_PASSWORD=\nMYTHICBEASTS_USERNAME=");
  718. break;
  719. case "namedotcom":
  720. $("#dnsCredentials").val("NAMECOM_API_TOKEN=\nNAMECOM_USERNAME=");
  721. break;
  722. case "namecheap":
  723. $("#dnsCredentials").val("NAMECHEAP_API_KEY=\nNAMECHEAP_API_USER=");
  724. break;
  725. case "namesilo":
  726. $("#dnsCredentials").val("NAMESILO_API_KEY=");
  727. break;
  728. case "nearlyfreespeech":
  729. $("#dnsCredentials").val("NEARLYFREESPEECH_API_KEY=\nNEARLYFREESPEECH_LOGIN=");
  730. break;
  731. case "netcup":
  732. $("#dnsCredentials").val("NETCUP_API_KEY=\nNETCUP_API_PASSWORD=\nNETCUP_CUSTOMER_NUMBER=");
  733. break;
  734. case "netlify":
  735. $("#dnsCredentials").val("NETLIFY_TOKEN=");
  736. break;
  737. case "nicmanager":
  738. $("#dnsCredentials").val("NICMANAGER_API_EMAIL=\nNICMANAGER_API_LOGIN=\nNICMANAGER_API_PASSWORD=\nNICMANAGER_API_USERNAME=");
  739. break;
  740. case "nifcloud":
  741. $("#dnsCredentials").val("NIFCLOUD_ACCESS_KEY_ID=\nNIFCLOUD_SECRET_ACCESS_KEY=");
  742. break;
  743. case "njalla":
  744. $("#dnsCredentials").val("NJALLA_TOKEN=");
  745. break;
  746. case "nodion":
  747. $("#dnsCredentials").val("NODION_API_TOKEN=");
  748. break;
  749. case "ns1":
  750. $("#dnsCredentials").val("NS1_API_KEY=");
  751. break;
  752. case "otc":
  753. $("#dnsCredentials").val("OTC_DOMAIN_NAME=\nOTC_IDENTITY_ENDPOINT=\nOTC_PASSWORD=\nOTC_PROJECT_NAME=\nOTC_USER_NAME=");
  754. break;
  755. case "oraclecloud":
  756. $("#dnsCredentials").val("OCI_COMPARTMENT_OCID=\nOCI_PRIVKEY_FILE=\nOCI_PRIVKEY_PASS=\nOCI_PUBKEY_FINGERPRINT=\nOCI_REGION=\nOCI_TENANCY_OCID=\nOCI_USER_OCID=");
  757. break;
  758. case "ovh":
  759. $("#dnsCredentials").val("OVH_APPLICATION_KEY=\nOVH_APPLICATION_SECRET=\nOVH_CONSUMER_KEY=\nOVH_ENDPOINT=");
  760. break;
  761. case "plesk":
  762. $("#dnsCredentials").val("PLESK_PASSWORD=\nPLESK_SERVER_BASE_URL=\nPLESK_USERNAME=");
  763. break;
  764. case "porkbun":
  765. $("#dnsCredentials").val("PORKBUN_API_KEY=\nPORKBUN_SECRET_API_KEY=");
  766. break;
  767. case "pdns":
  768. $("#dnsCredentials").val("PDNS_API_KEY=\nPDNS_API_URL=");
  769. break;
  770. case "rackspace":
  771. $("#dnsCredentials").val("RACKSPACE_API_KEY=\nRACKSPACE_USER=");
  772. break;
  773. case "rcodezero":
  774. $("#dnsCredentials").val("RCODEZERO_API_TOKEN=");
  775. break;
  776. case "regru":
  777. $("#dnsCredentials").val("REGRU_PASSWORD=\nREGRU_USERNAME=");
  778. break;
  779. case "rfc2136":
  780. $("#dnsCredentials").val("RFC2136_NAMESERVER=\nRFC2136_TSIG_ALGORITHM=\nRFC2136_TSIG*=\nRFC2136_TSIG_KEY=\nRFC2136_TSIG*=\nRFC2136_TSIG_SECRET=\n RFC2136_TSIG*=");
  781. break;
  782. case "rimuhosting":
  783. $("#dnsCredentials").val("RIMUHOSTING_API_KEY=");
  784. break;
  785. case "sakuracloud":
  786. $("#dnsCredentials").val("SAKURACLOUD_ACCESS_TOKEN=\nSAKURACLOUD_ACCESS_TOKEN_SECRET=");
  787. break;
  788. case "scaleway":
  789. $("#dnsCredentials").val("SCW_PROJECT_ID=\nSCW_SECRET_KEY=");
  790. break;
  791. case "selectel":
  792. $("#dnsCredentials").val("SELECTEL_API_TOKEN=");
  793. break;
  794. case "selectelv2":
  795. $("#dnsCredentials").val("SELECTELV2_ACCOUNT_ID=\nSELECTELV2_PASSWORD=\nSELECTELV2_PROJECT_ID=\nSELECTELV2_USERNAME=");
  796. break;
  797. case "servercow":
  798. $("#dnsCredentials").val("SERVERCOW_PASSWORD=\nSERVERCOW_USERNAME=");
  799. break;
  800. case "shellrent":
  801. $("#dnsCredentials").val("SHELLRENT_TOKEN=\nSHELLRENT_USERNAME=");
  802. break;
  803. case "simply":
  804. $("#dnsCredentials").val("SIMPLY_ACCOUNT_NAME=\nSIMPLY_API_KEY=");
  805. break;
  806. case "sonic":
  807. $("#dnsCredentials").val("SONIC_API_KEY=\nSONIC_USER_ID=");
  808. break;
  809. case "stackpath":
  810. $("#dnsCredentials").val("STACKPATH_CLIENT_ID=\nSTACKPATH_CLIENT_SECRET=\nSTACKPATH_STACK_ID=");
  811. break;
  812. case "tencentcloud":
  813. $("#dnsCredentials").val("TENCENTCLOUD_SECRET_ID=\nTENCENTCLOUD_SECRET_KEY=");
  814. break;
  815. case "transip":
  816. $("#dnsCredentials").val("TRANSIP_ACCOUNT_NAME=\nTRANSIP_PRIVATE_KEY_PATH=");
  817. break;
  818. case "safedns":
  819. $("#dnsCredentials").val("SAFEDNS_AUTH_TOKEN=");
  820. break;
  821. case "ultradns":
  822. $("#dnsCredentials").val("ULTRADNS_PASSWORD=\nULTRADNS_USERNAME=");
  823. break;
  824. case "variomedia":
  825. $("#dnsCredentials").val("VARIOMEDIA_API_TOKEN=");
  826. break;
  827. case "vegadns":
  828. $("#dnsCredentials").val("SECRET_VEGADNS_KEY=\nSECRET_VEGADNS_SECRET=\nVEGADNS_URL=");
  829. break;
  830. case "vercel":
  831. $("#dnsCredentials").val("VERCEL_API_TOKEN=");
  832. break;
  833. case "versio":
  834. $("#dnsCredentials").val("VERSIO_PASSWORD=\nVERSIO_USERNAME=");
  835. break;
  836. case "vinyldns":
  837. $("#dnsCredentials").val("VINYLDNS_ACCESS_KEY=\nVINYLDNS_HOST=\nVINYLDNS_SECRET_KEY=");
  838. break;
  839. case "vkcloud":
  840. $("#dnsCredentials").val("VK_CLOUD_PASSWORD=\nVK_CLOUD_PROJECT_ID=\nVK_CLOUD_USERNAME=");
  841. break;
  842. case "vscale":
  843. $("#dnsCredentials").val("VSCALE_API_TOKEN=");
  844. break;
  845. case "vultr":
  846. $("#dnsCredentials").val("VULTR_API_KEY=");
  847. break;
  848. case "webnames":
  849. $("#dnsCredentials").val("WEBNAMES_API_KEY=");
  850. break;
  851. case "httpreq":
  852. $("#dnsCredentials").val("HTTPREQ_ENDPOINT=\nHTTPREQ_MODE=\nRAW=");
  853. break;
  854. case "websupport":
  855. $("#dnsCredentials").val("WEBSUPPORT_API_KEY=\nWEBSUPPORT_SECRET=");
  856. break;
  857. case "wedos":
  858. $("#dnsCredentials").val("WEDOS_USERNAME=\nWEDOS_WAPI_PASSWORD=");
  859. break;
  860. case "yandex360":
  861. $("#dnsCredentials").val("YANDEX360_OAUTH_TOKEN=\nYANDEX360_ORG_ID=");
  862. break;
  863. case "yandexcloud":
  864. $("#dnsCredentials").val("YANDEX_CLOUD_FOLDER_ID=\nYANDEX_CLOUD_IAM_TOKEN=\ndns.admin=");
  865. break;
  866. case "yandex":
  867. $("#dnsCredentials").val("YANDEX_PDD_TOKEN=");
  868. break;
  869. case "zoneee":
  870. $("#dnsCredentials").val("ZONEEE_API_KEY=\nZONEEE_API_USER=");
  871. break;
  872. case "zonomi":
  873. $("#dnsCredentials").val("ZONOMI_API_KEY=");
  874. break;
  875. }
  876. })
  877. // Get filename form domains and input
  878. function getFilename() {
  879. var domains = $("#domainsInput").val();
  880. var filename = $("#filenameInput").val();
  881. if (filename.trim() == "" && !domains.includes(",")){
  882. //Zoraxy filename are the matching name for domains.
  883. //Use the same as domains
  884. filename = domains;
  885. }else if (filename != "" && !domains.includes(",")){
  886. //Invalid settings. Force the filename to be same as domain
  887. //if there are only 1 domain
  888. filename = domains;
  889. }else if (filename == "" && domains.includes(",")){
  890. parent.msgbox("Filename cannot be empty for certs containing multiple domains.", false, 5000);
  891. $("#obtainButton").removeClass("loading").removeClass("disabled");
  892. return;
  893. }
  894. //Filename cannot contain wildcards, and wildcards are possible with DNS challenges
  895. filename = filename.replace("*", "_");
  896. return filename;
  897. }
  898. // Update EAB values for autorenewal
  899. function updateCertificateEAB() {
  900. var ca = $("#ca").dropdown("get value");
  901. var caURL = "";
  902. if (ca == "Custom ACME Server") {
  903. ca = "custom";
  904. caURL = $("#caURL").val();
  905. }else if(ca == "Buypass") {
  906. caURL = "https://api.buypass.com/acme/directory";
  907. }else if(ca == "ZeroSSL") {
  908. caURL = "https://acme.zerossl.com/v2/DV90";
  909. }
  910. if(caURL == "") {
  911. return;
  912. }
  913. var kid = $("#eab_kid").val();
  914. var hmac = $("#eab_hmac").val();
  915. if(kid == "" || hmac == "") {
  916. return;
  917. }
  918. console.log(caURL + " " + kid + " " + hmac);
  919. $.ajax({
  920. url: "/api/acme/autoRenew/setEAB",
  921. method: "GET",
  922. data: {
  923. acmeDirectoryURL: caURL,
  924. kid: kid,
  925. hmacEncoded: hmac,
  926. },
  927. success: function(response) {
  928. //$("#obtainButton").removeClass("loading").removeClass("disabled");
  929. if (response.error) {
  930. console.log("Error:", response.error);
  931. // Show error message
  932. parent.msgbox(response.error, false, 12000);
  933. } else {
  934. console.log("Certificate EAB updated successfully");
  935. // Show success message
  936. parent.msgbox("Certificate EAB updated successfully");
  937. // Renew the parent certificate list
  938. parent.initManagedDomainCertificateList();
  939. }
  940. },
  941. error: function(error) {
  942. //$("#obtainButton").removeClass("loading").removeClass("disabled");
  943. console.log("Failed to update EAB configuration:", error);
  944. parent.msgbox("Failed to update EAB configuration");
  945. }
  946. });
  947. }
  948. // Update DNS values for autorenewal
  949. function updateCertificateDNS() {
  950. var dns = $("#useDnsChallenge")[0].checked;
  951. var dnsProvider = "";
  952. var dnsCredentials = "";
  953. if (dns) {
  954. dnsProvider = $("#dnsProvider").dropdown("get value");
  955. dnsCredentials = $("#dnsCredentials").val();
  956. if(dnsProvider == "") {
  957. parent.msgbox("DNS Provider cannot be empty", false, 5000);
  958. $("#obtainButton").removeClass("loading").removeClass("disabled");
  959. return;
  960. }
  961. if(dnsCredentials == "") {
  962. parent.msgbox("DNS Credentials cannot be empty", false, 5000);
  963. $("#obtainButton").removeClass("loading").removeClass("disabled");
  964. return;
  965. }
  966. } else {
  967. return;
  968. }
  969. var filename = getFilename();
  970. if (filename == '') {
  971. return;
  972. }
  973. $.ajax({
  974. url: "/api/acme/autoRenew/setDNS",
  975. method: "POST",
  976. data: {
  977. filename: filename,
  978. dnsProvider: dnsProvider,
  979. dnsCredentials: dnsCredentials,
  980. },
  981. success: function(response) {
  982. //$("#obtainButton").removeClass("loading").removeClass("disabled");
  983. if (response.error) {
  984. console.log("Error:", response.error);
  985. // Show error message
  986. parent.msgbox(response.error, false, 12000);
  987. } else {
  988. console.log("Certificate DNS Credentials updated successfully");
  989. // Show success message
  990. parent.msgbox("Certificate DNS Credentials updated successfully");
  991. }
  992. },
  993. error: function(error) {
  994. //$("#obtainButton").removeClass("loading").removeClass("disabled");
  995. console.log("Failed to update DNS configuration:", error);
  996. parent.msgbox("Failed to update DNS configuration");
  997. }
  998. });
  999. }
  1000. // Obtain certificate from API
  1001. function obtainCertificate() {
  1002. var domains = $("#domainsInput").val();
  1003. var filename = getFilename();
  1004. if (filename == '') {
  1005. return;
  1006. }
  1007. var email = $("#caRegisterEmail").val();
  1008. if (email == ""){
  1009. parent.msgbox("ACME renew email is not set", false)
  1010. $("#obtainButton").removeClass("loading").removeClass("disabled");
  1011. return;
  1012. }
  1013. var ca = $("#ca").dropdown("get value");
  1014. var caURL = "";
  1015. if (ca == "Custom ACME Server") {
  1016. ca = "custom";
  1017. caURL = $("#caURL").val();
  1018. }
  1019. var dns = $("#useDnsChallenge")[0].checked;
  1020. var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
  1021. $.ajax({
  1022. url: "/api/acme/obtainCert",
  1023. method: "GET",
  1024. data: {
  1025. domains: domains,
  1026. filename: filename,
  1027. email: email,
  1028. ca: ca,
  1029. caURL: caURL,
  1030. skipTLS: skipTLSValue,
  1031. dns: dns,
  1032. },
  1033. success: function(response) {
  1034. $("#obtainButton").removeClass("loading").removeClass("disabled");
  1035. if (response.error) {
  1036. console.log("Error:", response.error);
  1037. // Show error message
  1038. parent.msgbox(response.error, false, 12000);
  1039. } else {
  1040. console.log("Certificate renewed successfully");
  1041. // Show success message
  1042. parent.msgbox("Certificate renewed successfully");
  1043. // Renew the parent certificate list
  1044. parent.initManagedDomainCertificateList();
  1045. }
  1046. },
  1047. error: function(error) {
  1048. $("#obtainButton").removeClass("loading").removeClass("disabled");
  1049. console.log("Failed to renewed certificate:", error);
  1050. }
  1051. });
  1052. }
  1053. function checkIfInputDomainIsMultiple(){
  1054. var inputDomains = $("#domainsInput").val();
  1055. if (inputDomains.includes(",")){
  1056. $(".multiDomainOnly").show();
  1057. }else{
  1058. $(".multiDomainOnly").hide();
  1059. }
  1060. }
  1061. function toggleDnsChallenge(){
  1062. if ( $("#useDnsChallenge")[0].checked){
  1063. $(".dnsChallengeOnly").show();
  1064. }else{
  1065. $(".dnsChallengeOnly").hide();
  1066. }
  1067. }
  1068. //Grab the longest common suffix of all domains
  1069. //not that smart technically
  1070. function autoDetectMatchingRules(){
  1071. var domainsString = $("#domainsInput").val();
  1072. if (!domainsString.includes(",")){
  1073. return domainsString;
  1074. }
  1075. let domains = domainsString.split(",");
  1076. //Clean out any spacing between commas
  1077. for (var i = 0; i < domains.length; i++){
  1078. domains[i] = domains[i].trim();
  1079. }
  1080. function getLongestCommonSuffix(strings) {
  1081. if (strings.length === 0) {
  1082. return ''; // Return an empty string if the array is empty
  1083. }
  1084. var sortedStrings = strings.slice().sort(); // Create a sorted copy of the array
  1085. var firstString = sortedStrings[0];
  1086. var lastString = sortedStrings[sortedStrings.length - 1];
  1087. var suffix = '';
  1088. var minLength = Math.min(firstString.length, lastString.length);
  1089. for (var i = 0; i < minLength; i++) {
  1090. if (firstString[firstString.length - 1 - i] !== lastString[lastString.length - 1 - i]) {
  1091. break; // Stop iterating if characters don't match
  1092. }
  1093. suffix = firstString[firstString.length - 1 - i] + suffix;
  1094. }
  1095. return suffix;
  1096. }
  1097. let longestSuffix = getLongestCommonSuffix(domains);
  1098. //Check if the suffix is a valid domain
  1099. if (longestSuffix.substr(0,1) == "."){
  1100. //Trim off the first dot
  1101. longestSuffix = longestSuffix.substr(1);
  1102. }
  1103. if (!longestSuffix.includes(".")){
  1104. parent.msgbox("Auto Detect failed: Multiple Domains", false, 5000);
  1105. return;
  1106. }
  1107. $("#filenameInput").val(longestSuffix);
  1108. }
  1109. //Handle the renew now btn click
  1110. function renewNow(){
  1111. $.get("/api/acme/autoRenew/renewNow", function(data){
  1112. if (data.error != undefined){
  1113. parent.msgbox(data.error, false, 6000);
  1114. }else{
  1115. parent.msgbox(data)
  1116. }
  1117. })
  1118. }
  1119. function initAutoRenewPolicy(){
  1120. $.get("/api/acme/autoRenew/listDomains", function(data){
  1121. if (data.error != undefined){
  1122. parent.msgbox(data.error, false)
  1123. }else{
  1124. if (data[0] == "*"){
  1125. //Auto select and renew is enabled
  1126. $("#renewAllSupported").parent().checkbox("set checked");
  1127. }else{
  1128. //This is a list of domain files
  1129. data.forEach(function(name) {
  1130. $('#domainTableBody input[type="checkbox"][name="' + name + '"]').prop('checked', true);
  1131. });
  1132. $("#domainCertFileTable").removeClass("disabled");
  1133. $("#renewNowBtn").addClass("disabled");
  1134. $("#renewSelectedButton").removeClass("disabled");
  1135. }
  1136. }
  1137. })
  1138. }
  1139. function saveAutoRenewPolicy(){
  1140. let autoRenewAll = $("#renewAllSupported").parent().checkbox("is checked");
  1141. if (autoRenewAll == true){
  1142. $.ajax({
  1143. url: "/api/acme/autoRenew/setDomains",
  1144. data: {opr: "setAuto"},
  1145. success: function(data){
  1146. parent.msgbox("Renew policy rule updated")
  1147. }
  1148. });
  1149. }else{
  1150. let checkedNames = [];
  1151. $('#domainTableBody input[type="checkbox"]:checked').each(function() {
  1152. checkedNames.push($(this).attr('name'));
  1153. });
  1154. $.ajax({
  1155. url: "/api/acme/autoRenew/setDomains",
  1156. data: {opr: "setSelected", domains: JSON.stringify(checkedNames)},
  1157. success: function(data){
  1158. parent.msgbox("Renew policy rule updated")
  1159. }
  1160. });
  1161. }
  1162. }
  1163. //Clear up the input field when page load
  1164. $("#filenameInput").val("");
  1165. </script>
  1166. </body>
  1167. </html>