feat: 增加自动续签设置

This commit is contained in:
zhengkunwang223 2023-01-04 11:44:43 +08:00 committed by zhengkunwang223
parent c7529469f8
commit 75756e8bb7
14 changed files with 111 additions and 23 deletions

View File

@ -12,6 +12,7 @@ type WebsiteSSLCreate struct {
Provider string `json:"provider" validate:"required"`
AcmeAccountID uint `json:"acmeAccountId" validate:"required"`
DnsAccountID uint `json:"dnsAccountId"`
AutoRenew bool `json:"autoRenew" validate:"required"`
}
type WebsiteDNSReq struct {

View File

@ -4,19 +4,21 @@ import "time"
type WebsiteSSL struct {
BaseModel
PrimaryDomain string `gorm:"type:varchar(256);not null" json:"primaryDomain"`
PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"`
Pem string `gorm:"type:longtext;not null" json:"pem"`
Domains string `gorm:"type:varchar(256);not null" json:"domains"`
CertURL string `gorm:"type:varchar(256);not null" json:"certURL"`
Type string `gorm:"type:varchar(64);not null" json:"type"`
Provider string `gorm:"type:varchar(64);not null" json:"provider"`
Organization string `gorm:"type:varchar(64);not null" json:"organization"`
DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"`
AcmeAccountID uint `gorm:"type:integer;not null" json:"acmeAccountId"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
PrimaryDomain string `gorm:"type:varchar(256);not null" json:"primaryDomain"`
PrivateKey string `gorm:"type:longtext;not null" json:"privateKey"`
Pem string `gorm:"type:longtext;not null" json:"pem"`
Domains string `gorm:"type:varchar(256);not null" json:"domains"`
CertURL string `gorm:"type:varchar(256);not null" json:"certURL"`
Type string `gorm:"type:varchar(64);not null" json:"type"`
Provider string `gorm:"type:varchar(64);not null" json:"provider"`
Organization string `gorm:"type:varchar(64);not null" json:"organization"`
DnsAccountID uint `gorm:"type:integer;not null" json:"dnsAccountId"`
AcmeAccountID uint `gorm:"type:integer;not null" json:"acmeAccountId"`
AutoRenew bool `gorm:"type:varchar(64);not null" json:"autoRenew"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount"`
}
func (w WebsiteSSL) TableName() string {

View File

@ -205,7 +205,6 @@ func nginxCheckAndReload(oldContent string, filePath string, containerName strin
_ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644)
return err
}
if err := opNginx(containerName, constant.NginxReload); err != nil {
_ = files.NewFileOp().WriteFile(filePath, strings.NewReader(oldContent), 0644)
return err

View File

@ -9,6 +9,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/ssl"
"path"
"strings"
@ -17,6 +18,21 @@ import (
type WebsiteSSLService struct {
}
type IWebsiteSSLService interface {
Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error)
GetSSL(id uint) (*response.WebsiteSSLDTO, error)
Search() ([]response.WebsiteSSLDTO, error)
Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error)
Renew(sslId uint) error
GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error)
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error)
Delete(id uint) error
}
func NewIWebsiteSSLService() IWebsiteSSLService {
return &WebsiteSSLService{}
}
func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) {
total, sslList, err := websiteSSLRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc"))
if err != nil {
@ -151,8 +167,6 @@ func (w WebsiteSSLService) Renew(sslId uint) error {
if err := client.UseHTTP(path.Join(constant.AppInstallDir, constant.AppNginx, appInstall.Name, "root")); err != nil {
return err
}
case constant.DnsManual:
}
resource, err := client.RenewSSL(websiteSSL.CertURL)
@ -172,7 +186,26 @@ func (w WebsiteSSLService) Renew(sslId uint) error {
websiteSSL.Type = cert.Issuer.CommonName
websiteSSL.Organization = cert.Issuer.Organization[0]
return websiteSSLRepo.Save(websiteSSL)
if err := websiteSSLRepo.Save(websiteSSL); err != nil {
return err
}
websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(sslId))
for _, website := range websites {
if err := createPemFile(website, websiteSSL); err != nil {
global.LOG.Errorf("create website [%s] ssl file failed! err:%s", website.PrimaryDomain, err.Error())
}
}
if len(websites) > 0 {
nginxInstall, err := getAppInstallByKey(constant.AppNginx)
if err != nil {
return err
}
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil {
return buserr.New(constant.ErrSSLApply)
}
}
return nil
}
func (w WebsiteSSLService) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) {

View File

@ -66,4 +66,5 @@ var (
var (
ErrSSLCannotDelete = "ErrSSLCannotDelete"
ErrAccountCannotDelete = "ErrAccountCannotDelete"
ErrSSLApply = "ErrSSLApply"
)

View File

@ -22,6 +22,10 @@ func Run() {
if err != nil {
global.LOG.Errorf("can not add website corn job: %s", err.Error())
}
_, err = Cron.AddJob("@daily", job.NewSSLJob())
if err != nil {
global.LOG.Errorf("can not add ssl corn job: %s", err.Error())
}
Cron.Start()
global.Cron = Cron

36
backend/cron/job/ssl.go Normal file
View File

@ -0,0 +1,36 @@
package job
import (
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/app/service"
"github.com/1Panel-dev/1Panel/backend/global"
"time"
)
type ssl struct {
}
func NewSSLJob() *ssl {
return &ssl{}
}
func (ssl *ssl) Run() {
sslRepo := repo.NewISSLRepo()
sslService := service.NewIWebsiteSSLService()
sslList, _ := sslRepo.List()
global.LOG.Info("ssl renew cron job start...")
now := time.Now()
for _, s := range sslList {
if !s.AutoRenew || s.Provider == "manual" || s.Provider == "dnsManual" {
continue
}
sum := s.ExpireDate.Sub(now)
if sum.Hours() < 168 {
if err := sslService.Renew(s.ID); err != nil {
global.LOG.Errorf("renew doamin [%s] ssl failed err:%s", s.PrimaryDomain, err.Error())
}
}
}
global.LOG.Info("ssl renew cron job end...")
}

View File

@ -18,7 +18,7 @@ func NewWebsiteJob() *website {
func (w *website) Run() {
websites, _ := repo.NewIWebsiteRepo().List()
global.LOG.Info("website cron job start....")
global.LOG.Info("website cron job start...")
now := time.Now()
if len(websites) > 0 {
neverExpireDate, _ := time.Parse(constant.DateLayout, constant.DefaultDate)
@ -36,7 +36,7 @@ func (w *website) Run() {
}
wg.Wait()
}
global.LOG.Info("website cron job end")
global.LOG.Info("website cron job end...")
}
func stopWebsite(websiteId uint, wg *sync.WaitGroup) {

View File

@ -34,4 +34,5 @@ ErrAppDelete: 'Other Website use this App'
#ssl
ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed"
ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted"
ErrAccountCannotDelete: "The certificate associated with the account cannot be deleted"
ErrSSLApply: "The certificate continues to be signed successfully, but openresty reload fails, please check the configuration"

View File

@ -33,4 +33,5 @@ ErrAppDelete: '其他网站使用此应用,不能删除'
#ssl
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"
ErrAccountCannotDelete: "账号关联证书,无法删除"
ErrAccountCannotDelete: "账号关联证书,无法删除"
ErrSSLApply: "证书续签成功openresty reload失败请检查配置"

View File

@ -12,6 +12,7 @@ export namespace Website {
webSiteGroupId: number;
otherDomains: string;
defaultServer: boolean;
autoRenew: boolean;
appinstall?: NewAppInstall;
webSiteSSL: SSL;
}

View File

@ -999,6 +999,9 @@ export default {
startDate: '生效时间',
organization: '签发机构',
renewConfirm: '是否确定续签',
autoRenew: '自动续签',
autoRenewHelper: '距离到期时间7天自动续签',
renewSuccess: '续签成功',
},
firewall: {
ccDeny: 'CC 防护',

View File

@ -4,7 +4,7 @@
:title="$t('commons.button.create')"
:destroy-on-close="true"
:close-on-click-modal="false"
width="60%"
width="50%"
:before-close="handleClose"
>
<el-form
@ -66,6 +66,9 @@
</el-descriptions>
</div>
</el-form-item>
<el-form-item :label="$t('ssl.autoRenew')" prop="autoRenew" v-if="ssl.provider !== 'dnsManual'">
<el-checkbox v-model="ssl.autoRenew" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
@ -115,6 +118,7 @@ let rules = ref({
acmeAccountId: [Rules.requiredSelectBusiness],
dnsAccountId: [Rules.requiredSelectBusiness],
provider: [Rules.requiredInput],
autoRenew: [Rules.requiredInput],
});
let ssl = ref({
primaryDomain: '',
@ -123,6 +127,7 @@ let ssl = ref({
websiteId: 0,
acmeAccountId: undefined,
dnsAccountId: undefined,
autoRenew: false,
});
let dnsResolve = ref<Website.DNSResolve[]>([]);
let hasResolve = ref(false);
@ -143,6 +148,7 @@ const resetForm = () => {
websiteId: 0,
acmeAccountId: undefined,
dnsAccountId: undefined,
autoRenew: false,
};
};

View File

@ -49,7 +49,7 @@ const submit = () => {
RenewSSL(renewReq)
.then(() => {
handleClose();
ElMessage.success(i18n.global.t('commons.msg.renewSuccess'));
ElMessage.success(i18n.global.t('ssl.renewSuccess'));
})
.finally(() => {
loading.value = false;