Added optional TLS bypass mechanism

+ Added opt-out for subdomains for global TLS settings #44
+ Optimized subdomain / vdir editing interface
This commit is contained in:
Toby Chui 2023-11-25 15:54:28 +08:00
parent e363d55899
commit ce4ce72820
8 changed files with 199 additions and 41 deletions

View File

@ -54,6 +54,7 @@ func initAPIs() {
authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS) authRouter.HandleFunc("/api/proxy/tlscheck", HandleCheckSiteSupportTLS)
authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet) authRouter.HandleFunc("/api/proxy/setIncoming", HandleIncomingPortSet)
authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect) authRouter.HandleFunc("/api/proxy/useHttpsRedirect", HandleUpdateHttpsRedirect)
authRouter.HandleFunc("/api/proxy/listenPort80", HandleUpdatePort80Listener)
authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck) authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
//Reverse proxy root related APIs //Reverse proxy root related APIs
authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList) authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList)

View File

@ -60,6 +60,12 @@ func (router *Router) UpdateTLSVersion(requireLatest bool) {
router.Restart() router.Restart()
} }
// Update port 80 listener state
func (router *Router) UpdatePort80ListenerState(useRedirect bool) {
router.Option.ListenOnPort80 = useRedirect
router.Restart()
}
// Update https redirect, which will require updates // Update https redirect, which will require updates
func (router *Router) UpdateHttpToHttpsRedirectSetting(useRedirect bool) { func (router *Router) UpdateHttpToHttpsRedirectSetting(useRedirect bool) {
router.Option.ForceHttpsRedirect = useRedirect router.Option.ForceHttpsRedirect = useRedirect
@ -112,16 +118,56 @@ func (router *Router) StartProxyService() error {
} }
router.Running = true router.Running = true
if router.Option.Port != 80 && router.Option.ForceHttpsRedirect { if router.Option.Port != 80 && router.Option.ListenOnPort80 {
//Add a 80 to 443 redirector //Add a 80 to 443 redirector
httpServer := &http.Server{ httpServer := &http.Server{
Addr: ":80", Addr: ":80",
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
protocol := "https://" //Check if the domain requesting allow non TLS mode
if router.Option.Port == 443 { domainOnly := r.Host
http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect) if strings.Contains(r.Host, ":") {
hostPath := strings.Split(r.Host, ":")
domainOnly = hostPath[0]
}
sep := router.getSubdomainProxyEndpointFromHostname(domainOnly)
if sep != nil && sep.BypassGlobalTLS {
//Allow routing via non-TLS handler
originalHostHeader := r.Host
if r.URL != nil {
r.Host = r.URL.Host
} else {
//Fallback when the upstream proxy screw something up in the header
r.URL, _ = url.Parse(originalHostHeader)
}
sep.Proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
ProxyDomain: sep.Domain,
OriginalHost: originalHostHeader,
UseTLS: sep.RequireTLS,
PathPrefix: "",
})
return
}
if router.Option.ForceHttpsRedirect {
//Redirect to https is enabled
protocol := "https://"
if router.Option.Port == 443 {
http.Redirect(w, r, protocol+r.Host+r.RequestURI, http.StatusTemporaryRedirect)
} else {
http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect)
}
} else { } else {
http.Redirect(w, r, protocol+r.Host+":"+strconv.Itoa(router.Option.Port)+r.RequestURI, http.StatusTemporaryRedirect) //Do not do redirection
if sep != nil {
//Sub-domain exists but not allow non-TLS access
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("400 - Bad Request"))
} else {
//No defined sub-domain
http.NotFound(w, r)
}
} }
}), }),

View File

@ -27,6 +27,7 @@ type RouterOption struct {
Port int //Incoming port Port int //Incoming port
UseTls bool //Use TLS to serve incoming requsts UseTls bool //Use TLS to serve incoming requsts
ForceTLSLatest bool //Force TLS1.2 or above ForceTLSLatest bool //Force TLS1.2 or above
ListenOnPort80 bool //Enable port 80 http listener
ForceHttpsRedirect bool //Force redirection of http to https endpoint ForceHttpsRedirect bool //Force redirection of http to https endpoint
TlsManager *tlscert.Manager TlsManager *tlscert.Manager
RedirectRuleTable *redirection.RuleTable RedirectRuleTable *redirection.RuleTable

View File

@ -45,10 +45,20 @@ func ReverseProxtInit() {
SystemWideLogger.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0") SystemWideLogger.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0")
} }
listenOnPort80 := false
sysdb.Read("settings", "listenP80", &listenOnPort80)
if listenOnPort80 {
SystemWideLogger.Println("Port 80 listener enabled")
} else {
SystemWideLogger.Println("Port 80 listener disabled")
}
forceHttpsRedirect := false forceHttpsRedirect := false
sysdb.Read("settings", "redirect", &forceHttpsRedirect) sysdb.Read("settings", "redirect", &forceHttpsRedirect)
if forceHttpsRedirect { if forceHttpsRedirect {
SystemWideLogger.Println("Force HTTPS mode enabled") SystemWideLogger.Println("Force HTTPS mode enabled")
//Port 80 listener must be enabled to perform http -> https redirect
listenOnPort80 = true
} else { } else {
SystemWideLogger.Println("Force HTTPS mode disabled") SystemWideLogger.Println("Force HTTPS mode disabled")
} }
@ -58,6 +68,7 @@ func ReverseProxtInit() {
Port: inboundPort, Port: inboundPort,
UseTls: useTls, UseTls: useTls,
ForceTLSLatest: forceLatestTLSVersion, ForceTLSLatest: forceLatestTLSVersion,
ListenOnPort80: listenOnPort80,
ForceHttpsRedirect: forceHttpsRedirect, ForceHttpsRedirect: forceHttpsRedirect,
TlsManager: tlsCertManager, TlsManager: tlsCertManager,
RedirectRuleTable: redirectTable, RedirectRuleTable: redirectTable,
@ -343,9 +354,15 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
if stv == "" { if stv == "" {
stv = "false" stv = "false"
} }
skipTlsValidation := (stv == "true") skipTlsValidation := (stv == "true")
//Load bypass TLS option
bpgtls, _ := utils.PostPara(r, "bpgtls")
if bpgtls == "" {
bpgtls = "false"
}
bypassGlobalTLS := (bpgtls == "true")
rba, _ := utils.PostPara(r, "bauth") rba, _ := utils.PostPara(r, "bauth")
if rba == "" { if rba == "" {
rba = "false" rba = "false"
@ -365,6 +382,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
RootName: targetProxyEntry.RootOrMatchingDomain, RootName: targetProxyEntry.RootOrMatchingDomain,
Domain: endpoint, Domain: endpoint,
RequireTLS: useTLS, RequireTLS: useTLS,
BypassGlobalTLS: false,
SkipCertValidations: skipTlsValidation, SkipCertValidations: skipTlsValidation,
RequireBasicAuth: requireBasicAuth, RequireBasicAuth: requireBasicAuth,
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials, BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
@ -377,6 +395,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
MatchingDomain: targetProxyEntry.RootOrMatchingDomain, MatchingDomain: targetProxyEntry.RootOrMatchingDomain,
Domain: endpoint, Domain: endpoint,
RequireTLS: useTLS, RequireTLS: useTLS,
BypassGlobalTLS: bypassGlobalTLS,
SkipCertValidations: skipTlsValidation, SkipCertValidations: skipTlsValidation,
RequireBasicAuth: requireBasicAuth, RequireBasicAuth: requireBasicAuth,
BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials, BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
@ -749,6 +768,35 @@ func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
} }
} }
// Handle port 80 incoming traffics
func HandleUpdatePort80Listener(w http.ResponseWriter, r *http.Request) {
enabled, err := utils.GetPara(r, "enable")
if err != nil {
//Load the current status
currentEnabled := false
err = sysdb.Read("settings", "listenP80", &currentEnabled)
if err != nil {
utils.SendErrorResponse(w, err.Error())
return
}
js, _ := json.Marshal(currentEnabled)
utils.SendJSONResponse(w, string(js))
} else {
if enabled == "true" {
sysdb.Write("settings", "listenP80", true)
SystemWideLogger.Println("Enabling port 80 listener")
dynamicProxyRouter.UpdatePort80ListenerState(true)
} else if enabled == "false" {
sysdb.Write("settings", "listenP80", false)
SystemWideLogger.Println("Disabling port 80 listener")
dynamicProxyRouter.UpdatePort80ListenerState(true)
} else {
utils.SendErrorResponse(w, "invalid mode given: "+enabled)
}
utils.SendOK(w)
}
}
// Handle https redirect // Handle https redirect
func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) { func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
useRedirect, err := utils.GetPara(r, "set") useRedirect, err := utils.GetPara(r, "set")

View File

@ -8,7 +8,7 @@
<div class="field"> <div class="field">
<label>Proxy Type</label> <label>Proxy Type</label>
<div class="ui selection dropdown"> <div class="ui selection dropdown">
<input type="hidden" id="ptype" value="subd"> <input type="hidden" id="ptype" value="subd" onchange="handleProxyTypeOptionChange(this.value)">
<i class="dropdown icon"></i> <i class="dropdown icon"></i>
<div class="default text">Proxy Type</div> <div class="default text">Proxy Type</div>
<div class="menu"> <div class="menu">
@ -22,7 +22,7 @@
<input type="text" id="rootname" placeholder="s1.mydomain.com"> <input type="text" id="rootname" placeholder="s1.mydomain.com">
</div> </div>
<div class="field"> <div class="field">
<label>IP Address or Domain Name with port</label> <label>Target IP Address or Domain Name with port</label>
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);"> <input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
<small>E.g. 192.168.0.101:8000 or example.com</small> <small>E.g. 192.168.0.101:8000 or example.com</small>
</div> </div>
@ -44,13 +44,13 @@
<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
<input type="checkbox" id="skipTLSValidation"> <input type="checkbox" id="skipTLSValidation">
<label>Ignore TLS/SSL Verification Error<br><small>E.g. self-signed, expired certificate (Not Recommended)</small></label> <label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
<input type="checkbox" id="bypassGlobalTLS"> <input type="checkbox" id="bypassGlobalTLS">
<label>Bypass Global TLS<br><small>Allow this subdomain / vdir to be connected without TLS</small></label> <label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
</div> </div>
</div> </div>
<div class="field"> <div class="field">
@ -214,6 +214,14 @@
} }
function handleProxyTypeOptionChange(newType){
if (newType == "subd"){
$("#bypassGlobalTLS").parent().removeClass("disabled");
}else if (newType == "vdir"){
$("#bypassGlobalTLS").parent().addClass("disabled");
}
}
//Generic functions for delete rp endpoints //Generic functions for delete rp endpoints
function deleteEndpoint(ptype, epoint){ function deleteEndpoint(ptype, epoint){
if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){ if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){
@ -339,7 +347,7 @@
var columns = row.find('td[data-label]'); var columns = row.find('td[data-label]');
var payload = $(row).attr("payload"); var payload = $(row).attr("payload");
payload = JSON.parse(decodeURIComponent(payload)); payload = JSON.parse(decodeURIComponent(payload));
console.log(payload);
//console.log(payload); //console.log(payload);
columns.each(function(index) { columns.each(function(index) {
var column = $(this); var column = $(this);
@ -355,34 +363,37 @@
var datatype = $(this).attr("datatype"); var datatype = $(this).attr("datatype");
if (datatype == "domain"){ if (datatype == "domain"){
let domain = payload.Domain; let domain = payload.Domain;
//Target require TLS for proxying
let tls = payload.RequireTLS; let tls = payload.RequireTLS;
if (tls){ if (tls){
tls = "checked"; tls = "checked";
}else{ }else{
tls = ""; tls = "";
} }
//Require TLS validation
let skipTLSValidation = payload.SkipCertValidations;
let checkstate = "";
if (skipTLSValidation){
checkstate = "checked";
}
input = ` input = `
<div class="ui mini fluid input"> <div class="ui mini fluid input">
<input type="text" class="Domain" value="${domain}"> <input type="text" class="Domain" value="${domain}">
</div> </div>
<div class="ui checkbox" style="margin-top: 0.4em;"> <div class="ui checkbox" style="margin-top: 0.4em;">
<input type="checkbox" class="RequireTLS" ${tls}> <input type="checkbox" class="RequireTLS" ${tls}>
<label>Require TLS</label> <label>Require TLS<br>
<small>Proxy target require HTTPS connection</small></label>
</div><br>
<div class="ui checkbox" style="margin-top: 0.4em;">
<input type="checkbox" class="SkipCertValidations" ${checkstate}>
<label>Skip Verification<br>
<small>Check this if proxy target is using self signed certificates</small></label>
</div> </div>
`; `;
column.empty().append(input); column.empty().append(input);
}else if (datatype == "skipver"){
let skipTLSValidation = payload.SkipCertValidations;
let checkstate = "";
if (skipTLSValidation){
checkstate = "checked";
}
column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
<input type="checkbox" class="SkipCertValidations" ${checkstate}>
<label>Skip Verification</label>
<small>Check this if you are using self signed certificates</small>
</div>`);
}else if (datatype == "basicauth"){ }else if (datatype == "basicauth"){
let requireBasicAuth = payload.RequireBasicAuth; let requireBasicAuth = payload.RequireBasicAuth;
let checkstate = ""; let checkstate = "";
@ -400,6 +411,16 @@
<button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button> <button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button>
<button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button> <button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button>
`); `);
}else if (datatype == "inbound" && payload.ProxyType == 0){
let originalContent = $(column).html();
column.empty().append(`${originalContent}
<div class="ui divider"></div>
<div class="ui checkbox" style="margin-top: 0.4em;">
<input type="checkbox" class="BypassGlobalTLS" ${payload.BypassGlobalTLS?"checked":""}>
<label>Allow plain HTTP access<br>
<small>Allow inbound connections without TLS/SSL</small></label>
</div><br>
`);
}else{ }else{
//Unknown field. Leave it untouched //Unknown field. Leave it untouched
} }
@ -431,6 +452,7 @@
let requireTLS = $(row).find(".RequireTLS")[0].checked; let requireTLS = $(row).find(".RequireTLS")[0].checked;
let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked; let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked; let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked;
let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;
console.log(newDomain, requireTLS, skipCertValidations, requireBasicAuth) console.log(newDomain, requireTLS, skipCertValidations, requireBasicAuth)
@ -441,6 +463,7 @@
"type": epttype, "type": epttype,
"rootname": uuid, "rootname": uuid,
"ep":newDomain, "ep":newDomain,
"bpgtls": bypassGlobalTLS,
"tls" :requireTLS, "tls" :requireTLS,
"tlsval": skipCertValidations, "tlsval": skipCertValidations,
"bauth" :requireBasicAuth, "bauth" :requireBasicAuth,

View File

@ -72,10 +72,15 @@
<label>Use TLS to serve proxy request</label> <label>Use TLS to serve proxy request</label>
</div> </div>
<br> <br>
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em;"> <div id="listenP80" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em;" >
<input type="checkbox"> <input type="checkbox">
<label>Force redirect HTTP request to HTTPS<br> <label>Enable HTTP server on port 80<br>
<small>(Only apply when listening port is not 80)</small></label> <small>(Only apply when TLS enabled and not using port 80)</small></label>
</div>
<br>
<div id="redirect" class="ui toggle notloopbackOnly tlsEnabledOnly checkbox" style="margin-top: 0.6em; padding-left: 2em;">
<input type="checkbox">
<label>Force redirect HTTP request to HTTPS</label>
</div> </div>
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;"> <div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
<div class="ui accordion advanceSettings"> <div class="ui accordion advanceSettings">
@ -181,6 +186,7 @@
$("#serverstatus").removeClass("green"); $("#serverstatus").removeClass("green");
} }
$("#incomingPort").val(data.Option.Port); $("#incomingPort").val(data.Option.Port);
}); });
} }
@ -305,6 +311,27 @@
}); });
} }
function handleP80ListenerStateChange(enabled){
$.ajax({
url: "/api/proxy/listenPort80",
data: {"enable": enabled},
success: function(data){
if (data.error != undefined){
console.log(data.error);
return;
}
if (enabled){
$("#redirect").show();
msgbox("Port 80 listener enabled");
}else{
$("#redirect").hide();
msgbox("Port 80 listener disabled");
}
}
});
}
function handlePortChange(){ function handlePortChange(){
var newPortValue = $("#incomingPort").val(); var newPortValue = $("#incomingPort").val();
@ -323,6 +350,25 @@
}); });
} }
function initPort80ListenerSetting(){
$.get("/api/proxy/listenPort80", function(data){
if (data){
$("#listenP80").checkbox("set checked");
$("#redirect").show();
}else{
$("#listenP80").checkbox("set unchecked");
$("#redirect").hide();
}
$("#listenP80").find("input").on("change", function(){
let enabled = $(this)[0].checked;
handleP80ListenerStateChange(enabled);
})
});
}
initPort80ListenerSetting();
function initHTTPtoHTTPSRedirectSetting(){ function initHTTPtoHTTPSRedirectSetting(){
$.get("/api/proxy/useHttpsRedirect", function(data){ $.get("/api/proxy/useHttpsRedirect", function(data){
if (data == true){ if (data == true){
@ -356,8 +402,6 @@
}) })
}); });
}); });
} }
initHTTPtoHTTPSRedirectSetting(); initHTTPtoHTTPSRedirectSetting();

View File

@ -9,7 +9,6 @@
<tr> <tr>
<th>Matching Domain</th> <th>Matching Domain</th>
<th>Proxy To</th> <th>Proxy To</th>
<th>TLS/SSL Verification</th>
<th>Basic Auth</th> <th>Basic Auth</th>
<th class="no-sort" style="min-width: 7.2em;">Actions</th> <th class="no-sort" style="min-width: 7.2em;">Actions</th>
</tr> </tr>
@ -41,19 +40,14 @@
let subdData = encodeURIComponent(JSON.stringify(subd)); let subdData = encodeURIComponent(JSON.stringify(subd));
if (subd.RequireTLS){ if (subd.RequireTLS){
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`; tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
} if (subd.SkipCertValidations){
tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
let tlsVerificationField = ""; }
if (subd.RequireTLS){
tlsVerificationField = !subd.SkipCertValidations?`<i class="ui green check icon"></i>`:`<i class="ui yellow exclamation circle icon" title="TLS/SSL Verification will be skipped on this host"></i>`
}else{
tlsVerificationField = "N/A"
} }
$("#subdList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry"> $("#subdList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
<td data-label="" editable="false"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a></td> <td data-label="" editable="true" datatype="inbound"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a></td>
<td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td> <td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
<td data-label="" editable="true" datatype="skipver">${tlsVerificationField}</td>
<td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td> <td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
<td class="center aligned" editable="true" datatype="action" data-label=""> <td class="center aligned" editable="true" datatype="action" data-label="">
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button> <button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button>

View File

@ -9,7 +9,6 @@
<tr> <tr>
<th>Virtual Directory</th> <th>Virtual Directory</th>
<th>Proxy To</th> <th>Proxy To</th>
<th>TLS/SSL Verification</th>
<th>Basic Auth</th> <th>Basic Auth</th>
<th class="no-sort" style="min-width: 7.2em;">Actions</th> <th class="no-sort" style="min-width: 7.2em;">Actions</th>
</tr> </tr>
@ -43,6 +42,9 @@
let vdirData = encodeURIComponent(JSON.stringify(vdir)); let vdirData = encodeURIComponent(JSON.stringify(vdir));
if (vdir.RequireTLS){ if (vdir.RequireTLS){
tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`; tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
if (vdir.SkipCertValidations){
tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
}
} }
let tlsVerificationField = ""; let tlsVerificationField = "";
@ -55,7 +57,6 @@
$("#vdirList").append(`<tr eptuuid="${vdir.RootOrMatchingDomain}" payload="${vdirData}" class="vdirEntry"> $("#vdirList").append(`<tr eptuuid="${vdir.RootOrMatchingDomain}" payload="${vdirData}" class="vdirEntry">
<td data-label="" editable="false">${vdir.RootOrMatchingDomain}</td> <td data-label="" editable="false">${vdir.RootOrMatchingDomain}</td>
<td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td> <td data-label="" editable="true" datatype="domain">${vdir.Domain} ${tlsIcon}</td>
<td data-label="" editable="true" datatype="skipver">${tlsVerificationField}</td>
<td data-label="" editable="true" datatype="basicauth">${vdir.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td> <td data-label="" editable="true" datatype="basicauth">${vdir.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
<td class="center aligned" editable="true" datatype="action" data-label=""> <td class="center aligned" editable="true" datatype="action" data-label="">
<button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="edit icon"></i></button> <button class="ui circular mini basic icon button editBtn" onclick='editEndpoint("vdir","${vdir.RootOrMatchingDomain}")'><i class="edit icon"></i></button>