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"`
|
||||
}
|
||||
|
||||
type WebsiteWafReq struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
Rule string `json:"rule" validate:"required"`
|
||||
}
|
||||
|
||||
type WebsiteRedirectUpdate struct {
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Key string `json:"key" validate:"required"`
|
||||
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 {
|
||||
WebsiteName string `json:"websiteName" validate:"required"`
|
||||
Type string `json:"type" validate:"required"`
|
||||
@ -207,12 +195,12 @@ type WebsiteRedirectReq struct {
|
||||
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 {
|
||||
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"`
|
||||
}
|
||||
|
||||
type WebsiteWafConfig struct {
|
||||
Enable bool `json:"enable"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type WebsiteHTTPS struct {
|
||||
Enable bool `json:"enable"`
|
||||
HttpConfig string `json:"httpConfig"`
|
||||
|
@ -61,6 +61,7 @@ type IWebsiteService interface {
|
||||
UpdateWebsite(req request.WebsiteUpdate) error
|
||||
DeleteWebsite(req request.WebsiteDelete) error
|
||||
GetWebsite(id uint) (response.WebsiteDTO, error)
|
||||
|
||||
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
|
||||
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, 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 {
|
||||
return err
|
||||
}
|
||||
if err = createWafConfig(website, domains); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, ctx := helper.GetTxAndContext()
|
||||
defer tx.Rollback()
|
||||
if err = websiteRepo.Create(ctx, website); err != nil {
|
||||
@ -420,7 +425,11 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
@ -489,6 +498,53 @@ func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate)
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
domains = append(domains, webSiteDomain.Domain)
|
||||
}
|
||||
|
||||
if len(ports) > 0 || len(domains) > 0 {
|
||||
stringBinds := make([]string, len(ports))
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"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 {
|
||||
@ -233,12 +234,8 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
server.UpdateServerName(serverNames)
|
||||
|
||||
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("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")
|
||||
switch website.Type {
|
||||
@ -285,6 +282,92 @@ func configDefaultNginx(website *model.Website, domains []model.WebsiteDomain, a
|
||||
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 {
|
||||
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
|
||||
if err != nil {
|
||||
@ -322,6 +405,52 @@ func delNginxConfig(website model.Website, force bool) error {
|
||||
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 {
|
||||
nginxFull, err := getNginxFull(&website)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user