mirror of https://github.com/1Panel-dev/1Panel
feat: 网站增加手动导入证书
parent
74b28cbf23
commit
3ccac92df6
|
@ -84,8 +84,10 @@ const (
|
|||
)
|
||||
|
||||
type WebsiteHTTPSOp struct {
|
||||
WebsiteID uint `json:"websiteId"`
|
||||
Enable bool `json:"enable"`
|
||||
WebsiteID uint `json:"websiteId" validate:"required"`
|
||||
Enable bool `json:"enable" validate:"required"`
|
||||
WebsiteSSLID uint `json:"websiteSSLId"`
|
||||
Type SSlType `json:"type"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Certificate string `json:"certificate"`
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ const (
|
|||
DNSAccount = "dnsAccount"
|
||||
DnsManual = "dnsManual"
|
||||
Http = "http"
|
||||
Manual = "manual"
|
||||
)
|
||||
|
||||
type WebsiteSSLSearch struct {
|
||||
|
|
|
@ -2,6 +2,8 @@ package service
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
|
@ -304,29 +306,80 @@ func (w WebsiteService) OpWebsiteHTTPS(req dto.WebsiteHTTPSOp) (dto.WebsiteHTTPS
|
|||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
|
||||
var res dto.WebsiteHTTPS
|
||||
var (
|
||||
res dto.WebsiteHTTPS
|
||||
websiteSSL model.WebSiteSSL
|
||||
)
|
||||
res.Enable = req.Enable
|
||||
ssl, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(req.WebsiteSSLID))
|
||||
if err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
|
||||
if req.Type == dto.SSLExisted {
|
||||
website.WebSiteSSLID = ssl.ID
|
||||
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.WebsiteSSLID))
|
||||
if err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
website.WebSiteSSLID = websiteSSL.ID
|
||||
if err := websiteRepo.Save(context.TODO(), &website); err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
res.SSL = ssl
|
||||
res.SSL = websiteSSL
|
||||
}
|
||||
|
||||
if req.Type == dto.Manual {
|
||||
certBlock, _ := pem.Decode([]byte(req.Certificate))
|
||||
cert, err := x509.ParseCertificate(certBlock.Bytes)
|
||||
if err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
websiteSSL.ExpireDate = cert.NotAfter
|
||||
websiteSSL.StartDate = cert.NotBefore
|
||||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
websiteSSL.Organization = cert.Issuer.Organization[0]
|
||||
websiteSSL.PrimaryDomain = cert.Subject.CommonName
|
||||
if len(cert.Subject.Names) > 0 {
|
||||
var domains []string
|
||||
for _, name := range cert.Subject.Names {
|
||||
if v, ok := name.Value.(string); ok {
|
||||
if v != cert.Subject.CommonName {
|
||||
domains = append(domains, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(domains) > 0 {
|
||||
websiteSSL.Domains = strings.Join(domains, "")
|
||||
}
|
||||
}
|
||||
|
||||
websiteSSL.Provider = dto.Manual
|
||||
websiteSSL.PrivateKey = req.PrivateKey
|
||||
websiteSSL.Pem = req.Certificate
|
||||
|
||||
res.SSL = websiteSSL
|
||||
}
|
||||
|
||||
if req.Enable {
|
||||
website.Protocol = constant.ProtocolHTTPS
|
||||
if err := applySSL(website, ssl); err != nil {
|
||||
if err := applySSL(website, websiteSSL); err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
} else {
|
||||
website.Protocol = constant.ProtocolHTTP
|
||||
website.WebSiteSSLID = 0
|
||||
if err := deleteNginxConfig(website, getKeysFromStaticFile(dto.SSL)); err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
}
|
||||
|
||||
tx, ctx := getTxAndContext()
|
||||
if websiteSSL.ID == 0 {
|
||||
if err := websiteSSLRepo.Create(ctx, &websiteSSL); err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
website.WebSiteSSLID = websiteSSL.ID
|
||||
}
|
||||
if err := websiteRepo.Save(ctx, &website); err != nil {
|
||||
return dto.WebsiteHTTPS{}, err
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -59,25 +59,20 @@ func (w WebSiteSSLService) Create(create dto.WebsiteSSLCreate) (dto.WebsiteSSLCr
|
|||
switch create.Provider {
|
||||
case dto.DNSAccount:
|
||||
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID))
|
||||
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
if err := client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization); err != nil {
|
||||
return res, err
|
||||
}
|
||||
case dto.Http:
|
||||
|
||||
appInstall, err := getAppInstallByKey("nginx")
|
||||
if err != nil {
|
||||
return dto.WebsiteSSLCreate{}, err
|
||||
}
|
||||
|
||||
if err := client.UseHTTP(path.Join(constant.AppInstallDir, "nginx", appInstall.Name, "root")); err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
case dto.DnsManual:
|
||||
|
||||
}
|
||||
|
@ -110,10 +105,6 @@ func (w WebSiteSSLService) Create(create dto.WebsiteSSLCreate) (dto.WebsiteSSLCr
|
|||
websiteSSL.Type = cert.Issuer.CommonName
|
||||
websiteSSL.Organization = cert.Issuer.Organization[0]
|
||||
|
||||
//if err := createPemFile(websiteSSL); err != nil {
|
||||
// return dto.WebsiteSSLCreate{}, err
|
||||
//}
|
||||
|
||||
if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
@ -146,6 +137,13 @@ func (w WebSiteSSLService) Renew(sslId uint) error {
|
|||
return err
|
||||
}
|
||||
case dto.Http:
|
||||
appInstall, err := getAppInstallByKey("nginx")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.UseHTTP(path.Join(constant.AppInstallDir, "nginx", appInstall.Name, "root")); err != nil {
|
||||
return err
|
||||
}
|
||||
case dto.DnsManual:
|
||||
|
||||
}
|
||||
|
|
|
@ -326,6 +326,19 @@ func getNginxParamsFromStaticFile(scope dto.NginxKey) []dto.NginxParam {
|
|||
return nginxParams
|
||||
}
|
||||
|
||||
func getKeysFromStaticFile(scope dto.NginxKey) []string {
|
||||
var res []string
|
||||
newConfig := &components.Config{}
|
||||
switch scope {
|
||||
case dto.SSL:
|
||||
newConfig = parser.NewStringParser(string(nginx_conf.SSL)).Parse()
|
||||
}
|
||||
for _, dir := range newConfig.GetDirectives() {
|
||||
res = append(res, dir.GetName())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func deleteNginxConfig(website model.WebSite, keys []string) error {
|
||||
nginxConfig, err := getNginxConfig(website.Alias)
|
||||
if err != nil {
|
||||
|
@ -385,6 +398,17 @@ func createPemFile(website model.WebSite, websiteSSL model.WebSiteSSL) error {
|
|||
|
||||
func applySSL(website model.WebSite, websiteSSL model.WebSiteSSL) error {
|
||||
|
||||
nginxConfig, err := getNginxConfig(website.Alias)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
config := nginxConfig.Config
|
||||
server := config.FindServers()[0]
|
||||
server.UpdateListen("443", false)
|
||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := createPemFile(website, websiteSSL); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -172,8 +172,10 @@ export namespace WebSite {
|
|||
export interface HTTPSReq {
|
||||
websiteId: number;
|
||||
enable: boolean;
|
||||
websiteSSLId: number;
|
||||
websiteSSLId?: number;
|
||||
type: string;
|
||||
certificate?: string;
|
||||
privateKey?: string;
|
||||
}
|
||||
|
||||
export interface HTTPSConfig {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-col :span="10" :offset="2">
|
||||
<el-form
|
||||
ref="httpsForm"
|
||||
label-position="left"
|
||||
|
@ -18,7 +18,7 @@
|
|||
<el-select v-model="form.type" @change="changeType()">
|
||||
<el-option :label="'选择已有证书'" :value="'existed'"></el-option>
|
||||
<el-option :label="'手动导入证书'" :value="'manual'"></el-option>
|
||||
<el-option :label="'自动生成证书'" :value="'auto'"></el-option>
|
||||
<!-- <el-option :label="'自动生成证书'" :value="'auto'"></el-option> -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="' '" prop="websiteSSLId" v-if="form.type === 'existed'">
|
||||
|
@ -35,6 +35,14 @@
|
|||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-if="form.type === 'manual'">
|
||||
<el-form-item :label="'密钥代码(pem格式)'" prop="privateKey">
|
||||
<el-input v-model="form.privateKey" :rows="6" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'证书代码(pem格式)'" prop="certificate">
|
||||
<el-input v-model="form.certificate" :rows="6" type="textarea" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item :label="' '" v-if="websiteSSL && websiteSSL.id > 0">
|
||||
<el-descriptions :column="3" border direction="vertical">
|
||||
<el-descriptions-item label="主域名">{{ websiteSSL.primaryDomain }}</el-descriptions-item>
|
||||
|
@ -77,12 +85,16 @@ let form = reactive({
|
|||
websiteId: id.value,
|
||||
websiteSSLId: undefined,
|
||||
type: 'existed',
|
||||
privateKey: '',
|
||||
certificate: '',
|
||||
});
|
||||
let loading = ref(false);
|
||||
const ssls = ref();
|
||||
let websiteSSL = ref();
|
||||
let rules = ref({
|
||||
type: [Rules.requiredSelect],
|
||||
privateKey: [Rules.requiredInput],
|
||||
certificate: [Rules.requiredInput],
|
||||
});
|
||||
|
||||
const listSSL = () => {
|
||||
|
|
Loading…
Reference in New Issue