mirror of
https://github.com/certimate-go/certimate.git
synced 2026-08-29 02:02:04 +08:00
feat(provider): new deployment provider: samwaf
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package deployers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/providers/samwaf"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeSamWAF, func(options *ProviderFactoryOptions) (deployer.Provider, error) {
|
||||
credentials := domain.AccessConfigForSamWAF{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := samwaf.NewDeployer(&samwaf.DeployerConfig{
|
||||
ServerUrl: credentials.ServerUrl,
|
||||
ApiKey: credentials.ApiKey,
|
||||
AllowInsecureConnections: credentials.AllowInsecureConnections,
|
||||
ResourceType: xmaps.GetString(options.ProviderExtendedConfig, "resourceType"),
|
||||
CertificateId: xmaps.GetString(options.ProviderExtendedConfig, "certificateId"),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -487,6 +487,12 @@ type AccessConfigForSafeLine struct {
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForSamWAF struct {
|
||||
ServerUrl string `json:"serverUrl"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForSlackBot struct {
|
||||
BotToken string `json:"botToken"`
|
||||
ChannelId string `json:"channelId,omitempty"`
|
||||
|
||||
@@ -100,6 +100,7 @@ const (
|
||||
AccessProviderTypeRFC2136 = AccessProviderType("rfc2136")
|
||||
AccessProviderTypeS3 = AccessProviderType("s3")
|
||||
AccessProviderTypeSafeLine = AccessProviderType("safeline")
|
||||
AccessProviderTypeSamWAF = AccessProviderType("samwaf")
|
||||
AccessProviderTypeSectigo = AccessProviderType("sectigo")
|
||||
AccessProviderTypeSlackBot = AccessProviderType("slackbot")
|
||||
AccessProviderTypeSpaceship = AccessProviderType("spaceship")
|
||||
@@ -345,6 +346,7 @@ const (
|
||||
DeploymentProviderTypeRatPanelConsole = DeploymentProviderType(AccessProviderTypeRatPanel + "-console")
|
||||
DeploymentProviderTypeS3 = DeploymentProviderType(AccessProviderTypeS3)
|
||||
DeploymentProviderTypeSafeLine = DeploymentProviderType(AccessProviderTypeSafeLine)
|
||||
DeploymentProviderTypeSamWAF = DeploymentProviderType(AccessProviderTypeSamWAF)
|
||||
DeploymentProviderTypeSSH = DeploymentProviderType(AccessProviderTypeSSH)
|
||||
DeploymentProviderTypeSynologyDSM = DeploymentProviderType(AccessProviderTypeSynologyDSM)
|
||||
DeploymentProviderTypeTencentCloudCDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-cdn")
|
||||
|
||||
@@ -42,7 +42,7 @@ Shell command to run this test:
|
||||
func TestDeploy(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Run("Deploy_ToCertificate", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package samwaf
|
||||
|
||||
const (
|
||||
// 资源类型:替换指定证书。
|
||||
RESOURCE_TYPE_CERTIFICATE = "certificate"
|
||||
)
|
||||
@@ -0,0 +1,118 @@
|
||||
package samwaf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
samwafsdk "github.com/certimate-go/certimate/pkg/sdk3rd/samwaf"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// SamWAF 服务地址。
|
||||
ServerUrl string `json:"serverUrl"`
|
||||
// SamWAF API Key。
|
||||
ApiKey string `json:"apiKey"`
|
||||
// 是否允许不安全的连接。
|
||||
AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"`
|
||||
// 部署资源类型。
|
||||
ResourceType string `json:"resourceType"`
|
||||
// 证书 ID。
|
||||
// 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
|
||||
CertificateId string `json:"certificateId,omitempty"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *samwafsdk.Client
|
||||
}
|
||||
|
||||
var _ deployer.Provider = (*Deployer)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
d.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*deployer.DeployResult, error) {
|
||||
// 根据部署资源类型决定部署方式``
|
||||
switch d.config.ResourceType {
|
||||
case RESOURCE_TYPE_CERTIFICATE:
|
||||
if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) deployToCertificate(ctx context.Context, certPEM, privkeyPEM string) error {
|
||||
if d.config.CertificateId == "" {
|
||||
return errors.New("config `certificateId` is required")
|
||||
}
|
||||
|
||||
// 获取 SSL 证书 详情
|
||||
// REF: https://doc.samwaf.com/api/
|
||||
sslConfigDetailResp, err := d.sdkClient.SslConfigDetailWithContext(ctx, d.config.CertificateId)
|
||||
d.logger.Debug("sdk request 'samwaf.SslConfigDetail'", slog.Any("request.sslId", d.config.CertificateId), slog.Any("response", sslConfigDetailResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'samwaf.SslConfigDetail': %w", err)
|
||||
} else if sslConfigDetailResp.Data == nil || sslConfigDetailResp.Data.Id == "" {
|
||||
return fmt.Errorf("could not find ssl config: '%s'", d.config.CertificateId)
|
||||
}
|
||||
|
||||
// 编辑 SSL 证书
|
||||
// REF: https://doc.samwaf.com/api/
|
||||
sslConfigEditReq := &samwafsdk.SslConfigEditRequest{
|
||||
Id: d.config.CertificateId,
|
||||
CertContent: certPEM,
|
||||
KeyContent: privkeyPEM,
|
||||
}
|
||||
sslConfigEditResp, err := d.sdkClient.SslConfigEditWithContext(ctx, sslConfigEditReq)
|
||||
d.logger.Debug("sdk request 'samwaf.SslConfigEdit'", slog.Any("request", sslConfigEditReq), slog.Any("response", sslConfigEditResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'samwaf.SslConfigEdit': %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*samwafsdk.Client, error) {
|
||||
client, err := samwafsdk.NewClient(serverUrl, apiKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if skipTlsVerify {
|
||||
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package samwaf_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/certimate-go/certimate/pkg/core/deployer/providers/samwaf"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fServerUrl string
|
||||
fApiKey string
|
||||
fCertificateId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "SAMWAF_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fServerUrl, argsPrefix+"SERVERURL", "", "")
|
||||
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
|
||||
flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./samwaf_test.go -args \
|
||||
--SAMWAF_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--SAMWAF_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--SAMWAF_SERVERURL="http://127.0.0.1:26666" \
|
||||
--SAMWAF_APIKEY="your-api-key" \
|
||||
--SAMWAF_CERTIFICATEID="your-certificate-id"
|
||||
*/
|
||||
func TestDeploy(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy_ToCertificate", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("SERVERURL: %v", fServerUrl),
|
||||
fmt.Sprintf("APIKEY: %v", fApiKey),
|
||||
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
|
||||
}, "\n"))
|
||||
|
||||
provider, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
ServerUrl: fServerUrl,
|
||||
ApiKey: fApiKey,
|
||||
AllowInsecureConnections: true,
|
||||
ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
|
||||
CertificateId: fCertificateId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := provider.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package samwaf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type SslConfigDetailResponse struct {
|
||||
sdkResponseBase
|
||||
Data *SslConfig `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) SslConfigDetail(sslId string) (*SslConfigDetailResponse, error) {
|
||||
return c.SslConfigDetailWithContext(context.Background(), sslId)
|
||||
}
|
||||
|
||||
func (c *Client) SslConfigDetailWithContext(ctx context.Context, sslId string) (*SslConfigDetailResponse, error) {
|
||||
if sslId == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset sslId")
|
||||
}
|
||||
|
||||
httpreq, err := c.newRequest(http.MethodGet, "/sslconfig/detail")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetQueryParam("id", sslId)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &SslConfigDetailResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package samwaf
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type SslConfigEditRequest struct {
|
||||
Id string `json:"id"`
|
||||
CertContent string `json:"cert_content"`
|
||||
CertPath string `json:"cert_path"`
|
||||
KeyContent string `json:"key_content"`
|
||||
KeyPath string `json:"key_path"`
|
||||
}
|
||||
|
||||
type SslConfigEditResponse struct {
|
||||
sdkResponseBase
|
||||
}
|
||||
|
||||
func (c *Client) SslConfigEdit(req *SslConfigEditRequest) (*SslConfigEditResponse, error) {
|
||||
return c.SslConfigEditWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) SslConfigEditWithContext(ctx context.Context, req *SslConfigEditRequest) (*SslConfigEditResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodPost, "/sslconfig/edit")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetBody(req)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &SslConfigEditResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package samwaf
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/app"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewClient(serverUrl, apiKey string) (*Client, error) {
|
||||
if serverUrl == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset serverUrl")
|
||||
}
|
||||
if _, err := url.Parse(serverUrl); err != nil {
|
||||
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
|
||||
}
|
||||
if apiKey == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset apiKey")
|
||||
}
|
||||
|
||||
client := resty.New().
|
||||
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/api/v1").
|
||||
SetHeader("Accept", "application/json").
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("User-Agent", app.AppUserAgent).
|
||||
SetHeader("X-API-Key", apiKey)
|
||||
|
||||
return &Client{client}, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetTimeout(timeout time.Duration) *Client {
|
||||
c.client.SetTimeout(timeout)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) SetTLSConfig(config *tls.Config) *Client {
|
||||
c.client.SetTLSClientConfig(config)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
|
||||
if method == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset method")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset path")
|
||||
}
|
||||
|
||||
req := c.client.R()
|
||||
req.Method = method
|
||||
req.URL = path
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("sdkerr: nil request")
|
||||
}
|
||||
|
||||
// WARN:
|
||||
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
|
||||
|
||||
resp, err := req.Send()
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
|
||||
} else if resp.IsError() {
|
||||
return resp, fmt.Errorf("sdkerr: unexpected status code: %d (resp: %s)", resp.StatusCode(), resp.String())
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequestWithResult(req *resty.Request, res sdkResponse) (*resty.Response, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("sdkerr: nil request")
|
||||
}
|
||||
|
||||
resp, err := c.doRequest(req)
|
||||
if err != nil {
|
||||
if resp != nil {
|
||||
json.Unmarshal(resp.Body(), &res)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if len(resp.Body()) != 0 {
|
||||
var errRes *sdkResponseBase
|
||||
if err := json.Unmarshal(resp.Body(), &errRes); err == nil {
|
||||
if tcode := errRes.GetCode(); tcode != 0 {
|
||||
return resp, fmt.Errorf("sdkerr: code='%d', msg='%s'", tcode, errRes.GetMsg())
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(resp.Body(), &res); err != nil {
|
||||
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w (resp: %s)", err, resp.String())
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package samwaf
|
||||
|
||||
type sdkResponse interface {
|
||||
GetCode() int
|
||||
GetMsg() string
|
||||
}
|
||||
|
||||
type sdkResponseBase struct {
|
||||
Code int `json:"code,omitempty"`
|
||||
Msg string `json:"msg,omitempty"`
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetCode() int {
|
||||
return r.Code
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetMsg() string {
|
||||
return r.Msg
|
||||
}
|
||||
|
||||
var _ sdkResponse = (*sdkResponseBase)(nil)
|
||||
|
||||
type SslConfig struct {
|
||||
Id string `json:"id"`
|
||||
CertContent string `json:"cert_content"`
|
||||
KeyContent string `json:"key_content"`
|
||||
SerialNo string `json:"serial_no"`
|
||||
Subject string `json:"subject"`
|
||||
Issuer string `json:"issuer"`
|
||||
ValidFrom string `json:"valid_from"`
|
||||
ValidTo string `json:"valid_to"`
|
||||
Domains string `json:"domains"`
|
||||
KeyPath string `json:"key_path"`
|
||||
CertPath string `json:"cert_path"`
|
||||
CreateTime string `json:"create_time"`
|
||||
UpdateTime string `json:"update_time"`
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
@@ -88,6 +88,7 @@ import AccessConfigFieldsProviderRatPanel from "./AccessConfigFieldsProviderRatP
|
||||
import AccessConfigFieldsProviderRFC2136 from "./AccessConfigFieldsProviderRFC2136";
|
||||
import AccessConfigFieldsProviderS3 from "./AccessConfigFieldsProviderS3";
|
||||
import AccessConfigFieldsProviderSafeLine from "./AccessConfigFieldsProviderSafeLine";
|
||||
import AccessConfigFieldsProviderSamWAF from "./AccessConfigFieldsProviderSamWAF";
|
||||
import AccessConfigFieldsProviderSectigo from "./AccessConfigFieldsProviderSectigo";
|
||||
import AccessConfigFieldsProviderSlackBot from "./AccessConfigFieldsProviderSlackBot";
|
||||
import AccessConfigFieldsProviderSpaceship from "./AccessConfigFieldsProviderSpaceship";
|
||||
@@ -202,6 +203,7 @@ const providerComponentMap: Partial<Record<AccessProviderType, React.ComponentTy
|
||||
[ACCESS_PROVIDERS.RFC2136]: AccessConfigFieldsProviderRFC2136,
|
||||
[ACCESS_PROVIDERS.S3]: AccessConfigFieldsProviderS3,
|
||||
[ACCESS_PROVIDERS.SAFELINE]: AccessConfigFieldsProviderSafeLine,
|
||||
[ACCESS_PROVIDERS.SAMWAF]: AccessConfigFieldsProviderSamWAF,
|
||||
[ACCESS_PROVIDERS.SECTIGO]: AccessConfigFieldsProviderSectigo,
|
||||
[ACCESS_PROVIDERS.SLACKBOT]: AccessConfigFieldsProviderSlackBot,
|
||||
[ACCESS_PROVIDERS.SPACESHIP]: AccessConfigFieldsProviderSpaceship,
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Switch } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const AccessConfigFormFieldsProviderSamWAF = () => {
|
||||
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, "serverUrl"]}
|
||||
initialValue={initialValues.serverUrl}
|
||||
label={t("access.form.samwaf_server_url.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input type="url" placeholder={t("access.form.samwaf_server_url.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "apiKey"]}
|
||||
initialValue={initialValues.apiKey}
|
||||
label={t("access.form.samwaf_api_key.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.samwaf_api_key.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.samwaf_api_key.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "allowInsecureConnections"]}
|
||||
initialValue={initialValues.allowInsecureConnections}
|
||||
label={t("access.form.shared_allow_insecure_conns.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
serverUrl: "http://<your-host-addr>:26666/",
|
||||
apiKey: "",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z.object({
|
||||
serverUrl: z.url(t("common.errmsg.url_invalid")),
|
||||
apiKey: z.string().nonempty(t("access.form.samwaf_api_key.placeholder")),
|
||||
allowInsecureConnections: z.boolean().nullish(),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(AccessConfigFormFieldsProviderSamWAF, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { DEPLOYMENT_PROVIDERS, type DeploymentProviderType } from "@/domain/provider";
|
||||
|
||||
import BizDeployNodeConfigFieldsProvider1Panel from "./BizDeployNodeConfigFieldsProvider1Panel.tsx";
|
||||
import BizDeployNodeConfigFieldsProvider1Panel from "./BizDeployNodeConfigFieldsProvider1Panel";
|
||||
import BizDeployNodeConfigFieldsProvider1PanelConsole from "./BizDeployNodeConfigFieldsProvider1PanelConsole";
|
||||
import BizDeployNodeConfigFieldsProviderAliyunALB from "./BizDeployNodeConfigFieldsProviderAliyunALB";
|
||||
import BizDeployNodeConfigFieldsProviderAliyunAPIGW from "./BizDeployNodeConfigFieldsProviderAliyunAPIGW";
|
||||
@@ -30,16 +30,16 @@ import BizDeployNodeConfigFieldsProviderBaiduCloudAppBLB from "./BizDeployNodeCo
|
||||
import BizDeployNodeConfigFieldsProviderBaiduCloudBLB from "./BizDeployNodeConfigFieldsProviderBaiduCloudBLB";
|
||||
import BizDeployNodeConfigFieldsProviderBaiduCloudCDN from "./BizDeployNodeConfigFieldsProviderBaiduCloudCDN";
|
||||
import BizDeployNodeConfigFieldsProviderBaishanCDN from "./BizDeployNodeConfigFieldsProviderBaishanCDN";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanel from "./BizDeployNodeConfigFieldsProviderBaotaPanel.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanel from "./BizDeployNodeConfigFieldsProviderBaotaPanel";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanelConsole from "./BizDeployNodeConfigFieldsProviderBaotaPanelConsole";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanelGo from "./BizDeployNodeConfigFieldsProviderBaotaPanelGo.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanelGo from "./BizDeployNodeConfigFieldsProviderBaotaPanelGo";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaPanelGoConsole from "./BizDeployNodeConfigFieldsProviderBaotaPanelGoConsole";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaWAF from "./BizDeployNodeConfigFieldsProviderBaotaWAF.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaWAFConsole from "./BizDeployNodeConfigFieldsProviderBaotaWAFConsole.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaWAF from "./BizDeployNodeConfigFieldsProviderBaotaWAF";
|
||||
import BizDeployNodeConfigFieldsProviderBaotaWAFConsole from "./BizDeployNodeConfigFieldsProviderBaotaWAFConsole";
|
||||
import BizDeployNodeConfigFieldsProviderBunnyCDN from "./BizDeployNodeConfigFieldsProviderBunnyCDN";
|
||||
import BizDeployNodeConfigFieldsProviderBytePlusCDN from "./BizDeployNodeConfigFieldsProviderBytePlusCDN";
|
||||
import BizDeployNodeConfigFieldsProviderCdnfly from "./BizDeployNodeConfigFieldsProviderCdnfly";
|
||||
import BizDeployNodeConfigFieldsProviderCPanel from "./BizDeployNodeConfigFieldsProviderCPanel.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderCPanel from "./BizDeployNodeConfigFieldsProviderCPanel";
|
||||
import BizDeployNodeConfigFieldsProviderCTCCCloudAO from "./BizDeployNodeConfigFieldsProviderCTCCCloudAO";
|
||||
import BizDeployNodeConfigFieldsProviderCTCCCloudCDN from "./BizDeployNodeConfigFieldsProviderCTCCCloudCDN";
|
||||
import BizDeployNodeConfigFieldsProviderCTCCCloudELB from "./BizDeployNodeConfigFieldsProviderCTCCCloudELB";
|
||||
@@ -70,7 +70,7 @@ import BizDeployNodeConfigFieldsProviderKubernetesSecret from "./BizDeployNodeCo
|
||||
import BizDeployNodeConfigFieldsProviderLeCDN from "./BizDeployNodeConfigFieldsProviderLeCDN";
|
||||
import BizDeployNodeConfigFieldsProviderLocal from "./BizDeployNodeConfigFieldsProviderLocal";
|
||||
import BizDeployNodeConfigFieldsProviderMohuaMVH from "./BizDeployNodeConfigFieldsProviderMohuaMVH";
|
||||
import BizDeployNodeConfigFieldsProviderNetlify from "./BizDeployNodeConfigFieldsProviderNetlify.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderNetlify from "./BizDeployNodeConfigFieldsProviderNetlify";
|
||||
import BizDeployNodeConfigFieldsProviderNginxProxyManager from "./BizDeployNodeConfigFieldsProviderNginxProxyManager";
|
||||
import BizDeployNodeConfigFieldsProviderProxmoxVE from "./BizDeployNodeConfigFieldsProviderProxmoxVE";
|
||||
import BizDeployNodeConfigFieldsProviderQiniuCDN from "./BizDeployNodeConfigFieldsProviderQiniuCDN";
|
||||
@@ -78,9 +78,10 @@ import BizDeployNodeConfigFieldsProviderQiniuKodo from "./BizDeployNodeConfigFie
|
||||
import BizDeployNodeConfigFieldsProviderQiniuPili from "./BizDeployNodeConfigFieldsProviderQiniuPili";
|
||||
import BizDeployNodeConfigFieldsProviderRainYunRCDN from "./BizDeployNodeConfigFieldsProviderRainYunRCDN";
|
||||
import BizDeployNodeConfigFieldsProviderRainYunSSLCenter from "./BizDeployNodeConfigFieldsProviderRainYunSSLCenter";
|
||||
import BizDeployNodeConfigFieldsProviderRatPanel from "./BizDeployNodeConfigFieldsProviderRatPanel.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderRatPanel from "./BizDeployNodeConfigFieldsProviderRatPanel";
|
||||
import BizDeployNodeConfigFieldsProviderS3 from "./BizDeployNodeConfigFieldsProviderS3";
|
||||
import BizDeployNodeConfigFieldsProviderSafeLine from "./BizDeployNodeConfigFieldsProviderSafeLine.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderSafeLine from "./BizDeployNodeConfigFieldsProviderSafeLine";
|
||||
import BizDeployNodeConfigFieldsProviderSamWAF from "./BizDeployNodeConfigFieldsProviderSamWAF";
|
||||
import BizDeployNodeConfigFieldsProviderSSH from "./BizDeployNodeConfigFieldsProviderSSH";
|
||||
import BizDeployNodeConfigFieldsProviderSynologyDSM from "./BizDeployNodeConfigFieldsProviderSynologyDSM";
|
||||
import BizDeployNodeConfigFieldsProviderTencentCloudCDN from "./BizDeployNodeConfigFieldsProviderTencentCloudCDN";
|
||||
@@ -114,8 +115,8 @@ import BizDeployNodeConfigFieldsProviderVolcEngineDCDN from "./BizDeployNodeConf
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineImageX from "./BizDeployNodeConfigFieldsProviderVolcEngineImageX";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineLive from "./BizDeployNodeConfigFieldsProviderVolcEngineLive";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineTOS from "./BizDeployNodeConfigFieldsProviderVolcEngineTOS";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineVOD from "./BizDeployNodeConfigFieldsProviderVolcEngineVOD.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineWAF from "./BizDeployNodeConfigFieldsProviderVolcEngineWAF.tsx";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineVOD from "./BizDeployNodeConfigFieldsProviderVolcEngineVOD";
|
||||
import BizDeployNodeConfigFieldsProviderVolcEngineWAF from "./BizDeployNodeConfigFieldsProviderVolcEngineWAF";
|
||||
import BizDeployNodeConfigFieldsProviderWangsuCDN from "./BizDeployNodeConfigFieldsProviderWangsuCDN";
|
||||
import BizDeployNodeConfigFieldsProviderWangsuCDNPro from "./BizDeployNodeConfigFieldsProviderWangsuCDNPro";
|
||||
import BizDeployNodeConfigFieldsProviderWangsuCertificate from "./BizDeployNodeConfigFieldsProviderWangsuCertificate";
|
||||
@@ -205,6 +206,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
|
||||
[DEPLOYMENT_PROVIDERS.RATPANEL]: BizDeployNodeConfigFieldsProviderRatPanel,
|
||||
[DEPLOYMENT_PROVIDERS.S3]: BizDeployNodeConfigFieldsProviderS3,
|
||||
[DEPLOYMENT_PROVIDERS.SAFELINE]: BizDeployNodeConfigFieldsProviderSafeLine,
|
||||
[DEPLOYMENT_PROVIDERS.SAMWAF]: BizDeployNodeConfigFieldsProviderSamWAF,
|
||||
[DEPLOYMENT_PROVIDERS.SSH]: BizDeployNodeConfigFieldsProviderSSH,
|
||||
[DEPLOYMENT_PROVIDERS.SYNOLOGYDSM]: BizDeployNodeConfigFieldsProviderSynologyDSM,
|
||||
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CDN]: BizDeployNodeConfigFieldsProviderTencentCloudCDN,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import Tips from "@/components/Tips";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const RESOURCE_TYPE_CERTIFICATE = "certificate" as const;
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderSamWAF = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
const fieldResourceType = Form.useWatch([parentNamePath, "resourceType"], formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item>
|
||||
<Tips message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.samwaf.guide") }}></span>} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceType"]}
|
||||
initialValue={initialValues.resourceType}
|
||||
label={t("workflow_node.deploy.form.shared_resource_type.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Select
|
||||
options={[RESOURCE_TYPE_CERTIFICATE].map((s) => ({
|
||||
value: s,
|
||||
label: t(`workflow_node.deploy.form.samwaf_resource_type.option.${s}.label`),
|
||||
}))}
|
||||
placeholder={t("workflow_node.deploy.form.shared_resource_type.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "certificateId"]}
|
||||
initialValue={initialValues.certificateId}
|
||||
label={t("workflow_node.deploy.form.samwaf_certificate_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.samwaf_certificate_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="number" placeholder={t("workflow_node.deploy.form.samwaf_certificate_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
resourceType: RESOURCE_TYPE_CERTIFICATE,
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z
|
||||
.object({
|
||||
resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, t("workflow_node.deploy.form.shared_resource_type.placeholder")),
|
||||
certificateId: z.union([z.string(), z.number().int()]).nullish(),
|
||||
})
|
||||
.superRefine((values, ctx) => {
|
||||
switch (values.resourceType) {
|
||||
case RESOURCE_TYPE_CERTIFICATE:
|
||||
{
|
||||
const scCertificateId = z.coerce.number().int().positive();
|
||||
if (!scCertificateId.safeParse(values.certificateId).success) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: t("workflow_node.deploy.form.samwaf_certificate_id.placeholder"),
|
||||
path: ["certificateId"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderSamWAF, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -104,6 +104,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
RFC2136: "rfc2136",
|
||||
S3: "s3",
|
||||
SAFELINE: "safeline",
|
||||
SAMWAF: "samwaf",
|
||||
SECTIGO: "sectigo",
|
||||
SLACKBOT: "slackbot",
|
||||
SPACESHIP: "spaceship",
|
||||
@@ -199,6 +200,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.PROXMOXVE, "provider.proxmoxve", "/imgs/providers/proxmoxve.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.RATPANEL, "provider.ratpanel", "/imgs/providers/ratpanel.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.SAFELINE, "provider.safeline", "/imgs/providers/safeline.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.SAMWAF, "provider.samwaf", "/imgs/providers/samwaf.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.SYNOLOGYDSM, "provider.synologydsm", "/imgs/providers/synologydsm.png", [ACCESS_USAGES.HOSTING]],
|
||||
|
||||
[ACCESS_PROVIDERS.AKAMAI, "provider.akamai", "/imgs/providers/akamai.svg", [ACCESS_USAGES.DNS]],
|
||||
@@ -639,6 +641,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
RATPANEL_CONSOLE: `${ACCESS_PROVIDERS.RATPANEL}-console`,
|
||||
S3: `${ACCESS_PROVIDERS.S3}`,
|
||||
SAFELINE: `${ACCESS_PROVIDERS.SAFELINE}`,
|
||||
SAMWAF: `${ACCESS_PROVIDERS.SAMWAF}`,
|
||||
SSH: `${ACCESS_PROVIDERS.SSH}`,
|
||||
SYNOLOGYDSM: `${ACCESS_PROVIDERS.SYNOLOGYDSM}`,
|
||||
TENCENTCLOUD_CDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-cdn`,
|
||||
@@ -830,6 +833,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.BAOTAWAF, "provider.baotawaf_common", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.BAOTAWAF_CONSOLE, "provider.baotawaf_console", DEPLOYMENT_CATEGORIES.OTHER],
|
||||
[DEPLOYMENT_PROVIDERS.SAFELINE, "provider.safeline", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.SAMWAF, "provider.samwaf", DEPLOYMENT_CATEGORIES.FIREWALL],
|
||||
[DEPLOYMENT_PROVIDERS.APISIX, "provider.apisix", DEPLOYMENT_CATEGORIES.APIGATEWAY],
|
||||
[DEPLOYMENT_PROVIDERS.KONG, "provider.kong", DEPLOYMENT_CATEGORIES.APIGATEWAY],
|
||||
[DEPLOYMENT_PROVIDERS.CPANEL, "provider.cpanel", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
|
||||
@@ -571,6 +571,11 @@
|
||||
"access.form.s3_signature_version.placeholder": "Please select signature version",
|
||||
"access.form.s3_use_path_style.label": "Use path style addressing",
|
||||
"access.form.s3_use_path_style.tooltip": "<ol style=\"list-style: disc;\"><li>Virtual-hosted style (default): https://<BUCKET>.<ENDPOINT>/<KEY> </li><li>Path style: https://<ENDPOINT>/<BUCKET>/<KEY> </li></ol>",
|
||||
"access.form.samwaf_server_url.label": "SamWAF server URL",
|
||||
"access.form.samwaf_server_url.placeholder": "Please enter SamWAF server URL",
|
||||
"access.form.samwaf_api_key.label": "SamWAF API Key",
|
||||
"access.form.samwaf_api_key.placeholder": "Please enter SamWAF API Key",
|
||||
"access.form.samwaf_api_key.tooltip": "For more information, see <a href=\"https://doc.samwaf.com/api/\" target=\"_blank\">https://doc.samwaf.com/api/</a>",
|
||||
"access.form.safeline_server_url.label": "SafeLine server URL",
|
||||
"access.form.safeline_server_url.placeholder": "Please enter SafeLine server URL",
|
||||
"access.form.safeline_api_token.label": "SafeLine API token",
|
||||
|
||||
@@ -171,6 +171,7 @@
|
||||
"provider.s3": "Object storage (S3-compatible)",
|
||||
"provider.s3_upload": "Upload to S3-compatible object storage",
|
||||
"provider.safeline": "SafeLine",
|
||||
"provider.samwaf": "SamWAF",
|
||||
"provider.sectigo": "Sectigo",
|
||||
"provider.slackbot": "Slack Bot",
|
||||
"provider.spaceship": "Spaceship",
|
||||
|
||||
@@ -574,7 +574,7 @@
|
||||
"workflow_node.deploy.form.flexcdn_resource_type.option.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.label": "FlexCDN certificate ID",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.placeholder": "Please enter FlexCDN certificate ID",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.tooltip": "You can find it on FlexCDN dashboard.",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.tooltip": "You can find it on FlexCDN dashboard. <br><br>(Please open the browser devtools, and visit the \"网站列表 -> 证书管理 -> 证书\" page to capture network requests, then you can get the certificate ID.)",
|
||||
"workflow_node.deploy.form.flyio_app_name.label": "Fly.io App name",
|
||||
"workflow_node.deploy.form.flyio_app_name.placeholder": "Please enter Fly.io App name",
|
||||
"workflow_node.deploy.form.flyio_domain.label": "Fly.io custom domain",
|
||||
@@ -590,7 +590,7 @@
|
||||
"workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge certificate ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.placeholder": "Please enter GoEdge certificate ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.tooltip": "You can find it on GoEdge dashboard.",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.tooltip": "You can find it on GoEdge dashboard. <br><br>(Please open the browser devtools, and visit the \"网站列表 -> 证书管理 -> 证书\" page to capture network requests, then you can get the certificate ID.)",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_domain.label": "Huawei Cloud AAD domain",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_domain.placeholder": "Please enter Huawei Cloud AAD domain name",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_instance_id.label": "Huawei Cloud AAD instance ID",
|
||||
@@ -875,6 +875,11 @@
|
||||
"workflow_node.deploy.form.safeline_certificate_id.label": "SafeLine certificate ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.placeholder": "Please enter SafeLine certificate ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.tooltip": "You can find it on SafeLine dashboard.",
|
||||
"workflow_node.deploy.form.samwaf.guide": "Requires SamWAF v1.3.20 or higher.",
|
||||
"workflow_node.deploy.form.samwaf_resource_type.option.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.label": "SamWAF certificate ID",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.placeholder": "Please enter SamWAF certificate ID",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.tooltip": "You can find it on SamWAF dashboard.",
|
||||
"workflow_node.deploy.form.ssh_format.label": "File format",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
"access.form.shared_acme_eab_kid.placeholder": "请输入 ACME EAB KID",
|
||||
"access.form.shared_acme_eab_hmac_key.label": "ACME EAB HMAC Key",
|
||||
"access.form.shared_acme_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC Key",
|
||||
"access.form.shared_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误",
|
||||
"access.form.shared_allow_insecure_conns.label": "忽略 SSL/TLS 证书验证",
|
||||
"access.form.1panel_server_url.label": "1Panel 服务地址",
|
||||
"access.form.1panel_server_url.placeholder": "请输入 1Panel 服务地址",
|
||||
"access.form.1panel_server_url.help": "提示:请勿包含安全入口后缀。",
|
||||
@@ -571,6 +571,11 @@
|
||||
"access.form.s3_signature_version.placeholder": "请选择签名版本",
|
||||
"access.form.s3_use_path_style.label": "使用路径风格地址",
|
||||
"access.form.s3_use_path_style.tooltip": "<ol style=\"list-style: disc;\"><li>虚拟托管风格(默认):<br><em>https://<BUCKET>.<ENDPOINT>/<KEY></em> </li><li>路径风格:<br><em>https://<ENDPOINT>/<BUCKET>/<KEY></em> </li></ol>",
|
||||
"access.form.samwaf_server_url.label": "SamWAF 服务地址",
|
||||
"access.form.samwaf_server_url.placeholder": "请输入 SamWAF 服务地址",
|
||||
"access.form.samwaf_api_key.label": "SamWAF API Key",
|
||||
"access.form.samwaf_api_key.placeholder": "请输入 SamWAF API Key",
|
||||
"access.form.samwaf_api_key.tooltip": "这是什么?请参阅 <a href=\"https://doc.samwaf.com/api/\" target=\"_blank\">https://doc.samwaf.com/api/</a>",
|
||||
"access.form.safeline_server_url.label": "雷池服务地址",
|
||||
"access.form.safeline_server_url.placeholder": "请输入雷池服务地址",
|
||||
"access.form.safeline_api_token.label": "雷池 API Token",
|
||||
|
||||
@@ -171,6 +171,7 @@
|
||||
"provider.s3": "对象存储(S3 兼容)",
|
||||
"provider.s3_upload": "上传到 S3 兼容的对象存储",
|
||||
"provider.safeline": "雷池",
|
||||
"provider.samwaf": "SamWAF",
|
||||
"provider.sectigo": "Sectigo",
|
||||
"provider.slackbot": "Slack 机器人",
|
||||
"provider.spaceship": "Spaceship",
|
||||
|
||||
@@ -572,7 +572,7 @@
|
||||
"workflow_node.deploy.form.flexcdn_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.label": "FlexCDN 证书 ID",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.placeholder": "请输入 FlexCDN 证书 ID",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.tooltip": "请登录 FlexCDN 控制台查看",
|
||||
"workflow_node.deploy.form.flexcdn_certificate_id.tooltip": "请登录 FlexCDN 控制台查看<br><br>(目前需要在「网站列表 -> 证书管理 -> 证书」页面,并打开浏览器开发者工具抓取网络请求后得到证书 ID)",
|
||||
"workflow_node.deploy.form.flyio_app_name.label": "Fly.io 应用名称",
|
||||
"workflow_node.deploy.form.flyio_app_name.placeholder": "请输入 Fly.io 应用名称",
|
||||
"workflow_node.deploy.form.flyio_domain.label": "Fly.io 自定义域名",
|
||||
@@ -588,7 +588,7 @@
|
||||
"workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge 证书 ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.placeholder": "请输入 GoEdge 证书 ID",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.tooltip": "请登录 GoEdge 控制台查看",
|
||||
"workflow_node.deploy.form.goedge_certificate_id.tooltip": "请登录 GoEdge 控制台查看<br><br>(目前需要在「网站列表 -> 证书管理 -> 证书」页面,并打开浏览器开发者工具抓取网络请求后得到证书 ID)",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_instance_id.label": "华为云 DDoS 高防实例 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_instance_id.placeholder": "请输入华为云 DDoS 高防实例 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_aad_instance_id.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/cnad/#/cnad/cad/list\" target=\"_blank\">https://console.huaweicloud.com/cnad/#/cnad/cad/list</a>",
|
||||
@@ -873,6 +873,11 @@
|
||||
"workflow_node.deploy.form.safeline_certificate_id.label": "雷池证书 ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.placeholder": "请输入雷池证书 ID",
|
||||
"workflow_node.deploy.form.safeline_certificate_id.tooltip": "请登录雷池控制台查看",
|
||||
"workflow_node.deploy.form.samwaf.guide": "需要 SamWAF v1.3.20 或更高版本。",
|
||||
"workflow_node.deploy.form.samwaf_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.label": "SamWAF 证书 ID",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.placeholder": "请输入 SamWAF 证书 ID",
|
||||
"workflow_node.deploy.form.samwaf_certificate_id.tooltip": "请登录 SamWAF 控制台查看",
|
||||
"workflow_node.deploy.form.ssh_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
|
||||
Reference in New Issue
Block a user