mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-28 05:01:48 +08:00
feat: 增加自动续签设置
This commit is contained in:
parent
c7529469f8
commit
75756e8bb7
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -66,4 +66,5 @@ var (
|
||||
var (
|
||||
ErrSSLCannotDelete = "ErrSSLCannotDelete"
|
||||
ErrAccountCannotDelete = "ErrAccountCannotDelete"
|
||||
ErrSSLApply = "ErrSSLApply"
|
||||
)
|
||||
|
@ -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
36
backend/cron/job/ssl.go
Normal 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...")
|
||||
}
|
@ -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) {
|
||||
|
@ -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!"
|
@ -33,4 +33,5 @@ ErrAppDelete: '其他网站使用此应用,不能删除'
|
||||
|
||||
#ssl
|
||||
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"
|
||||
ErrAccountCannotDelete: "账号关联证书,无法删除"
|
||||
ErrAccountCannotDelete: "账号关联证书,无法删除"
|
||||
ErrSSLApply: "证书续签成功,openresty reload失败,请检查配置!"
|
@ -12,6 +12,7 @@ export namespace Website {
|
||||
webSiteGroupId: number;
|
||||
otherDomains: string;
|
||||
defaultServer: boolean;
|
||||
autoRenew: boolean;
|
||||
appinstall?: NewAppInstall;
|
||||
webSiteSSL: SSL;
|
||||
}
|
||||
|
@ -999,6 +999,9 @@ export default {
|
||||
startDate: '生效时间',
|
||||
organization: '签发机构',
|
||||
renewConfirm: '是否确定续签?',
|
||||
autoRenew: '自动续签',
|
||||
autoRenewHelper: '距离到期时间7天自动续签',
|
||||
renewSuccess: '续签成功',
|
||||
},
|
||||
firewall: {
|
||||
ccDeny: 'CC 防护',
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user