mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new acme dns-01 provider: rucenter
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package certifiers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
"github.com/certimate-go/certimate/pkg/core/certifier/challengers/dns01/rucenter"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ACMEDns01Registries.MustRegister(domain.ACMEDns01ProviderTypeRuCenter, func(options *ProviderFactoryOptions) (core.ACMEChallenger, error) {
|
||||
credentials := domain.AccessConfigForRuCenter{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := rucenter.NewChallenger(&rucenter.ChallengerConfig{
|
||||
Username: credentials.Username,
|
||||
Password: credentials.Password,
|
||||
ApplicationId: credentials.ApplicationId,
|
||||
ApplicationToken: credentials.ApplicationToken,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -500,6 +500,13 @@ type AccessConfigForRFC2136 struct {
|
||||
TsigSecret string `json:"tsigSecret,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForRuCenter struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
ApplicationId string `json:"applicationId"`
|
||||
ApplicationToken string `json:"applicationToken"`
|
||||
}
|
||||
|
||||
type AccessConfigForS3 struct {
|
||||
Endpoint string `json:"endpoint"`
|
||||
AccessKey string `json:"accessKey"`
|
||||
|
||||
@@ -106,6 +106,7 @@ const (
|
||||
AccessProviderTypeRatPanel = AccessProviderType("ratpanel")
|
||||
AccessProviderTypeRegru = AccessProviderType("regru")
|
||||
AccessProviderTypeRFC2136 = AccessProviderType("rfc2136")
|
||||
AccessProviderTypeRuCenter = AccessProviderType("rucenter")
|
||||
AccessProviderTypeS3 = AccessProviderType("s3")
|
||||
AccessProviderTypeSafeLine = AccessProviderType("safeline")
|
||||
AccessProviderTypeSamWAF = AccessProviderType("samwaf")
|
||||
@@ -246,6 +247,7 @@ const (
|
||||
ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun)
|
||||
ACMEDns01ProviderTypeRegru = ACMEDns01ProviderType(AccessProviderTypeRegru)
|
||||
ACMEDns01ProviderTypeRFC2136 = ACMEDns01ProviderType(AccessProviderTypeRFC2136)
|
||||
ACMEDns01ProviderTypeRuCenter = ACMEDns01ProviderType(AccessProviderTypeRuCenter)
|
||||
ACMEDns01ProviderTypeSpaceship = ACMEDns01ProviderType(AccessProviderTypeSpaceship)
|
||||
ACMEDns01ProviderTypeTechnitiumDNS = ACMEDns01ProviderType(AccessProviderTypeTechnitiumDNS)
|
||||
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package rucenter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v5/providers/dns/nicru"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certifier"
|
||||
)
|
||||
|
||||
type ChallengerConfig struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
ApplicationId string `json:"applicationId"`
|
||||
ApplicationToken string `json:"applicationToken"`
|
||||
DnsPropagationTimeout int `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int `json:"dnsTTL,omitempty"`
|
||||
}
|
||||
|
||||
func NewChallenger(config *ChallengerConfig) (certifier.ACMEChallenger, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the acme challenge provider is nil")
|
||||
}
|
||||
|
||||
providerConfig := nicru.NewDefaultConfig()
|
||||
providerConfig.Username = config.Username
|
||||
providerConfig.Password = config.Password
|
||||
providerConfig.ServiceID = config.ApplicationId
|
||||
providerConfig.Secret = config.ApplicationToken
|
||||
if config.DnsPropagationTimeout != 0 {
|
||||
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
|
||||
}
|
||||
if config.DnsTTL != 0 {
|
||||
providerConfig.TTL = config.DnsTTL
|
||||
}
|
||||
|
||||
provider, err := nicru.NewDNSProviderConfig(providerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return provider, nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="-2 2 43 43" width="200" height="200"><path fill="#798E96" d="M18.675 13.16c0 5.148-4.18 9.32-9.338 9.32C4.182 22.48 0 18.309 0 13.16c0-5.148 4.18-9.32 9.338-9.32 5.157 0 9.337 4.172 9.337 9.32ZM29.752 22.481c-5.157 0-9.338-4.173-9.338-9.32 0-5.149 4.18-9.322 9.338-9.322 5.156 0 9.337 4.173 9.337 9.321s-4.18 9.321-9.337 9.321ZM9.337 42.854c5.157 0 9.338-4.173 9.338-9.321s-4.18-9.321-9.338-9.321C4.181 24.212 0 28.385 0 33.532c0 5.149 4.18 9.322 9.337 9.322Z"></path></svg>
|
||||
@@ -90,6 +90,7 @@ import AccessConfigFieldsProviderRainYun from "./AccessConfigFieldsProviderRainY
|
||||
import AccessConfigFieldsProviderRatPanel from "./AccessConfigFieldsProviderRatPanel";
|
||||
import AccessConfigFieldsProviderRegru from "./AccessConfigFieldsProviderRegru";
|
||||
import AccessConfigFieldsProviderRFC2136 from "./AccessConfigFieldsProviderRFC2136";
|
||||
import AccessConfigFieldsProviderRuCenter from "./AccessConfigFieldsProviderRuCenter";
|
||||
import AccessConfigFieldsProviderS3 from "./AccessConfigFieldsProviderS3";
|
||||
import AccessConfigFieldsProviderSafeLine from "./AccessConfigFieldsProviderSafeLine";
|
||||
import AccessConfigFieldsProviderSamWAF from "./AccessConfigFieldsProviderSamWAF";
|
||||
@@ -210,6 +211,7 @@ const providerComponentMap: Partial<Record<AccessProviderType, React.ComponentTy
|
||||
[ACCESS_PROVIDERS.RATPANEL]: AccessConfigFieldsProviderRatPanel,
|
||||
[ACCESS_PROVIDERS.REGRU]: AccessConfigFieldsProviderRegru,
|
||||
[ACCESS_PROVIDERS.RFC2136]: AccessConfigFieldsProviderRFC2136,
|
||||
[ACCESS_PROVIDERS.RUCENTER]: AccessConfigFieldsProviderRuCenter,
|
||||
[ACCESS_PROVIDERS.S3]: AccessConfigFieldsProviderS3,
|
||||
[ACCESS_PROVIDERS.SAFELINE]: AccessConfigFieldsProviderSafeLine,
|
||||
[ACCESS_PROVIDERS.SAMWAF]: AccessConfigFieldsProviderSamWAF,
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const AccessConfigFormFieldsProviderRuCenter = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name={[parentNamePath, "username"]} initialValue={initialValues.username} label={t("access.form.rucenter_username.label")} rules={[formRule]}>
|
||||
<Input autoComplete="new-password" placeholder={t("access.form.rucenter_username.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name={[parentNamePath, "password"]} initialValue={initialValues.password} label={t("access.form.rucenter_password.label")} rules={[formRule]}>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.rucenter_password.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "applicationId"]}
|
||||
initialValue={initialValues.applicationId}
|
||||
label={t("access.form.rucenter_application_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.rucenter_application_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("access.form.rucenter_application_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "applicationToken"]}
|
||||
initialValue={initialValues.applicationToken}
|
||||
label={t("access.form.rucenter_application_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.rucenter_application_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password placeholder={t("access.form.rucenter_application_token.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
username: "",
|
||||
password: "",
|
||||
applicationId: "",
|
||||
applicationToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
|
||||
const { t: _ } = i18n;
|
||||
|
||||
return z.object({
|
||||
username: z.union([z.string().endsWith("/NIC-D"), z.string().endsWith("/NIC-REG")]),
|
||||
password: z.string().nonempty(),
|
||||
applicationId: z.string().length(32),
|
||||
applicationToken: z.string().length(91),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(AccessConfigFormFieldsProviderRuCenter, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -106,6 +106,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
RATPANEL: "ratpanel",
|
||||
REGRU: "regru",
|
||||
RFC2136: "rfc2136",
|
||||
RUCENTER: "rucenter",
|
||||
S3: "s3",
|
||||
SAFELINE: "safeline",
|
||||
SAMWAF: "samwaf",
|
||||
@@ -242,6 +243,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.OVHCLOUD, "provider.ovhcloud", "/imgs/providers/ovhcloud.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.PORKBUN, "provider.porkbun", "/imgs/providers/porkbun.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.REGRU, "provider.regru", "/imgs/providers/regru.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.RUCENTER, "provider.rucenter", "/imgs/providers/rucenter.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.SPACESHIP, "provider.spaceship", "/imgs/providers/spaceship.png", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.VULTR, "provider.vultr", "/imgs/providers/vultr.svg", [ACCESS_USAGES.DNS]],
|
||||
[ACCESS_PROVIDERS.CMCCCLOUD, "provider.cmcccloud", "/imgs/providers/cmcccloud.svg", [ACCESS_USAGES.DNS]],
|
||||
@@ -421,6 +423,7 @@ export const ACME_DNS01_PROVIDERS = Object.freeze({
|
||||
RAINYUN: `${ACCESS_PROVIDERS.RAINYUN}`,
|
||||
REGRU: `${ACCESS_PROVIDERS.REGRU}`,
|
||||
RFC2136: `${ACCESS_PROVIDERS.RFC2136}`,
|
||||
RUCENTER: `${ACCESS_PROVIDERS.RUCENTER}`,
|
||||
SPACESHIP: `${ACCESS_PROVIDERS.SPACESHIP}`,
|
||||
UCLOUD: `${ACCESS_PROVIDERS.UCLOUD}`, // 兼容旧值,等同于 `UCLOUD_UDNR`
|
||||
UCLOUD_UDNR: `${ACCESS_PROVIDERS.UCLOUD}-udnr`,
|
||||
@@ -494,6 +497,7 @@ export const acmeDns01ProvidersMap: Map<ACMEDns01Provider["type"] | string, ACME
|
||||
[ACME_DNS01_PROVIDERS.OVHCLOUD, "provider.ovhcloud"],
|
||||
[ACME_DNS01_PROVIDERS.PORKBUN, "provider.porkbun"],
|
||||
[ACME_DNS01_PROVIDERS.REGRU, "provider.regru"],
|
||||
[ACME_DNS01_PROVIDERS.RUCENTER, "provider.rucenter"],
|
||||
[ACME_DNS01_PROVIDERS.SPACESHIP, "provider.spaceship"],
|
||||
[ACME_DNS01_PROVIDERS.VERCEL, "provider.vercel"],
|
||||
[ACME_DNS01_PROVIDERS.VULTR, "provider.vultr"],
|
||||
|
||||
@@ -1075,24 +1075,24 @@
|
||||
"tooltip": "For more information, see <a href=\"https://ratpanel.github.io/advanced/api.html\" target=\"_blank\">https://ratpanel.github.io/advanced/api.html</a>"
|
||||
},
|
||||
"regru_username": {
|
||||
"label": "Рег.ру username",
|
||||
"placeholder": "Please enter Рег.ру username"
|
||||
"label": "Reg.ru username",
|
||||
"placeholder": "Please enter Reg.ru username"
|
||||
},
|
||||
"regru_password": {
|
||||
"label": "Рег.ру password",
|
||||
"placeholder": "Please enter Рег.ру password or API password"
|
||||
"label": "Reg.ru password",
|
||||
"placeholder": "Please enter Reg.ru password or API password"
|
||||
},
|
||||
"regru_mtls_certificate": {
|
||||
"label": "Рег.ру mTLS certificate (Optional)",
|
||||
"placeholder": "Please enter Рег.ру mTLS certificate",
|
||||
"label": "Reg.ru mTLS certificate (Optional)",
|
||||
"placeholder": "Please enter Reg.ru mTLS certificate",
|
||||
"errmsg": {
|
||||
"invalid": "Invalid certificate"
|
||||
},
|
||||
"tooltip": "For more information, see <a href=\"https://www.reg.ru/user/account/#/settings/api/\" target=\"_blank\">https://www.reg.ru/user/account/#/settings/api/api/</a>"
|
||||
},
|
||||
"regru_mtls_private_key": {
|
||||
"label": "Рег.ру mTLS private key (Optional)",
|
||||
"placeholder": "Please enter Рег.ру mTLS private key",
|
||||
"label": "Reg.ru mTLS private key (Optional)",
|
||||
"placeholder": "Please enter Reg.ru mTLS private key",
|
||||
"errmsg": {
|
||||
"invalid": "Invalid private key"
|
||||
},
|
||||
@@ -1118,6 +1118,24 @@
|
||||
"label": "TSIG authentication secret (Optional)",
|
||||
"placeholder": "Please enter TSIG authentication secret"
|
||||
},
|
||||
"rucenter_username": {
|
||||
"label": "Ru-Center username",
|
||||
"placeholder": "Please enter Ru-Center username"
|
||||
},
|
||||
"rucenter_password": {
|
||||
"label": "Ru-Center password",
|
||||
"placeholder": "Please enter Ru-Center password"
|
||||
},
|
||||
"rucenter_application_id": {
|
||||
"label": "Ru-Center application ID",
|
||||
"placeholder": "Please enter Ru-Center application ID",
|
||||
"tooltip": "For more information, see <a href=\"https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list\" target=\"_blank\">https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list</a>"
|
||||
},
|
||||
"rucenter_application_token": {
|
||||
"label": "Ru-Center application token",
|
||||
"placeholder": "Please enter Ru-Center application token",
|
||||
"tooltip": "For more information, see <a href=\"https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list\" target=\"_blank\">https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list</a>"
|
||||
},
|
||||
"s3_endpoint": {
|
||||
"label": "Endpoint",
|
||||
"placeholder": "Please enter endpoint",
|
||||
|
||||
@@ -200,6 +200,7 @@
|
||||
"ratpanel_console": "AcePanel - Console itself",
|
||||
"regru": "Рег.ру (Reg.ru)",
|
||||
"rfc2136": "Dynamic DNS Updates (RFC 2136)",
|
||||
"rucenter": "Руцентр (Ru-Center)",
|
||||
"s3": "Object storage (S3-compatible)",
|
||||
"s3_upload": "Upload to S3-compatible object storage",
|
||||
"safeline": "SafeLine",
|
||||
|
||||
@@ -1073,24 +1073,24 @@
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://ratpanel.github.io/advanced/api.html\" target=\"_blank\">https://ratpanel.github.io/advanced/api.html</a>"
|
||||
},
|
||||
"regru_username": {
|
||||
"label": "Рег.ру 用户名",
|
||||
"placeholder": "请输入 Рег.ру 用户名"
|
||||
"label": "Reg.ru 用户名",
|
||||
"placeholder": "请输入 Reg.ru 用户名"
|
||||
},
|
||||
"regru_password": {
|
||||
"label": "Рег.ру 密码",
|
||||
"placeholder": "请输入 Рег.ру 密码或 API 密码"
|
||||
"label": "Reg.ru 密码",
|
||||
"placeholder": "请输入 Reg.ru 密码或 API 密码"
|
||||
},
|
||||
"regru_mtls_certificate": {
|
||||
"label": "Рег.ру SSL 双向认证证书(可选)",
|
||||
"placeholder": "请输入 Рег.ру SSL 双向认证证书",
|
||||
"label": "Reg.ru SSL 双向认证证书(可选)",
|
||||
"placeholder": "请输入 Reg.ru SSL 双向认证证书",
|
||||
"errmsg": {
|
||||
"invalid": "无效的证书"
|
||||
},
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://www.reg.ru/user/account/#/settings/api/\" target=\"_blank\">https://www.reg.ru/user/account/#/settings/api/api/</a>"
|
||||
},
|
||||
"regru_mtls_private_key": {
|
||||
"label": "Рег.ру SSL 双向认证私钥(可选)",
|
||||
"placeholder": "请输入 Рег.ру SSL 双向认证私钥",
|
||||
"label": "Reg.ru SSL 双向认证私钥(可选)",
|
||||
"placeholder": "请输入 Reg.ru SSL 双向认证私钥",
|
||||
"errmsg": {
|
||||
"invalid": "无效的私钥"
|
||||
},
|
||||
@@ -1116,6 +1116,24 @@
|
||||
"label": "TSIG 认证密钥 Secret(可选)",
|
||||
"placeholder": "请输入 TSIG 认证密钥 Secret"
|
||||
},
|
||||
"rucenter_username": {
|
||||
"label": "Ru-Center 用户名",
|
||||
"placeholder": "请输入 Ru-Center 用户名"
|
||||
},
|
||||
"rucenter_password": {
|
||||
"label": "Ru-Center 密码",
|
||||
"placeholder": "请输入 Ru-Center 密码"
|
||||
},
|
||||
"rucenter_application_id": {
|
||||
"label": "Ru-Center 应用服务 ID",
|
||||
"placeholder": "请输入 Ru-Center 应用服务 ID",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list\" target=\"_blank\">https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list</a>"
|
||||
},
|
||||
"rucenter_application_token": {
|
||||
"label": "Ru-Center 应用服务 Token",
|
||||
"placeholder": "请输入 Ru-Center 应用服务 Token",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list\" target=\"_blank\">https://www.nic.ru/manager/oauth.cgi?step=oauth.app_list</a>"
|
||||
},
|
||||
"s3_endpoint": {
|
||||
"label": "终端节点",
|
||||
"placeholder": "请输入终端节点",
|
||||
|
||||
@@ -200,6 +200,7 @@
|
||||
"ratpanel_console": "耗子面板 - 面板自身",
|
||||
"regru": "Рег.ру(REG.ru)",
|
||||
"rfc2136": "Dynamic DNS Updates (RFC 2136)",
|
||||
"rucenter": "Руцентр(Ru-Center)",
|
||||
"s3": "对象存储(S3 兼容)",
|
||||
"s3_upload": "上传到 S3 兼容的对象存储",
|
||||
"safeline": "雷池",
|
||||
|
||||
Reference in New Issue
Block a user