feat(provider): new acme dns-01 provider: simplycom

This commit is contained in:
Fu Diwei
2026-06-24 17:34:55 +08:00
committed by RHQYZ
parent dfc0c3a8f1
commit 312c27dd2e
12 changed files with 166 additions and 0 deletions
@@ -0,0 +1,27 @@
package certifiers
import (
"fmt"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/pkg/core"
chlgimpl "github.com/certimate-go/certimate/pkg/core/certifier/challengers/dns01/simplycom"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
func init() {
ACMEDns01Registries.MustRegister(domain.ACMEDns01ProviderTypeSimplyCom, func(options *ProviderFactoryOptions) (core.ACMEChallenger, error) {
credentials := domain.AccessConfigForSimplyCom{}
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
provider, err := chlgimpl.NewChallenger(&chlgimpl.ChallengerConfig{
AccountNumber: credentials.AccountNumber,
ApiKey: credentials.ApiKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
})
return provider, err
})
}
+5
View File
@@ -546,6 +546,11 @@ type AccessConfigForSamWAF struct {
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
}
type AccessConfigForSimplyCom struct {
AccountNumber string `json:"accountNumber"`
ApiKey string `json:"apiKey"`
}
type AccessConfigForSlackBot struct {
BotToken string `json:"botToken"`
ChannelId string `json:"channelId,omitempty"`
+2
View File
@@ -114,6 +114,7 @@ const (
AccessProviderTypeSafeLine = AccessProviderType("safeline")
AccessProviderTypeSamWAF = AccessProviderType("samwaf")
AccessProviderTypeSectigo = AccessProviderType("sectigo")
AccessProviderTypeSimplyCom = AccessProviderType("simplycom")
AccessProviderTypeSlackBot = AccessProviderType("slackbot")
AccessProviderTypeSpaceship = AccessProviderType("spaceship")
AccessProviderTypeSSH = AccessProviderType("ssh")
@@ -256,6 +257,7 @@ const (
ACMEDns01ProviderTypeRegru = ACMEDns01ProviderType(AccessProviderTypeRegru)
ACMEDns01ProviderTypeRFC2136 = ACMEDns01ProviderType(AccessProviderTypeRFC2136)
ACMEDns01ProviderTypeRuCenter = ACMEDns01ProviderType(AccessProviderTypeRuCenter)
ACMEDns01ProviderTypeSimplyCom = ACMEDns01ProviderType(AccessProviderTypeSimplyCom)
ACMEDns01ProviderTypeSpaceship = ACMEDns01ProviderType(AccessProviderTypeSpaceship)
ACMEDns01ProviderTypeTechnitiumDNS = ACMEDns01ProviderType(AccessProviderTypeTechnitiumDNS)
ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS]
@@ -0,0 +1,40 @@
package gandinet
import (
"fmt"
"time"
"github.com/go-acme/lego/v5/providers/dns/simply"
"github.com/certimate-go/certimate/pkg/core"
)
type ChallengerConfig struct {
AccountNumber string `json:"accountNumber"`
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int `json:"dnsTTL,omitempty"`
}
func NewChallenger(config *ChallengerConfig) (core.ACMEChallenger, error) {
if config == nil {
return nil, fmt.Errorf("the configuration of the acme challenge provider is nil")
}
providerConfig := simply.NewDefaultConfig()
providerConfig.AccountName = config.AccountNumber
providerConfig.APIKey = config.ApiKey
if config.DnsPropagationTimeout != 0 {
providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
}
if config.DnsTTL != 0 {
providerConfig.TTL = config.DnsTTL
}
provider, err := simply.NewDNSProviderConfig(providerConfig)
if err != nil {
return nil, err
}
return provider, nil
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

@@ -98,6 +98,7 @@ import AccessConfigFieldsProviderS3 from "./AccessConfigFieldsProviderS3";
import AccessConfigFieldsProviderSafeLine from "./AccessConfigFieldsProviderSafeLine";
import AccessConfigFieldsProviderSamWAF from "./AccessConfigFieldsProviderSamWAF";
import AccessConfigFieldsProviderSectigo from "./AccessConfigFieldsProviderSectigo";
import AccessConfigFieldsProviderSimplyCom from "./AccessConfigFieldsProviderSimplyCom";
import AccessConfigFieldsProviderSlackBot from "./AccessConfigFieldsProviderSlackBot";
import AccessConfigFieldsProviderSpaceship from "./AccessConfigFieldsProviderSpaceship";
import AccessConfigFieldsProviderSSH from "./AccessConfigFieldsProviderSSH";
@@ -222,6 +223,7 @@ const providerComponentMap: Partial<Record<AccessProviderType, React.ComponentTy
[ACCESS_PROVIDERS.SAFELINE]: AccessConfigFieldsProviderSafeLine,
[ACCESS_PROVIDERS.SAMWAF]: AccessConfigFieldsProviderSamWAF,
[ACCESS_PROVIDERS.SECTIGO]: AccessConfigFieldsProviderSectigo,
[ACCESS_PROVIDERS.SIMPLYCOM]: AccessConfigFieldsProviderSimplyCom,
[ACCESS_PROVIDERS.SLACKBOT]: AccessConfigFieldsProviderSlackBot,
[ACCESS_PROVIDERS.SPACESHIP]: AccessConfigFieldsProviderSpaceship,
[ACCESS_PROVIDERS.SSLCOM]: AccessConfigFieldsProviderSSLCom,
@@ -0,0 +1,64 @@
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 AccessConfigFormFieldsProviderSimplyCom = () => {
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, "accountNumber"]}
initialValue={initialValues.accountNumber}
label={t("access.form.simplycom_account_number.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.simplycom_account_number.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.simplycom_account_number.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "apiKey"]}
initialValue={initialValues.apiKey}
label={t("access.form.simplycom_api_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.simplycom_api_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.simplycom_api_key.placeholder")} />
</Form.Item>
</>
);
};
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
accountNumber: "",
apiKey: "",
};
};
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
const { t: _ } = i18n;
return z.object({
accountNumber: z.string().nonempty(),
apiKey: z.string().nonempty(),
});
};
const _default = Object.assign(AccessConfigFormFieldsProviderSimplyCom, {
getInitialValues,
getSchema,
});
export default _default;
+4
View File
@@ -114,6 +114,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
SAFELINE: "safeline",
SAMWAF: "samwaf",
SECTIGO: "sectigo",
SIMPLYCOM: "simplycom",
SLACKBOT: "slackbot",
SPACESHIP: "spaceship",
SSH: "ssh",
@@ -251,6 +252,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
[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.SIMPLYCOM, "provider.simplycom", "/imgs/providers/simplycom.png", [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["35CN"], "provider.35cn", "/imgs/providers/35cn.png", [ACCESS_USAGES.DNS]],
@@ -435,6 +437,7 @@ export const ACME_DNS01_PROVIDERS = Object.freeze({
REGRU: `${ACCESS_PROVIDERS.REGRU}`,
RFC2136: `${ACCESS_PROVIDERS.RFC2136}`,
RUCENTER: `${ACCESS_PROVIDERS.RUCENTER}`,
SIMPLYCOM: `${ACCESS_PROVIDERS.SIMPLYCOM}`,
SPACESHIP: `${ACCESS_PROVIDERS.SPACESHIP}`,
UCLOUD: `${ACCESS_PROVIDERS.UCLOUD}`, // 兼容旧值,等同于 `UCLOUD_UDNR`
UCLOUD_UDNR: `${ACCESS_PROVIDERS.UCLOUD}-udnr`,
@@ -509,6 +512,7 @@ export const acmeDns01ProvidersMap: Map<ACMEDns01Provider["type"] | string, ACME
[ACME_DNS01_PROVIDERS.PORKBUN, "provider.porkbun"],
[ACME_DNS01_PROVIDERS.REGRU, "provider.regru"],
[ACME_DNS01_PROVIDERS.RUCENTER, "provider.rucenter"],
[ACME_DNS01_PROVIDERS.SIMPLYCOM, "provider.simplycom"],
[ACME_DNS01_PROVIDERS.SPACESHIP, "provider.spaceship"],
[ACME_DNS01_PROVIDERS.VERCEL, "provider.vercel"],
[ACME_DNS01_PROVIDERS.VULTR, "provider.vultr"],
+10
View File
@@ -1237,6 +1237,16 @@
"sectigo_eab": {
"guide": "Learn more about using EAB key in Sectigo: <br><a href=\"https://www.sectigo.com/enterprise-solutions/certificate-manager/integrations-acme\" target=\"_blank\">https://www.sectigo.com/enterprise-solutions/certificate-manager/integrations-acme</a>"
},
"simplycom_account_number": {
"label": "Simply.com account number",
"placeholder": "Please enter Simply.com account number",
"tooltip": "For more information, see <a href=\"https://www.simply.com/en/docs/api/\" target=\"_blank\">https://www.simply.com/en/docs/api/</a>"
},
"simplycom_api_key": {
"label": "Simply.com API key",
"placeholder": "Please enter Simply.com API key",
"tooltip": "For more information, see <a href=\"https://www.simply.com/en/docs/api/\" target=\"_blank\">https://www.simply.com/en/docs/api/</a>"
},
"slackbot_token": {
"label": "Slack bot token",
"placeholder": "Please enter Slack bot token",
@@ -230,6 +230,7 @@
"safeline": "SafeLine",
"samwaf": "SamWAF",
"sectigo": "Sectigo",
"simplycom": "Simply.com",
"slackbot": "Slack Bot",
"spaceship": "Spaceship",
"ssh": "Remote host (SSH)",
+10
View File
@@ -1237,6 +1237,16 @@
"sectigo_eab": {
"guide": "点击下方链接了解如何获取 Sectigo EAB:<br><a href=\"https://www.sectigo.com/enterprise-solutions/certificate-manager/integrations-acme\" target=\"_blank\">https://www.sectigo.com/enterprise-solutions/certificate-manager/integrations-acme</a>"
},
"simplycom_account_number": {
"label": "Simply.com 账号",
"placeholder": "请输入 Simply.com 账号",
"tooltip": "这是什么?请参阅 <a href=\"https://www.simply.com/en/docs/api/\" target=\"_blank\">https://www.simply.com/en/docs/api/</a>"
},
"simplycom_api_key": {
"label": "Simply.com API Key",
"placeholder": "请输入 Simply.com API Key",
"tooltip": "这是什么?请参阅 <a href=\"https://www.simply.com/en/docs/api/\" target=\"_blank\">https://www.simply.com/en/docs/api/</a>"
},
"slackbot_token": {
"label": "Slack 机器人 Token",
"placeholder": "请输入 Slack 机器人 Token",
@@ -230,6 +230,7 @@
"safeline": "雷池",
"samwaf": "SamWAF",
"sectigo": "Sectigo",
"simplycom": "Simply.com",
"slackbot": "Slack 机器人",
"spaceship": "Spaceship",
"ssh": "远程主机(SSH)",