feat: 手动创建证书增加更新功能 (#3087)

Refs https://github.com/1Panel-dev/1Panel/issues/2329
pull/3090/head
zhengkunwang 2023-11-28 15:42:10 +08:00 committed by GitHub
parent 73b2804d68
commit 59c216c184
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 33 deletions

View File

@ -63,8 +63,12 @@ type WebsiteBatchDelReq struct {
}
type WebsiteSSLUpdate struct {
ID uint `json:"id" validate:"required"`
AutoRenew bool `json:"autoRenew"`
ID uint `json:"id" validate:"required"`
AutoRenew bool `json:"autoRenew"`
Description string `json:"description"`
PrivateKey string `json:"privateKey"`
Certificate string `json:"certificate"`
Type string `json:"type" validate:"required,oneof=autoRenew description certificate privateKey"`
}
type WebsiteSSLUpload struct {
@ -73,6 +77,7 @@ type WebsiteSSLUpload struct {
PrivateKeyPath string `json:"privateKeyPath"`
CertificatePath string `json:"certificatePath"`
Type string `json:"type" validate:"required,oneof=paste local"`
SSLID uint `json:"sslID"`
}
type WebsiteCASearch struct {

View File

@ -28,6 +28,7 @@ type WebsiteSSL struct {
KeyType string `gorm:"not null;default:2048" json:"keyType"`
PushDir bool `gorm:"not null;default:0" json:"pushDir"`
Dir string `json:"dir"`
Description string `json:"description"`
AcmeAccount WebsiteAcmeAccount `json:"acmeAccount" gorm:"-:migration"`
DnsAccount WebsiteDnsAccount `json:"dnsAccount" gorm:"-:migration"`

View File

@ -345,10 +345,16 @@ func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error {
}
func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
newSSL := &model.WebsiteSSL{
websiteSSL := &model.WebsiteSSL{
Provider: constant.Manual,
}
var err error
if req.SSLID > 0 {
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID))
if err != nil {
return err
}
}
if req.Type == "local" {
fileOp := files.NewFileOp()
if !fileOp.Stat(req.PrivateKeyPath) {
@ -360,24 +366,24 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
return err
} else {
newSSL.PrivateKey = string(content)
websiteSSL.PrivateKey = string(content)
}
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
return err
} else {
newSSL.Pem = string(content)
websiteSSL.Pem = string(content)
}
} else {
newSSL.PrivateKey = req.PrivateKey
newSSL.Pem = req.Certificate
websiteSSL.PrivateKey = req.PrivateKey
websiteSSL.Pem = req.Certificate
}
privateKeyCertBlock, _ := pem.Decode([]byte(newSSL.PrivateKey))
privateKeyCertBlock, _ := pem.Decode([]byte(websiteSSL.PrivateKey))
if privateKeyCertBlock == nil {
return buserr.New("ErrSSLKeyFormat")
}
certBlock, _ := pem.Decode([]byte(newSSL.Pem))
certBlock, _ := pem.Decode([]byte(websiteSSL.Pem))
if certBlock == nil {
return buserr.New("ErrSSLCertificateFormat")
}
@ -385,23 +391,23 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
if err != nil {
return err
}
newSSL.ExpireDate = cert.NotAfter
newSSL.StartDate = cert.NotBefore
newSSL.Type = cert.Issuer.CommonName
websiteSSL.ExpireDate = cert.NotAfter
websiteSSL.StartDate = cert.NotBefore
websiteSSL.Type = cert.Issuer.CommonName
if len(cert.Issuer.Organization) > 0 {
newSSL.Organization = cert.Issuer.Organization[0]
websiteSSL.Organization = cert.Issuer.Organization[0]
} else {
newSSL.Organization = cert.Issuer.CommonName
websiteSSL.Organization = cert.Issuer.CommonName
}
var domains []string
if len(cert.DNSNames) > 0 {
newSSL.PrimaryDomain = cert.DNSNames[0]
websiteSSL.PrimaryDomain = cert.DNSNames[0]
domains = cert.DNSNames[1:]
}
if len(cert.IPAddresses) > 0 {
if newSSL.PrimaryDomain == "" {
newSSL.PrimaryDomain = cert.IPAddresses[0].String()
if websiteSSL.PrimaryDomain == "" {
websiteSSL.PrimaryDomain = cert.IPAddresses[0].String()
for _, ip := range cert.IPAddresses[1:] {
domains = append(domains, ip.String())
}
@ -411,9 +417,12 @@ func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error {
}
}
}
newSSL.Domains = strings.Join(domains, ",")
websiteSSL.Domains = strings.Join(domains, ",")
return websiteSSLRepo.Create(context.Background(), newSSL)
if websiteSSL.ID > 0 {
return websiteSSLRepo.Save(websiteSSL)
}
return websiteSSLRepo.Create(context.Background(), websiteSSL)
}
func (w WebsiteSSLService) SyncForRestart() error {

View File

@ -27,7 +27,7 @@ var AddWebsiteCA = &gormigrate.Migration{
}
var UpdateWebsiteSSL = &gormigrate.Migration{
ID: "20231127-update-website-ssl",
ID: "20231128-update-website-ssl",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.WebsiteSSL{}); err != nil {
return err

View File

@ -451,6 +451,7 @@ export namespace Website {
privateKeyPath: string;
certificatePath: string;
type: string;
sslID: number;
}
export interface SSLObtain {

View File

@ -53,7 +53,7 @@
</el-descriptions>
</div>
<div v-else-if="curr === 'ssl'">
<el-input v-model="ssl.pem" :autosize="{ minRows: 10, maxRows: 15 }" type="textarea" id="textArea" />
<el-input v-model="ssl.pem" :autosize="{ minRows: 15, maxRows: 30 }" type="textarea" id="textArea" />
<div>
<br />
<el-button type="primary" @click="copyText(ssl.pem)">{{ $t('file.copy') }}</el-button>
@ -62,7 +62,7 @@
<div v-else>
<el-input
v-model="ssl.privateKey"
:autosize="{ minRows: 10, maxRows: 15 }"
:autosize="{ minRows: 15, maxRows: 30 }"
type="textarea"
id="textArea"
/>

View File

@ -83,11 +83,13 @@
placement="bottom"
:width="400"
trigger="hover"
:content="row.message"
>
<template #reference>
<Status :key="row.status" :status="row.status"></Status>
</template>
<div class="max-h-96 overflow-auto">
<span>{{ row.message }}</span>
</div>
</el-popover>
<div v-else>
<Status :key="row.status" :status="row.status"></Status>
@ -214,6 +216,18 @@ const buttons = [
applySSL(row);
}
},
show: function (row: Website.SSLDTO) {
return row.provider != 'manual';
},
},
{
label: i18n.global.t('commons.operate.update'),
click: function (row: Website.SSLDTO) {
sslUploadRef.value.acceptParams(row.id);
},
show: function (row: Website.SSLDTO) {
return row.provider == 'manual';
},
},
{
label: i18n.global.t('commons.button.delete'),

View File

@ -70,13 +70,15 @@ const rules = ref({
certificatePath: [Rules.requiredInput],
type: [Rules.requiredSelect],
});
const ssl = ref({
const initData = () => ({
privateKey: '',
certificate: '',
privateKeyPath: '',
certificatePath: '',
type: 'paste',
sslID: 0,
});
const ssl = ref(initData());
const em = defineEmits(['close']);
const handleClose = () => {
@ -86,17 +88,14 @@ const handleClose = () => {
};
const resetForm = () => {
sslForm.value?.resetFields();
ssl.value = {
privateKey: '',
certificate: '',
privateKeyPath: '',
certificatePath: '',
type: 'paste',
};
ssl.value = initData();
};
const acceptParams = () => {
const acceptParams = (id: number) => {
resetForm();
if (id && id > 0) {
ssl.value.sslID = id;
}
open.value = true;
};