mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2025-12-06 06:58:54 +08:00
@@ -44,6 +44,7 @@ type APIGroup struct {
|
||||
WafVpConfigApi
|
||||
WafFileApi
|
||||
WafSystemMonitorApi
|
||||
WafCaServerInfoApi
|
||||
}
|
||||
|
||||
var APIGroupAPP = new(APIGroup)
|
||||
@@ -102,4 +103,6 @@ var (
|
||||
wafTunnelService = waf_service.WafTunnelServiceApp
|
||||
|
||||
wafMonitorService = waf_service.WafSystemMonitorServiceApp
|
||||
|
||||
wafCaServerInfoService = waf_service.WafCaServerInfoServiceApp
|
||||
)
|
||||
|
||||
95
api/waf_caserverinfo_api.go
Normal file
95
api/waf_caserverinfo_api.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"SamWaf/model/common/response"
|
||||
"SamWaf/model/request"
|
||||
"errors"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type WafCaServerInfoApi struct {
|
||||
}
|
||||
|
||||
func (w *WafCaServerInfoApi) AddApi(c *gin.Context) {
|
||||
var req request.WafCaServerInfoAddReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
|
||||
cnt := wafCaServerInfoService.CheckIsExistApi(req)
|
||||
if cnt == 0 {
|
||||
err = wafCaServerInfoService.AddApi(req)
|
||||
if err == nil {
|
||||
response.OkWithMessage("添加成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("添加失败", c)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
response.FailWithMessage("当前记录已经存在", c)
|
||||
return
|
||||
}
|
||||
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WafCaServerInfoApi) GetDetailApi(c *gin.Context) {
|
||||
var req request.WafCaServerInfoDetailReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
bean := wafCaServerInfoService.GetDetailApi(req)
|
||||
response.OkWithDetailed(bean, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WafCaServerInfoApi) GetListApi(c *gin.Context) {
|
||||
var req request.WafCaServerInfoSearchReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
CaServerInfo, total, _ := wafCaServerInfoService.GetListApi(req)
|
||||
response.OkWithDetailed(response.PageResult{
|
||||
List: CaServerInfo,
|
||||
Total: total,
|
||||
PageIndex: req.PageIndex,
|
||||
PageSize: req.PageSize,
|
||||
}, "获取成功", c)
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WafCaServerInfoApi) DelApi(c *gin.Context) {
|
||||
var req request.WafCaServerInfoDelReq
|
||||
err := c.ShouldBind(&req)
|
||||
if err == nil {
|
||||
err = wafCaServerInfoService.DelApi(req)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.FailWithMessage("请检测参数", c)
|
||||
} else if err != nil {
|
||||
response.FailWithMessage("发生错误", c)
|
||||
} else {
|
||||
response.OkWithMessage("删除成功", c)
|
||||
}
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WafCaServerInfoApi) ModifyApi(c *gin.Context) {
|
||||
var req request.WafCaServerInfoEditReq
|
||||
err := c.ShouldBindJSON(&req)
|
||||
if err == nil {
|
||||
err = wafCaServerInfoService.ModifyApi(req)
|
||||
if err != nil {
|
||||
response.FailWithMessage("编辑发生错误"+err.Error(), c)
|
||||
} else {
|
||||
response.OkWithMessage("编辑成功", c)
|
||||
}
|
||||
} else {
|
||||
response.FailWithMessage("解析失败", c)
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,7 @@ import (
|
||||
func TestCodeGeneration(t *testing.T) {
|
||||
// 唯一校验定义字段信息的字符串
|
||||
fieldDefs := []string{
|
||||
"PrivateGroupName:private_group_name:string",
|
||||
"PrivateGroupBelongCloud:private_group_belong_cloud:string",
|
||||
"CaServerName:ca_server_name:string",
|
||||
}
|
||||
|
||||
// 构造 `uniFields` 列表
|
||||
@@ -28,6 +27,6 @@ func TestCodeGeneration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
fields := GetStructFields(model.PrivateGroup{})
|
||||
CodeGeneration("PrivateGroup", fields, uniFields)
|
||||
fields := GetStructFields(model.CaServerInfo{})
|
||||
CodeGeneration("CaServerInfo", fields, uniFields)
|
||||
}
|
||||
|
||||
10
model/ca_server_info.go
Normal file
10
model/ca_server_info.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package model
|
||||
|
||||
import "SamWaf/model/baseorm"
|
||||
|
||||
type CaServerInfo struct {
|
||||
baseorm.BaseOrm
|
||||
CaServerName string `json:"ca_server_name"` //CA服务器名称
|
||||
CaServerAddress string `json:"ca_server_address"` //CA服务器地址
|
||||
Remarks string `json:"remarks"` //备注
|
||||
}
|
||||
25
model/request/waf_caserverinfo_req.go
Normal file
25
model/request/waf_caserverinfo_req.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package request
|
||||
|
||||
import "SamWaf/model/common/request"
|
||||
|
||||
type WafCaServerInfoAddReq struct {
|
||||
CaServerName string `json:"ca_server_name" form:"ca_server_name"`
|
||||
CaServerAddress string `json:"ca_server_address" form:"ca_server_address"`
|
||||
Remarks string `json:"remarks" form:"remarks"`
|
||||
}
|
||||
type WafCaServerInfoEditReq struct {
|
||||
Id string `json:"id"`
|
||||
|
||||
CaServerName string `json:"ca_server_name" form:"ca_server_name"`
|
||||
CaServerAddress string `json:"ca_server_address" form:"ca_server_address"`
|
||||
Remarks string `json:"remarks" form:"remarks"`
|
||||
}
|
||||
type WafCaServerInfoDetailReq struct {
|
||||
Id string `json:"id" form:"id"`
|
||||
}
|
||||
type WafCaServerInfoDelReq struct {
|
||||
Id string `json:"id" form:"id"`
|
||||
}
|
||||
type WafCaServerInfoSearchReq struct {
|
||||
request.PageInfo
|
||||
}
|
||||
@@ -42,6 +42,7 @@ type ApiGroup struct {
|
||||
WafVpConfigRouter
|
||||
WafFileRouter
|
||||
WafSystemMonitorRouter
|
||||
WafCaServerInfoRouter
|
||||
}
|
||||
type PublicApiGroup struct {
|
||||
LoginRouter
|
||||
|
||||
19
router/waf_caserverinfo_router.go
Normal file
19
router/waf_caserverinfo_router.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"SamWaf/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type WafCaServerInfoRouter struct {
|
||||
}
|
||||
|
||||
func (receiver *WafCaServerInfoRouter) InitWafCaServerInfoRouter(group *gin.RouterGroup) {
|
||||
api := api.APIGroupAPP.WafCaServerInfoApi
|
||||
router := group.Group("")
|
||||
router.POST("/samwaf/wafhost/caserverinfo/add", api.AddApi)
|
||||
router.POST("/samwaf/wafhost/caserverinfo/list", api.GetListApi)
|
||||
router.GET("/samwaf/wafhost/caserverinfo/detail", api.GetDetailApi)
|
||||
router.POST("/samwaf/wafhost/caserverinfo/edit", api.ModifyApi)
|
||||
router.GET("/samwaf/wafhost/caserverinfo/del", api.DelApi)
|
||||
}
|
||||
133
service/waf_service/waf_caserverinfo_service.go
Normal file
133
service/waf_service/waf_caserverinfo_service.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package waf_service
|
||||
|
||||
import (
|
||||
"SamWaf/common/uuid"
|
||||
"SamWaf/customtype"
|
||||
"SamWaf/global"
|
||||
"SamWaf/model"
|
||||
"SamWaf/model/baseorm"
|
||||
"SamWaf/model/request"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WafCaServerInfoService struct{}
|
||||
|
||||
var WafCaServerInfoServiceApp = new(WafCaServerInfoService)
|
||||
|
||||
func (receiver *WafCaServerInfoService) AddApi(req request.WafCaServerInfoAddReq) error {
|
||||
var bean = &model.CaServerInfo{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
USER_CODE: global.GWAF_USER_CODE,
|
||||
Tenant_ID: global.GWAF_TENANT_ID,
|
||||
CREATE_TIME: customtype.JsonTime(time.Now()),
|
||||
UPDATE_TIME: customtype.JsonTime(time.Now()),
|
||||
},
|
||||
|
||||
CaServerName: req.CaServerName,
|
||||
CaServerAddress: req.CaServerAddress,
|
||||
Remarks: req.Remarks,
|
||||
}
|
||||
global.GWAF_LOCAL_DB.Create(bean)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (receiver *WafCaServerInfoService) CheckIsExistApi(req request.WafCaServerInfoAddReq) int {
|
||||
var total int64 = 0
|
||||
/*where条件*/
|
||||
var whereField = ""
|
||||
var whereValues []interface{}
|
||||
//where字段
|
||||
whereField = ""
|
||||
|
||||
if len(req.CaServerName) > 0 {
|
||||
if len(whereField) > 0 {
|
||||
whereField = whereField + " and "
|
||||
}
|
||||
whereField = whereField + " ca_server_name=? "
|
||||
}
|
||||
|
||||
//where字段赋值
|
||||
|
||||
if len(req.CaServerName) > 0 {
|
||||
if len(whereField) > 0 {
|
||||
whereValues = append(whereValues, req.CaServerName)
|
||||
}
|
||||
}
|
||||
|
||||
global.GWAF_LOCAL_DB.Model(&model.CaServerInfo{}).Where(whereField, whereValues...).Count(&total)
|
||||
return int(total)
|
||||
}
|
||||
|
||||
func (receiver *WafCaServerInfoService) ModifyApi(req request.WafCaServerInfoEditReq) error {
|
||||
// 根据唯一字段生成查询条件(只有在UniFields不为空时才进行存在性检查)
|
||||
|
||||
var total int64 = 0
|
||||
/*where条件*/
|
||||
var whereField = ""
|
||||
var whereValues []interface{}
|
||||
//where字段
|
||||
whereField = ""
|
||||
|
||||
if len(req.CaServerName) > 0 {
|
||||
if len(whereField) > 0 {
|
||||
whereField = whereField + " and "
|
||||
}
|
||||
whereField = whereField + " ca_server_name=? "
|
||||
}
|
||||
|
||||
//where字段赋值
|
||||
|
||||
if len(req.CaServerName) > 0 {
|
||||
whereValues = append(whereValues, req.CaServerName)
|
||||
}
|
||||
|
||||
global.GWAF_LOCAL_DB.Model(&model.CaServerInfo{}).Where(whereField, whereValues...).Count(&total)
|
||||
// 查询是否已存在记录
|
||||
var bean model.CaServerInfo
|
||||
global.GWAF_LOCAL_DB.Model(&model.CaServerInfo{}).Where(whereField, whereValues...).Limit(1).Find(&bean)
|
||||
|
||||
if int(total) > 0 && bean.Id != "" && bean.Id != req.Id {
|
||||
return errors.New("当前记录已经存在")
|
||||
}
|
||||
|
||||
beanMap := map[string]interface{}{
|
||||
|
||||
"CaServerName": req.CaServerName,
|
||||
"CaServerAddress": req.CaServerAddress,
|
||||
"Remarks": req.Remarks,
|
||||
|
||||
"UPDATE_TIME": customtype.JsonTime(time.Now()),
|
||||
}
|
||||
err := global.GWAF_LOCAL_DB.Model(model.CaServerInfo{}).Where("id = ?", req.Id).Updates(beanMap).Error
|
||||
|
||||
return err
|
||||
}
|
||||
func (receiver *WafCaServerInfoService) GetDetailApi(req request.WafCaServerInfoDetailReq) model.CaServerInfo {
|
||||
var bean model.CaServerInfo
|
||||
global.GWAF_LOCAL_DB.Where("id=?", req.Id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafCaServerInfoService) GetDetailByIdApi(id string) model.CaServerInfo {
|
||||
var bean model.CaServerInfo
|
||||
global.GWAF_LOCAL_DB.Where("id=?", id).Find(&bean)
|
||||
return bean
|
||||
}
|
||||
func (receiver *WafCaServerInfoService) GetListApi(req request.WafCaServerInfoSearchReq) ([]model.CaServerInfo, int64, error) {
|
||||
var list []model.CaServerInfo
|
||||
var total int64 = 0
|
||||
global.GWAF_LOCAL_DB.Model(&model.CaServerInfo{}).Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&list)
|
||||
global.GWAF_LOCAL_DB.Model(&model.CaServerInfo{}).Count(&total)
|
||||
|
||||
return list, total, nil
|
||||
}
|
||||
func (receiver *WafCaServerInfoService) DelApi(req request.WafCaServerInfoDelReq) error {
|
||||
var bean model.CaServerInfo
|
||||
err := global.GWAF_LOCAL_DB.Where("id = ?", req.Id).First(&bean).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = global.GWAF_LOCAL_DB.Where("id = ?", req.Id).Delete(model.CaServerInfo{}).Error
|
||||
return err
|
||||
}
|
||||
@@ -171,3 +171,27 @@ func (receiver *WafSSLOrderService) GetLastedInfo(hostCode string) (model.SslOrd
|
||||
|
||||
return bean, nil
|
||||
}
|
||||
|
||||
// GetCAServerAddress 根据CA服务器名称获取地址
|
||||
func GetCAServerAddress(caServerName string) string {
|
||||
// 如果没有指定CA服务器名称,默认使用letsencrypt
|
||||
if caServerName == "" {
|
||||
caServerName = "letsencrypt"
|
||||
}
|
||||
|
||||
// 从数据库查询CA服务器信息
|
||||
var caServer model.CaServerInfo
|
||||
err := global.GWAF_LOCAL_DB.Where("ca_server_name = ?", caServerName).First(&caServer).Error
|
||||
|
||||
// 如果查询失败或没有找到记录,返回默认的letsencrypt地址
|
||||
if err != nil {
|
||||
return "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
// 如果找到记录但地址为空,也返回默认地址
|
||||
if caServer.CaServerAddress == "" {
|
||||
return "https://acme-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
return caServer.CaServerAddress
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
||||
return u.key
|
||||
}
|
||||
|
||||
func RegistrationSSL(order model.SslOrder, savePath string) (model.SslOrder, error) {
|
||||
func RegistrationSSL(order model.SslOrder, savePath string, caServerAddress string) (model.SslOrder, error) {
|
||||
myUser := MyUser{
|
||||
Email: order.ApplyEmail,
|
||||
}
|
||||
@@ -67,8 +67,7 @@ func RegistrationSSL(order model.SslOrder, savePath string) (model.SslOrder, err
|
||||
//order.ApplyKey = privateKey
|
||||
config := lego.NewConfig(&myUser)
|
||||
|
||||
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
|
||||
config.CADirURL = lego.LEDirectoryProduction // 测试用 LEDirectoryStaging 正式用 LEDirectoryProduction
|
||||
config.CADirURL = caServerAddress
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
// A client facilitates communication with the CA server.
|
||||
@@ -137,7 +136,7 @@ func RegistrationSSL(order model.SslOrder, savePath string) (model.SslOrder, err
|
||||
return order, nil
|
||||
}
|
||||
|
||||
func ReNewSSL(order model.SslOrder, savePath string) (model.SslOrder, error) {
|
||||
func ReNewSSL(order model.SslOrder, savePath string, caServerAddress string) (model.SslOrder, error) {
|
||||
myUser := MyUser{
|
||||
Email: order.ApplyEmail,
|
||||
}
|
||||
@@ -165,9 +164,7 @@ func ReNewSSL(order model.SslOrder, savePath string) (model.SslOrder, error) {
|
||||
|
||||
//order.ApplyKey = privateKey
|
||||
config := lego.NewConfig(&myUser)
|
||||
|
||||
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
|
||||
config.CADirURL = lego.LEDirectoryProduction // 测试用 LEDirectoryStaging 正式用 LEDirectoryProduction
|
||||
config.CADirURL = caServerAddress
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
// A client facilitates communication with the CA server.
|
||||
|
||||
@@ -24,5 +24,5 @@ func TestRegistrationSSL(t *testing.T) {
|
||||
ResultCSR: nil,
|
||||
Remarks: "",
|
||||
}
|
||||
RegistrationSSL(order, "C:\\huawei\\goproject\\SamWaf\\data\\vhost\\ssl#samwaf#com")
|
||||
RegistrationSSL(order, "C:\\huawei\\goproject\\SamWaf\\data\\vhost\\ssl#samwaf#com", "https://acme-v02.api.letsencrypt.org/directory")
|
||||
}
|
||||
|
||||
@@ -158,6 +158,9 @@ func InitCoreDb(currentDir string) (bool, error) {
|
||||
//隧道
|
||||
db.AutoMigrate(&model.Tunnel{})
|
||||
|
||||
//CA服务器信息
|
||||
db.AutoMigrate(&model.CaServerInfo{})
|
||||
|
||||
global.GWAF_LOCAL_DB.Callback().Query().Before("gorm:query").Register("tenant_plugin:before_query", before_query)
|
||||
global.GWAF_LOCAL_DB.Callback().Query().Before("gorm:update").Register("tenant_plugin:before_update", before_update)
|
||||
|
||||
|
||||
@@ -203,6 +203,32 @@ func pathCoreSql(db *gorm.DB) {
|
||||
} else {
|
||||
zlog.Info("db", "hosts :static_site_json sensitive_paths update successfully")
|
||||
}
|
||||
//20250827 初始化 letsencrypt CA 服务器记录
|
||||
var letsencryptCount int64
|
||||
db.Model(&model.CaServerInfo{}).Where("ca_server_name = ?", "letsencrypt").Count(&letsencryptCount)
|
||||
|
||||
// 如果不存在 letsencrypt 记录,则创建
|
||||
if letsencryptCount == 0 {
|
||||
letsencryptCA := model.CaServerInfo{
|
||||
BaseOrm: baseorm.BaseOrm{
|
||||
Id: uuid.GenUUID(),
|
||||
USER_CODE: global.GWAF_USER_CODE,
|
||||
Tenant_ID: global.GWAF_TENANT_ID,
|
||||
CREATE_TIME: customtype.JsonTime(time.Now()),
|
||||
UPDATE_TIME: customtype.JsonTime(time.Now()),
|
||||
},
|
||||
CaServerName: "letsencrypt",
|
||||
CaServerAddress: "https://acme-v02.api.letsencrypt.org/directory",
|
||||
Remarks: "Let's Encrypt",
|
||||
}
|
||||
|
||||
err := db.Create(&letsencryptCA).Error
|
||||
if err != nil {
|
||||
zlog.Error("db", "init letsencrypt CA server fail", "error", err.Error())
|
||||
} else {
|
||||
zlog.Info("db", "init letsencrypt CA server success")
|
||||
}
|
||||
}
|
||||
// 记录结束时间并计算耗时
|
||||
duration := time.Since(startTime)
|
||||
zlog.Info("create core default value completely", "duration", duration.String())
|
||||
|
||||
@@ -41,7 +41,7 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
if filePathErr != nil {
|
||||
zlog.Error("ApplySSLOrder", filePathErr.Error())
|
||||
}
|
||||
updateSSLOrder, err := ssl.RegistrationSSL(bean, filePath)
|
||||
updateSSLOrder, err := ssl.RegistrationSSL(bean, filePath, waf_service.GetCAServerAddress(bean.ApplyPlatform))
|
||||
if err == nil {
|
||||
zlog.Info(fmt.Sprintf("%s 首次证书申请成功", bean.ApplyDomain))
|
||||
|
||||
@@ -75,7 +75,7 @@ func (waf *WafEngine) ApplySSLOrder(chanType int, bean model.SslOrder) {
|
||||
if filePathErr != nil {
|
||||
zlog.Error("ApplySSLOrder", filePathErr.Error())
|
||||
}
|
||||
updateSSLOrder, err := ssl.ReNewSSL(bean, filePath)
|
||||
updateSSLOrder, err := ssl.ReNewSSL(bean, filePath, waf_service.GetCAServerAddress(bean.ApplyPlatform))
|
||||
if err == nil {
|
||||
zlog.Info(fmt.Sprintf("%s 证书续期申请成功", bean.ApplyDomain))
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ func (web *WafWebManager) initRouter(r *gin.Engine) {
|
||||
router.ApiGroupApp.InitWafVpConfigRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitWafFileRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitWafSystemMonitorRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitWafCaServerInfoRouter(RouterGroup)
|
||||
}
|
||||
|
||||
if global.GWAF_RELEASE == "true" {
|
||||
|
||||
Reference in New Issue
Block a user