mirror of
https://github.com/certimate-go/certimate.git
synced 2026-10-16 15:16:05 +08:00
feat(provider): new purge provider: jdcloud ssl
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package purgers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
pgrimpl "github.com/certimate-go/certimate/pkg/core/purger/providers/jdcloud-ssl"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.PurgeProviderTypeJDCloudSSL, func(options *ProviderFactoryOptions) (core.Purger, error) {
|
||||
credentials := domain.AccessConfigForJDCloud{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := pgrimpl.NewPurger(&pgrimpl.PurgerConfig{
|
||||
AccessKeyId: credentials.AccessKeyId,
|
||||
AccessKeySecret: credentials.AccessKeySecret,
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -499,6 +499,7 @@ const (
|
||||
PurgeProviderTypeHuaweiCloudELB = PurgeProviderType(AccessProviderTypeHuaweiCloud + "-elb")
|
||||
PurgeProviderTypeHuaweiCloudSCM = PurgeProviderType(AccessProviderTypeHuaweiCloud + "-scm")
|
||||
PurgeProviderTypeHuaweiCloudWAF = PurgeProviderType(AccessProviderTypeHuaweiCloud + "-waf")
|
||||
PurgeProviderTypeJDCloudSSL = PurgeProviderType(AccessProviderTypeJDCloud + "-ssl")
|
||||
PurgeProviderTypeTencentCloudGAAP = PurgeProviderType(AccessProviderTypeTencentCloud + "-gaap")
|
||||
PurgeProviderTypeTencentCloudSSL = PurgeProviderType(AccessProviderTypeTencentCloud + "-ssl")
|
||||
PurgeProviderTypeTencentCloudTSE = PurgeProviderType(AccessProviderTypeTencentCloud + "-tse")
|
||||
|
||||
@@ -280,7 +280,7 @@ func (d *Deployer) updateListenerSniCertificate(ctx context.Context, cloudLoadba
|
||||
|
||||
sslItem := describeSSLV2Resp.DataSet[0]
|
||||
if sslItem.Domains == d.config.Domain {
|
||||
sslIdsToDelete = append(sslIdsToDelete, sslItem.SSLId) // 同域名证书需要删除
|
||||
sslIdsToDelete = append(sslIdsToDelete, sslItem.SSLId)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
//go:build tester
|
||||
|
||||
package jdcloudssl_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
tester "github.com/certimate-go/certimate/pkg/core/purger/providers-tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/purger/providers/jdcloud-ssl"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.InitArgs("JDCLOUDSSL_")
|
||||
fAccessKeyId string
|
||||
fAccessKeySecret string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fAccessKeySecret, "ACCESSKEYSECRET")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -tags=tester -v ./jdcloud_ssl_test.go -args \
|
||||
--JDCLOUDSSL_ACCESSKEYID="your-access-key-id" \
|
||||
--JDCLOUDSSL_ACCESSKEYSECRET="your-access-key-secret"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Purge", func(t *testing.T) {
|
||||
provider, err := impl.NewPurger(&impl.PurgerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
tester.Purge(t, provider, tester.PurgeInput{})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package jdcloudssl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core"
|
||||
jdsslapis "github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/apis"
|
||||
|
||||
jdssl "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/client"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xloop "github.com/certimate-go/certimate/pkg/utils/loop"
|
||||
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Purger
|
||||
PurgeResult = core.PurgerPurgeResult
|
||||
)
|
||||
|
||||
type PurgerConfig struct {
|
||||
// 京东云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 京东云 AccessKeySecret。
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
}
|
||||
|
||||
type Purger struct {
|
||||
config *PurgerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *jdssl.SslClient
|
||||
}
|
||||
|
||||
var _ Provider = (*Purger)(nil)
|
||||
|
||||
func NewPurger(config *PurgerConfig) (*Purger, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the purger provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.AccessKeyId, config.AccessKeySecret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
return &Purger{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Purger) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
p.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
p.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Purger) Purge(ctx context.Context, expiry time.Duration) (*PurgeResult, error) {
|
||||
purgingCertIds := make([]string, 0)
|
||||
|
||||
// 查看证书列表
|
||||
// REF: https://docs.jdcloud.com/cn/ssl-certificate/api/describecerts
|
||||
describeCertsPageNumber := 1
|
||||
describeCertsPageSize := 10
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
describeCertsReq := jdsslapis.NewDescribeCertsRequestWithoutParam()
|
||||
describeCertsReq.SetPageNumber(describeCertsPageNumber)
|
||||
describeCertsReq.SetPageSize(describeCertsPageSize)
|
||||
describeCertsResp, err := p.sdkClient.DescribeCerts(describeCertsReq)
|
||||
p.logger.Debug("sdk request 'ssl.DescribeCerts'", slog.Any("request", describeCertsReq), slog.Any("response", describeCertsResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeCerts': %w", err)
|
||||
}
|
||||
|
||||
for _, certItem := range describeCertsResp.Result.CertListDetails {
|
||||
certNotAfter, err := time.Parse(time.RFC3339, certItem.EndTime)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if time.Since(certNotAfter) >= expiry {
|
||||
purgingCertIds = append(purgingCertIds, certItem.CertId)
|
||||
}
|
||||
}
|
||||
|
||||
if len(describeCertsResp.Result.CertListDetails) < int(describeCertsPageSize) {
|
||||
break
|
||||
}
|
||||
|
||||
describeCertsPageNumber++
|
||||
}
|
||||
|
||||
// 删除证书
|
||||
// REF: https://docs.jdcloud.com/cn/ssl-certificate/api/deletecerts
|
||||
purgedCount := 0
|
||||
if len(purgingCertIds) > 0 {
|
||||
p.logger.Info("found certificates to purge", slog.Any("certIds", purgingCertIds))
|
||||
|
||||
if err := xloop.ForRangeAllWithContext(ctx, purgingCertIds, func(ctx context.Context, certId string, i int) error {
|
||||
if i > 0 {
|
||||
if err := xwait.DelayWithContext(ctx, 1*time.Second); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
deleteCertsReq := jdsslapis.NewDeleteCertsRequestWithoutParam()
|
||||
deleteCertsReq.SetCertId(certId)
|
||||
deleteCertResp, err := p.sdkClient.DeleteCerts(deleteCertsReq)
|
||||
p.logger.Debug("sdk request 'ssl.DeleteCerts'", slog.Any("request", deleteCertsReq), slog.Any("response", deleteCertResp))
|
||||
if err != nil {
|
||||
if deleteCertResp != nil && deleteCertResp.Error.Code == 404 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to execute sdk request 'ssl.DeleteCerts': %w", err)
|
||||
}
|
||||
|
||||
purgedCount++
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &PurgeResult{
|
||||
Count: purgedCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createSDKClient(accessKeyId, accessKeySecret string) (*jdssl.SslClient, error) {
|
||||
clientCredentials := jdcore.NewCredentials(accessKeyId, accessKeySecret)
|
||||
client := jdssl.NewSslClient(clientCredentials)
|
||||
client.DisableLogger()
|
||||
return client, nil
|
||||
}
|
||||
+19
@@ -35,6 +35,25 @@ func (c *SslClient) DisableLogger() {
|
||||
c.Logger = core.NewDummyLogger()
|
||||
}
|
||||
|
||||
func (c *SslClient) DeleteCerts(request *ssl.DeleteCertsRequest) (*ssl.DeleteCertsResponse, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("Request object is nil.")
|
||||
}
|
||||
resp, err := c.Send(request, c.ServiceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jdResp := &ssl.DeleteCertsResponse{}
|
||||
err = json.Unmarshal(resp, jdResp)
|
||||
if err != nil {
|
||||
c.Logger.Log(core.LogError, "Unmarshal json failed, resp: %s", string(resp))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return jdResp, err
|
||||
}
|
||||
|
||||
func (c *SslClient) DescribeCerts(request *ssl.DescribeCertsRequest) (*ssl.DescribeCertsResponse, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("Request object is nil.")
|
||||
|
||||
@@ -993,6 +993,7 @@ export const PURGE_PROVIDERS = Object.freeze(
|
||||
HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`,
|
||||
HUAWEICLOUD_SCM: `${ACCESS_PROVIDERS.HUAWEICLOUD}-scm`,
|
||||
HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`,
|
||||
JDCLOUD_SSL: `${ACCESS_PROVIDERS.JDCLOUD}-ssl`,
|
||||
TENCENTCLOUD_GAAP: `${ACCESS_PROVIDERS.TENCENTCLOUD}-gaap`,
|
||||
TENCENTCLOUD_SSL: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssl`,
|
||||
TENCENTCLOUD_TSE: `${ACCESS_PROVIDERS.TENCENTCLOUD}-tse`,
|
||||
@@ -1021,6 +1022,7 @@ export const purgeProvidersMap: Map<PurgeProvider["type"] | string, PurgeProvide
|
||||
[PURGE_PROVIDERS.HUAWEICLOUD_ELB, "provider.huaweicloud_elb"],
|
||||
[PURGE_PROVIDERS.HUAWEICLOUD_WAF, "provider.huaweicloud_waf"],
|
||||
[PURGE_PROVIDERS.BAIDUCLOUD_CERT, "provider.baiducloud_cert"],
|
||||
[PURGE_PROVIDERS.JDCLOUD_SSL, "provider.jdcloud_ssl"],
|
||||
[PURGE_PROVIDERS.UCLOUD_USSL, "provider.ucloud_ussl"],
|
||||
] satisfies Array<[PurgeProviderType, string, "builtin"] | [PurgeProviderType, string]>
|
||||
).map(([type, name]) => [
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
"jdcloud_dns": "JD Cloud - DNS",
|
||||
"jdcloud_live": "JD Cloud - Live Video",
|
||||
"jdcloud_vod": "JD Cloud - VOD (Video on Demand)",
|
||||
"jdcloud_ssl": "JD Cloud - SSL Certificate",
|
||||
"jdcloud_ssl_upload": "JD Cloud - Upload to SSL Certificate",
|
||||
"jdcloud_waf": "JD Cloud - WAF (Web Application Firewall)",
|
||||
"kong": "Kong",
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
"jdcloud_dns": "京东云 - 云解析 DNS",
|
||||
"jdcloud_live": "京东云 - 视频直播 Live",
|
||||
"jdcloud_vod": "京东云 - 视频点播 VOD",
|
||||
"jdcloud_ssl": "京东云 - SSL 数字证书",
|
||||
"jdcloud_ssl_upload": "京东云 - 上传到 SSL 数字证书",
|
||||
"jdcloud_waf": "京东云 - Web 应用防火墙 WAF",
|
||||
"kong": "Kong",
|
||||
|
||||
Reference in New Issue
Block a user