feat: add ExtractCertificatesFromPEM util func

This commit is contained in:
Fu Diwei
2025-02-06 13:11:40 +08:00
parent bc29cce645
commit 5f5c835533
7 changed files with 125 additions and 97 deletions

View File

@@ -2,13 +2,13 @@
import (
"context"
"encoding/pem"
"errors"
xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/utils/certs"
edgsdk "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7"
edgsdkDtos "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos"
)
@@ -57,7 +57,10 @@ func NewWithLogger(config *EdgioApplicationsDeployerConfig, logger logger.Logger
func (d *EdgioApplicationsDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 提取 Edgio 所需的服务端证书和中间证书内容
privateCertPem, intermediateCertPem := extractCertChains(certPem)
privateCertPem, intermediateCertPem, err := certs.ExtractCertificatesFromPEM(certPem)
if err != nil {
return nil, err
}
// 上传 TLS 证书
// REF: https://docs.edg.io/rest_api/#tag/tls-certs/operation/postConfigV01TlsCerts
@@ -81,32 +84,3 @@ func createSdkClient(clientId, clientSecret string) (*edgsdk.EdgioClient, error)
client := edgsdk.NewEdgioClient(clientId, clientSecret, "", "")
return client, nil
}
func extractCertChains(certPem string) (primaryCertPem string, intermediateCertPem string) {
pemBlocks := make([]*pem.Block, 0)
pemData := []byte(certPem)
for {
block, rest := pem.Decode(pemData)
if block == nil {
break
}
pemBlocks = append(pemBlocks, block)
pemData = rest
}
primaryCertPem = ""
intermediateCertPem = ""
if len(pemBlocks) > 0 {
primaryCertPem = string(pem.EncodeToMemory(pemBlocks[0]))
}
if len(pemBlocks) > 1 {
for i := 1; i < len(pemBlocks); i++ {
intermediateCertPem += string(pem.EncodeToMemory(pemBlocks[i]))
}
}
return primaryCertPem, intermediateCertPem
}

View File

@@ -0,0 +1,48 @@
package certs
import (
"encoding/pem"
"errors"
)
// 从 PEM 编码的证书字符串解析并提取服务器证书和中间证书。
//
// 入参:
// - certPem: 证书 PEM 内容。
//
// 出参:
// - serverCertPem: 服务器证书的 PEM 内容。
// - interCertPem: 中间证书的 PEM 内容。
// - err: 错误。
func ExtractCertificatesFromPEM(certPem string) (serverCertPem string, interCertPem string, err error) {
pemBlocks := make([]*pem.Block, 0)
pemData := []byte(certPem)
for {
block, rest := pem.Decode(pemData)
if block == nil || block.Type != "CERTIFICATE" {
break
}
pemBlocks = append(pemBlocks, block)
pemData = rest
}
serverCertPem = ""
interCertPem = ""
if len(pemBlocks) == 0 {
return "", "", errors.New("failed to decode PEM block")
}
if len(pemBlocks) > 0 {
serverCertPem = string(pem.EncodeToMemory(pemBlocks[0]))
}
if len(pemBlocks) > 1 {
for i := 1; i < len(pemBlocks); i++ {
interCertPem += string(pem.EncodeToMemory(pemBlocks[i]))
}
}
return serverCertPem, interCertPem, nil
}

View File

@@ -13,6 +13,7 @@ import (
)
// 从 PEM 编码的证书字符串解析并返回一个 x509.Certificate 对象。
// PEM 内容可能是包含多张证书的证书链,但只返回第一个证书(即服务器证书)。
//
// 入参:
// - certPem: 证书 PEM 内容。

View File

@@ -183,7 +183,7 @@ func GetValueOrDefaultAsBool(dict map[string]any, key string, defaultValue bool)
return defaultValue
}
// 将字典解码为指定类型的结构体。
// 将字典填充到指定类型的结构体。
// 与 [json.Unmarshal] 类似,但传入的是一个 [map[string]interface{}] 对象而非 JSON 格式的字符串。
//
// 入参:
@@ -191,8 +191,8 @@ func GetValueOrDefaultAsBool(dict map[string]any, key string, defaultValue bool)
// - output: 结构体指针。
//
// 出参:
// - 错误信息。如果解码失败,则返回错误信息。
func Decode(dict map[string]any, output any) error {
// - 错误信息。如果填充失败,则返回错误信息。
func Populate(dict map[string]any, output any) error {
config := &mapstructure.DecoderConfig{
Metadata: nil,
Result: output,
@@ -207,3 +207,8 @@ func Decode(dict map[string]any, output any) error {
return decoder.Decode(dict)
}
// Deprecated: Use [Populate] instead.
func Decode(dict map[string]any, output any) error {
return Populate(dict, output)
}

View File

@@ -150,7 +150,7 @@ func (c *GnameClient) sendRequestWithResult(path string, params map[string]any,
if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil {
return fmt.Errorf("failed to parse response: %w", err)
}
if err := maps.Decode(jsonResp, &result); err != nil {
if err := maps.Populate(jsonResp, &result); err != nil {
return fmt.Errorf("failed to parse response: %w", err)
}