package clusters import ( "encoding/json" "strconv" "strings" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/policies" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/maps" ) type ClusterSettingsAction struct { actionutils.ParentAction } func (this *ClusterSettingsAction) Init() { this.Nav("httpdns", "cluster", "settings") } func (this *ClusterSettingsAction) RunGet(params struct { ClusterId int64 Section string }) { httpdnsutils.AddLeftMenu(this.Parent()) cluster := pickCluster(params.ClusterId) settings := loadClusterSettings(cluster) cluster["name"] = settings.GetString("name") // 构建顶部 tabbar httpdnsutils.AddClusterTabbar(this.Parent(), cluster.GetString("name"), params.ClusterId, "setting") // 当前选中的 section section := params.Section if len(section) == 0 { section = "basic" } this.Data["activeSection"] = section // 左侧菜单 cid := strconv.FormatInt(params.ClusterId, 10) this.Data["leftMenuItems"] = []map[string]interface{}{ {"name": "基础设置", "url": "/httpdns/clusters/cluster/settings?clusterId=" + cid + "§ion=basic", "isActive": section == "basic"}, {"name": "端口设置", "url": "/httpdns/clusters/cluster/settings?clusterId=" + cid + "§ion=tls", "isActive": section == "tls"}, } settings["isDefaultCluster"] = (policies.LoadDefaultClusterID() == cluster.GetInt64("id")) this.Data["cluster"] = cluster // 构造前端需要的 tlsConfig 格式 var listenAddresses []*serverconfigs.NetworkAddressConfig listenAddrsRaw := settings.GetString("listenAddrsJSON") if len(listenAddrsRaw) > 0 { _ = json.Unmarshal([]byte(listenAddrsRaw), &listenAddresses) } else { // 默认 443 端口 listenAddresses = []*serverconfigs.NetworkAddressConfig{ { Protocol: serverconfigs.ProtocolHTTPS, Host: "", PortRange: "443", }, } } // 构造前端需要的 SSLPolicy var sslPolicy *sslconfigs.SSLPolicy originCertPem := settings.GetString("originCertPem") originKeyPem := settings.GetString("originKeyPem") if len(originCertPem) > 0 && len(originKeyPem) > 0 { sslPolicy = &sslconfigs.SSLPolicy{ IsOn: true, MinVersion: settings.GetString("tlsMinVersion"), CipherSuitesIsOn: settings.GetBool("tlsCipherSuitesOn"), OCSPIsOn: settings.GetBool("tlsOcspOn"), ClientAuthType: int(settings.GetInt32("tlsClientAuthType")), Certs: []*sslconfigs.SSLCertConfig{ { IsOn: true, CertData: []byte(originCertPem), KeyData: []byte(originKeyPem), }, }, } } else { sslPolicy = &sslconfigs.SSLPolicy{ IsOn: true, MinVersion: "TLS 1.1", } } this.Data["tlsConfig"] = maps.Map{ "isOn": true, "listen": listenAddresses, "sslPolicy": sslPolicy, } this.Data["cluster"] = cluster this.Data["settings"] = settings this.Show() } func (this *ClusterSettingsAction) RunPost(params struct { ClusterId int64 Name string GatewayDomain string CacheTtl int32 FallbackTimeout int32 InstallDir string IsOn bool IsDefaultCluster bool Addresses []byte SslPolicyJSON []byte Must *actions.Must CSRF *actionutils.CSRF }) { params.Must.Field("clusterId", params.ClusterId).Gt(0, "please select cluster") params.Must.Field("name", params.Name).Require("please input cluster name") params.Must.Field("gatewayDomain", params.GatewayDomain).Require("please input service domain") params.Must.Field("cacheTtl", params.CacheTtl).Gt(0, "cache ttl should be greater than 0") params.Must.Field("fallbackTimeout", params.FallbackTimeout).Gt(0, "fallback timeout should be greater than 0") params.Must.Field("installDir", params.InstallDir).Require("please input install dir") if params.IsDefaultCluster && !params.IsOn { this.Fail("默认集群必须保持启用状态") return } cluster := pickCluster(params.ClusterId) settings := loadClusterSettings(cluster) settings["name"] = strings.TrimSpace(params.Name) settings["gatewayDomain"] = strings.TrimSpace(params.GatewayDomain) settings["cacheTtl"] = int(params.CacheTtl) settings["fallbackTimeout"] = int(params.FallbackTimeout) settings["installDir"] = strings.TrimSpace(params.InstallDir) settings["isOn"] = params.IsOn // 处理地址 var addresses = []*serverconfigs.NetworkAddressConfig{} if len(params.Addresses) > 0 { err := json.Unmarshal(params.Addresses, &addresses) if err != nil { this.Fail("端口地址解析失败:" + err.Error()) } addressesJSON, _ := json.Marshal(addresses) settings["listenAddrsJSON"] = string(addressesJSON) } // 处理 SSL 配置 var originCertPem = "" var originKeyPem = "" var tlsMinVersion = "TLS 1.1" var tlsCipherSuitesOn = false var tlsOcspOn = false var tlsClientAuthType = sslconfigs.SSLClientAuthType(0) if len(params.SslPolicyJSON) > 0 { sslPolicy := &sslconfigs.SSLPolicy{} err := json.Unmarshal(params.SslPolicyJSON, sslPolicy) if err == nil { tlsMinVersion = sslPolicy.MinVersion tlsCipherSuitesOn = sslPolicy.CipherSuitesIsOn tlsOcspOn = sslPolicy.OCSPIsOn tlsClientAuthType = sslconfigs.SSLClientAuthType(sslPolicy.ClientAuthType) if len(sslPolicy.Certs) > 0 { cert := sslPolicy.Certs[0] originCertPem = string(cert.CertData) originKeyPem = string(cert.KeyData) } } } if len(originCertPem) == 0 || len(originKeyPem) == 0 { this.Fail("请上传或选择证书") } settings["originHttps"] = true settings["originCertPem"] = originCertPem settings["originKeyPem"] = originKeyPem if len(tlsMinVersion) == 0 { tlsMinVersion = "TLS 1.1" } settings["tlsMinVersion"] = tlsMinVersion settings["tlsCipherSuitesOn"] = tlsCipherSuitesOn settings["tlsOcspOn"] = tlsOcspOn settings["tlsClientAuthType"] = int(tlsClientAuthType) settings["lastModifiedAt"] = nowDateTime() settings["certUpdatedAt"] = nowDateTime() saveClusterSettings(params.ClusterId, settings) currentDefaultClusterId := policies.LoadDefaultClusterID() if params.IsDefaultCluster { policies.SaveDefaultClusterID(params.ClusterId) } else if currentDefaultClusterId == params.ClusterId { policies.SaveDefaultClusterID(0) } this.Success() }