Files
EdgeAdmin/internal/web/actions/default/servers/create.go

615 lines
15 KiB
Go
Raw Normal View History

2020-07-29 19:34:54 +08:00
package servers
import (
"encoding/json"
2020-10-25 18:27:07 +08:00
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
2020-07-29 19:34:54 +08:00
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
2023-06-30 18:08:30 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
2020-09-13 20:37:07 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
2020-07-29 19:34:54 +08:00
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/logs"
2020-07-29 19:34:54 +08:00
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"strings"
2020-07-29 19:34:54 +08:00
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
2020-08-21 12:32:16 +08:00
this.Nav("", "server", "create")
2020-07-29 19:34:54 +08:00
}
func (this *CreateAction) RunGet(params struct{}) {
2020-12-23 16:49:53 +08:00
// 审核中的数量
countAuditingResp, err := this.RPC().ServerRPC().CountAllEnabledServersMatch(this.AdminContext(), &pb.CountAllEnabledServersMatchRequest{
AuditingFlag: 1,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countAuditing"] = countAuditingResp.Count
2020-08-21 12:32:16 +08:00
// 服务类型
2020-09-13 20:37:07 +08:00
this.Data["serverTypes"] = serverconfigs.AllServerTypes()
2020-08-21 12:32:16 +08:00
2021-11-22 14:34:32 +08:00
// 检查是否有用户
countUsersResp, err := this.RPC().UserRPC().CountAllEnabledUsers(this.AdminContext(), &pb.CountAllEnabledUsersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["hasUsers"] = countUsersResp.Count > 0
2020-07-29 19:34:54 +08:00
this.Show()
}
func (this *CreateAction) RunPost(params struct {
2020-08-21 12:32:16 +08:00
Name string
Description string
2021-11-09 15:36:18 +08:00
UserId int64
UserPlanId int64
ClusterId int64
GroupIds []int64
2020-08-21 12:32:16 +08:00
ServerType string
Addresses string
ServerNames []byte
CertIdsJSON []byte
2020-08-21 12:32:16 +08:00
Origins string
AccessLogIsOn bool
WebsocketIsOn bool
CacheIsOn bool
WafIsOn bool
RemoteAddrIsOn bool
StatIsOn bool
2020-08-21 12:32:16 +08:00
WebRoot string
2020-07-29 19:34:54 +08:00
Must *actions.Must
}) {
2021-11-09 15:36:18 +08:00
var clusterId = params.ClusterId
// 用户
var userId = params.UserId
2021-11-22 14:34:32 +08:00
if userId > 0 {
clusterIdResp, err := this.RPC().UserRPC().FindUserNodeClusterId(this.AdminContext(), &pb.FindUserNodeClusterIdRequest{UserId: userId})
if err != nil {
this.ErrorPage(err)
return
}
clusterId = clusterIdResp.NodeClusterId
if clusterId <= 0 {
this.Fail("请选择部署的集群")
}
2020-07-29 19:34:54 +08:00
}
2021-11-09 15:36:18 +08:00
// 套餐
var userPlanId = params.UserPlanId
2020-07-29 19:34:54 +08:00
2020-08-21 12:32:16 +08:00
// 端口地址
2020-09-15 14:44:52 +08:00
var httpConfig *serverconfigs.HTTPProtocolConfig = nil
var httpsConfig *serverconfigs.HTTPSProtocolConfig = nil
var tcpConfig *serverconfigs.TCPProtocolConfig = nil
var tlsConfig *serverconfigs.TLSProtocolConfig = nil
var unixConfig *serverconfigs.UnixProtocolConfig = nil
var udpConfig *serverconfigs.UDPProtocolConfig = nil
var webId int64 = 0
2020-08-21 12:32:16 +08:00
switch params.ServerType {
2020-09-13 20:37:07 +08:00
case serverconfigs.ServerTypeHTTPProxy, serverconfigs.ServerTypeHTTPWeb:
2023-03-21 16:56:45 +08:00
var listen = []*serverconfigs.NetworkAddressConfig{}
2020-08-21 12:32:16 +08:00
err := json.Unmarshal([]byte(params.Addresses), &listen)
if err != nil {
this.Fail("端口地址解析失败:" + err.Error())
}
2020-09-15 14:44:52 +08:00
if len(listen) == 0 {
this.Fail("至少需要绑定一个端口")
}
2020-08-21 12:32:16 +08:00
for _, addr := range listen {
2020-09-15 14:44:52 +08:00
switch addr.Protocol.Primary() {
case serverconfigs.ProtocolHTTP:
if httpConfig == nil {
httpConfig = &serverconfigs.HTTPProtocolConfig{
2020-08-21 12:32:16 +08:00
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
},
}
}
2020-09-15 14:44:52 +08:00
httpConfig.AddListen(addr)
case serverconfigs.ProtocolHTTPS:
if httpsConfig == nil {
httpsConfig = &serverconfigs.HTTPSProtocolConfig{
2020-08-21 12:32:16 +08:00
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
},
}
}
2020-09-15 14:44:52 +08:00
httpsConfig.AddListen(addr)
2020-08-21 12:32:16 +08:00
}
}
2020-09-13 20:37:07 +08:00
case serverconfigs.ServerTypeTCPProxy:
2020-10-25 18:27:07 +08:00
// 在DEMO模式下不能创建
if teaconst.IsDemoMode {
2020-10-25 18:27:07 +08:00
this.Fail("DEMO模式下不能创建TCP反向代理")
}
2023-03-21 16:56:45 +08:00
var listen = []*serverconfigs.NetworkAddressConfig{}
2020-08-21 12:32:16 +08:00
err := json.Unmarshal([]byte(params.Addresses), &listen)
if err != nil {
this.Fail("端口地址解析失败:" + err.Error())
}
2020-09-15 14:44:52 +08:00
if len(listen) == 0 {
this.Fail("至少需要绑定一个端口")
}
2020-08-21 12:32:16 +08:00
for _, addr := range listen {
2020-09-15 14:44:52 +08:00
switch addr.Protocol.Primary() {
case serverconfigs.ProtocolTCP:
if tcpConfig == nil {
tcpConfig = &serverconfigs.TCPProtocolConfig{
2020-08-21 12:32:16 +08:00
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
},
}
}
2020-09-15 14:44:52 +08:00
tcpConfig.AddListen(addr)
case serverconfigs.ProtocolTLS:
if tlsConfig == nil {
tlsConfig = &serverconfigs.TLSProtocolConfig{
2020-08-21 12:32:16 +08:00
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
},
}
}
2020-09-15 14:44:52 +08:00
tlsConfig.AddListen(addr)
2020-08-21 12:32:16 +08:00
}
}
2023-03-21 16:56:45 +08:00
if len(params.Name) == 0 {
params.Name = "TCP负载均衡"
}
2021-06-07 15:43:43 +08:00
case serverconfigs.ServerTypeUDPProxy:
// 在DEMO模式下不能创建
if teaconst.IsDemoMode {
2021-06-07 15:43:43 +08:00
this.Fail("DEMO模式下不能创建UDP反向代理")
}
2023-03-21 16:56:45 +08:00
var listen = []*serverconfigs.NetworkAddressConfig{}
2021-06-07 15:43:43 +08:00
err := json.Unmarshal([]byte(params.Addresses), &listen)
if err != nil {
this.Fail("端口地址解析失败:" + err.Error())
}
if len(listen) == 0 {
this.Fail("至少需要绑定一个端口")
}
for _, addr := range listen {
switch addr.Protocol.Primary() {
case serverconfigs.ProtocolUDP:
if udpConfig == nil {
udpConfig = &serverconfigs.UDPProtocolConfig{
BaseProtocol: serverconfigs.BaseProtocol{
IsOn: true,
},
}
}
udpConfig.AddListen(addr)
}
}
2023-03-21 16:56:45 +08:00
if len(params.Name) == 0 {
params.Name = "UDP负载均衡"
}
2020-08-21 12:32:16 +08:00
default:
this.Fail("请选择正确的服务类型")
}
// 证书
if len(params.CertIdsJSON) > 0 {
2023-03-27 16:31:52 +08:00
var certIds = []int64{}
err := json.Unmarshal(params.CertIdsJSON, &certIds)
if err != nil {
this.ErrorPage(err)
return
}
if len(certIds) > 0 {
2023-03-27 16:31:52 +08:00
var certRefs = []*sslconfigs.SSLCertRef{}
for _, certId := range certIds {
certRefs = append(certRefs, &sslconfigs.SSLCertRef{
IsOn: true,
CertId: certId,
})
}
certRefsJSON, err := json.Marshal(certRefs)
if err != nil {
this.ErrorPage(err)
return
}
sslPolicyIdResp, err := this.RPC().SSLPolicyRPC().CreateSSLPolicy(this.AdminContext(), &pb.CreateSSLPolicyRequest{
2023-06-01 17:44:39 +08:00
Http2Enabled: false, // 默认值
Http3Enabled: false,
MinVersion: "TLS 1.1", // 默认值
SslCertsJSON: certRefsJSON,
HstsJSON: nil,
ClientAuthType: 0,
ClientCACertsJSON: nil,
CipherSuites: nil,
CipherSuitesIsOn: false,
})
if err != nil {
this.ErrorPage(err)
return
}
2023-03-27 16:31:52 +08:00
var sslPolicyId = sslPolicyIdResp.SslPolicyId
httpsConfig.SSLPolicyRef = &sslconfigs.SSLPolicyRef{
IsOn: true,
SSLPolicyId: sslPolicyId,
}
}
}
2020-08-21 12:32:16 +08:00
// 域名
var serverNames = []*serverconfigs.ServerNameConfig{}
2020-09-15 14:44:52 +08:00
if len(params.ServerNames) > 0 {
err := json.Unmarshal(params.ServerNames, &serverNames)
2020-09-15 14:44:52 +08:00
if err != nil {
this.Fail("域名解析失败:" + err.Error())
}
// 检查域名是否已经存在
2023-03-21 16:56:45 +08:00
var allServerNames = serverconfigs.PlainServerNames(serverNames)
if len(allServerNames) > 0 {
2023-03-21 16:56:45 +08:00
// 指定默认名称
if len(params.Name) == 0 {
params.Name = allServerNames[0]
}
dupResp, err := this.RPC().ServerRPC().CheckServerNameDuplicationInNodeCluster(this.AdminContext(), &pb.CheckServerNameDuplicationInNodeClusterRequest{
ServerNames: allServerNames,
2021-11-09 15:36:18 +08:00
NodeClusterId: clusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
if len(dupResp.DuplicatedServerNames) > 0 {
2023-07-19 19:40:11 +08:00
this.Fail("域名 " + strings.Join(dupResp.DuplicatedServerNames, ", ") + " 已经被其他网站所占用,不能重复使用")
}
}
2020-08-21 12:32:16 +08:00
}
if params.ServerType == serverconfigs.ServerTypeHTTPProxy && len(serverNames) == 0 {
this.FailField("emptyDomain", "请输入添加至少一个域名")
}
2020-08-21 12:32:16 +08:00
// 源站地址
2022-03-25 14:42:28 +08:00
var reverseProxyRefJSON = []byte{}
2020-08-21 12:32:16 +08:00
switch params.ServerType {
2021-06-07 15:43:43 +08:00
case serverconfigs.ServerTypeHTTPProxy, serverconfigs.ServerTypeTCPProxy, serverconfigs.ServerTypeUDPProxy:
2022-03-25 14:42:28 +08:00
var originConfigs = []*serverconfigs.OriginConfig{}
2020-10-01 16:51:32 +08:00
err := json.Unmarshal([]byte(params.Origins), &originConfigs)
2020-08-21 12:32:16 +08:00
if err != nil {
this.Fail("源站地址解析失败:" + err.Error())
}
2022-03-25 14:42:28 +08:00
if len(originConfigs) == 0 {
this.FailField("emptyOrigin", "请添加至少一个源站地址")
2022-03-25 14:42:28 +08:00
}
2020-09-15 14:44:52 +08:00
2022-03-25 14:42:28 +08:00
var originRefs = []*serverconfigs.OriginRef{}
2020-10-01 16:51:32 +08:00
for _, originConfig := range originConfigs {
if originConfig.Id > 0 {
originRefs = append(originRefs, &serverconfigs.OriginRef{
IsOn: true,
OriginId: originConfig.Id,
})
}
}
originRefsJSON, err := json.Marshal(originRefs)
if err != nil {
this.ErrorPage(err)
return
}
2020-09-15 14:44:52 +08:00
resp, err := this.RPC().ReverseProxyRPC().CreateReverseProxy(this.AdminContext(), &pb.CreateReverseProxyRequest{
SchedulingJSON: nil,
2020-10-01 16:51:32 +08:00
PrimaryOriginsJSON: originRefsJSON,
2020-09-15 14:44:52 +08:00
BackupOriginsJSON: nil,
})
if err != nil {
this.ErrorPage(err)
return
2020-08-21 12:32:16 +08:00
}
2022-07-05 20:07:37 +08:00
var reverseProxyRef = &serverconfigs.ReverseProxyRef{
2020-09-21 11:37:24 +08:00
IsOn: true,
ReverseProxyId: resp.ReverseProxyId,
}
reverseProxyRefJSON, err = json.Marshal(reverseProxyRef)
if err != nil {
this.ErrorPage(err)
return
}
2020-08-21 12:32:16 +08:00
}
// Web地址
switch params.ServerType {
2020-09-13 20:37:07 +08:00
case serverconfigs.ServerTypeHTTPWeb:
2020-09-26 11:21:52 +08:00
var rootJSON []byte
var err error
if len(params.WebRoot) > 0 {
var rootConfig = serverconfigs.NewHTTPRootConfig()
2020-09-26 11:21:52 +08:00
rootConfig.IsOn = true
rootConfig.Dir = params.WebRoot
rootConfig.Indexes = []string{"index.html", "index.htm"}
rootJSON, err = json.Marshal(rootConfig)
if err != nil {
this.ErrorPage(err)
return
}
}
webResp, err := this.RPC().HTTPWebRPC().CreateHTTPWeb(this.AdminContext(), &pb.CreateHTTPWebRequest{RootJSON: rootJSON})
2020-09-15 14:44:52 +08:00
if err != nil {
this.ErrorPage(err)
return
2020-08-21 12:32:16 +08:00
}
2021-11-24 11:58:01 +08:00
webId = webResp.HttpWebId
2020-07-29 19:34:54 +08:00
}
// 包含条件
2022-07-05 20:07:37 +08:00
var includeNodes = []maps.Map{}
2020-07-29 19:34:54 +08:00
includeNodesJSON, err := json.Marshal(includeNodes)
if err != nil {
this.ErrorPage(err)
return
}
// 排除条件
2022-07-05 20:07:37 +08:00
var excludeNodes = []maps.Map{}
2020-07-29 19:34:54 +08:00
excludeNodesJSON, err := json.Marshal(excludeNodes)
if err != nil {
this.ErrorPage(err)
return
}
var req = &pb.CreateServerRequest{
2021-11-09 15:36:18 +08:00
UserId: userId,
UserPlanId: userPlanId,
2020-07-29 19:34:54 +08:00
AdminId: this.AdminId(),
2020-09-13 20:37:07 +08:00
Type: params.ServerType,
Name: params.Name,
2023-06-01 17:44:39 +08:00
ServerNamesJSON: params.ServerNames,
2020-09-13 20:37:07 +08:00
Description: params.Description,
2021-11-09 15:36:18 +08:00
NodeClusterId: clusterId,
2020-07-29 19:34:54 +08:00
IncludeNodesJSON: includeNodesJSON,
ExcludeNodesJSON: excludeNodesJSON,
2020-09-15 14:44:52 +08:00
WebId: webId,
2020-09-21 11:37:24 +08:00
ReverseProxyJSON: reverseProxyRefJSON,
2021-05-25 17:48:51 +08:00
ServerGroupIds: params.GroupIds,
2020-09-15 14:44:52 +08:00
}
if httpConfig != nil {
data, err := json.Marshal(httpConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.HttpJSON = data
}
if httpsConfig != nil {
data, err := json.Marshal(httpsConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.HttpsJSON = data
}
if tcpConfig != nil {
data, err := json.Marshal(tcpConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.TcpJSON = data
}
if tlsConfig != nil {
data, err := json.Marshal(tlsConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.TlsJSON = data
}
if unixConfig != nil {
data, err := json.Marshal(unixConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.UnixJSON = data
}
if udpConfig != nil {
data, err := json.Marshal(udpConfig)
if err != nil {
this.ErrorPage(err)
return
}
req.UdpJSON = data
}
2020-11-10 21:37:48 +08:00
createResp, err := this.RPC().ServerRPC().CreateServer(this.AdminContext(), req)
2020-07-29 19:34:54 +08:00
if err != nil {
this.ErrorPage(err)
return
}
var serverId = createResp.ServerId
// 开启访问日志和Websocket
if params.ServerType == serverconfigs.ServerTypeHTTPProxy {
webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), serverId)
if err != nil {
logs.Error(err)
} else {
// 访问日志
if params.AccessLogIsOn {
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebAccessLog(this.AdminContext(), &pb.UpdateHTTPWebAccessLogRequest{
2021-11-24 11:58:01 +08:00
HttpWebId: webConfig.Id,
AccessLogJSON: []byte(`{
"isPrior": false,
"isOn": true,
"fields": [1, 2, 6, 7],
"status1": true,
"status2": true,
"status3": true,
"status4": true,
"status5": true,
"storageOnly": false,
"storagePolicies": [],
"firewallOnly": false
}`),
})
if err != nil {
logs.Error(err)
}
}
// websocket
if params.WebsocketIsOn {
createWebSocketResp, err := this.RPC().HTTPWebsocketRPC().CreateHTTPWebsocket(this.AdminContext(), &pb.CreateHTTPWebsocketRequest{
HandshakeTimeoutJSON: []byte(`{
"count": 30,
"unit": "second"
}`),
AllowAllOrigins: true,
AllowedOrigins: nil,
RequestSameOrigin: true,
RequestOrigin: "",
})
if err != nil {
logs.Error(err)
} else {
websocketId := createWebSocketResp.WebsocketId
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebWebsocket(this.AdminContext(), &pb.UpdateHTTPWebWebsocketRequest{
2021-11-24 11:58:01 +08:00
HttpWebId: webConfig.Id,
WebsocketJSON: []byte(` {
"isPrior": false,
"isOn": true,
"websocketId": ` + types.String(websocketId) + `
}`),
})
if err != nil {
logs.Error(err)
}
}
}
// cache
if params.CacheIsOn {
var cacheConfig = &serverconfigs.HTTPCacheConfig{
IsPrior: false,
IsOn: true,
AddStatusHeader: true,
PurgeIsOn: false,
PurgeKey: "",
2021-11-04 11:12:59 +08:00
CacheRefs: []*serverconfigs.HTTPCacheRef{},
}
cacheConfigJSON, err := json.Marshal(cacheConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebCache(this.AdminContext(), &pb.UpdateHTTPWebCacheRequest{
2021-11-24 11:58:01 +08:00
HttpWebId: webConfig.Id,
CacheJSON: cacheConfigJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
// waf
if params.WafIsOn {
var firewallRef = &firewallconfigs.HTTPFirewallRef{
IsPrior: false,
IsOn: true,
FirewallPolicyId: 0,
}
firewallRefJSON, err := json.Marshal(firewallRef)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebFirewall(this.AdminContext(), &pb.UpdateHTTPWebFirewallRequest{
2021-11-24 11:58:01 +08:00
HttpWebId: webConfig.Id,
FirewallJSON: firewallRefJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
// remoteAddr
var remoteAddrConfig = &serverconfigs.HTTPRemoteAddrConfig{
IsOn: true,
Value: "${rawRemoteAddr}",
2023-09-07 18:01:52 +08:00
Type: serverconfigs.HTTPRemoteAddrTypeDefault,
}
if params.RemoteAddrIsOn {
remoteAddrConfig.Value = "${remoteAddr}"
2023-09-07 18:01:52 +08:00
remoteAddrConfig.Type = serverconfigs.HTTPRemoteAddrTypeProxy
}
remoteAddrConfigJSON, err := json.Marshal(remoteAddrConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRemoteAddr(this.AdminContext(), &pb.UpdateHTTPWebRemoteAddrRequest{
2021-11-24 11:58:01 +08:00
HttpWebId: webConfig.Id,
RemoteAddrJSON: remoteAddrConfigJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
// 统计
if params.StatIsOn {
var statConfig = &serverconfigs.HTTPStatRef{
IsPrior: false,
IsOn: true,
}
statJSON, err := json.Marshal(statConfig)
if err != nil {
this.ErrorPage(err)
return
}
_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebStat(this.AdminContext(), &pb.UpdateHTTPWebStatRequest{
HttpWebId: webConfig.Id,
StatJSON: statJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
}
}
}
2020-07-29 19:34:54 +08:00
2020-11-10 21:37:48 +08:00
// 创建日志
2023-06-30 18:08:30 +08:00
defer this.CreateLogInfo(codes.Server_LogCreateServer, createResp.ServerId)
2020-11-10 21:37:48 +08:00
2020-07-29 19:34:54 +08:00
this.Success()
}