Files
EdgeAPI/internal/tasks/ssl_cert_expire_check_executor.go
2020-11-27 09:57:21 +08:00

205 lines
6.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package tasks
import (
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"strconv"
"time"
)
func init() {
dbs.OnReady(func() {
go NewSSLCertExpireCheckExecutor().Start()
})
}
// 证书检查任务
type SSLCertExpireCheckExecutor struct {
}
func NewSSLCertExpireCheckExecutor() *SSLCertExpireCheckExecutor {
return &SSLCertExpireCheckExecutor{}
}
// 启动任务
func (this *SSLCertExpireCheckExecutor) Start() {
seconds := int64(3600)
ticker := time.NewTicker(time.Duration(seconds) * time.Second)
for range ticker.C {
err := this.loop(seconds)
if err != nil {
logs.Println("[ERROR][SSLCertExpireCheckExecutor]" + err.Error())
}
}
}
// 单次执行
func (this *SSLCertExpireCheckExecutor) loop(seconds int64) error {
// 检查上次运行时间,防止重复运行
settingKey := "sslCertExpiringCheck"
timestamp := time.Now().Unix()
c, err := models.SharedSysSettingDAO.CompareInt64Setting(settingKey, timestamp-seconds)
if err != nil {
return err
}
if c > 0 {
return nil
}
// 记录时间
err = models.SharedSysSettingDAO.UpdateSetting(settingKey, []byte(numberutils.FormatInt64(timestamp)))
if err != nil {
return err
}
// 查找需要自动更新的证书
// 30, 14 ... 是到期的天数
for _, days := range []int{30, 14, 7} {
certs, err := models.SharedSSLCertDAO.FindAllExpiringCerts(days)
if err != nil {
return err
}
for _, cert := range certs {
// 发送消息
msg := "SSL证书\"" + cert.Name + "\"" + cert.DnsNames + ")在" + strconv.Itoa(days) + "天后将到期,"
// 是否有自动更新任务
if cert.AcmeTaskId > 0 {
task, err := models.SharedACMETaskDAO.FindEnabledACMETask(int64(cert.AcmeTaskId))
if err != nil {
return err
}
if task != nil {
if task.AutoRenew == 1 {
msg += "此证书是免费申请的证书,且已设置了自动续期,将会在到期前三天自动尝试续期。"
} else {
msg += "此证书是免费申请的证书,没有设置自动续期,请在到期前手动执行续期任务。"
}
}
} else {
msg += "请及时更新证书。"
}
err = models.SharedMessageDAO.CreateMessage(int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertExpiring, models.MessageLevelWarning, msg, maps.Map{
"certId": cert.Id,
"acmeTaskId": cert.AcmeTaskId,
}.AsJSON())
if err != nil {
return err
}
// 设置最后通知时间
err = models.SharedSSLCertDAO.UpdateCertNotifiedAt(int64(cert.Id))
if err != nil {
return err
}
}
}
// 自动续期
for _, days := range []int{3, 2, 1} {
certs, err := models.SharedSSLCertDAO.FindAllExpiringCerts(days)
if err != nil {
return err
}
for _, cert := range certs {
// 发送消息
msg := "SSL证书\"" + cert.Name + "\"" + cert.DnsNames + ")在" + strconv.Itoa(days) + "天后将到期,"
// 是否有自动更新任务
if cert.AcmeTaskId > 0 {
task, err := models.SharedACMETaskDAO.FindEnabledACMETask(int64(cert.AcmeTaskId))
if err != nil {
return err
}
if task != nil {
if task.AutoRenew == 1 {
isOk, errMsg, _ := models.SharedACMETaskDAO.RunTask(int64(cert.AcmeTaskId))
if isOk {
// 发送成功通知
msg = "系统已成功为你自动更新了证书\"" + cert.Name + "\"" + cert.DnsNames + ")。"
err = models.SharedMessageDAO.CreateMessage(int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertACMETaskSuccess, models.MessageLevelSuccess, msg, maps.Map{
"certId": cert.Id,
"acmeTaskId": cert.AcmeTaskId,
}.AsJSON())
// 更新通知时间
err = models.SharedSSLCertDAO.UpdateCertNotifiedAt(int64(cert.Id))
if err != nil {
return err
}
} else {
// 发送失败通知
msg = "系统在尝试自动更新证书\"" + cert.Name + "\"" + cert.DnsNames + ")时发生错误:" + errMsg + "。请检查系统设置并修复错误。"
err = models.SharedMessageDAO.CreateMessage(int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertACMETaskFailed, models.MessageLevelError, msg, maps.Map{
"certId": cert.Id,
"acmeTaskId": cert.AcmeTaskId,
}.AsJSON())
// 更新通知时间
err = models.SharedSSLCertDAO.UpdateCertNotifiedAt(int64(cert.Id))
if err != nil {
return err
}
}
// 中止不发送消息
continue
} else {
msg += "此证书是免费申请的证书,没有设置自动续期,请在到期前手动执行续期任务。"
}
}
} else {
msg += "请及时更新证书。"
}
err = models.SharedMessageDAO.CreateMessage(int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertExpiring, models.MessageLevelWarning, msg, maps.Map{
"certId": cert.Id,
"acmeTaskId": cert.AcmeTaskId,
}.AsJSON())
if err != nil {
return err
}
// 设置最后通知时间
err = models.SharedSSLCertDAO.UpdateCertNotifiedAt(int64(cert.Id))
if err != nil {
return err
}
}
}
// 当天过期
for _, days := range []int{0} {
certs, err := models.SharedSSLCertDAO.FindAllExpiringCerts(days)
if err != nil {
return err
}
for _, cert := range certs {
// 发送消息
today := timeutil.Format("Y-m-d")
msg := "SSL证书\"" + cert.Name + "\"" + cert.DnsNames + ")在今天(" + today + ")过期,请及时更新证书,之后将不再重复提醒。"
err = models.SharedMessageDAO.CreateMessage(int64(cert.AdminId), int64(cert.UserId), models.MessageTypeSSLCertExpiring, models.MessageLevelWarning, msg, maps.Map{
"certId": cert.Id,
"acmeTaskId": cert.AcmeTaskId,
}.AsJSON())
if err != nil {
return err
}
// 设置最后通知时间
err = models.SharedSSLCertDAO.UpdateCertNotifiedAt(int64(cert.Id))
if err != nil {
return err
}
}
}
return nil
}