|
@@ -41,6 +41,8 @@ type WafFormatterService interface {
|
|
|
ConvertToPunycodeIfIDN(ctx context.Context, domain string) (isIDN bool, punycodeDomain string, err error)
|
|
|
// 解析证书
|
|
|
ParseCert(ctx context.Context, httpsCert string, httpKey string) (serverName string, commonName []string, DNSNames []string, before int64, after int64, isSelfSigned bool, err error)
|
|
|
+ AddSSLPolicy(ctx context.Context, req v1.SSL) (sslPolicyId int64, sslCertId int64, err error)
|
|
|
+ EditSSL(ctx context.Context, req v1.SSL) error
|
|
|
}
|
|
|
|
|
|
func NewWafFormatterService(
|
|
@@ -533,3 +535,106 @@ func (s *wafFormatterService) ParseCert(ctx context.Context, httpsCert string, h
|
|
|
return serverName, commonNames, DNSNames, x509Cert.NotBefore.Unix(), x509Cert.NotAfter.Unix(), isSelfSigned, nil
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+// HandleSSLPolicy 负责处理SSL证书的完整生命周期:解析、上传到CDN并创建或更新SSL策略。
|
|
|
+// 它封装了与CDN服务交互的复杂性,并返回一个可用的SSL策略ID。
|
|
|
+func (s *wafFormatterService) AddSSLPolicy(ctx context.Context, req v1.SSL) (sslPolicyId int64, sslCertId int64, err error) {
|
|
|
+ // 1. 解析证书文件,提取元数据
|
|
|
+ serverName, commonNames, DNSNames, before, after, isSelfSigned, err := s.ParseCert(ctx, req.CertData, req.KeyData)
|
|
|
+ if err != nil {
|
|
|
+ return 0, 0, fmt.Errorf("解析证书失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 将证书添加到CDN提供商
|
|
|
+ // 这是获取可以在策略中引用的 `sslCertId` 的前提
|
|
|
+ newSslCertId, err := s.cdn.AddSSLCert(ctx, v1.SSlCert{
|
|
|
+ IsOn: true,
|
|
|
+ UserId: int64(req.CdnUserId),
|
|
|
+ Name: req.Domain, // 使用域名作为证书名称
|
|
|
+ ServerName: serverName,
|
|
|
+ Description: req.Description,
|
|
|
+ CertData: []byte(req.CertData),
|
|
|
+ KeyData: []byte(req.KeyData),
|
|
|
+ TimeBeginAt: before,
|
|
|
+ TimeEndAt: after,
|
|
|
+ DnsNames: DNSNames,
|
|
|
+ CommonNames: commonNames,
|
|
|
+ IsSelfSigned: isSelfSigned,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ return 0, 0, fmt.Errorf("添加SSL证书到CDN失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 基于获取到的证书ID,创建SSL策略
|
|
|
+ if newSslCertId != 0 {
|
|
|
+ // 构造策略中引用的证书列表
|
|
|
+ type sslCerts struct {
|
|
|
+ IsOn bool `json:"isOn" form:"isOn"`
|
|
|
+ CertId int64 `json:"certId" form:"certId"`
|
|
|
+ }
|
|
|
+ var sslCertsSlice []sslCerts
|
|
|
+ sslCertsSlice = append(sslCertsSlice, sslCerts{
|
|
|
+ IsOn: true,
|
|
|
+ CertId: newSslCertId,
|
|
|
+ })
|
|
|
+ sslCertsJson, err := json.Marshal(sslCertsSlice)
|
|
|
+ if err != nil {
|
|
|
+ return 0, 0, fmt.Errorf("序列化SSL证书引用失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调用CDN服务创建策略
|
|
|
+ newSslPolicyId, err := s.cdn.AddSSLPolicy(ctx, v1.AddSSLPolicy{
|
|
|
+ Http2Enabled: true,
|
|
|
+ SslCertsJSON: sslCertsJson,
|
|
|
+ MinVersion: "TLS 1.1", // 可根据安全要求调整
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ // 如果策略创建失败,需要考虑回滚或记录错误,这里直接返回错误
|
|
|
+ return 0, 0, fmt.Errorf("通过CDN添加SSL策略失败: %w", err)
|
|
|
+ }
|
|
|
+ return newSslPolicyId, newSslCertId, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0, 0, fmt.Errorf("未能创建有效的SSL证书ID,无法继续创建策略")
|
|
|
+}
|
|
|
+
|
|
|
+func (s *wafFormatterService) EditSSL(ctx context.Context, req v1.SSL) error {
|
|
|
+ oldData, err := s.webForwardingRep.GetWebForwarding(ctx, req.WebId)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if oldData.HttpsKey != req.KeyData || oldData.HttpsCert != req.CertData {
|
|
|
+ serverName, commonNames, DNSNames, before, after, isSelfSigned, err := s.ParseCert(ctx, req.CertData, req.KeyData)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("解析证书失败: %w", err)
|
|
|
+ }
|
|
|
+ sslCert, err := s.webForwardingRep.GetSslCertId(ctx, oldData.SslCertId)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("获取SSL证书失败: %w", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range sslCert {
|
|
|
+ err = s.cdn.EditSSLCert(ctx, v1.SSlCert{
|
|
|
+ SslCertId: v.CertId,
|
|
|
+ IsOn: v.IsOn,
|
|
|
+ UserId: int64(req.CdnUserId),
|
|
|
+ Name: req.Domain, // 使用域名作为证书名称
|
|
|
+ ServerName: serverName,
|
|
|
+ Description: req.Description,
|
|
|
+ CertData: []byte(req.CertData),
|
|
|
+ KeyData: []byte(req.KeyData),
|
|
|
+ TimeBeginAt: before,
|
|
|
+ TimeEndAt: after,
|
|
|
+ DnsNames: DNSNames,
|
|
|
+ CommonNames: commonNames,
|
|
|
+ IsSelfSigned: isSelfSigned,
|
|
|
+ })
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("更新SSL证书失败: %w", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|