From cb7e388bd393241a8bc6a1a02a11f6eec9e207b5 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 29 Jul 2026 17:02:13 +0800 Subject: [PATCH] feat(provider): new acme dns-01 provider: yandexcloud --- go.mod | 9 +++ go.sum | 17 +++++ .../certacme/certifiers/sp_yandexcloud_dns.go | 29 ++++++++ internal/domain/access.go | 5 ++ internal/domain/provider.go | 3 + .../dns01/yandexcloud/yandexcloud.go | 41 ++++++++++++ ui/public/imgs/providers/yandexcloud.svg | 1 + .../forms/AccessConfigFieldsProvider.tsx | 2 + .../AccessConfigFieldsProviderGoogleCloud.tsx | 1 + .../AccessConfigFieldsProviderYandexCloud.tsx | 67 +++++++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/resources/en/nls.access.json | 16 ++++- ui/src/i18n/resources/en/nls.provider.json | 2 + .../i18n/resources/en/nls.workflow.nodes.json | 8 +-- ui/src/i18n/resources/zh/nls.access.json | 16 ++++- ui/src/i18n/resources/zh/nls.provider.json | 2 + .../i18n/resources/zh/nls.workflow.nodes.json | 6 +- 17 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 internal/certacme/certifiers/sp_yandexcloud_dns.go create mode 100644 pkg/core/certifier/challengers/dns01/yandexcloud/yandexcloud.go create mode 100644 ui/public/imgs/providers/yandexcloud.svg create mode 100644 ui/src/components/access/forms/AccessConfigFieldsProviderYandexCloud.tsx diff --git a/go.mod b/go.mod index 422b6b6ee..b64a65404 100644 --- a/go.mod +++ b/go.mod @@ -203,6 +203,7 @@ require ( github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/ganigeorgiev/fexpr v0.5.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/go-acme/alidns-20150109/v5 v5.4.1 // indirect github.com/go-acme/esa-20240910/v3 v3.2.2 // indirect github.com/go-acme/jdcloud-sdk-go v1.64.0 // indirect @@ -212,6 +213,8 @@ require ( github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect github.com/go-test/deep v1.1.1 // indirect github.com/gofrs/flock v0.13.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.17 // indirect @@ -254,6 +257,9 @@ require ( github.com/spf13/cast v1.10.0 // indirect github.com/tinylib/msgp v1.6.4 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/yandex-cloud/go-genproto v0.84.0 // indirect + github.com/yandex-cloud/go-sdk/services/dns v0.0.65 // indirect + github.com/yandex-cloud/go-sdk/v2 v2.114.0 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/zeebo/xxh3 v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect @@ -261,6 +267,8 @@ require ( go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/image v0.41.0 // indirect golang.org/x/mod v0.37.0 // indirect golang.org/x/net v0.56.0 // indirect @@ -268,6 +276,7 @@ require ( golang.org/x/text v0.40.0 // indirect golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.47.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 // indirect google.golang.org/grpc v1.82.0 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/go.sum b/go.sum index 8d7507d9f..dd9afcde6 100644 --- a/go.sum +++ b/go.sum @@ -349,6 +349,7 @@ github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9 github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk= github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-acme/alidns-20150109/v5 v5.4.1 h1:Bp+EDtIGxBVKnIq1hPECBFf6eueTiESYqsHkY+T+CIQ= github.com/go-acme/alidns-20150109/v5 v5.4.1/go.mod h1:L+SrZRmoQFx2UzOqng3z3+LA/gNgFCaLXrwr/ndyW6g= @@ -448,6 +449,8 @@ github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= +github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= @@ -704,6 +707,8 @@ github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXx github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -948,6 +953,12 @@ github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6 github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/yandex-cloud/go-genproto v0.84.0 h1:lzptMyo1wleGBGNkkEb8bzpgbnW3xPlha0f94g4prBE= +github.com/yandex-cloud/go-genproto v0.84.0/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo= +github.com/yandex-cloud/go-sdk/services/dns v0.0.65 h1:7jhZMHsK1GThGzAKC7Mjq8wu/Xbr/TbhRUoNFzot4K4= +github.com/yandex-cloud/go-sdk/services/dns v0.0.65/go.mod h1:Qm5HbUbmFI2Y8eDv8tcwr7OHgNumHuN/RtK3icd3bYU= +github.com/yandex-cloud/go-sdk/v2 v2.114.0 h1:gx03giWYrzMhgpFK4NJNuOnASSgdCuv4nkLUFejnCSs= +github.com/yandex-cloud/go-sdk/v2 v2.114.0/go.mod h1:XrF79/a3olVf0YUUCMYePI8Ik0m4KDcQlTooHGGZJB0= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= @@ -1000,12 +1011,18 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= diff --git a/internal/certacme/certifiers/sp_yandexcloud_dns.go b/internal/certacme/certifiers/sp_yandexcloud_dns.go new file mode 100644 index 000000000..eb6f91e88 --- /dev/null +++ b/internal/certacme/certifiers/sp_yandexcloud_dns.go @@ -0,0 +1,29 @@ +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/yandexcloud" + xmaps "github.com/certimate-go/certimate/pkg/utils/maps" +) + +func init() { + ACMEDns01Registries.MustRegister(domain.ACMEDns01ProviderTypeYandexCloudDNS, func(options *ProviderFactoryOptions) (core.ACMEChallenger, error) { + credentials := domain.AccessConfigForYandexCloud{} + 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{ + FolderId: credentials.FolderId, + ServiceAccountKey: credentials.ServiceAccountKey, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return provider, err + }) + + ACMEDns01Registries.MustRegisterAlias(domain.ACMEDns01ProviderTypeYandexCloud, domain.ACMEDns01ProviderTypeYandexCloudDNS) +} diff --git a/internal/domain/access.go b/internal/domain/access.go index 59ba16567..13a130e58 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -688,6 +688,11 @@ type AccessConfigForXinnet struct { ApiPassword string `json:"apiPassword"` } +type AccessConfigForYandexCloud struct { + FolderId string `json:"folderId"` + ServiceAccountKey string `json:"serviceAccountKey"` +} + type AccessConfigForZenlayer struct { AccessKeyId string `json:"accessKeyId"` AccessKeyPassword string `json:"accessKeyPassword"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 3d131a484..0d88f5dcc 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -136,6 +136,7 @@ const ( AccessProviderTypeWeComBot = AccessProviderType("wecombot") AccessProviderTypeWestcn = AccessProviderType("westcn") AccessProviderTypeXinnet = AccessProviderType("xinnet") + AccessProviderTypeYandexCloud = AccessProviderType("yandexcloud") AccessProviderTypeZenlayer = AccessProviderType("zenlayer") AccessProviderTypeZeroSSL = AccessProviderType("zerossl") ) @@ -275,6 +276,8 @@ const ( ACMEDns01ProviderTypeVultr = ACMEDns01ProviderType(AccessProviderTypeVultr) ACMEDns01ProviderTypeWestcn = ACMEDns01ProviderType(AccessProviderTypeWestcn) ACMEDns01ProviderTypeXinnet = ACMEDns01ProviderType(AccessProviderTypeXinnet) + ACMEDns01ProviderTypeYandexCloud = ACMEDns01ProviderType(AccessProviderTypeYandexCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeYandexCloudDNS] + ACMEDns01ProviderTypeYandexCloudDNS = ACMEDns01ProviderType(AccessProviderTypeYandexCloud + "-dns") ) type ACMEHttp01ProviderType ACMEChallengeProviderType diff --git a/pkg/core/certifier/challengers/dns01/yandexcloud/yandexcloud.go b/pkg/core/certifier/challengers/dns01/yandexcloud/yandexcloud.go new file mode 100644 index 000000000..6bb2f4f9b --- /dev/null +++ b/pkg/core/certifier/challengers/dns01/yandexcloud/yandexcloud.go @@ -0,0 +1,41 @@ +package yandexcloud + +import ( + "encoding/base64" + "fmt" + "time" + + "github.com/go-acme/lego/v5/providers/dns/yandexcloud" + + "github.com/certimate-go/certimate/pkg/core" +) + +type ChallengerConfig struct { + FolderId string `json:"folderId"` + ServiceAccountKey string `json:"serviceAccountKey"` + 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 := yandexcloud.NewDefaultConfig() + providerConfig.FolderID = config.FolderId + providerConfig.IamToken = base64.StdEncoding.EncodeToString([]byte(config.ServiceAccountKey)) + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + + provider, err := yandexcloud.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/yandexcloud.svg b/ui/public/imgs/providers/yandexcloud.svg new file mode 100644 index 000000000..1186d7a76 --- /dev/null +++ b/ui/public/imgs/providers/yandexcloud.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx index 8657c105d..920d9466d 100644 --- a/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx +++ b/ui/src/components/access/forms/AccessConfigFieldsProvider.tsx @@ -120,6 +120,7 @@ import AccessConfigFieldsProviderWebhook from "./AccessConfigFieldsProviderWebho import AccessConfigFieldsProviderWeComBot from "./AccessConfigFieldsProviderWeComBot"; import AccessConfigFieldsProviderWestcn from "./AccessConfigFieldsProviderWestcn"; import AccessConfigFieldsProviderXinnet from "./AccessConfigFieldsProviderXinnet"; +import AccessConfigFieldsProviderYandexCloud from "./AccessConfigFieldsProviderYandexCloud"; import AccessConfigFieldsProviderZenlayer from "./AccessConfigFieldsProviderZenlayer"; import AccessConfigFieldsProviderZeroSSL from "./AccessConfigFieldsProviderZeroSSL"; @@ -246,6 +247,7 @@ const providerComponentMap: Partial { initialValue={initialValues.projectId} label={t("access.form.googlecloud_project_id.label")} rules={[formRule]} + tooltip={} > diff --git a/ui/src/components/access/forms/AccessConfigFieldsProviderYandexCloud.tsx b/ui/src/components/access/forms/AccessConfigFieldsProviderYandexCloud.tsx new file mode 100644 index 000000000..f1ba4631b --- /dev/null +++ b/ui/src/components/access/forms/AccessConfigFieldsProviderYandexCloud.tsx @@ -0,0 +1,67 @@ +import { getI18n, useTranslation } from "react-i18next"; +import { Form, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import FileTextInput from "@/components/FileTextInput"; +import { isJsonObject } from "@/utils/validator"; + +import { useFormNestedFieldsContext } from "./_context"; + +const AccessConfigFieldsProviderYandexCloud = () => { + const { i18n, t } = useTranslation(); + + const { parentNamePath } = useFormNestedFieldsContext(); + const formSchema = z.object({ + [parentNamePath]: getSchema({ i18n }), + }); + const formRule = createSchemaFieldRule(formSchema); + const initialValues = getInitialValues(); + + return ( + <> + } + > + + + + } + > + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + folderId: "", + serviceAccountKey: "", + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType }) => { + const { t } = i18n; + + return z.object({ + folderId: z.string().nonempty(), + serviceAccountKey: z.string().refine((v) => isJsonObject(v), t("common.errmsg.json_invalid")), + }); +}; + +const _default = Object.assign(AccessConfigFieldsProviderYandexCloud, { + getInitialValues, + getSchema, +}); + +export default _default; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index f3b247028..6efb6fcf6 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -136,6 +136,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ WECOMBOT: "wecombot", WESTCN: "westcn", XINNET: "xinnet", + YANDEXCLOUD: "yandexcloud", ZENLAYER: "zenlayer", ZEROSSL: "zerossl", } as const); @@ -257,6 +258,7 @@ export const accessProvidersMap: Maphttps://github.com/joohoi/acme-dns" }, "acmehttpreq_endpoint": { @@ -737,7 +737,7 @@ }, "googlecloud_project_id": { "label": "GCP project ID", - "placeholder": "Please enter GCP project ID", + "placeholder": "Please enter GCP project ID\r\n\r\n{\r\n \"name\": \"projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL/keys/KEY_ID\",\r\n \"privateKeyType\": \"TYPE_GOOGLE_CREDENTIALS_FILE\",\r\n \"privateKeyData\": \"ENCODED_PRIVATE_KEY\",\r\n \"validAfterTime\": \"DATE\",\r\n \"validBeforeTime\": \"DATE\",\r\n \"keyAlgorithm\": \"KEY_ALG_RSA_2048\"\r\n}", "tooltip": "For more information, see https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects" }, "googlecloud_service_account_key": { @@ -1353,7 +1353,7 @@ }, "ssh_key": { "label": "SSH key", - "placeholder": "Please enter SSH key" + "placeholder": "Please enter SSH key\r\n\r\n-----BEGIN OPENSSH PRIVATE KEY-----\r\n...\r\n-----END OPENSSH PRIVATE KEY-----" }, "ssh_key_passphrase": { "label": "SSH key passphrase (Optional)", @@ -1586,6 +1586,16 @@ "xinnet_agent": { "guide": "Xinnet.com API only supports calls from agents. Learn more about this:
https://apidoc.xin.cn/doc-7283837" }, + "yandexcloud_folder_id": { + "label": "Yandex Cloud folder ID", + "placeholder": "Please enter Yandex Cloud folder ID", + "tooltip": "For more information, see https://yandex.cloud/en/docs/resource-manager/operations/folder/get-id" + }, + "yandexcloud_service_account_key": { + "label": "Yandex Cloud service account authorized key", + "placeholder": "Please enter Yandex Cloud service account authorized key\r\n\r\n{\r\n \"id\": \"AUTHORIZED_KEY_ID\",\r\n \"service_account_id\": \"SERVICE_ACCOUNT_ID\",\r\n \"created_at\": \"DATE\",\r\n \"key_algorithm\": \"RSA_2048\",\r\n \"public_key\": \"ENCODED_PUBLIC_KEY\",\r\n \"private_key\": \"ENCODED_PRIVATE_KEY\"\r\n}", + "tooltip": "For more information, see https://yandex.cloud/en/docs/iam/operations/authentication/manage-authorized-keys" + }, "zenlayer_access_key_id": { "label": "Zenlayer AccessKeyID", "placeholder": "Please enter Zenlayer AccessKeyID", diff --git a/ui/src/i18n/resources/en/nls.provider.json b/ui/src/i18n/resources/en/nls.provider.json index c6e78f7e7..6e6cd29ee 100644 --- a/ui/src/i18n/resources/en/nls.provider.json +++ b/ui/src/i18n/resources/en/nls.provider.json @@ -298,6 +298,8 @@ "wecombot": "WeCom Bot", "westcn": "West.cn", "xinnet": "Xinnet.com", + "yandexcloud": "Yandex Cloud", + "yandexcloud_dns": "Yandex Cloud - DNS", "zerossl": "ZeroSSL", "zenlayer": "Zenlayer", "zenlayer_cdn": "Zenlayer - CDN (Content Delivery Network)", diff --git a/ui/src/i18n/resources/en/nls.workflow.nodes.json b/ui/src/i18n/resources/en/nls.workflow.nodes.json index 71a70d2e6..a0b1ca4ac 100644 --- a/ui/src/i18n/resources/en/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/en/nls.workflow.nodes.json @@ -183,7 +183,7 @@ }, "key_content": { "label": "Private key (PEM format)", - "placeholder": "-----BEGIN (RSA|EC) PRIVATE KEY-----...-----END(RSA|EC) PRIVATE KEY-----", + "placeholder": "Please enter private key\r\n\r\n-----BEGIN (RSA|EC) PRIVATE KEY-----\r\n...\r\n-----END (RSA|EC) PRIVATE KEY-----", "errmsg": { "invalid": "Invalid PEM private key", "not_matched": "Private key does not match the key algorithm (Expected: {{expected}}, Actual: {{actual}})" @@ -375,11 +375,11 @@ }, "name": { "label": "Domains / IP addresses", - "placholder": "Please select certificate file" + "placeholder": "Please select certificate file" }, "certificate_pem": { "label": "Certificate (PEM format)", - "placeholder": "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----", + "placeholder": "Please enter certificate\r\n\r\n-----BEGIN CERTIFICATE-----\r\n...\r\n-----END CERTIFICATE-----", "errmsg": { "invalid": "Invalid PEM certificate" } @@ -394,7 +394,7 @@ }, "private_key_pem": { "label": "Private key (PEM format)", - "placeholder": "-----BEGIN (RSA|EC) PRIVATE KEY-----...-----END(RSA|EC) PRIVATE KEY-----", + "placeholder": "Please enter private key\r\n\r\n-----BEGIN (RSA|EC) PRIVATE KEY-----\r\n...\r\n-----END (RSA|EC) PRIVATE KEY-----", "errmsg": { "invalid": "Invalid PEM private key" } diff --git a/ui/src/i18n/resources/zh/nls.access.json b/ui/src/i18n/resources/zh/nls.access.json index 1fbf5cb43..59b6497dd 100644 --- a/ui/src/i18n/resources/zh/nls.access.json +++ b/ui/src/i18n/resources/zh/nls.access.json @@ -145,7 +145,7 @@ }, "acmedns_credentials": { "label": "ACME-DNS 凭证文件", - "placeholder": "请输入 ACME-DNS 凭证文件", + "placeholder": "请输入 ACME-DNS 凭证文件\r\n\r\n{\r\n \"allowfrom\": [\r\n \"192.168.100.1/24\",\r\n \"1.2.3.4/32\",\r\n \"2002:c0a8:2a00::0/40\"\r\n ],\r\n \"fulldomain\": \"SUBDOMAIN.auth.acme-dns.io\",\r\n \"subdomain\": \"SUBDOMAIN\",\r\n \"username\": \"USERNAME\",\r\n \"password\": \"PASSWORD\"\r\n}", "tooltip": "这是什么?请参阅 https://github.com/joohoi/acme-dns" }, "acmehttpreq_endpoint": { @@ -742,7 +742,7 @@ }, "googlecloud_service_account_key": { "label": "GCP 服务账号密钥", - "placeholder": "请输入 GCP 服务账号密钥", + "placeholder": "请输入 GCP 服务账号密钥\r\n\r\n{\r\n \"name\": \"projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL/keys/KEY_ID\",\r\n \"privateKeyType\": \"TYPE_GOOGLE_CREDENTIALS_FILE\",\r\n \"privateKeyData\": \"ENCODED_PRIVATE_KEY\",\r\n \"validAfterTime\": \"DATE\",\r\n \"validBeforeTime\": \"DATE\",\r\n \"keyAlgorithm\": \"KEY_ALG_RSA_2048\"\r\n}", "tooltip": "这是什么?请参阅 https://docs.cloud.google.com/iam/docs/keys-create-delete" }, "googletrustservices_eab": { @@ -1353,7 +1353,7 @@ }, "ssh_key": { "label": "SSH 密钥", - "placeholder": "请输入 SSH 密钥文件内容" + "placeholder": "请输入 SSH 密钥文件内容\r\n\r\n-----BEGIN OPENSSH PRIVATE KEY-----\r\n...\r\n-----END OPENSSH PRIVATE KEY-----" }, "ssh_key_passphrase": { "label": "SSH 密钥口令(可选)", @@ -1585,6 +1585,16 @@ "xinnet_agent": { "guide": "新网数码 API 仅支持代理商调用。点击下方链接了解更多:
https://apidoc.xin.cn/doc-7283837" }, + "yandexcloud_folder_id": { + "label": "Yandex Cloud 项目文件夹 ID", + "placeholder": "请输入 Yandex Cloud 项目文件夹 ID", + "tooltip": "这是什么?请参阅 https://yandex.cloud/en/docs/resource-manager/operations/folder/get-id" + }, + "yandexcloud_service_account_key": { + "label": "Yandex Cloud 服务账号授权密钥", + "placeholder": "请输入Yandex Cloud 服务账号授权密钥\r\n\r\n{\r\n \"id\": \"AUTHORIZED_KEY_ID\",\r\n \"service_account_id\": \"SERVICE_ACCOUNT_ID\",\r\n \"created_at\": \"DATE\",\r\n \"key_algorithm\": \"RSA_2048\",\r\n \"public_key\": \"ENCODED_PUBLIC_KEY\",\r\n \"private_key\": \"ENCODED_PRIVATE_KEY\"\r\n}", + "tooltip": "这是什么?请参阅 https://yandex.cloud/en/docs/iam/operations/authentication/manage-authorized-keys" + }, "zenlayer_access_key_id": { "label": "Zenlayer AccessKeyID", "placeholder": "请输入 Zenlayer AccessKeyID", diff --git a/ui/src/i18n/resources/zh/nls.provider.json b/ui/src/i18n/resources/zh/nls.provider.json index 70baabbd8..d0ddaaacd 100644 --- a/ui/src/i18n/resources/zh/nls.provider.json +++ b/ui/src/i18n/resources/zh/nls.provider.json @@ -298,6 +298,8 @@ "wecombot": "企业微信群机器人", "westcn": "西部数码", "xinnet": "新网数码", + "yandexcloud": "Yandex Cloud", + "yandexcloud_dns": "Yandex Cloud - DNS", "zerossl": "ZeroSSL", "zenlayer": "Zenlayer", "zenlayer_cdn": "Zenlayer - 内容分发网络 CDN", diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index dcf9e98a8..ea4553d5d 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -183,7 +183,7 @@ }, "key_content": { "label": "私钥文件(PEM 格式)", - "placeholder": "-----BEGIN (RSA|EC) PRIVATE KEY-----...-----END(RSA|EC) PRIVATE KEY-----", + "placeholder": "请输入私钥文件内容\r\n\r\n-----BEGIN (RSA|EC) PRIVATE KEY-----\r\n...\r\n-----END (RSA|EC) PRIVATE KEY-----", "errmsg": { "invalid": "无效的 PEM 格式私钥文件", "not_matched": "私钥内容与算法不匹配(预期:{{expected}},实际:{{actual}})" @@ -378,7 +378,7 @@ }, "certificate_pem": { "label": "证书文件(PEM 格式)", - "placeholder": "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----", + "placeholder": "请输入证书文件内容\r\n\r\n-----BEGIN CERTIFICATE-----\r\n...\r\n-----END CERTIFICATE-----", "errmsg": { "invalid": "无效的 PEM 格式证书文件" } @@ -393,7 +393,7 @@ }, "private_key_pem": { "label": "私钥文件(PEM 格式)", - "placeholder": "-----BEGIN (RSA|EC) PRIVATE KEY-----...-----END(RSA|EC) PRIVATE KEY-----", + "placeholder": "请输入私钥文件内容\r\n\r\n-----BEGIN (RSA|EC) PRIVATE KEY-----\r\n...\r\n-----END (RSA|EC) PRIVATE KEY-----", "errmsg": { "invalid": "无效的 PEM 格式私钥文件" }