mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-21 12:43:46 +08:00
feat: support configuring 'subscriptionId' and 'resourceGroupName' for azure credentials
This commit is contained in:
@@ -21,6 +21,8 @@ func init() {
|
||||
TenantId: credentials.TenantId,
|
||||
ClientId: credentials.ClientId,
|
||||
ClientSecret: credentials.ClientSecret,
|
||||
SubscriptionId: credentials.SubscriptionId,
|
||||
ResourceGroupName: credentials.ResourceGroupName,
|
||||
CloudName: credentials.CloudName,
|
||||
DnsPropagationTimeout: options.DnsPropagationTimeout,
|
||||
DnsTTL: options.DnsTTL,
|
||||
|
||||
@@ -87,10 +87,12 @@ type AccessConfigForAWS struct {
|
||||
}
|
||||
|
||||
type AccessConfigForAzure struct {
|
||||
TenantId string `json:"tenantId"`
|
||||
ClientId string `json:"clientId"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
CloudName string `json:"cloudName,omitempty"`
|
||||
TenantId string `json:"tenantId"`
|
||||
ClientId string `json:"clientId"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
SubscriptionId string `json:"subscriptionId,omitempty"`
|
||||
ResourceGroupName string `json:"resourceGroupName,omitempty"`
|
||||
CloudName string `json:"cloudName,omitempty"`
|
||||
}
|
||||
|
||||
type AccessConfigForBaiduCloud struct {
|
||||
|
||||
@@ -14,6 +14,8 @@ type ChallengerConfig struct {
|
||||
TenantId string `json:"tenantId"`
|
||||
ClientId string `json:"clientId"`
|
||||
ClientSecret string `json:"clientSecret"`
|
||||
SubscriptionId string `json:"subscriptionId,omitempty"`
|
||||
ResourceGroupName string `json:"resourceGroupName,omitempty"`
|
||||
CloudName string `json:"cloudName,omitempty"`
|
||||
DnsPropagationTimeout int `json:"dnsPropagationTimeout,omitempty"`
|
||||
DnsTTL int `json:"dnsTTL,omitempty"`
|
||||
@@ -29,6 +31,8 @@ func NewChallenger(config *ChallengerConfig) (certifier.ACMEChallenger, error) {
|
||||
providerConfig.TenantID = config.TenantId
|
||||
providerConfig.ClientID = config.ClientId
|
||||
providerConfig.ClientSecret = config.ClientSecret
|
||||
providerConfig.SubscriptionID = config.SubscriptionId
|
||||
providerConfig.ResourceGroup = config.ResourceGroupName
|
||||
if config.CloudName != "" {
|
||||
env, err := azenv.GetCloudEnvConfiguration(config.CloudName)
|
||||
if err != nil {
|
||||
|
||||
@@ -44,7 +44,7 @@ func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
|
||||
return nil, errors.New("the configuration of the certmgr provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.TenantId, config.ClientId, config.ClientSecret, config.CloudName, config.KeyVaultName)
|
||||
client, err := createSDKClient(config.CloudName, config.TenantId, config.ClientId, config.ClientSecret, config.KeyVaultName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
@@ -72,14 +72,12 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*cert
|
||||
}
|
||||
|
||||
// 生成 Azure 业务参数
|
||||
const TAG_CERTCN = "certimate/cert-cn"
|
||||
const TAG_CERTSN = "certimate/cert-sn"
|
||||
certCN := certX509.Subject.CommonName
|
||||
certSN := certX509.SerialNumber.Text(16)
|
||||
|
||||
// 获取证书列表,避免重复上传
|
||||
// REF: https://learn.microsoft.com/en-us/rest/api/keyvault/certificates/get-certificates/get-certificates
|
||||
listCertificatesPager := c.sdkClient.NewListCertificatePropertiesPager(nil)
|
||||
listCertificatesPager := c.sdkClient.NewListCertificatePropertiesPager(&azcertificates.ListCertificatePropertiesOptions{})
|
||||
for listCertificatesPager.More() {
|
||||
page, err := listCertificatesPager.NextPage(ctx)
|
||||
if err != nil {
|
||||
@@ -99,14 +97,14 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*cert
|
||||
}
|
||||
|
||||
// 对比 Tag 中的通用名称
|
||||
if v, ok := certItem.Tags[TAG_CERTCN]; !ok || v == nil {
|
||||
if v, ok := certItem.Tags[kvTagCertCN]; !ok || v == nil {
|
||||
continue
|
||||
} else if *v != certCN {
|
||||
continue
|
||||
}
|
||||
|
||||
// 对比 Tag 中的序列号
|
||||
if v, ok := certItem.Tags[TAG_CERTSN]; !ok || v == nil {
|
||||
if v, ok := certItem.Tags[kvTagCertSN]; !ok || v == nil {
|
||||
continue
|
||||
} else if *v != certSN {
|
||||
continue
|
||||
@@ -153,8 +151,8 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*cert
|
||||
},
|
||||
},
|
||||
Tags: map[string]*string{
|
||||
TAG_CERTCN: to.Ptr(certCN),
|
||||
TAG_CERTSN: to.Ptr(certSN),
|
||||
kvTagCertCN: to.Ptr(certCN),
|
||||
kvTagCertSN: to.Ptr(certSN),
|
||||
},
|
||||
}
|
||||
importCertificateResp, err := c.sdkClient.ImportCertificate(ctx, certName, importCertificateParams, nil)
|
||||
@@ -208,8 +206,8 @@ func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, pri
|
||||
},
|
||||
},
|
||||
Tags: map[string]*string{
|
||||
"certimate/cert-cn": to.Ptr(certX509.Subject.CommonName),
|
||||
"certimate/cert-sn": to.Ptr(certX509.SerialNumber.Text(16)),
|
||||
kvTagCertCN: to.Ptr(certX509.Subject.CommonName),
|
||||
kvTagCertSN: to.Ptr(certX509.SerialNumber.Text(16)),
|
||||
},
|
||||
}
|
||||
importCertificateResp, err := c.sdkClient.ImportCertificate(ctx, certIdOrName, importCertificateParams, nil)
|
||||
@@ -221,13 +219,18 @@ func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, pri
|
||||
return &certmgr.OperateResult{}, nil
|
||||
}
|
||||
|
||||
func createSDKClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) {
|
||||
const (
|
||||
kvTagCertCN = "certimate/cert-cn"
|
||||
kvTagCertSN = "certimate/cert-sn"
|
||||
)
|
||||
|
||||
func createSDKClient(cloudName, tenantId, clientId, clientSecret, keyvaultName string) (*azcertificates.Client, error) {
|
||||
env, err := azenv.GetCloudEnvConfiguration(cloudName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientOptions := azcore.ClientOptions{Cloud: env}
|
||||
|
||||
clientOptions := azcore.ClientOptions{Cloud: env}
|
||||
credential, err := azidentity.NewClientSecretCredential(tenantId, clientId, clientSecret,
|
||||
&azidentity.ClientSecretCredentialOptions{ClientOptions: clientOptions})
|
||||
if err != nil {
|
||||
|
||||
@@ -6,14 +6,9 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certmgr"
|
||||
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/azure-keyvault"
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer"
|
||||
azenv "github.com/certimate-go/certimate/pkg/sdk3rd/azure/env"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
@@ -35,7 +30,6 @@ type DeployerConfig struct {
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *azcertificates.Client
|
||||
sdkCertmgr certmgr.Provider
|
||||
}
|
||||
|
||||
@@ -46,11 +40,6 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
return nil, errors.New("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.TenantId, config.ClientId, config.ClientSecret, config.CloudName, config.KeyVaultName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
pcertmgr, err := mcertmgr.NewCertmgr(&mcertmgr.CertmgrConfig{
|
||||
TenantId: config.TenantId,
|
||||
ClientId: config.ClientId,
|
||||
@@ -65,7 +54,6 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
sdkCertmgr: pcertmgr,
|
||||
}, nil
|
||||
}
|
||||
@@ -101,31 +89,3 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func createSDKClient(tenantId, clientId, clientSecret, cloudName, keyvaultName string) (*azcertificates.Client, error) {
|
||||
env, err := azenv.GetCloudEnvConfiguration(cloudName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientOptions := azcore.ClientOptions{Cloud: env}
|
||||
|
||||
credential, err := azidentity.NewClientSecretCredential(tenantId, clientId, clientSecret,
|
||||
&azidentity.ClientSecretCredentialOptions{ClientOptions: clientOptions})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpoint := fmt.Sprintf("https://%s.vault.azure.net", keyvaultName)
|
||||
if azenv.IsUSGovernmentEnv(cloudName) {
|
||||
endpoint = fmt.Sprintf("https://%s.vault.usgovcloudapi.net", keyvaultName)
|
||||
} else if azenv.IsChinaEnv(cloudName) {
|
||||
endpoint = fmt.Sprintf("https://%s.vault.azure.cn", keyvaultName)
|
||||
}
|
||||
|
||||
client, err := azcertificates.NewClient(endpoint, credential, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
@@ -47,6 +47,26 @@ const AccessConfigFormFieldsProviderAzure = () => {
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.azure_client_secret.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "subscriptionId"]}
|
||||
initialValue={initialValues.subscriptionId}
|
||||
label={t("access.form.azure_subscription_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.azure_subscription_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear autoComplete="new-password" placeholder={t("access.form.azure_subscription_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "resourceGroupName"]}
|
||||
initialValue={initialValues.resourceGroupName}
|
||||
label={t("access.form.azure_resource_group_name.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.azure_resource_group_name.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("access.form.azure_resource_group_name.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "cloudName"]}
|
||||
initialValue={initialValues.cloudName}
|
||||
@@ -81,6 +101,8 @@ const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) =
|
||||
tenantId: z.string().nonempty(t("access.form.azure_tenant_id.placeholder")),
|
||||
clientId: z.string().nonempty(t("access.form.azure_client_id.placeholder")),
|
||||
clientSecret: z.string().nonempty(t("access.form.azure_client_secret.placeholder")),
|
||||
subscriptionId: z.string().nullish(),
|
||||
resourceGroupName: z.string().nullish(),
|
||||
cloudName: z.string().nullish(),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -136,6 +136,12 @@
|
||||
"access.form.azure_client_secret.label": "Azure client secret",
|
||||
"access.form.azure_client_secret.placeholder": "Please enter Azure client secret",
|
||||
"access.form.azure_client_secret.tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/azure/azure-monitor/logs/api/register-app-for-token\" target=\"_blank\">https://learn.microsoft.com/en-us/azure/azure-monitor/logs/api/register-app-for-token</a>",
|
||||
"access.form.azure_subscription_id.label": "Azure subscription ID (Optional)",
|
||||
"access.form.azure_subscription_id.placeholder": "Please enter Azure subscription ID",
|
||||
"access.form.azure_subscription_id.tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id\" target=\"_blank\">https://learn.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id</a>",
|
||||
"access.form.azure_resource_group_name.label": "Azure resource group name (Optional)",
|
||||
"access.form.azure_resource_group_name.placeholder": "Please enter Azure resource group name",
|
||||
"access.form.azure_resource_group_name.tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal\" target=\"_blank\">https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal</a>",
|
||||
"access.form.azure_cloud_name.label": "Azure sovereign cloud name (Optional)",
|
||||
"access.form.azure_cloud_name.placeholder": "Please enter Azure sovereign cloud name (e.g. public)",
|
||||
"access.form.azure_cloud_name.tooltip": "For more information, see <a href=\"https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/sovereign-clouds\" target=\"_blank\">https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/sovereign-clouds</a>",
|
||||
|
||||
@@ -136,6 +136,12 @@
|
||||
"access.form.azure_client_secret.label": "Azure 客户端密码",
|
||||
"access.form.azure_client_secret.placeholder": "请输入 Azure 客户端密码",
|
||||
"access.form.azure_client_secret.tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/azure/azure-monitor/logs/api/register-app-for-token\" target=\"_blank\">https://learn.microsoft.com/zh-cn/azure/azure-monitor/logs/api/register-app-for-token</a>",
|
||||
"access.form.azure_subscription_id.label": "Azure 订阅 ID(可选)",
|
||||
"access.form.azure_subscription_id.placeholder": "请输入 Azure 订阅 ID",
|
||||
"access.form.azure_subscription_id.tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/azure/azure-portal/get-subscription-tenant-id\" target=\"_blank\">https://learn.microsoft.com/zh-cn/azure/azure-portal/get-subscription-tenant-id</a>",
|
||||
"access.form.azure_resource_group_name.label": "Azure 资源组名称(可选)",
|
||||
"access.form.azure_resource_group_name.placeholder": "请输入 Azure 资源组名称",
|
||||
"access.form.azure_resource_group_name.tooltip": "这是什么?请参阅 <a href=\"https://docs.azure.cn/zh-cn/azure-resource-manager/management/manage-resource-groups-portal\" target=\"_blank\">https://docs.azure.cn/zh-cn/azure-resource-manager/management/manage-resource-groups-portal</a>",
|
||||
"access.form.azure_cloud_name.label": "Azure 主权云环境(可选)",
|
||||
"access.form.azure_cloud_name.placeholder": "请输入 Azure 主权云环境(例如:public)",
|
||||
"access.form.azure_cloud_name.tooltip": "这是什么?请参阅 <a href=\"https://learn.microsoft.com/zh-cn/azure/developer/azure-developer-cli/sovereign-clouds\" target=\"_blank\">https://learn.microsoft.com/zh-cn/azure/developer/azure-developer-cli/sovereign-clouds</a>",
|
||||
|
||||
Reference in New Issue
Block a user