feat: add sync waf ip group cron job (#10802)

Refs https://github.com/1Panel-dev/1Panel/issues/8915
This commit is contained in:
CityFun 2025-10-28 18:18:18 +08:00 committed by GitHub
parent 08f9f6f8e5
commit 1b53cd4ca8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 87 additions and 0 deletions

View file

@ -1,11 +1,15 @@
package service
import (
"bufio"
"context"
"fmt"
"io"
"net/http"
"os"
"path"
pathUtils "path"
"path/filepath"
"strings"
"time"
@ -127,6 +131,8 @@ func (u *CronjobService) loadTask(cronjob *model.Cronjob, record *model.JobRecor
err = u.handleDirectory(*cronjob, record.StartTime, taskItem)
case "log":
err = u.handleSystemLog(*cronjob, record.StartTime, taskItem)
case "syncIpGroup":
u.handleSyncIpGroup(*cronjob, taskItem)
}
return err
}
@ -210,6 +216,74 @@ func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskItem *task.Tas
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
}
func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task.Task) {
taskItem.AddSubTaskWithOps(i18n.GetWithName("SyncIpGroup", cronjob.Name), func(t *task.Task) error {
appInstall, err := getAppInstallByKey(constant.AppOpenresty)
if err != nil {
return err
}
ipGroupDir := path.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group")
urlDir := path.Join(ipGroupDir, "ip_group_url")
urlsFiles, err := os.ReadDir(urlDir)
if err != nil {
return err
}
for _, file := range urlsFiles {
if file.IsDir() || !strings.HasSuffix(file.Name(), "_url") {
continue
}
urlFilePath := filepath.Join(urlDir, file.Name())
urlContent, err := os.ReadFile(urlFilePath)
if err != nil {
continue
}
remoteURL := strings.TrimSpace(string(urlContent))
if remoteURL == "" {
continue
}
resp, err := http.Get(remoteURL)
if err != nil {
continue
}
ipGroupFile := strings.TrimSuffix(file.Name(), "_url")
ipGroupPath := filepath.Join(ipGroupDir, ipGroupFile)
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
taskItem.Logf("get remote ip group %s failed %s status code %d", ipGroupFile, remoteURL, resp.StatusCode)
continue
}
outFile, err := os.OpenFile(ipGroupPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
resp.Body.Close()
taskItem.Logf("sync %s failed %v", ipGroupFile, err)
continue
}
writer := bufio.NewWriter(outFile)
_, err = io.Copy(writer, resp.Body)
if err != nil {
outFile.Close()
resp.Body.Close()
taskItem.Logf("sync %s failed , write file failed %v", ipGroupFile, err)
continue
}
writer.Flush()
outFile.Close()
resp.Body.Close()
taskItem.LogSuccess(i18n.Get("TaskSync") + " " + ipGroupFile)
}
if err := opNginx(appInstall.ContainerName, constant.NginxReload); err != nil {
return err
}
return nil
}, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second)
}
func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time, taskItem *task.Task) error {
clientMap := NewBackupClientMap([]string{fmt.Sprintf("%v", cronjob.DownloadAccountID)})
if !clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk {

View file

@ -1142,6 +1142,7 @@ const message = {
errPath: 'Backup path [{0}] error, cannot download!',
cutWebsiteLog: 'Website log rotation',
cutWebsiteLogHelper: 'The rotated log files will be backed up to the backup directory of 1Panel.',
syncIpGroup: 'Sync WAF IP groups',
requestExpirationTime: 'Upload request expiration time(Hours)',
unitHours: 'Unit: Hours',

View file

@ -1144,6 +1144,8 @@ const message = {
errPath: '¡Error en la ruta de respaldo [{0}], no se puede descargar!',
cutWebsiteLog: 'Rotación de logs del sitio',
cutWebsiteLogHelper: 'Los archivos de log rotados se respaldarán en el directorio de respaldos de 1Panel.',
syncIpGroup: 'Sincronizar grupos de IP de WAF',
requestExpirationTime: 'Tiempo de expiración de solicitud de subida (Horas)',
unitHours: 'Unidad: Horas',
alertTitle: 'Tarea programada - {0} {1} Alerta de fallo',

View file

@ -1104,6 +1104,7 @@ const message = {
errPath: 'バックアップパス[{0}]エラーダウンロードできません',
cutWebsiteLog: 'ウェブサイトのログローテーション',
cutWebsiteLogHelper: '回転したログファイルは1パネルのバックアップディレクトリにバックアップされます',
syncIpGroup: 'WAF IP グループを同期',
requestExpirationTime: 'リクエストの有効期限時間のアップロード',
unitHours: 'ユニット:時間',

View file

@ -1098,6 +1098,8 @@ const message = {
errPath: '백업 경로 [{0}] 오류, 다운로드할 없습니다!',
cutWebsiteLog: '웹사이트 로그 회전',
cutWebsiteLogHelper: '회전된 로그 파일은 1Panel 백업 디렉토리로 백업됩니다.',
syncIpGroup: 'WAF IP 그룹 동기화',
requestExpirationTime: '업로드 요청 만료 시간(시간)',
unitHours: '단위: 시간',
alertTitle: '예정된 작업 - {0} {1} 작업 실패 경고',

View file

@ -1135,6 +1135,7 @@ const message = {
errPath: 'Laluan sandaran [{0}] salah, tidak boleh dimuat turun!',
cutWebsiteLog: 'Putaran log laman web',
cutWebsiteLogHelper: 'Fail log yang diputar akan disandarkan ke direktori sandaran 1Panel.',
syncIpGroup: 'Segerakkan kumpulan IP WAF',
requestExpirationTime: 'Waktu luput permintaan muat naik (Jam)',
unitHours: 'Unit: Jam',

View file

@ -1127,6 +1127,7 @@ const message = {
errPath: 'Caminho de backup [{0}] com erro, não é possível fazer o download!',
cutWebsiteLog: 'Rotação de log do site',
cutWebsiteLogHelper: 'Os arquivos de log rotacionados serão salvos no diretório de backup do 1Panel.',
syncIpGroup: 'Sincronizar grupos de IP do WAF',
requestExpirationTime: 'Tempo de expiração da solicitação de upload (Horas)',
unitHours: 'Unidade: Horas',

View file

@ -1131,6 +1131,7 @@ const message = {
errPath: 'Ошибка пути резервной копии [{0}], невозможно скачать!',
cutWebsiteLog: 'Ротация логов сайта',
cutWebsiteLogHelper: 'Ротированные файлы логов будут сохранены в директории резервных копий 1Panel.',
syncIpGroup: 'Синхронизировать группы IP WAF',
requestExpirationTime: 'Время истечения запроса на загрузку (часы)',
unitHours: 'Единица: часы',

View file

@ -1154,6 +1154,7 @@ const message = {
errPath: 'Yedek yolu [{0}] hatası, indirilemez!',
cutWebsiteLog: 'Website log döndürme',
cutWebsiteLogHelper: 'Döndürülen log dosyaları 1Panel yedek dizinine yedeklenecektir.',
syncIpGroup: 'WAF IP gruplarını senkronize et',
requestExpirationTime: 'Yükleme isteği son kullanma süresi(Saat)',
unitHours: 'Birim: Saat',

View file

@ -1082,6 +1082,7 @@ const message = {
errPath: '備份路徑 [{0}] 錯誤無法下載',
cutWebsiteLog: '切割網站日誌',
cutWebsiteLogHelper: '切割的日誌檔案會備份到 1Panel backup 目錄下',
syncIpGroup: '同步 WAF IP ',
requestExpirationTime: '上傳請求過期時間小時',
unitHours: '單位小時',

View file

@ -1083,6 +1083,7 @@ const message = {
errPath: '备份路径 [{0}] 错误无法下载',
cutWebsiteLog: '切割网站日志',
cutWebsiteLogHelper: '切割的日志文件会备份到 1Panel backup 目录下',
syncIpGroup: '同步 WAF IP ',
requestExpirationTime: '上传请求过期时间小时',
unitHours: '单位小时',

View file

@ -26,6 +26,7 @@
<el-option value="clean" :label="$t('setting.diskClean')" />
<el-option value="snapshot" :label="$t('cronjob.snapshot')" />
<el-option value="ntp" :label="$t('cronjob.ntp')" />
<el-option value="syncIpGroup" :label="$t('cronjob.syncIpGroup')" />
</el-select>
<div v-else class="w-full">
<el-tag>{{ $t('cronjob.' + form.type) }}</el-tag>