Merge pull request #57 from daluntw/dev-custom-acme

Add Skip TLS Verify Feature For ACME Server
This commit is contained in:
Toby Chui 2023-08-29 10:06:52 +08:00 committed by GitHub
commit 069f4805f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 11 deletions

View File

@ -5,6 +5,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
"encoding/pem" "encoding/pem"
@ -30,6 +31,7 @@ import (
type CertificateInfoJSON struct { type CertificateInfoJSON struct {
AcmeName string `json:"acme_name"` AcmeName string `json:"acme_name"`
AcmeUrl string `json:"acme_url"` AcmeUrl string `json:"acme_url"`
SkipTLS bool `json:"skip_tls"`
} }
// ACMEUser represents a user in the ACME system. // ACMEUser represents a user in the ACME system.
@ -69,7 +71,7 @@ func NewACME(acmeServer string, port string) *ACMEHandler {
} }
// ObtainCert obtains a certificate for the specified domains. // ObtainCert obtains a certificate for the specified domains.
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string) (bool, error) { func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool) (bool, error) {
log.Println("[ACME] Obtaining certificate...") log.Println("[ACME] Obtaining certificate...")
// generate private key // generate private key
@ -88,6 +90,24 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
// create config // create config
config := lego.NewConfig(&adminUser) config := lego.NewConfig(&adminUser)
// skip TLS verify if need
// Ref: https://github.com/go-acme/lego/blob/6af2c756ac73a9cb401621afca722d0f4112b1b8/lego/client_config.go#L74
if skipTLS {
log.Println("[INFO] Ignore TLS/SSL Verification Error for ACME Server")
config.HTTPClient.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 30 * time.Second,
ResponseHeaderTimeout: 30 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}
// setup the custom ACME url endpoint. // setup the custom ACME url endpoint.
if caUrl != "" { if caUrl != "" {
config.CADirURL = caUrl config.CADirURL = caUrl
@ -159,6 +179,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
certInfo := &CertificateInfoJSON{ certInfo := &CertificateInfoJSON{
AcmeName: caName, AcmeName: caName,
AcmeUrl: caUrl, AcmeUrl: caUrl,
SkipTLS: skipTLS,
} }
certInfoBytes, err := json.Marshal(certInfo) certInfoBytes, err := json.Marshal(certInfo)
@ -287,15 +308,25 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
} }
if ca == "custom" { if ca == "custom" {
caUrl, err = utils.PostPara(r, "ca_url") caUrl, err = utils.PostPara(r, "caURL")
if err != nil { if err != nil {
log.Println("Custom CA set but no URL provide, Using default") log.Println("Custom CA set but no URL provide, Using default")
ca, caUrl = "", "" ca, caUrl = "", ""
} }
} }
var skipTLS bool
if skipTLSString, err := utils.PostPara(r, "skipTLS"); err != nil {
skipTLS = false
} else if skipTLSString != "true" {
skipTLS = false
} else {
skipTLS = true
}
domains := strings.Split(domainPara, ",") domains := strings.Split(domainPara, ",")
result, err := a.ObtainCert(domains, filename, email, ca, caUrl) result, err := a.ObtainCert(domains, filename, email, ca, caUrl, skipTLS)
if err != nil { if err != nil {
utils.SendErrorResponse(w, jsonEscape(err.Error())) utils.SendErrorResponse(w, jsonEscape(err.Error()))
return return

View File

@ -365,7 +365,7 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
certInfo = &CertificateInfoJSON{} certInfo = &CertificateInfoJSON{}
} }
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl) _, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS)
if err != nil { if err != nil {
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error()) log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error())
} else { } else {

View File

@ -114,9 +114,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="field" id="customca" style="display:none;"> <div class="field" id="caInput" style="display:none;">
<label>ACME Server URL</label> <label>ACME Server URL</label>
<input id="caurl" type="text" placeholder="https://example.com/acme/dictionary"> <input id="caURL" type="text" placeholder="https://example.com/acme/dictionary">
</div>
<div class="field" id="skipTLS" style="display:none;">
<div class="ui checkbox">
<input type="checkbox" id="skipTLSCheckbox">
<label>Ignore TLS/SSL Verification Error<br><small>E.g. self-signed, expired certificate (Not Recommended)</small></label>
</div>
</div> </div>
<button id="obtainButton" class="ui basic button" type="submit"><i class="yellow refresh icon"></i> Renew Certificate</button> <button id="obtainButton" class="ui basic button" type="submit"><i class="yellow refresh icon"></i> Renew Certificate</button>
</div> </div>
@ -302,9 +308,11 @@
$("input[name=ca]").on('change', function() { $("input[name=ca]").on('change', function() {
if(this.value == "Custom ACME Server") { if(this.value == "Custom ACME Server") {
$("#customca").show(); $("#caInput").show();
$("#skipTLS").show();
} else { } else {
$("#customca").hide(); $("#caInput").hide();
$("#skipTLS").hide();
} }
}) })
@ -331,12 +339,14 @@
} }
var ca = $("#ca").dropdown("get value"); var ca = $("#ca").dropdown("get value");
var ca_url = ""; var caURL = "";
if (ca == "Custom ACME Server") { if (ca == "Custom ACME Server") {
ca = "custom"; ca = "custom";
ca_url = $("#caurl").val(); caURL = $("#caURL").val();
} }
var skipTLSValue = $("#skipTLSCheckbox")[0].checked;
$.ajax({ $.ajax({
url: "/api/acme/obtainCert", url: "/api/acme/obtainCert",
method: "GET", method: "GET",
@ -345,7 +355,8 @@
filename: filename, filename: filename,
email: email, email: email,
ca: ca, ca: ca,
ca_url: ca_url, caURL: caURL,
skipTLS: skipTLSValue,
}, },
success: function(response) { success: function(response) {
$("#obtainButton").removeClass("loading").removeClass("disabled"); $("#obtainButton").removeClass("loading").removeClass("disabled");