Compare commits
2 Commits
a2923bdfc0
...
3ce7c99bfe
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ce7c99bfe | |||
| 9bae6b1d9b |
Executable
BIN
Binary file not shown.
@@ -35,7 +35,9 @@ func CredentialTypeMeta(ctype CredentialType) []CredentialField {
|
|||||||
}
|
}
|
||||||
case CredentialCloudflare:
|
case CredentialCloudflare:
|
||||||
return []CredentialField{
|
return []CredentialField{
|
||||||
{Key: "cf_api_token", Label: "API Token", Type: "password", Required: true},
|
{Key: "cf_api_token", Label: "API Token", Type: "password", Required: false},
|
||||||
|
{Key: "cf_email", Label: "Email (Global API Key 方式)", Type: "text", Required: false},
|
||||||
|
{Key: "cf_api_key", Label: "Global API Key", Type: "password", Required: false},
|
||||||
}
|
}
|
||||||
case CredentialDNSPod:
|
case CredentialDNSPod:
|
||||||
return []CredentialField{
|
return []CredentialField{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@@ -67,6 +68,11 @@ func (h *CredentialHandler) CreateCredential(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trim whitespace from all values
|
||||||
|
for k, v := range testData {
|
||||||
|
testData[k] = strings.TrimSpace(v)
|
||||||
|
}
|
||||||
|
|
||||||
// Validate fields for the provider type
|
// Validate fields for the provider type
|
||||||
fields := config.CredentialTypeMeta(req.Type)
|
fields := config.CredentialTypeMeta(req.Type)
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
@@ -78,10 +84,23 @@ func (h *CredentialHandler) CreateCredential(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cloudflare: require either API Token or Email+Key
|
||||||
|
if req.Type == config.CredentialCloudflare {
|
||||||
|
hasToken := testData["cf_api_token"] != ""
|
||||||
|
hasEmailKey := testData["cf_email"] != "" && testData["cf_api_key"] != ""
|
||||||
|
if !hasToken && !hasEmailKey {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "请填写 API Token,或者同时填写 Email 和 Global API Key"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-serialize trimmed data
|
||||||
|
trimmedData, _ := json.Marshal(testData)
|
||||||
|
|
||||||
cred := &config.Credential{
|
cred := &config.Credential{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
Type: req.Type,
|
Type: req.Type,
|
||||||
Data: req.Data,
|
Data: string(trimmedData),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := config.CredStore.Create(cred); err != nil {
|
if err := config.CredStore.Create(cred); err != nil {
|
||||||
@@ -122,16 +141,28 @@ func (h *CredentialHandler) UpdateCredential(c *gin.Context) {
|
|||||||
existing.Type = req.Type
|
existing.Type = req.Type
|
||||||
}
|
}
|
||||||
if req.Data != "" {
|
if req.Data != "" {
|
||||||
// If it's the masked placeholder, keep existing data
|
// If it's the masked placeholder, keep existing data unchanged
|
||||||
if req.Data == "********" {
|
if req.Data != "********" {
|
||||||
existing.Data = existing.Data
|
|
||||||
} else {
|
|
||||||
var testData map[string]string
|
var testData map[string]string
|
||||||
if err := json.Unmarshal([]byte(req.Data), &testData); err != nil {
|
if err := json.Unmarshal([]byte(req.Data), &testData); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "data must be valid JSON"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "data must be valid JSON"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
existing.Data = req.Data
|
// Trim whitespace from all values
|
||||||
|
for k, v := range testData {
|
||||||
|
testData[k] = strings.TrimSpace(v)
|
||||||
|
}
|
||||||
|
// Cloudflare: require either API Token or Email+Key
|
||||||
|
if existing.Type == config.CredentialCloudflare {
|
||||||
|
hasToken := testData["cf_api_token"] != ""
|
||||||
|
hasEmailKey := testData["cf_email"] != "" && testData["cf_api_key"] != ""
|
||||||
|
if !hasToken && !hasEmailKey {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "请填写 API Token,或者同时填写 Email 和 Global API Key"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trimmedData, _ := json.Marshal(testData)
|
||||||
|
existing.Data = string(trimmedData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ type DNSConfig struct {
|
|||||||
|
|
||||||
// Cloudflare
|
// Cloudflare
|
||||||
CFAPIToken string `json:"cf_api_token,omitempty"`
|
CFAPIToken string `json:"cf_api_token,omitempty"`
|
||||||
|
CFEmail string `json:"cf_email,omitempty"`
|
||||||
|
CFAPIKey string `json:"cf_api_key,omitempty"`
|
||||||
|
|
||||||
// DNSPod
|
// DNSPod
|
||||||
DNSPodID string `json:"dnspod_id,omitempty"`
|
DNSPodID string `json:"dnspod_id,omitempty"`
|
||||||
@@ -84,8 +86,8 @@ func GetACMECertificate(cert *config.Certificate, cfg *config.Config) error {
|
|||||||
|
|
||||||
// Use custom DNS timeout for better reliability
|
// Use custom DNS timeout for better reliability
|
||||||
if err := client.Challenge.SetDNS01Provider(provider,
|
if err := client.Challenge.SetDNS01Provider(provider,
|
||||||
dns01.AddRecursiveNameservers(dns01.ParseNameservers([]string{"8.8.8.8:53", "1.1.1.1:53"})),
|
dns01.AddRecursiveNameservers(dns01.ParseNameservers([]string{"223.5.5.5:53", "119.29.29.29:53", "8.8.8.8:53"})),
|
||||||
dns01.AddDNSTimeout(15*time.Second),
|
dns01.AddDNSTimeout(120*time.Second),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
||||||
}
|
}
|
||||||
@@ -155,8 +157,8 @@ func RenewCertificate(cert *config.Certificate, cfg *config.Config) error {
|
|||||||
|
|
||||||
// Use custom DNS timeout for better reliability
|
// Use custom DNS timeout for better reliability
|
||||||
if err := client.Challenge.SetDNS01Provider(provider,
|
if err := client.Challenge.SetDNS01Provider(provider,
|
||||||
dns01.AddRecursiveNameservers(dns01.ParseNameservers([]string{"8.8.8.8:53", "1.1.1.1:53"})),
|
dns01.AddRecursiveNameservers(dns01.ParseNameservers([]string{"223.5.5.5:53", "119.29.29.29:53", "8.8.8.8:53"})),
|
||||||
dns01.AddDNSTimeout(15*time.Second),
|
dns01.AddDNSTimeout(120*time.Second),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
||||||
}
|
}
|
||||||
@@ -327,13 +329,19 @@ func getDNSProvider(cert *config.Certificate) (challenge.Provider, error) {
|
|||||||
|
|
||||||
case "cloudflare":
|
case "cloudflare":
|
||||||
cfg := cloudflareprov.NewDefaultConfig()
|
cfg := cloudflareprov.NewDefaultConfig()
|
||||||
if dnsCfg.CFAPIToken != "" {
|
token := strings.TrimSpace(dnsCfg.CFAPIToken)
|
||||||
prefix := dnsCfg.CFAPIToken
|
if token != "" {
|
||||||
|
prefix := token
|
||||||
if len(prefix) > 8 {
|
if len(prefix) > 8 {
|
||||||
prefix = prefix[:8]
|
prefix = prefix[:8]
|
||||||
}
|
}
|
||||||
log.Printf("Cloudflare token length: %d, prefix: %s, has_****: %v", len(dnsCfg.CFAPIToken), prefix, strings.Contains(dnsCfg.CFAPIToken, "****"))
|
log.Printf("Cloudflare token length: %d, prefix: %s, has_****: %v", len(token), prefix, strings.Contains(token, "****"))
|
||||||
cfg.AuthToken = dnsCfg.CFAPIToken
|
cfg.AuthToken = token
|
||||||
|
}
|
||||||
|
// Also support email + Global API Key auth
|
||||||
|
if dnsCfg.CFEmail != "" && dnsCfg.CFAPIKey != "" {
|
||||||
|
cfg.AuthEmail = strings.TrimSpace(dnsCfg.CFEmail)
|
||||||
|
cfg.AuthKey = strings.TrimSpace(dnsCfg.CFAPIKey)
|
||||||
}
|
}
|
||||||
provider, err := cloudflareprov.NewDNSProviderConfig(cfg)
|
provider, err := cloudflareprov.NewDNSProviderConfig(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIAvBPT8bw9RlsWdzY+Ga/bZcaGoRC1o9KQylxwMt2xpwoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEtsNoIrvUk9RE8/tXhzlGTqOZH2oQjxrrlyvnVV7wj2YWo2Q5diNp
|
||||||
|
oL1EDmDWVBMBO6enEgGkU3OtNyqCmTFBKA==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"body": {
|
||||||
|
"status": "valid"
|
||||||
|
},
|
||||||
|
"uri": "https://acme-v02.api.letsencrypt.org/acme/acct/3565382145"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIF9G4xzfZxxH/8Zp+EabrGlDlH8s5ftlLFXqd5di4wIYoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEo4RIUksl7FCK3+QnlsUSWEBSWuVPwWWsqGeQxXdGu8qqiNGtypXE
|
||||||
|
ESu0EWaXjQcbZE476xH67DDmtHsEcz0q8g==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"body": {
|
||||||
|
"status": "valid"
|
||||||
|
},
|
||||||
|
"uri": "https://acme-v02.api.letsencrypt.org/acme/acct/3565389605"
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"created_at": "2026-07-25T00:06:36.635806194+08:00",
|
||||||
|
"updated_at": "2026-07-25T00:08:43.014181606+08:00",
|
||||||
|
"domain": "harbor.yunwei.blog",
|
||||||
|
"email": "a@qq.com",
|
||||||
|
"provider": "letsencrypt",
|
||||||
|
"challenge_type": "dns",
|
||||||
|
"dns_provider": "cloudflare",
|
||||||
|
"dns_config": "{\"cf_api_token\":\"cfut_VLxUPTOTAWBwTmY8WM4uuZYQW0iztWSdXEWhQYB348f7e25a\"}",
|
||||||
|
"credential_id": 1,
|
||||||
|
"status": "error",
|
||||||
|
"error_message": "failed to obtain certificate: error: one or more domains had a problem:\n[harbor.yunwei.blog] propagation: time limit exceeded: last error: authoritative nameservers: NS blakely.ns.cloudflare.com.:53 did not return the expected TXT record [fqdn: _acme-challenge.harbor.yunwei.blog., value: iLtFsQrgk5mSpKlWk69-KKxf0kBHCUK4PivtBRC-vNI]: \n",
|
||||||
|
"auto_renew": true,
|
||||||
|
"renew_days": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"created_at": "2026-07-24T23:10:52.210274514+08:00",
|
||||||
|
"updated_at": "2026-07-25T00:02:51.1655217+08:00",
|
||||||
|
"domain": "*.k8s.yunwei.blog",
|
||||||
|
"email": "a@qq.com",
|
||||||
|
"provider": "letsencrypt",
|
||||||
|
"challenge_type": "dns",
|
||||||
|
"dns_provider": "cloudflare",
|
||||||
|
"dns_config": "{\"cf_api_key\":\"6eabf25cb487d39f166c3ff4dc3145b5c5fb3\",\"cf_email\":\"mrtom0506@gmail.com\"}",
|
||||||
|
"credential_id": 1,
|
||||||
|
"status": "active",
|
||||||
|
"cert_url": "https://acme-v02.api.letsencrypt.org/acme/cert/06f366c19b0ae2a6bfdedfbfcdecbc5a0f4a",
|
||||||
|
"expires_at": "2026-10-22T15:04:18Z",
|
||||||
|
"last_renewed_at": "2026-07-25T00:02:51.165423851+08:00",
|
||||||
|
"auto_renew": true,
|
||||||
|
"renew_days": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE2jCCAsKgAwIBAgIQTr0klH4k05SALYSlL9WzGTANBgkqhkiG9w0BAQsFADAu
|
||||||
|
MQswCQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZUjAe
|
||||||
|
Fw0yNTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYw
|
||||||
|
FAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZUjIwggEiMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDwAwggEKAoIBAQDZ0LxwBppqh84luqMerV/eeL/fXQ7mLQQv1Lnp
|
||||||
|
WKZbyvGpx6wh6AfnslAnF6ewTkcHA+gSOoBvm3Dfm06AuGiF+KRut4fAcowqnAQQ
|
||||||
|
CW98+QPP/eOv/wug7Iyk4NkOxf2I6g2f55T6nJoOTLFcukeRq80JGQEYan+dPFr9
|
||||||
|
OGUgQK2hGKgNkW87pappsOAuUJcroYhRt5uUis4qaZireiseu32gzDJNBAiKtsvd
|
||||||
|
6HX4v25bpkRNcS/B/Gtc9kVbUpD+2PLPxdei3Tim55k4tfAEXwD2qyiPTxrTNq6l
|
||||||
|
N+AMr5g2c1dNqkOTwjxeV6L5lpP1rGiYvLnRaPlOqyZRPW+5AgMBAAGjge4wgesw
|
||||||
|
DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMBMBIGA1UdEwEB/wQI
|
||||||
|
MAYBAf8CAQAwHQYDVR0OBBYEFEAVLSZ57TIgnt+ach3WMh+BDIEMMB8GA1UdIwQY
|
||||||
|
MBaAFN7nW2DQIm1AKH0/DQH+pLVStFGUMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEF
|
||||||
|
BQcwAoYWaHR0cDovL3lyLmkubGVuY3Iub3JnLzATBgNVHSAEDDAKMAgGBmeBDAEC
|
||||||
|
ATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veXIuYy5sZW5jci5vcmcvMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4ICAQB0ZUQWZ9/Yn9COEpo+JfecMnB0h0vwDm/M66IqXqw3LoaL
|
||||||
|
mx9lZvRTeDIS67PUeI3yCA2W6PKRD0/FE/G57lOmS+Xy5AaaL00ICGOqjNcCaMWW
|
||||||
|
8o8nevHOd4i4lqgtznE/28QwlcdJyF8yBiWHpnyjhEpmNWJURgOCOg2xpwRMBCsj
|
||||||
|
MScqYPtOhBeuYQvSwAEeTML2Ukh6uGuX4E14q65Ja8cdjF5bAldnP1eE4FBaAwsZ
|
||||||
|
G2fOqqrKV03Y85Nw2btedP1AtliQuJZs/Jo/gXxXdc7LrH3McgnpnbTiAncX7yES
|
||||||
|
hP6kzQejllqMCIt52HOjxDGWafS7Xw+DKwqmH+Eqy8dcbOuag/1AYlQoKNVK3F5q
|
||||||
|
Hh6tEDiMqQcLIibGKteE6iHo4A/bIScbzrhXUYuism42ZYzmc48FMVIH3qy4L84E
|
||||||
|
TdAH2gtxw0PAhvRVXp8HP7wfngpzsN/8xOTpeRSbM4+Qbc56G6+Bifmv6sk1ieQb
|
||||||
|
NA3wJdl4DDUuQSV8hBgx6zoI1ZSGORprDFux7c6rhc77QZMSRrEgomBeklervEve
|
||||||
|
86ylWmZ3WWHV6RLMi8xNvjd71r4EPIGgY7BZU/VPBkq+uA7Gb6mbJnFgV43uh3xy
|
||||||
|
LRFgxIAphIukwTGSMZZR+AI+Qnp0BYTWovHXozOf3H8r6hozEoT02JHn0AeTfA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIE2jCCAsKgAwIBAgIQTr0klH4k05SALYSlL9WzGTANBgkqhkiG9w0BAQsFADAu
|
||||||
|
MQswCQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZUjAe
|
||||||
|
Fw0yNTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYw
|
||||||
|
FAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQDEwNZUjIwggEiMA0GCSqGSIb3
|
||||||
|
DQEBAQUAA4IBDwAwggEKAoIBAQDZ0LxwBppqh84luqMerV/eeL/fXQ7mLQQv1Lnp
|
||||||
|
WKZbyvGpx6wh6AfnslAnF6ewTkcHA+gSOoBvm3Dfm06AuGiF+KRut4fAcowqnAQQ
|
||||||
|
CW98+QPP/eOv/wug7Iyk4NkOxf2I6g2f55T6nJoOTLFcukeRq80JGQEYan+dPFr9
|
||||||
|
OGUgQK2hGKgNkW87pappsOAuUJcroYhRt5uUis4qaZireiseu32gzDJNBAiKtsvd
|
||||||
|
6HX4v25bpkRNcS/B/Gtc9kVbUpD+2PLPxdei3Tim55k4tfAEXwD2qyiPTxrTNq6l
|
||||||
|
N+AMr5g2c1dNqkOTwjxeV6L5lpP1rGiYvLnRaPlOqyZRPW+5AgMBAAGjge4wgesw
|
||||||
|
DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMBMBIGA1UdEwEB/wQI
|
||||||
|
MAYBAf8CAQAwHQYDVR0OBBYEFEAVLSZ57TIgnt+ach3WMh+BDIEMMB8GA1UdIwQY
|
||||||
|
MBaAFN7nW2DQIm1AKH0/DQH+pLVStFGUMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEF
|
||||||
|
BQcwAoYWaHR0cDovL3lyLmkubGVuY3Iub3JnLzATBgNVHSAEDDAKMAgGBmeBDAEC
|
||||||
|
ATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veXIuYy5sZW5jci5vcmcvMA0GCSqG
|
||||||
|
SIb3DQEBCwUAA4ICAQB0ZUQWZ9/Yn9COEpo+JfecMnB0h0vwDm/M66IqXqw3LoaL
|
||||||
|
mx9lZvRTeDIS67PUeI3yCA2W6PKRD0/FE/G57lOmS+Xy5AaaL00ICGOqjNcCaMWW
|
||||||
|
8o8nevHOd4i4lqgtznE/28QwlcdJyF8yBiWHpnyjhEpmNWJURgOCOg2xpwRMBCsj
|
||||||
|
MScqYPtOhBeuYQvSwAEeTML2Ukh6uGuX4E14q65Ja8cdjF5bAldnP1eE4FBaAwsZ
|
||||||
|
G2fOqqrKV03Y85Nw2btedP1AtliQuJZs/Jo/gXxXdc7LrH3McgnpnbTiAncX7yES
|
||||||
|
hP6kzQejllqMCIt52HOjxDGWafS7Xw+DKwqmH+Eqy8dcbOuag/1AYlQoKNVK3F5q
|
||||||
|
Hh6tEDiMqQcLIibGKteE6iHo4A/bIScbzrhXUYuism42ZYzmc48FMVIH3qy4L84E
|
||||||
|
TdAH2gtxw0PAhvRVXp8HP7wfngpzsN/8xOTpeRSbM4+Qbc56G6+Bifmv6sk1ieQb
|
||||||
|
NA3wJdl4DDUuQSV8hBgx6zoI1ZSGORprDFux7c6rhc77QZMSRrEgomBeklervEve
|
||||||
|
86ylWmZ3WWHV6RLMi8xNvjd71r4EPIGgY7BZU/VPBkq+uA7Gb6mbJnFgV43uh3xy
|
||||||
|
LRFgxIAphIukwTGSMZZR+AI+Qnp0BYTWovHXozOf3H8r6hozEoT02JHn0AeTfA==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEA0xZkXlTfiktNExx4KUsxJmGUZqxdvr/bmw7ppFQnyA8hP+kr
|
||||||
|
J2rZ/a3JdN0ZIPteWNRgksMfOUQpDKTN8WZWrAagQQwuLJzBm/KeciqEb7Epve/t
|
||||||
|
woLplhG7wcmTN+frnijA7vNQA+AEmPQ5nErPvE1/h7NyXNfgXqtj6uDQv8HtTyEd
|
||||||
|
LC6jIlyVK9fxt3L8BDRMZLf4M9Toko7W165vfIm2CH6z/fs9qD32awvqdH/RjL9o
|
||||||
|
B1Sf/2DyMvNCi00gU3LiQPwPbT1nYGZQeSyxBS371D1BKF87T0z98JFR6rlZTk4+
|
||||||
|
kOS7twFLzdf+d8TobigvX6GjZrvFXB/PhuT0twIDAQABAoIBABTfEe2B1tiFuYk6
|
||||||
|
N2dd1+5Dl7jPMjW6IqyiPNfSulw9orv/AhVTq1o55MF5WxK3yAxgc2wPfvbalnR5
|
||||||
|
lyNXSxqXTSEhYy9mEH6q7p+7NH0Wt1ngb1HcP9xmxHnUxImylMl+nhUCWdcIP2wg
|
||||||
|
OdIKU5/6ybFRPO2RKs4xhB+lOv66sAsZzMjLl94ufKg9CC/yXxaoP00wDi/aIUPR
|
||||||
|
SLrf7f5pOipeYTtKeahFlYe4tgtTABTCyJi6sh/lhznFFkHav3a10n9cl1DLoMsv
|
||||||
|
pjq62ZsNLlZBoca+jvCquWI2MDUvr9eMWhydX/wkha8QPyRlJb7nUbB6mXKFBRb3
|
||||||
|
KuHXuoECgYEA8ZbzhllP81+O7HgfC5yTyh0NrvST7vKMRFjHiR3OY93Zv2G6AH/o
|
||||||
|
jd9wLorgZdu1N4wkJPlpnif2/gAtZP6D2tODI9sC71fW3ZYt3F1pZHQfcf0h+qRi
|
||||||
|
TO4I+rL9ZngtrPgE7NlpV2lqC1Sjog4l/L9UB9wHWL1+TFj3KGCHoRsCgYEA362s
|
||||||
|
9isIYP6aB+IdYr9uuC7rmCqio32i/Mz083zaAZJkZ6ex6XiNwBxFVZJ9x3Cco88w
|
||||||
|
iqim8Z7a0XXrylAQpYVqo6U4EkfaJkf9nMjqUWPo36t+MpbwEIs8B8lJ3lspf83n
|
||||||
|
Rz+4NSba0HNIBuVXuZZK9yqflqBziFdgNGJPkJUCgYA1PcofYpFvFjEeRf65hWFA
|
||||||
|
mpSIaRgtAcEN0u7udeYlNiAlwDjIoWez1HkZmLuJVxkhy72vdFPlafNR2OIoLrsK
|
||||||
|
P7DX9w03iAkvPkiPFvsCC2FesqWJYi7Tu2W5MjcMHRIb23Dibat8exvGsXl6Xlna
|
||||||
|
0KOJM+Femiw6USTu/g8F3wKBgQCSfWL+YZZ+N6BXM149ctQnags/wAR+AGVDHVP7
|
||||||
|
NzRrvR1myWv6VMq5G4rJDUS03mqn2aSX2vZi3b+/WHRRLniIfsUlYapERqx3T8Sn
|
||||||
|
7umO3lkAS4c9yJ52p0lsbAalypx2KDqk7fVNUiISTL3KTl9SmzyDfXXBJ1oi296U
|
||||||
|
0CH9tQKBgA4dX9/5GoWWZ3/5dRny3lb4z8AQQFoCj2fTKIN5usNUzsAOUMZp+p24
|
||||||
|
h/BzmUtcGUlKNPwg4LYjndIuK4Eembuyaiif5OdaDWWePacsP5pudIYlibXUyZqb
|
||||||
|
Ad3K4WIp0pVjzqt7HGXwDluBS3y1YApX/kky1o3b4vxoh8me8AX4
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "cloudflare_yunweiblog",
|
||||||
|
"type": "cloudflare",
|
||||||
|
"data": "{\"cf_api_token\":\"cfut_VLxUPTOTAWBwTmY8WM4uuZYQW0iztWSdXEWhQYB348f7e25a\"}",
|
||||||
|
"masked": "{\"cf_api_token\":\"cfut****\"}",
|
||||||
|
"created_at": "2026-07-24T23:08:11.019112775+08:00",
|
||||||
|
"updated_at": "2026-07-24T23:08:11.019112775+08:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "cloudflare_globalcloudflare_global",
|
||||||
|
"type": "cloudflare",
|
||||||
|
"data": "{\"cf_api_key\":\"6eabf25cb487d39f166c3ff4dc3145b5c5fb3\",\"cf_email\":\"mrtom0506@gmail.com\"}",
|
||||||
|
"masked": "{\"cf_api_key\":\"6eab****\",\"cf_email\":\"mrto****\"}",
|
||||||
|
"created_at": "2026-07-24T23:52:19.826553941+08:00",
|
||||||
|
"updated_at": "2026-07-24T23:52:19.826553941+08:00"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -81,7 +81,14 @@
|
|||||||
<!-- Cloudflare Config -->
|
<!-- Cloudflare Config -->
|
||||||
<template v-if="form.dns_provider === 'cloudflare'">
|
<template v-if="form.dns_provider === 'cloudflare'">
|
||||||
<el-form-item label="API Token">
|
<el-form-item label="API Token">
|
||||||
<el-input v-model="manualConfig.cf_api_token" type="password" show-password placeholder="Cloudflare API Token" />
|
<el-input v-model="manualConfig.cf_api_token" type="password" show-password placeholder="Cloudflare API Token(推荐)" />
|
||||||
|
<div class="form-tip">需要 Zone:Read + DNS:Edit 权限。也可留空,改用下方 Email + Global API Key 方式</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Email">
|
||||||
|
<el-input v-model="manualConfig.cf_email" placeholder="Cloudflare 账号邮箱(Global API Key 方式)" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Global API Key">
|
||||||
|
<el-input v-model="manualConfig.cf_api_key" type="password" show-password placeholder="Global API Key(与 Email 配合使用)" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -162,6 +169,8 @@ const manualConfig = reactive({
|
|||||||
ali_key: '',
|
ali_key: '',
|
||||||
ali_secret: '',
|
ali_secret: '',
|
||||||
cf_api_token: '',
|
cf_api_token: '',
|
||||||
|
cf_email: '',
|
||||||
|
cf_api_key: '',
|
||||||
dnspod_id: '',
|
dnspod_id: '',
|
||||||
dnspod_key: '',
|
dnspod_key: '',
|
||||||
})
|
})
|
||||||
@@ -220,6 +229,8 @@ const buildDnsConfigJson = (): string => {
|
|||||||
case 'cloudflare':
|
case 'cloudflare':
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
cf_api_token: manualConfig.cf_api_token,
|
cf_api_token: manualConfig.cf_api_token,
|
||||||
|
cf_email: manualConfig.cf_email,
|
||||||
|
cf_api_key: manualConfig.cf_api_key,
|
||||||
})
|
})
|
||||||
case 'dnspod':
|
case 'dnspod':
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
@@ -246,10 +257,14 @@ const handleSubmit = async () => {
|
|||||||
ElMessage.warning('请填写阿里云 AccessKey')
|
ElMessage.warning('请填写阿里云 AccessKey')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (form.dns_provider === 'cloudflare' && !manualConfig.cf_api_token) {
|
if (form.dns_provider === 'cloudflare') {
|
||||||
ElMessage.warning('请填写 Cloudflare API Token')
|
const hasToken = !!manualConfig.cf_api_token
|
||||||
|
const hasEmailKey = !!manualConfig.cf_email && !!manualConfig.cf_api_key
|
||||||
|
if (!hasToken && !hasEmailKey) {
|
||||||
|
ElMessage.warning('请填写 Cloudflare API Token,或者同时填写 Email 和 Global API Key')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (form.dns_provider === 'dnspod' && (!manualConfig.dnspod_id || !manualConfig.dnspod_key)) {
|
if (form.dns_provider === 'dnspod' && (!manualConfig.dnspod_id || !manualConfig.dnspod_key)) {
|
||||||
ElMessage.warning('请填写 DNSPod 凭证')
|
ElMessage.warning('请填写 DNSPod 凭证')
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user