package apisix import ( "context" "crypto/tls" "errors" "fmt" "log/slog" "github.com/usual2970/certimate/pkg/core" apisixsdk "github.com/usual2970/certimate/pkg/sdk3rd/apisix" xcert "github.com/usual2970/certimate/pkg/utils/cert" xtypes "github.com/usual2970/certimate/pkg/utils/types" ) type SSLDeployerProviderConfig struct { // APISIX 服务地址。 ServerUrl string `json:"serverUrl"` // APISIX Admin API Key。 ApiKey string `json:"apiKey"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` // 部署资源类型。 ResourceType ResourceType `json:"resourceType"` // 证书 ID。 // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 CertificateId string `json:"certificateId,omitempty"` } type SSLDeployerProvider struct { config *SSLDeployerProviderConfig logger *slog.Logger sdkClient *apisixsdk.Client } var _ core.SSLDeployer = (*SSLDeployerProvider)(nil) func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProvider, error) { if config == nil { return nil, errors.New("the configuration of the ssl deployer provider is nil") } client, err := createSDKClient(config.ServerUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { return nil, fmt.Errorf("could not create sdk client: %w", err) } return &SSLDeployerProvider{ config: config, logger: slog.Default(), sdkClient: client, }, nil } func (d *SSLDeployerProvider) SetLogger(logger *slog.Logger) { if logger == nil { d.logger = slog.New(slog.DiscardHandler) } else { d.logger = logger } } func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*core.SSLDeployResult, 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 &core.SSLDeployResult{}, nil } func (d *SSLDeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } // 解析证书内容 certX509, err := xcert.ParseCertificateFromPEM(certPEM) if err != nil { return err } // 更新 SSL 证书 // REF: https://apisix.apache.org/zh/docs/apisix/admin-api/#ssl updateSSLReq := &apisixsdk.UpdateSSLRequest{ Cert: xtypes.ToPtr(certPEM), Key: xtypes.ToPtr(privkeyPEM), SNIs: xtypes.ToPtr(certX509.DNSNames), Type: xtypes.ToPtr("server"), Status: xtypes.ToPtr(int32(1)), } updateSSLResp, err := d.sdkClient.UpdateSSL(d.config.CertificateId, updateSSLReq) d.logger.Debug("sdk request 'apisix.UpdateSSL'", slog.String("sslId", d.config.CertificateId), slog.Any("request", updateSSLReq), slog.Any("response", updateSSLResp)) if err != nil { return fmt.Errorf("failed to execute sdk request 'apisix.UpdateSSL': %w", err) } return nil } func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*apisixsdk.Client, error) { client, err := apisixsdk.NewClient(serverUrl, apiKey) if err != nil { return nil, err } if skipTlsVerify { client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true}) } return client, nil }