feat(certificate): add certificate type detection and update logic in AddCert and ModifyCert functions

This commit is contained in:
Jacky 2025-04-06 01:08:14 +00:00
parent 440982fc76
commit 771859d3b8
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
6 changed files with 125 additions and 13 deletions

View file

@ -131,6 +131,31 @@ func AddCert(c *gin.Context) {
return
}
// Detect and set certificate type
if len(json.SSLCertificate) > 0 {
keyType, err := cert.GetKeyType(json.SSLCertificate)
if err == nil && keyType != "" {
// Set KeyType based on certificate type
switch keyType {
case "2048":
certModel.KeyType = certcrypto.RSA2048
case "3072":
certModel.KeyType = certcrypto.RSA3072
case "4096":
certModel.KeyType = certcrypto.RSA4096
case "P256":
certModel.KeyType = certcrypto.EC256
case "P384":
certModel.KeyType = certcrypto.EC384
}
// Update certificate model
err = certModel.Updates(&model.Cert{KeyType: certModel.KeyType})
if err != nil {
notification.Error("Update Certificate Type Error", err.Error(), nil)
}
}
}
err = cert.SyncToRemoteServer(certModel)
if err != nil {
notification.Error("Sync Certificate Error", err.Error(), nil)
@ -157,7 +182,8 @@ func ModifyCert(c *gin.Context) {
return
}
err = certModel.Updates(&model.Cert{
// Create update data object
updateData := &model.Cert{
Name: json.Name,
SSLCertificatePath: json.SSLCertificatePath,
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
@ -166,11 +192,6 @@ func ModifyCert(c *gin.Context) {
DnsCredentialID: json.DnsCredentialID,
ACMEUserID: json.ACMEUserID,
SyncNodeIds: json.SyncNodeIds,
})
if err != nil {
cosy.ErrHandler(c, err)
return
}
content := &cert.Content{
@ -186,6 +207,32 @@ func ModifyCert(c *gin.Context) {
return
}
// Detect and set certificate type
if len(json.SSLCertificate) > 0 {
keyType, err := cert.GetKeyType(json.SSLCertificate)
if err == nil && keyType != "" {
// Set KeyType based on certificate type
switch keyType {
case "2048":
updateData.KeyType = certcrypto.RSA2048
case "3072":
updateData.KeyType = certcrypto.RSA3072
case "4096":
updateData.KeyType = certcrypto.RSA4096
case "P256":
updateData.KeyType = certcrypto.EC256
case "P384":
updateData.KeyType = certcrypto.EC384
}
}
}
err = certModel.Updates(updateData)
if err != nil {
cosy.ErrHandler(c, err)
return
}
err = cert.SyncToRemoteServer(certModel)
if err != nil {
notification.Error("Sync Certificate Error", err.Error(), nil)

View file

@ -33,27 +33,24 @@ const columns: Column[] = [{
if (text === true || text === 1) {
template.push(
<Tag bordered={false} color="processing">
{ managed }
{managed}
</Tag>,
)
}
else if (text === 2) {
template.push(
<Tag bordered={false} color="success">
{ sync }
{sync}
</Tag>,
)
}
else {
template.push(
<Tag bordered={false} color="purple">
{
general
}
{general}
</Tag>,
)
}
return h('div', template)
},
sorter: true,

View file

@ -164,7 +164,7 @@ function handleBatchUpdated() {
:get-params="{
env_group_id: envGroupId,
}"
:scroll-x="1200"
:scroll-x="1600"
@click-edit="(r: string) => router.push({
path: `/sites/${r}`,
})"

View file

@ -24,6 +24,7 @@ const columns: Column[] = [{
type: input,
},
search: true,
width: 150,
}, {
title: () => $gettext('Node Group'),
dataIndex: 'env_group_id',

View file

@ -10,4 +10,5 @@ var (
ErrCertParse = e.New(50004, "certificate parse error")
ErrPayloadResourceIsNil = e.New(50005, "payload resource is nil")
ErrPathIsNotUnderTheNginxConfDir = e.New(50006, "path: {0} is not under the nginx conf dir: {1}")
ErrCertPathIsEmpty = e.New(50007, "certificate path is empty")
)

View file

@ -1,6 +1,8 @@
package cert
import (
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
@ -79,3 +81,67 @@ func IsPrivateKeyPath(path string) bool {
return IsPrivateKey(string(bytes))
}
// GetKeyType determines the key type from a PEM certificate string.
// Returns "2048", "3072", "4096", "P256", "P384" or empty string.
func GetKeyType(pemStr string) (string, error) {
block, _ := pem.Decode([]byte(pemStr))
if block == nil {
return "", ErrCertDecode
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return "", ErrCertParse
}
switch cert.PublicKeyAlgorithm {
case x509.RSA:
rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
if !ok {
return "", nil
}
keySize := rsaKey.Size() * 8 // Size returns size in bytes, convert to bits
switch keySize {
case 2048:
return "2048", nil
case 3072:
return "3072", nil
case 4096:
return "4096", nil
default:
return "", nil
}
case x509.ECDSA:
ecKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
if !ok {
return "", nil
}
curve := ecKey.Curve.Params().Name
switch curve {
case "P-256":
return "P256", nil
case "P-384":
return "P384", nil
default:
return "", nil
}
default:
return "", nil
}
}
// GetKeyTypeFromPath determines the key type from a certificate file.
// Returns "2048", "3072", "4096", "P256", "P384" or empty string.
func GetKeyTypeFromPath(path string) (string, error) {
if path == "" {
return "", ErrCertPathIsEmpty
}
bytes, err := os.ReadFile(path)
if err != nil {
return "", err
}
return GetKeyType(string(bytes))
}