Skip to content

Commit 22d62e4

Browse files
committed
feat: configurable cert key type #264
1 parent a095c88 commit 22d62e4

File tree

12 files changed

+115
-28
lines changed

12 files changed

+115
-28
lines changed

api/certificate/certificate.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/0xJacky/Nginx-UI/model"
88
"github.com/0xJacky/Nginx-UI/query"
99
"github.com/gin-gonic/gin"
10+
"github.com/go-acme/lego/v4/certcrypto"
1011
"github.com/spf13/cast"
1112
"net/http"
1213
"os"
@@ -76,13 +77,14 @@ func GetCert(c *gin.Context) {
7677
}
7778

7879
type certJson struct {
79-
Name string `json:"name" binding:"required"`
80-
SSLCertificatePath string `json:"ssl_certificate_path" binding:"required,certificate_path"`
81-
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required,privatekey_path"`
82-
SSLCertificate string `json:"ssl_certificate" binding:"omitempty,certificate"`
83-
SSLCertificateKey string `json:"ssl_certificate_key" binding:"omitempty,privatekey"`
84-
ChallengeMethod string `json:"challenge_method"`
85-
DnsCredentialID int `json:"dns_credential_id"`
80+
Name string `json:"name" binding:"required"`
81+
SSLCertificatePath string `json:"ssl_certificate_path" binding:"required,certificate_path"`
82+
SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required,privatekey_path"`
83+
SSLCertificate string `json:"ssl_certificate" binding:"omitempty,certificate"`
84+
SSLCertificateKey string `json:"ssl_certificate_key" binding:"omitempty,privatekey"`
85+
KeyType certcrypto.KeyType `json:"key_type" binding:"omitempty,auto_cert_key_type"`
86+
ChallengeMethod string `json:"challenge_method"`
87+
DnsCredentialID int `json:"dns_credential_id"`
8688
}
8789

8890
func AddCert(c *gin.Context) {
@@ -96,6 +98,7 @@ func AddCert(c *gin.Context) {
9698
Name: json.Name,
9799
SSLCertificatePath: json.SSLCertificatePath,
98100
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
101+
KeyType: json.KeyType,
99102
ChallengeMethod: json.ChallengeMethod,
100103
DnsCredentialID: json.DnsCredentialID,
101104
}
@@ -146,6 +149,7 @@ func ModifyCert(c *gin.Context) {
146149
SSLCertificatePath: json.SSLCertificatePath,
147150
SSLCertificateKeyPath: json.SSLCertificateKeyPath,
148151
ChallengeMethod: json.ChallengeMethod,
152+
KeyType: json.KeyType,
149153
DnsCredentialID: json.DnsCredentialID,
150154
})
151155

api/certificate/issue.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ func IssueCert(c *gin.Context) {
122122
SSLCertificatePath: sslCertificatePath,
123123
SSLCertificateKeyPath: sslCertificateKeyPath,
124124
AutoCert: model.AutoCertEnabled,
125+
KeyType: payload.KeyType,
125126
})
126127

127128
if err != nil {

app/src/api/cert.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface Cert extends ModelBase {
1414
challenge_method: string
1515
dns_credential_id: number
1616
dns_credential?: DnsCredential
17+
key_type: string
1718
log: string
1819
certificate_info: CertificateInfo
1920
}

app/src/views/certificate/RenewCert.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const data = inject('data') as Ref<Cert>
2121
const issueCert = () => {
2222
modalVisible.value = true
2323
24-
refObtainCertLive.value.issue_cert(data.value.name, data.value.domains).then(() => {
24+
refObtainCertLive.value.issue_cert(data.value.name, data.value.domains, data.value.key_type).then(() => {
2525
message.success($gettext('Renew successfully'))
2626
emit('renewed')
2727
})

app/src/views/certificate/WildcardCertificate.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ const issueCert = () => {
4444
step.value++
4545
modalVisible.value = true
4646
47-
refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value]).then(() => {
48-
message.success($gettext('Renew successfully'))
49-
emit('issued')
50-
})
47+
refObtainCertLive.value.issue_cert(computedDomain.value,
48+
[computedDomain.value, domain.value])
49+
.then(() => {
50+
message.success($gettext('Renew successfully'))
51+
emit('issued')
52+
})
5153
}
5254
</script>
5355

app/src/views/domain/cert/components/AutoCertStepOne.vue

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useGettext } from 'vue3-gettext'
33
import type { Ref } from 'vue'
44
import type { DnsChallenge } from '@/api/auto_cert'
55
import DNSChallenge from '@/views/domain/cert/components/DNSChallenge.vue'
6+
import type { Cert } from '@/api/cert'
67
78
defineProps<{
89
hideNote?: boolean
@@ -13,7 +14,39 @@ const { $gettext } = useGettext()
1314
const no_server_name = inject('no_server_name')
1415
1516
// Provide by ObtainCert.vue
16-
const data = inject('data') as Ref<DnsChallenge>
17+
const data = inject('data') as Ref<DnsChallenge & Cert>
18+
19+
const keyType = shallowRef([
20+
{
21+
key: '2048',
22+
name: 'RSA2048',
23+
},
24+
{
25+
key: '3072',
26+
name: 'RSA3072',
27+
},
28+
{
29+
key: '4096',
30+
name: 'RSA4096',
31+
},
32+
{
33+
key: '8192',
34+
name: 'RAS8192',
35+
},
36+
{
37+
key: 'P256',
38+
name: 'EC256',
39+
},
40+
{
41+
key: 'P384',
42+
name: 'EC384',
43+
},
44+
])
45+
46+
onMounted(() => {
47+
if (data.value.key_type === '')
48+
data.value.key_type = 'RSA2048'
49+
})
1750
</script>
1851

1952
<template>
@@ -72,6 +105,17 @@ const data = inject('data') as Ref<DnsChallenge>
72105
</ASelectOption>
73106
</ASelect>
74107
</AFormItem>
108+
<AFormItem :label="$gettext('Key Type')">
109+
<ASelect v-model:value="data.key_type">
110+
<ASelectOption
111+
v-for="t in keyType"
112+
:key="t.key"
113+
:value="t.key"
114+
>
115+
{{ t.name }}
116+
</ASelectOption>
117+
</ASelect>
118+
</AFormItem>
75119
</AForm>
76120
<DNSChallenge v-if="data.challenge_method === 'dns01'" />
77121
</div>

app/src/views/domain/cert/components/ObtainCertLive.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function log(msg: string) {
5959
logContainer.value?.scroll({ top: 100000, left: 0, behavior: 'smooth' })
6060
}
6161
62-
const issue_cert = async (config_name: string, server_name: string[]) => {
62+
const issue_cert = async (config_name: string, server_name: string[], key_type: string) => {
6363
return new Promise<CertificateResult>((resolve, reject) => {
6464
progressStatus.value = 'active'
6565
modalClosable.value = false
@@ -74,6 +74,7 @@ const issue_cert = async (config_name: string, server_name: string[]) => {
7474
ws.onopen = () => {
7575
ws.send(JSON.stringify({
7676
server_name,
77+
key_type,
7778
...data.value,
7879
}))
7980
}

internal/cert/auto_cert.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func renew(certModel *model.Cert) {
7474
ServerName: certModel.Domains,
7575
ChallengeMethod: certModel.ChallengeMethod,
7676
DNSCredentialID: certModel.DnsCredentialID,
77+
KeyType: certModel.GetKeyType(),
7778
}
7879

7980
// errChan will be closed inside IssueCert

internal/cert/cert.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ const (
3232
)
3333

3434
type ConfigPayload struct {
35-
ServerName []string `json:"server_name"`
36-
ChallengeMethod string `json:"challenge_method"`
37-
DNSCredentialID int `json:"dns_credential_id"`
35+
ServerName []string `json:"server_name"`
36+
ChallengeMethod string `json:"challenge_method"`
37+
DNSCredentialID int `json:"dns_credential_id"`
38+
KeyType certcrypto.KeyType `json:"key_type"`
3839
}
3940

4041
func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error) {
@@ -93,7 +94,7 @@ func IssueCert(payload *ConfigPayload, logChan chan string, errChan chan error)
9394
}
9495
}
9596

96-
config.Certificate.KeyType = certcrypto.RSA2048
97+
config.Certificate.KeyType = payload.KeyType
9798

9899
l.Println("[INFO] [Nginx UI] Creating client facilitates communication with the CA server")
99100
// A client facilitates communication with the CA server.

internal/validation/key_type.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package validation
2+
3+
import (
4+
"github.com/go-acme/lego/v4/certcrypto"
5+
val "github.com/go-playground/validator/v10"
6+
)
7+
8+
func autoCertKeyType(fl val.FieldLevel) bool {
9+
switch certcrypto.KeyType(fl.Field().String()) {
10+
case certcrypto.RSA2048, certcrypto.RSA3072, certcrypto.RSA4096,
11+
certcrypto.EC256, certcrypto.EC384:
12+
return true
13+
}
14+
return false
15+
}

0 commit comments

Comments
 (0)