mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 创建网站增加 waf 关联 (#4333)
This commit is contained in:
parent
a5d853c61a
commit
9b9fe5444d
@ -69,24 +69,12 @@ type WebsiteOp struct {
|
|||||||
Operate string `json:"operate"`
|
Operate string `json:"operate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteWafReq struct {
|
|
||||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
|
||||||
Key string `json:"key" validate:"required"`
|
|
||||||
Rule string `json:"rule" validate:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebsiteRedirectUpdate struct {
|
type WebsiteRedirectUpdate struct {
|
||||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||||
Key string `json:"key" validate:"required"`
|
Key string `json:"key" validate:"required"`
|
||||||
Enable bool `json:"enable"`
|
Enable bool `json:"enable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteWafUpdate struct {
|
|
||||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
|
||||||
Key string `json:"key" validate:"required"`
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebsiteRecover struct {
|
type WebsiteRecover struct {
|
||||||
WebsiteName string `json:"websiteName" validate:"required"`
|
WebsiteName string `json:"websiteName" validate:"required"`
|
||||||
Type string `json:"type" validate:"required"`
|
Type string `json:"type" validate:"required"`
|
||||||
@ -207,12 +195,12 @@ type WebsiteRedirectReq struct {
|
|||||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteWafFileUpdate struct {
|
|
||||||
WebsiteID uint `json:"websiteID" validate:"required"`
|
|
||||||
Content string `json:"content" validate:"required"`
|
|
||||||
Type string `json:"type" validate:"required,oneof=cc ip_white ip_block url_white url_block cookie_block args_check post_check ua_check file_ext_block user_agent"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebsiteCommonReq struct {
|
type WebsiteCommonReq struct {
|
||||||
ID uint `json:"id" validate:"required"`
|
ID uint `json:"id" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WafWebsite struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Domains []string `json:"domains"`
|
||||||
|
Host []string `json:"host"`
|
||||||
|
}
|
||||||
|
@ -31,11 +31,6 @@ type WebsiteNginxConfig struct {
|
|||||||
Params []NginxParam `json:"params"`
|
Params []NginxParam `json:"params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsiteWafConfig struct {
|
|
||||||
Enable bool `json:"enable"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WebsiteHTTPS struct {
|
type WebsiteHTTPS struct {
|
||||||
Enable bool `json:"enable"`
|
Enable bool `json:"enable"`
|
||||||
HttpConfig string `json:"httpConfig"`
|
HttpConfig string `json:"httpConfig"`
|
||||||
|
@ -61,6 +61,7 @@ type IWebsiteService interface {
|
|||||||
UpdateWebsite(req request.WebsiteUpdate) error
|
UpdateWebsite(req request.WebsiteUpdate) error
|
||||||
DeleteWebsite(req request.WebsiteDelete) error
|
DeleteWebsite(req request.WebsiteDelete) error
|
||||||
GetWebsite(id uint) (response.WebsiteDTO, error)
|
GetWebsite(id uint) (response.WebsiteDTO, error)
|
||||||
|
|
||||||
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
|
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
|
||||||
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
|
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
|
||||||
DeleteWebsiteDomain(domainId uint) error
|
DeleteWebsiteDomain(domainId uint) error
|
||||||
@ -328,6 +329,10 @@ func (w WebsiteService) CreateWebsite(create request.WebsiteCreate) (err error)
|
|||||||
if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil {
|
if err = configDefaultNginx(website, domains, appInstall, runtime); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err = createWafConfig(website, domains); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
tx, ctx := helper.GetTxAndContext()
|
tx, ctx := helper.GetTxAndContext()
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
if err = websiteRepo.Create(ctx, website); err != nil {
|
if err = websiteRepo.Create(ctx, website); err != nil {
|
||||||
@ -420,7 +425,11 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := delNginxConfig(website, req.ForceDelete); err != nil {
|
if err = delNginxConfig(website, req.ForceDelete); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = delWafConfig(website, req.ForceDelete); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,6 +498,53 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
if fileOp.Stat(wafDataPath) {
|
||||||
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||||
|
content, err := fileOp.GetContent(websitesConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var websitesArray []request.WafWebsite
|
||||||
|
if content != nil {
|
||||||
|
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for index, wafWebsite := range websitesArray {
|
||||||
|
if wafWebsite.Key == website.Alias {
|
||||||
|
wafSite := request.WafWebsite{
|
||||||
|
Key: website.Alias,
|
||||||
|
Domains: wafWebsite.Domains,
|
||||||
|
Host: wafWebsite.Host,
|
||||||
|
}
|
||||||
|
for _, domain := range domainModels {
|
||||||
|
wafSite.Domains = append(wafSite.Domains, domain.Domain)
|
||||||
|
if domain.Port != 80 && domain.Port != 443 {
|
||||||
|
wafSite.Host = append(wafSite.Host, domain.Domain+":"+string(rune(domain.Port)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(wafSite.Host) == 0 {
|
||||||
|
wafSite.Host = []string{}
|
||||||
|
}
|
||||||
|
websitesArray[index] = wafSite
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
websitesContent, err := json.Marshal(websitesArray)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels)
|
return domainModels, websiteDomainRepo.BatchCreate(context.TODO(), domainModels)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,6 +574,7 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
|||||||
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 {
|
if oldDomains, _ := websiteDomainRepo.GetBy(websiteDomainRepo.WithWebsiteId(webSiteDomain.WebsiteID), websiteDomainRepo.WithDomain(webSiteDomain.Domain)); len(oldDomains) == 1 {
|
||||||
domains = append(domains, webSiteDomain.Domain)
|
domains = append(domains, webSiteDomain.Domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ports) > 0 || len(domains) > 0 {
|
if len(ports) > 0 || len(domains) > 0 {
|
||||||
stringBinds := make([]string, len(ports))
|
stringBinds := make([]string, len(ports))
|
||||||
for i := 0; i < len(ports); i++ {
|
for i := 0; i < len(ports); i++ {
|
||||||
@ -528,6 +585,63 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
if fileOp.Stat(wafDataPath) {
|
||||||
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||||
|
content, err := fileOp.GetContent(websitesConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var websitesArray []request.WafWebsite
|
||||||
|
var newWebsitesArray []request.WafWebsite
|
||||||
|
if content != nil {
|
||||||
|
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, wafWebsite := range websitesArray {
|
||||||
|
if wafWebsite.Key == website.Alias {
|
||||||
|
wafSite := wafWebsite
|
||||||
|
oldDomains := wafSite.Domains
|
||||||
|
var newDomains []string
|
||||||
|
for _, domain := range oldDomains {
|
||||||
|
if domain == webSiteDomain.Domain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newDomains = append(newDomains, domain)
|
||||||
|
}
|
||||||
|
wafSite.Domains = newDomains
|
||||||
|
oldHostArray := wafSite.Host
|
||||||
|
var newHostArray []string
|
||||||
|
for _, host := range oldHostArray {
|
||||||
|
if host == webSiteDomain.Domain+":"+string(rune(webSiteDomain.Port)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newHostArray = append(newHostArray, host)
|
||||||
|
}
|
||||||
|
wafSite.Host = newHostArray
|
||||||
|
if len(wafSite.Host) == 0 {
|
||||||
|
wafSite.Host = []string{}
|
||||||
|
}
|
||||||
|
newWebsitesArray = append(newWebsitesArray, wafSite)
|
||||||
|
} else {
|
||||||
|
newWebsitesArray = append(newWebsitesArray, wafWebsite)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
websitesContent, err := json.Marshal(newWebsitesArray)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId))
|
return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -197,7 +198,7 @@ func createWebsiteFolder(nginxInstall model.AppInstall, website *model.Website,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fileOp.CopyDir(path.Join(nginxFolder, "www", "common", "waf", "rules"), path.Join(siteFolder, "waf"))
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error {
|
func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, appInstall *model.AppInstall, runtime *model.Runtime) error {
|
||||||
@ -233,12 +234,8 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
|||||||
server.UpdateServerName(serverNames)
|
server.UpdateServerName(serverNames)
|
||||||
|
|
||||||
siteFolder := path.Join("/www", "sites", website.Alias)
|
siteFolder := path.Join("/www", "sites", website.Alias)
|
||||||
commonFolder := path.Join("/www", "common")
|
|
||||||
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log")})
|
server.UpdateDirective("access_log", []string{path.Join(siteFolder, "log", "access.log")})
|
||||||
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
server.UpdateDirective("error_log", []string{path.Join(siteFolder, "log", "error.log")})
|
||||||
server.UpdateDirective("access_by_lua_file", []string{path.Join(commonFolder, "waf", "access.lua")})
|
|
||||||
server.UpdateDirective("set", []string{"$RulePath", path.Join(siteFolder, "waf", "rules")})
|
|
||||||
server.UpdateDirective("set", []string{"$logdir", path.Join(siteFolder, "log")})
|
|
||||||
|
|
||||||
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
rootIndex := path.Join("/www/sites", website.Alias, "index")
|
||||||
switch website.Type {
|
switch website.Type {
|
||||||
@ -285,6 +282,92 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createWafConfig(website *model.Website, domains []model.WebsiteDomain) error {
|
||||||
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
if !fileOp.Stat(wafDataPath) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||||
|
content, err := fileOp.GetContent(websitesConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var websitesArray []request.WafWebsite
|
||||||
|
if len(content) != 0 {
|
||||||
|
if err := json.Unmarshal(content, &websitesArray); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wafWebsite := request.WafWebsite{
|
||||||
|
Key: website.Alias,
|
||||||
|
Domains: make([]string, 0),
|
||||||
|
Host: make([]string, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, domain := range domains {
|
||||||
|
wafWebsite.Domains = append(wafWebsite.Domains, domain.Domain)
|
||||||
|
if domain.Port != 80 && domain.Port != 443 {
|
||||||
|
wafWebsite.Host = append(wafWebsite.Host, domain.Domain+":"+string(rune(domain.Port)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
websitesArray = append(websitesArray, wafWebsite)
|
||||||
|
websitesContent, err := json.Marshal(websitesArray)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
sitesDir = path.Join(wafDataPath, "sites")
|
||||||
|
defaultConfigPath = path.Join(wafDataPath, "conf", "siteConfig.json")
|
||||||
|
defaultRuleDir = path.Join(wafDataPath, "rules")
|
||||||
|
websiteDir = path.Join(sitesDir, website.Alias)
|
||||||
|
)
|
||||||
|
|
||||||
|
defaultConfigContent, err := fileOp.GetContent(defaultConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fileOp.Stat(websiteDir) {
|
||||||
|
if err = fileOp.CreateDir(websiteDir, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
_ = fileOp.DeleteDir(websiteDir)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err = fileOp.SaveFileWithByte(path.Join(websiteDir, "config.json"), defaultConfigContent, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
websiteRuleDir := path.Join(websiteDir, "rules")
|
||||||
|
if !fileOp.Stat(websiteRuleDir) {
|
||||||
|
if err := fileOp.CreateDir(websiteRuleDir, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defaultRulesName := []string{"acl", "args", "cookie", "defaultUaBlack", "defaultUrlBlack", "fileExt", "header", "methodWhite"}
|
||||||
|
for _, ruleName := range defaultRulesName {
|
||||||
|
srcPath := path.Join(defaultRuleDir, ruleName+".json")
|
||||||
|
if err = fileOp.Copy(srcPath, websiteRuleDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func delNginxConfig(website model.Website, force bool) error {
|
func delNginxConfig(website model.Website, force bool) error {
|
||||||
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
|
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -322,6 +405,52 @@ func delNginxConfig(website model.Website, force bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func delWafConfig(website model.Website, force bool) error {
|
||||||
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wafDataPath := path.Join(nginxInstall.GetPath(), "1pwaf", "data")
|
||||||
|
fileOp := files.NewFileOp()
|
||||||
|
if !fileOp.Stat(wafDataPath) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
websitesConfigPath := path.Join(wafDataPath, "conf", "sites.json")
|
||||||
|
content, err := fileOp.GetContent(websitesConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var websitesArray []request.WafWebsite
|
||||||
|
var newWebsiteArray []request.WafWebsite
|
||||||
|
if len(content) > 0 {
|
||||||
|
if err = json.Unmarshal(content, &websitesArray); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, wafWebsite := range websitesArray {
|
||||||
|
if wafWebsite.Key != website.Alias {
|
||||||
|
newWebsiteArray = append(newWebsiteArray, wafWebsite)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
websitesContent, err := json.Marshal(newWebsiteArray)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := fileOp.SaveFileWithByte(websitesConfigPath, websitesContent, 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = fileOp.DeleteDir(path.Join(wafDataPath, "sites", website.Alias))
|
||||||
|
|
||||||
|
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
|
||||||
|
if force {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func addListenAndServerName(website model.Website, ports []int, domains []string) error {
|
func addListenAndServerName(website model.Website, ports []int, domains []string) error {
|
||||||
nginxFull, err := getNginxFull(&website)
|
nginxFull, err := getNginxFull(&website)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user