Skip to content

Commit 7a6e537

Browse files
feat(system): Fix issue with certificate failure in settings panel (#8063)
1 parent 6092e76 commit 7a6e537

File tree

10 files changed

+173
-11
lines changed

10 files changed

+173
-11
lines changed

agent/app/api/v2/website_ca.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ func (b *BaseApi) ObtainWebsiteCA(c *gin.Context) {
113113
if err := helper.CheckBindAndValidate(&req, c); err != nil {
114114
return
115115
}
116-
if _, err := websiteCAService.ObtainSSL(req); err != nil {
116+
res, err := websiteCAService.ObtainSSL(req)
117+
if err != nil {
117118
helper.InternalServer(c, err)
118119
return
119120
}
120-
helper.SuccessWithOutData(c)
121+
helper.SuccessWithData(c, res)
121122
}
122123

123124
// @Tags Website CA

core/app/model/agent.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package model
2+
3+
import (
4+
"time"
5+
)
6+
7+
type WebsiteSSL struct {
8+
BaseModel
9+
PrimaryDomain string `json:"primaryDomain"`
10+
PrivateKey string `json:"privateKey"`
11+
Pem string `json:"pem"`
12+
Domains string `json:"domains"`
13+
CertURL string `json:"certURL"`
14+
Type string `json:"type"`
15+
Provider string `json:"provider"`
16+
Organization string `json:"organization"`
17+
DnsAccountID uint `json:"dnsAccountId"`
18+
AcmeAccountID uint `gorm:"column:acme_account_id" json:"acmeAccountId" `
19+
CaID uint `json:"caId"`
20+
AutoRenew bool `json:"autoRenew"`
21+
ExpireDate time.Time `json:"expireDate"`
22+
StartDate time.Time `json:"startDate"`
23+
Status string `json:"status"`
24+
Message string `json:"message"`
25+
KeyType string `json:"keyType"`
26+
PushDir bool `json:"pushDir"`
27+
Dir string `json:"dir"`
28+
Description string `json:"description"`
29+
SkipDNS bool `json:"skipDNS"`
30+
Nameserver1 string `json:"nameserver1"`
31+
Nameserver2 string `json:"nameserver2"`
32+
DisableCNAME bool `json:"disableCNAME"`
33+
ExecShell bool `json:"execShell"`
34+
Shell string `json:"shell"`
35+
}
36+
37+
func (w WebsiteSSL) TableName() string {
38+
return "website_ssls"
39+
}
40+
41+
type WebsiteCA struct {
42+
BaseModel
43+
CSR string `gorm:"not null;" json:"csr"`
44+
Name string `gorm:"not null;" json:"name"`
45+
PrivateKey string `gorm:"not null" json:"privateKey"`
46+
KeyType string `gorm:"not null;default:2048" json:"keyType"`
47+
}

core/app/repo/agent.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package repo
2+
3+
import (
4+
"github.com/1Panel-dev/1Panel/core/app/model"
5+
"github.com/1Panel-dev/1Panel/core/global"
6+
)
7+
8+
type AgentRepo struct{}
9+
10+
type IAgentRepo interface {
11+
GetWebsiteSSL(opts ...global.DBOption) (model.WebsiteSSL, error)
12+
GetCA(opts ...global.DBOption) (model.WebsiteCA, error)
13+
}
14+
15+
func NewIAgentRepo() IAgentRepo {
16+
return &AgentRepo{}
17+
}
18+
19+
func (a *AgentRepo) GetWebsiteSSL(opts ...global.DBOption) (model.WebsiteSSL, error) {
20+
var ssl model.WebsiteSSL
21+
db := global.AgentDB
22+
for _, opt := range opts {
23+
db = opt(db)
24+
}
25+
err := db.First(&ssl).Error
26+
return ssl, err
27+
}
28+
29+
func (a *AgentRepo) GetCA(opts ...global.DBOption) (model.WebsiteCA, error) {
30+
var ca model.WebsiteCA
31+
db := global.AgentDB
32+
for _, opt := range opts {
33+
db = opt(db)
34+
}
35+
err := db.First(&ca).Error
36+
return ca, err
37+
}

core/app/service/entry.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ var (
1313
upgradeLogRepo = repo.NewIUpgradeLogRepo()
1414

1515
taskRepo = repo.NewITaskRepo()
16+
17+
agentRepo = repo.NewIAgentRepo()
1618
)

core/app/service/setting.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package service
22

33
import (
4+
"bytes"
45
"crypto/rand"
56
"crypto/rsa"
67
"crypto/tls"
78
"crypto/x509"
89
"encoding/json"
910
"encoding/pem"
1011
"fmt"
12+
"github.com/1Panel-dev/1Panel/core/app/model"
13+
"github.com/1Panel-dev/1Panel/core/utils/req_helper"
1114
"net"
15+
"net/http"
1216
"os"
1317
"path"
1418
"strconv"
@@ -265,6 +269,48 @@ func (u *SettingService) UpdateSSL(c *gin.Context, req dto.SSLUpdate) error {
265269
return err
266270
}
267271
secret = string(certFile)
272+
case "select":
273+
ssl, err := agentRepo.GetWebsiteSSL(repo.WithByID(req.SSLID))
274+
if err != nil {
275+
return err
276+
}
277+
secret = ssl.Pem
278+
key = ssl.PrivateKey
279+
if err := settingRepo.Update("SSLID", strconv.Itoa(int(req.SSLID))); err != nil {
280+
return err
281+
}
282+
case "self":
283+
ca, err := agentRepo.GetCA(repo.WithByName("1Panel"))
284+
if err != nil {
285+
return err
286+
}
287+
params := make(map[string]interface{})
288+
params["domains"] = req.Domain
289+
params["time"] = 10
290+
params["unit"] = "year"
291+
params["keyType"] = "P256"
292+
params["id"] = ca.ID
293+
jsonData, err := json.Marshal(params)
294+
if err != nil {
295+
return err
296+
}
297+
res, err := req_helper.NewLocalClient("/api/v2/websites/ca/obtain", http.MethodPost, bytes.NewReader(jsonData))
298+
if err != nil {
299+
return err
300+
}
301+
jsonBytes, err := json.Marshal(res)
302+
if err != nil {
303+
return err
304+
}
305+
var ssl model.WebsiteSSL
306+
if err := json.Unmarshal(jsonBytes, &ssl); err != nil {
307+
return err
308+
}
309+
secret = ssl.Pem
310+
key = ssl.PrivateKey
311+
if err := settingRepo.Update("SSLID", strconv.Itoa(int(ssl.ID))); err != nil {
312+
return err
313+
}
268314
}
269315

270316
if err := os.WriteFile(path.Join(secretDir, "server.crt.tmp"), []byte(secret), 0600); err != nil {
@@ -325,7 +371,18 @@ func (u *SettingService) LoadFromCert() (*dto.SSLInfo, error) {
325371
keyFile, _ := os.ReadFile(path.Join(global.CONF.Base.InstallDir, "1panel/secret/server.key"))
326372
data.Key = string(keyFile)
327373
case "select":
328-
// TODO select ssl from website
374+
sslID, err := settingRepo.Get(repo.WithByKey("SSLID"))
375+
if err != nil {
376+
return nil, err
377+
}
378+
id, _ := strconv.Atoi(sslID.Value)
379+
ssl, err := agentRepo.GetWebsiteSSL(repo.WithByID(uint(id)))
380+
if err != nil {
381+
return nil, err
382+
}
383+
data.Domain = ssl.PrimaryDomain
384+
data.SSLID = uint(id)
385+
data.Timeout = ssl.ExpireDate.Format(constant.DateTimeLayout)
329386
}
330387
return &data, nil
331388
}

core/global/global.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
var (
1414
DB *gorm.DB
1515
TaskDB *gorm.DB
16+
AgentDB *gorm.DB
1617
LOG *logrus.Logger
1718
CONF ServerConfig
1819
Api ApiInterface

core/init/db/db.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ import (
1010
func Init() {
1111
global.DB = common.LoadDBConnByPath(path.Join(global.CONF.Base.InstallDir, "1panel/db/core.db"), "core")
1212
global.TaskDB = common.LoadDBConnByPath(path.Join(global.CONF.Base.InstallDir, "1panel/db/task.db"), "task")
13+
global.AgentDB = common.LoadDBConnByPath(path.Join(global.CONF.Base.InstallDir, "1panel/db/agent.db"), "agent")
1314
}

frontend/src/api/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ class RequestHttp {
2727
'Accept-Language': language,
2828
...config.headers,
2929
};
30-
config.headers.CurrentNode = globalStore.currentNode;
30+
if (config.headers.CurrentNode == undefined) {
31+
config.headers.CurrentNode = globalStore.currentNode;
32+
}
3133
if (config.url === '/core/auth/login' || config.url === '/core/auth/mfalogin') {
3234
let entrance = Base64.encode(globalStore.entrance);
3335
config.headers.EntranceCode = entrance;
@@ -125,6 +127,16 @@ class RequestHttp {
125127
withCredentials: true,
126128
});
127129
}
130+
postLocalNode<T>(url: string, params?: object, timeout?: number): Promise<ResultData<T>> {
131+
return this.service.post(url, params, {
132+
baseURL: import.meta.env.VITE_API_URL as string,
133+
timeout: timeout ? timeout : (ResultEnum.TIMEOUT as number),
134+
withCredentials: true,
135+
headers: {
136+
CurrentNode: 'local',
137+
},
138+
});
139+
}
128140
put<T>(url: string, params?: object, _object = {}): Promise<ResultData<T>> {
129141
return this.service.put(url, params, _object);
130142
}

frontend/src/api/modules/website.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ export const listSSL = (req: Website.SSLReq) => {
110110
return http.post<Website.SSLDTO[]>(`/websites/ssl/search`, req);
111111
};
112112

113+
export const listLocalNodeSSL = (req: Website.SSLReq) => {
114+
return http.postLocalNode<Website.SSLDTO[]>(`/websites/ssl/search`, req);
115+
};
116+
113117
export const createSSL = (req: Website.SSLCreate) => {
114118
return http.post<Website.SSLCreate>(`/websites/ssl`, req, TimeoutEnum.T_10M);
115119
};

frontend/src/views/setting/safe/ssl/index.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727

2828
<el-form-item v-if="form.timeout">
2929
<el-tag>{{ $t('setting.domainOrIP') }} {{ form.domain }}</el-tag>
30-
<el-tag style="margin-left: 5px">{{ $t('setting.timeOut') }} {{ form.timeout }}</el-tag>
30+
<el-tag class="p-ml-5">{{ $t('setting.timeOut') }} {{ form.timeout }}</el-tag>
3131
<el-button
3232
@click="onDownload"
33-
style="margin-left: 5px"
33+
class="p-ml-5"
3434
v-if="form.sslType === 'self'"
3535
type="primary"
3636
link
@@ -116,7 +116,7 @@
116116
<script lang="ts" setup>
117117
import { Website } from '@/api/interface/website';
118118
import { dateFormatSimple, getProvider } from '@/utils/util';
119-
import { listSSL } from '@/api/modules/website';
119+
import { listLocalNodeSSL } from '@/api/modules/website';
120120
import { reactive, ref } from 'vue';
121121
import i18n from '@/lang';
122122
import { MsgSuccess } from '@/utils/message';
@@ -131,7 +131,7 @@ const loading = ref();
131131
const drawerVisible = ref();
132132
133133
const form = reactive({
134-
ssl: 'enable',
134+
ssl: 'Enable',
135135
domain: '',
136136
sslType: 'self',
137137
itemSSLType: 'paste',
@@ -172,7 +172,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
172172
173173
if (params.sslInfo?.sslID) {
174174
form.sslID = params.sslInfo.sslID;
175-
const ssls = await listSSL({});
175+
const ssls = await listLocalNodeSSL({});
176176
sslList.value = ssls.data || [];
177177
changeSSl(params.sslInfo?.sslID);
178178
} else {
@@ -183,7 +183,7 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
183183
const emit = defineEmits<{ (e: 'search'): void }>();
184184
185185
const loadSSLs = async () => {
186-
const res = await listSSL({});
186+
const res = await listLocalNodeSSL({});
187187
sslList.value = res.data || [];
188188
};
189189
@@ -228,7 +228,7 @@ const onSaveSSL = async (formEl: FormInstance | undefined) => {
228228
itemType = form.itemSSLType === 'paste' ? 'import-paste' : 'import-local';
229229
}
230230
let param = {
231-
ssl: 'enable',
231+
ssl: 'Enable',
232232
sslType: itemType,
233233
domain: '',
234234
sslID: form.sslID,

0 commit comments

Comments
 (0)