添加自动下载ssl证书
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -41,7 +41,7 @@ namespace Hua.DDNS.Test.Start
|
|||||||
services.AddSingleton<Url>();
|
services.AddSingleton<Url>();
|
||||||
services.AddSingleton<SqlHelper>();
|
services.AddSingleton<SqlHelper>();
|
||||||
services.AddTransient<IHttpHelper, HttpHelper>();
|
services.AddTransient<IHttpHelper, HttpHelper>();
|
||||||
services.AddTransient<AppJob>();
|
services.AddTransient<NewJob>();
|
||||||
return services.BuildServiceProvider();
|
return services.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
Hua.DDNS/Common/Config/Options/AliCloudOption.cs
Normal file
10
Hua.DDNS/Common/Config/Options/AliCloudOption.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
|
{
|
||||||
|
public class AliCloudOption
|
||||||
|
{
|
||||||
|
public string AccessKeyId { get; set; }
|
||||||
|
public string AccessKeySecret { get; set; }
|
||||||
|
public string RegionId { get; set; }
|
||||||
|
public string Endpoint { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Hua.DDNS/Common/Config/Options/SslDownloadOption.cs
Normal file
24
Hua.DDNS/Common/Config/Options/SslDownloadOption.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
|
{
|
||||||
|
public enum SslPlatformEnum
|
||||||
|
{
|
||||||
|
Ali = 1,
|
||||||
|
Tencent = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SslDownloadOption
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public string Corn { get; set; }
|
||||||
|
public SslPlatformEnum Platform { get; set; }
|
||||||
|
public string SavePath { get; set; }
|
||||||
|
public int ExpireDays { get; set; }
|
||||||
|
public List<SslDownloadItem> DownloadItems { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SslDownloadItem
|
||||||
|
{
|
||||||
|
public string Domain { get; set; }
|
||||||
|
public string FileName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Hua.DDNS/Common/Config/Options/TencentCloudOption.cs
Normal file
12
Hua.DDNS/Common/Config/Options/TencentCloudOption.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Hua.DDNS.DDNSProviders.Dnspod;
|
||||||
|
|
||||||
|
namespace Hua.DDNS.Common.Config.Options
|
||||||
|
{
|
||||||
|
public class TencentCloudOption
|
||||||
|
{
|
||||||
|
public string SecretId { get; set; }
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
public string Region { get; set; }
|
||||||
|
public DnspodOption Dnspod { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,12 @@ namespace Hua.DDNS.Common.Http
|
|||||||
{
|
{
|
||||||
private static ILogger<HttpHelper> _logger;
|
private static ILogger<HttpHelper> _logger;
|
||||||
private static HttpClientHandler _handler;
|
private static HttpClientHandler _handler;
|
||||||
|
private IConfiguration _configuration;
|
||||||
|
|
||||||
public HttpHelper(ILogger<HttpHelper> logger)
|
public HttpHelper(ILogger<HttpHelper> logger, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_configuration = configuration;
|
||||||
_handler = new HttpClientHandler();
|
_handler = new HttpClientHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,31 +87,45 @@ namespace Hua.DDNS.Common.Http
|
|||||||
#region 下载文件
|
#region 下载文件
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// http下载文件 (仅支持小文件)
|
/// http下载文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">下载文件地址</param>
|
/// <param name="url">下载文件地址</param>
|
||||||
/// <param name="localPath">文件存放地址,包含文件名</param>
|
/// <param name="localPath">文件存放地址,包含文件名</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool DownloadFile(string url, string localPath)
|
public bool DownloadFile(string url, string localPath)
|
||||||
{
|
{
|
||||||
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
|
|
||||||
|
|
||||||
var request = WebRequest.Create(url) as HttpWebRequest;
|
|
||||||
Stream stream = new FileStream(localPath, FileMode.CreateNew);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 设置参数
|
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
|
||||||
//发送请求并获取相应回应数据
|
|
||||||
|
var request = WebRequest.Create(url) as HttpWebRequest;
|
||||||
var response = request?.GetResponse() as HttpWebResponse;
|
var response = request?.GetResponse() as HttpWebResponse;
|
||||||
//直到request.GetResponse()程序才开始向目标网页发送Post请求
|
|
||||||
var responseStream = response?.GetResponseStream();
|
var responseStream = response?.GetResponseStream();
|
||||||
//创建本地文件写入流
|
|
||||||
stream.Close();
|
if (responseStream == null)
|
||||||
responseStream?.Close();
|
{
|
||||||
|
_logger.LogError($"下载文件失败: {url}, 无法获取响应流");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var directory = Path.GetDirectoryName(localPath);
|
||||||
|
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var fileStream = new FileStream(localPath, FileMode.Create);
|
||||||
|
responseStream.CopyTo(fileStream);
|
||||||
|
fileStream.Close();
|
||||||
|
responseStream.Close();
|
||||||
|
response?.Close();
|
||||||
|
|
||||||
|
_logger.LogInformation($"文件下载成功: {url} -> {localPath}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
_logger.LogError($"下载文件失败: {url}, 错误: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +139,7 @@ namespace Hua.DDNS.Common.Http
|
|||||||
public async Task<string> GetCurrentPublicIpv4()
|
public async Task<string> GetCurrentPublicIpv4()
|
||||||
{
|
{
|
||||||
using var client = new HttpClient();
|
using var client = new HttpClient();
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Get, "http://175.24.175.136:8008/WebUtil/GetIp");
|
using var request = new HttpRequestMessage(HttpMethod.Get, _configuration["App:GetIpv4Url"]);
|
||||||
using var response = await client.SendAsync(request);
|
using var response = await client.SendAsync(request);
|
||||||
return await response.Content.ReadAsStringAsync();
|
return await response.Content.ReadAsStringAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,9 @@
|
|||||||
namespace Hua.DDNS.DDNSProviders.Ali
|
namespace Hua.DDNS.DDNSProviders.Ali
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain configuration Ali
|
/// domain configuration Ali
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AliDdnsOption
|
public class AliDdnsOption
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Id, the id and key from DnsPod
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Key
|
|
||||||
/// </summary>
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Endpoint
|
|
||||||
/// </summary>
|
|
||||||
public string Endpoint { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -21,24 +21,22 @@ namespace Hua.DDNS.DDNSProviders.Ali
|
|||||||
public class AliDdnsProvider : IDdnsProvider
|
public class AliDdnsProvider : IDdnsProvider
|
||||||
{
|
{
|
||||||
private readonly Client _client;
|
private readonly Client _client;
|
||||||
private readonly AliDdnsOption _aliDDNSOption;
|
private readonly AliCloudOption _aliCloudOption;
|
||||||
private readonly DdnsOption _ddnsOption;
|
private readonly DdnsOption _ddnsOption;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
public AliDdnsProvider(IOptions<AliDdnsOption> aliDDNSOption, IMapper mapper,IOptions<DdnsOption> ddnsOption)
|
public AliDdnsProvider(IOptions<AliCloudOption> aliCloudOption, IMapper mapper,IOptions<DdnsOption> ddnsOption)
|
||||||
{
|
{
|
||||||
_aliDDNSOption = aliDDNSOption.Value;
|
_aliCloudOption = aliCloudOption.Value;
|
||||||
_ddnsOption = ddnsOption.Value;
|
_ddnsOption = ddnsOption.Value;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
|
|
||||||
|
|
||||||
_client = new Client(new Config()
|
_client = new Client(new Config()
|
||||||
{
|
{
|
||||||
// 您的 AccessKey ID
|
AccessKeyId = _aliCloudOption.AccessKeyId,
|
||||||
AccessKeyId = _aliDDNSOption.Id,
|
AccessKeySecret = _aliCloudOption.AccessKeySecret,
|
||||||
// 您的 AccessKey Secret
|
Endpoint = _aliCloudOption.Endpoint,
|
||||||
AccessKeySecret = _aliDDNSOption.Key,
|
|
||||||
Endpoint = _aliDDNSOption.Endpoint,//alidns.cn-beijing.aliyuncs.com
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Hua.DDNS.DDNSProviders.Ali;
|
using Hua.DDNS.Common.Config.Options;
|
||||||
using Hua.DDNS.Models;
|
using Hua.DDNS.Models;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using TencentCloud.Common.Profile;
|
using TencentCloud.Common.Profile;
|
||||||
@@ -25,26 +25,22 @@ namespace Hua.DDNS.DDNSProviders.Dnspod
|
|||||||
{
|
{
|
||||||
|
|
||||||
private readonly DnspodClient _client;
|
private readonly DnspodClient _client;
|
||||||
private readonly DnspodOption _dnspodOption;
|
private readonly TencentCloudOption _tencentCloudOption;
|
||||||
private readonly DdnsOption _ddnsOption;
|
private readonly DdnsOption _ddnsOption;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
public DnspodDdnsProvider(IMapper mapper, IOptions<DnspodOption> dnspodOption, IOptions<DdnsOption> ddnsOption)
|
public DnspodDdnsProvider(IMapper mapper, IOptions<TencentCloudOption> tencentCloudOption, IOptions<DdnsOption> ddnsOption)
|
||||||
{
|
{
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_dnspodOption = dnspodOption.Value;
|
_tencentCloudOption = tencentCloudOption.Value;
|
||||||
_ddnsOption = ddnsOption.Value;
|
_ddnsOption = ddnsOption.Value;
|
||||||
|
|
||||||
_client = new DnspodClient(
|
_client = new DnspodClient(
|
||||||
// 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
|
new Credential { SecretId = _tencentCloudOption.SecretId, SecretKey = _tencentCloudOption.SecretKey },
|
||||||
// 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
|
|
||||||
new Credential { SecretId = _dnspodOption.Id, SecretKey = _dnspodOption.Key },
|
|
||||||
"",
|
"",
|
||||||
// 实例化一个client选项,可选的,没有特殊需求可以跳过
|
|
||||||
new ClientProfile()
|
new ClientProfile()
|
||||||
{
|
{
|
||||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
HttpProfile = new HttpProfile { Endpoint = _tencentCloudOption.Dnspod.Endpoint }
|
||||||
HttpProfile = new HttpProfile { Endpoint = (_dnspodOption.Endpoint) }//"dnspod.tencentcloudapi.com"
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
namespace Hua.DDNS.DDNSProviders.Dnspod
|
namespace Hua.DDNS.DDNSProviders.Dnspod
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// domain configuration Dnspod
|
/// domain configuration Dnspod
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DnspodOption
|
public class DnspodOption
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Id, the id and key from AliCould or DnsPod
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Key
|
|
||||||
/// </summary>
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Endpoint dnspod.tencentcloudapi.com
|
/// Endpoint dnspod.tencentcloudapi.com
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Endpoint { get; set; }
|
public string Endpoint { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,21 @@
|
|||||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS base
|
|
||||||
USER app
|
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
|
||||||
|
#For more information, please see https://aka.ms/containercompat
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
#EXPOSE 8080
|
|
||||||
#EXPOSE 8081
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY ["Hua.DDNS/Hua.DDNS.csproj", "Hua.DDNS/"]
|
COPY ["/Hua.DDNS.csproj", "Hua.DDNS/"]
|
||||||
RUN dotnet restore "./Hua.DDNS/Hua.DDNS.csproj"
|
RUN dotnet restore "Hua.DDNS/Hua.DDNS.csproj"
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR "/src/Hua.DDNS"
|
WORKDIR "/Hua.DDNS"
|
||||||
RUN dotnet build "./Hua.DDNS.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
RUN dotnet build "Hua.DDNS.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
FROM build AS publish
|
FROM build AS publish
|
||||||
ARG BUILD_CONFIGURATION=Release
|
RUN dotnet publish "Hua.DDNS.csproj" -c Release -o /app/publish
|
||||||
RUN dotnet publish "./Hua.DDNS.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=true
|
|
||||||
|
|
||||||
FROM base AS final
|
FROM base AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AlibabaCloud.SDK.Alidns20150109" Version="3.5.0" />
|
<PackageReference Include="AlibabaCloud.SDK.Alidns20150109" Version="3.5.0" />
|
||||||
|
<PackageReference Include="AlibabaCloud.SDK.Cas20200407" Version="3.0.4" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||||
<PackageReference Include="Hua.DotNet.Code" Version="0.0.15" />
|
<PackageReference Include="Hua.DotNet.Code" Version="0.0.15" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="TencentCloudSDK.Dnspod" Version="3.0.1024" />
|
<PackageReference Include="TencentCloudSDK.Dnspod" Version="3.0.1024" />
|
||||||
|
<PackageReference Include="TencentCloudSDK.Ssl" Version="3.0.1371" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
133
Hua.DDNS/Jobs/SslDownloadJob.cs
Normal file
133
Hua.DDNS/Jobs/SslDownloadJob.cs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
using Hua.DDNS.Common.Config.Options;
|
||||||
|
using Hua.DDNS.SslProviders;
|
||||||
|
using Hua.DDNS.SslProviders.Ali;
|
||||||
|
using Hua.DDNS.SslProviders.Tencent;
|
||||||
|
using Quartz;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Hua.DDNS.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
public class SslDownloadJob : IJob, IDisposable
|
||||||
|
{
|
||||||
|
private readonly ILogger<SslDownloadJob> _logger;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly SslDownloadOption _sslDownloadOption;
|
||||||
|
|
||||||
|
public SslDownloadJob(
|
||||||
|
ILogger<SslDownloadJob> logger,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
IOptions<SslDownloadOption> sslDownloadOption)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
_sslDownloadOption = sslDownloadOption.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!_sslDownloadOption.Enabled)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("SSL下载任务已禁用,跳过执行");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("开始SSL文件下载任务");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ISslDownloadProvider? sslProvider = _sslDownloadOption.Platform switch
|
||||||
|
{
|
||||||
|
SslPlatformEnum.Ali => _serviceProvider.GetService(typeof(AliSslProvider)) as ISslDownloadProvider,
|
||||||
|
SslPlatformEnum.Tencent => _serviceProvider.GetService(typeof(TencentSslProvider)) as ISslDownloadProvider,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sslProvider == null)
|
||||||
|
{
|
||||||
|
_logger.LogError($"未找到 SSL 下载提供者: {_sslDownloadOption.Platform}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (!Directory.Exists(_sslDownloadOption.SavePath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(_sslDownloadOption.SavePath);
|
||||||
|
_logger.LogInformation($"创建目录: {_sslDownloadOption.SavePath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var certificates = await sslProvider.GetCertificatesAsync();
|
||||||
|
var downloadTasks = new List<Task>();
|
||||||
|
|
||||||
|
foreach (var item in _sslDownloadOption.DownloadItems)
|
||||||
|
{
|
||||||
|
var matchingCertificates = certificates.Where(c => c.Domain == item.Domain).ToList();
|
||||||
|
|
||||||
|
if (matchingCertificates.Count == 0)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"未找到域名 {item.Domain} 的证书,跳过下载");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var certificate = matchingCertificates.OrderByDescending(c => c.CertEndTime).First();
|
||||||
|
|
||||||
|
var daysUntilExpiry = (certificate.CertEndTime - DateTime.Now).Days;
|
||||||
|
|
||||||
|
if (daysUntilExpiry <= _sslDownloadOption.ExpireDays)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"证书 {certificate.CertificateId} ({certificate.Domain}) 将在 {daysUntilExpiry} 天后过期,开始下载");
|
||||||
|
downloadTasks.Add(DownloadFileAsync(sslProvider, item, certificate.CertificateId, certificate.Domain));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"证书 {certificate.CertificateId} ({certificate.Domain}) 还有 {daysUntilExpiry} 天过期,跳过下载");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.WhenAll(downloadTasks);
|
||||||
|
|
||||||
|
_logger.LogInformation($"SSL文件下载任务完成,共下载 {downloadTasks.Count} 个文件");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "SSL文件下载任务执行失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadFileAsync(ISslDownloadProvider provider, SslDownloadItem item, string certificateId, string domain)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var domainPath = Path.Combine(_sslDownloadOption.SavePath, domain);
|
||||||
|
|
||||||
|
if (!Directory.Exists(domainPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(domainPath);
|
||||||
|
_logger.LogInformation($"创建域名目录: {domainPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var localPath = Path.Combine(domainPath, item.FileName);
|
||||||
|
_logger.LogInformation($"开始下载证书: {certificateId} -> {localPath}");
|
||||||
|
|
||||||
|
var success = await provider.DownloadCertificateAsync(certificateId, domainPath, item.FileName);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"证书下载成功: {domain}/{item.FileName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError($"证书下载失败: {domain}/{item.FileName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"下载证书时发生错误: {item.FileName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("SslDownloadJob已销毁");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
Hua.DDNS/SslProviders/Ali/AliSslOption.cs
Normal file
9
Hua.DDNS/SslProviders/Ali/AliSslOption.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Hua.DDNS.SslProviders.Ali
|
||||||
|
{
|
||||||
|
public class AliSslOption
|
||||||
|
{
|
||||||
|
public string AccessKeyId { get; set; }
|
||||||
|
public string AccessKeySecret { get; set; }
|
||||||
|
public string Endpoint { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Hua.DDNS/SslProviders/Ali/AliSslProvider.cs
Normal file
62
Hua.DDNS/SslProviders/Ali/AliSslProvider.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using AlibabaCloud.SDK.Cas20200407;
|
||||||
|
using AlibabaCloud.SDK.Cas20200407.Models;
|
||||||
|
using AlibabaCloud.OpenApiClient.Models;
|
||||||
|
using Hua.DDNS.Common.Config.Options;
|
||||||
|
using Hua.DDNS.SslProviders;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Hua.DDNS.SslProviders.Ali
|
||||||
|
{
|
||||||
|
public class AliSslProvider : ISslDownloadProvider
|
||||||
|
{
|
||||||
|
private readonly Client _client;
|
||||||
|
private readonly AliCloudOption _aliCloudOption;
|
||||||
|
private readonly ILogger<AliSslProvider> _logger;
|
||||||
|
|
||||||
|
public AliSslProvider(
|
||||||
|
ILogger<AliSslProvider> logger,
|
||||||
|
IOptions<AliCloudOption> aliCloudOption)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_aliCloudOption = aliCloudOption.Value;
|
||||||
|
|
||||||
|
var config = new Config
|
||||||
|
{
|
||||||
|
AccessKeyId = _aliCloudOption.AccessKeyId,
|
||||||
|
AccessKeySecret = _aliCloudOption.AccessKeySecret,
|
||||||
|
Endpoint = _aliCloudOption.Endpoint
|
||||||
|
};
|
||||||
|
|
||||||
|
_client = new Client(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogWarning("阿里云 SSL 证书列表功能待实现");
|
||||||
|
return new List<SslCertificate>();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "获取阿里云 SSL 证书列表失败");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"阿里云 SSL 证书下载功能待实现: {certificateId}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"下载证书失败: {certificateId}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Hua.DDNS/SslProviders/ISslDownloadProvider.cs
Normal file
19
Hua.DDNS/SslProviders/ISslDownloadProvider.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Hua.DDNS.SslProviders
|
||||||
|
{
|
||||||
|
public interface ISslDownloadProvider
|
||||||
|
{
|
||||||
|
Task<List<SslCertificate>> GetCertificatesAsync();
|
||||||
|
Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SslCertificate
|
||||||
|
{
|
||||||
|
public string CertificateId { get; set; }
|
||||||
|
public string Domain { get; set; }
|
||||||
|
public string Alias { get; set; }
|
||||||
|
public DateTime CertBeginTime { get; set; }
|
||||||
|
public DateTime CertEndTime { get; set; }
|
||||||
|
public int Status { get; set; }
|
||||||
|
public string StatusMsg { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Hua.DDNS/SslProviders/Tencent/TencentSslOption.cs
Normal file
11
Hua.DDNS/SslProviders/Tencent/TencentSslOption.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using Hua.DDNS.Common.Config.Options;
|
||||||
|
|
||||||
|
namespace Hua.DDNS.SslProviders.Tencent
|
||||||
|
{
|
||||||
|
public class TencentSslOption
|
||||||
|
{
|
||||||
|
public string SecretId { get; set; }
|
||||||
|
public string SecretKey { get; set; }
|
||||||
|
public string Region { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
176
Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs
Normal file
176
Hua.DDNS/SslProviders/Tencent/TencentSslProvider.cs
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
using Hua.DDNS.Common.Config.Options;
|
||||||
|
using Hua.DDNS.SslProviders;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using TencentCloud.Common;
|
||||||
|
using TencentCloud.Common.Profile;
|
||||||
|
using TencentCloud.Ssl.V20191205;
|
||||||
|
using TencentCloud.Ssl.V20191205.Models;
|
||||||
|
using System.IO.Compression;
|
||||||
|
|
||||||
|
namespace Hua.DDNS.SslProviders.Tencent
|
||||||
|
{
|
||||||
|
public class TencentSslProvider : ISslDownloadProvider
|
||||||
|
{
|
||||||
|
private readonly SslClient _client;
|
||||||
|
private readonly TencentCloudOption _tencentCloudOption;
|
||||||
|
private readonly ILogger<TencentSslProvider> _logger;
|
||||||
|
|
||||||
|
public TencentSslProvider(
|
||||||
|
ILogger<TencentSslProvider> logger,
|
||||||
|
IOptions<TencentCloudOption> tencentCloudOption)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_tencentCloudOption = tencentCloudOption.Value;
|
||||||
|
|
||||||
|
_client = new SslClient(
|
||||||
|
new Credential { SecretId = _tencentCloudOption.SecretId, SecretKey = _tencentCloudOption.SecretKey },
|
||||||
|
_tencentCloudOption.Region,
|
||||||
|
new ClientProfile()
|
||||||
|
{
|
||||||
|
HttpProfile = new HttpProfile { Endpoint = "ssl.tencentcloudapi.com" }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<SslCertificate>> GetCertificatesAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new DescribeCertificatesRequest
|
||||||
|
{
|
||||||
|
Limit = 100,
|
||||||
|
Offset = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _client.DescribeCertificates(request);
|
||||||
|
var certificates = new List<SslCertificate>();
|
||||||
|
|
||||||
|
if (response.Certificates != null)
|
||||||
|
{
|
||||||
|
foreach (var cert in response.Certificates)
|
||||||
|
{
|
||||||
|
certificates.Add(new SslCertificate
|
||||||
|
{
|
||||||
|
CertificateId = cert.CertificateId,
|
||||||
|
Domain = cert.Domain,
|
||||||
|
Alias = cert.Alias,
|
||||||
|
CertBeginTime = DateTime.Parse(cert.CertBeginTime),
|
||||||
|
CertEndTime = DateTime.Parse(cert.CertEndTime),
|
||||||
|
Status = (int)(cert.Status ?? 0),
|
||||||
|
StatusMsg = cert.StatusMsg
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation($"获取到 {certificates.Count} 个腾讯云 SSL 证书");
|
||||||
|
return certificates;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "获取腾讯云 SSL 证书列表失败");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DownloadCertificateAsync(string certificateId, string savePath, string fileName)
|
||||||
|
{
|
||||||
|
string tempZipPath = null;
|
||||||
|
string tempExtractPath = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new DownloadCertificateRequest
|
||||||
|
{
|
||||||
|
CertificateId = certificateId
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await _client.DownloadCertificate(request);
|
||||||
|
|
||||||
|
if (response == null || string.IsNullOrEmpty(response.Content))
|
||||||
|
{
|
||||||
|
_logger.LogError($"证书内容为空: {certificateId}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var zipBytes = Convert.FromBase64String(response.Content);
|
||||||
|
|
||||||
|
if (!Directory.Exists(savePath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(savePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
tempZipPath = Path.Combine(Path.GetTempPath(), $"ssl_{Guid.NewGuid()}.zip");
|
||||||
|
await File.WriteAllBytesAsync(tempZipPath, zipBytes);
|
||||||
|
_logger.LogInformation($"证书ZIP文件临时保存成功: {tempZipPath}");
|
||||||
|
|
||||||
|
tempExtractPath = Path.Combine(Path.GetTempPath(), $"ssl_extract_{Guid.NewGuid()}");
|
||||||
|
ZipFile.ExtractToDirectory(tempZipPath, tempExtractPath);
|
||||||
|
_logger.LogInformation($"证书ZIP文件解压成功: {tempExtractPath}");
|
||||||
|
|
||||||
|
var nginxPath = Path.Combine(tempExtractPath, "Nginx");
|
||||||
|
if (!Directory.Exists(nginxPath))
|
||||||
|
{
|
||||||
|
_logger.LogError($"ZIP文件中未找到Nginx目录");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var certFiles = Directory.GetFiles(nginxPath, "*.crt");
|
||||||
|
var keyFiles = Directory.GetFiles(nginxPath, "*.key");
|
||||||
|
|
||||||
|
if (certFiles.Length == 0 || keyFiles.Length == 0)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Nginx目录中未找到证书文件或私钥文件");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var certFile = certFiles[0];
|
||||||
|
var keyFile = keyFiles[0];
|
||||||
|
|
||||||
|
var certFileName = Path.GetFileNameWithoutExtension(fileName);
|
||||||
|
var certSavePath = Path.Combine(savePath, $"{certFileName}_bundle.crt");
|
||||||
|
var keySavePath = Path.Combine(savePath, $"{certFileName}.key");
|
||||||
|
|
||||||
|
File.Copy(certFile, certSavePath, true);
|
||||||
|
File.Copy(keyFile, keySavePath, true);
|
||||||
|
|
||||||
|
_logger.LogInformation($"证书文件保存成功: {certSavePath}");
|
||||||
|
_logger.LogInformation($"私钥文件保存成功: {keySavePath}");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"下载证书失败: {certificateId}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (tempExtractPath != null && Directory.Exists(tempExtractPath))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempExtractPath, true);
|
||||||
|
_logger.LogInformation($"清理临时解压目录: {tempExtractPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, $"清理临时解压目录失败: {tempExtractPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (tempZipPath != null && File.Exists(tempZipPath))
|
||||||
|
{
|
||||||
|
File.Delete(tempZipPath);
|
||||||
|
_logger.LogInformation($"清理临时ZIP文件: {tempZipPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, $"清理临时ZIP文件失败: {tempZipPath}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,16 @@ using System.Configuration;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Hua.DDNS.Common;
|
using Hua.DDNS.Common;
|
||||||
using Hua.DDNS.Common.Config;
|
using Hua.DDNS.Common.Config;
|
||||||
|
using Hua.DDNS.Common.Config.Options;
|
||||||
using Hua.DDNS.Common.Http;
|
using Hua.DDNS.Common.Http;
|
||||||
using Hua.DDNS.DDNSProviders;
|
using Hua.DDNS.DDNSProviders;
|
||||||
using Hua.DDNS.DDNSProviders.Ali;
|
using Hua.DDNS.DDNSProviders.Ali;
|
||||||
using Hua.DDNS.DDNSProviders.Dnspod;
|
using Hua.DDNS.DDNSProviders.Dnspod;
|
||||||
using Hua.DDNS.DDNSProviders.Namesilo;
|
using Hua.DDNS.DDNSProviders.Namesilo;
|
||||||
using Hua.DDNS.Jobs;
|
using Hua.DDNS.Jobs;
|
||||||
|
using Hua.DDNS.SslProviders;
|
||||||
|
using Hua.DDNS.SslProviders.Ali;
|
||||||
|
using Hua.DDNS.SslProviders.Tencent;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Extensions.Logging;
|
using Serilog.Extensions.Logging;
|
||||||
@@ -47,8 +51,9 @@ namespace Hua.DDNS.Start
|
|||||||
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
||||||
services.Configure<DdnsOption>(hostContext.Configuration.GetSection("DDNS"));
|
services.Configure<DdnsOption>(hostContext.Configuration.GetSection("DDNS"));
|
||||||
services.Configure<NamesiloOption>(hostContext.Configuration.GetSection("Namesilo"));
|
services.Configure<NamesiloOption>(hostContext.Configuration.GetSection("Namesilo"));
|
||||||
services.Configure<DnspodOption>(hostContext.Configuration.GetSection("Dnspod"));
|
services.Configure<TencentCloudOption>(hostContext.Configuration.GetSection("TencentCloud"));
|
||||||
services.Configure<AliDdnsOption>(hostContext.Configuration.GetSection("Ali"));
|
services.Configure<AliCloudOption>(hostContext.Configuration.GetSection("AliCloud"));
|
||||||
|
services.Configure<SslDownloadOption>(hostContext.Configuration.GetSection("SslDownload"));
|
||||||
ConfigDi(hostContext, services);
|
ConfigDi(hostContext, services);
|
||||||
ConfigQuartz(hostContext, services);
|
ConfigQuartz(hostContext, services);
|
||||||
});
|
});
|
||||||
@@ -62,6 +67,8 @@ namespace Hua.DDNS.Start
|
|||||||
services.AddTransient<NamesiloDdnsProvider>();
|
services.AddTransient<NamesiloDdnsProvider>();
|
||||||
services.AddTransient<AliDdnsProvider>();
|
services.AddTransient<AliDdnsProvider>();
|
||||||
services.AddTransient<DnspodDdnsProvider>();
|
services.AddTransient<DnspodDdnsProvider>();
|
||||||
|
services.AddTransient<AliSslProvider>();
|
||||||
|
services.AddTransient<TencentSslProvider>();
|
||||||
return services.BuildServiceProvider();
|
return services.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +109,27 @@ namespace Hua.DDNS.Start
|
|||||||
.WithDescription("NewJob trigger")
|
.WithDescription("NewJob trigger")
|
||||||
.StartNow()
|
.StartNow()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var sslDownloadJobKey = new JobKey("SslDownloadJob", "SslDownloadJobGroup");
|
||||||
|
q.AddJob<SslDownloadJob>(j => j
|
||||||
|
.StoreDurably()
|
||||||
|
.WithIdentity(sslDownloadJobKey)
|
||||||
|
.WithDescription("SslDownloadJob")
|
||||||
|
);
|
||||||
|
|
||||||
|
var sslCorn = hostContext.Configuration.GetSection("SslDownload:Corn").Value;
|
||||||
|
var sslEnabled = hostContext.Configuration.GetSection("SslDownload:Enabled").Get<bool>();
|
||||||
|
|
||||||
|
if (sslEnabled && !string.IsNullOrEmpty(sslCorn))
|
||||||
|
{
|
||||||
|
q.AddTrigger(t => t
|
||||||
|
.WithIdentity("SslDownloadJob Trigger")
|
||||||
|
.ForJob(sslDownloadJobKey)
|
||||||
|
.WithCronSchedule(sslCorn)
|
||||||
|
.WithDescription("SslDownloadJob trigger")
|
||||||
|
.StartNow()
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quartz.Extensions.Hosting hosting
|
// Quartz.Extensions.Hosting hosting
|
||||||
|
|||||||
@@ -8,15 +8,16 @@
|
|||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"App": {
|
"App": {
|
||||||
"AppJob": {
|
"GetIpv4Url": "http://47.108.74.59:8001/api/NetWork/GetIp",
|
||||||
"Corn": "* * * * * ?" //https://cron.qqe2.com/
|
"AppJob": {
|
||||||
}
|
"Corn": "0/5 * * * * ?" //https://cron.qqe2.com/
|
||||||
},
|
}
|
||||||
|
},
|
||||||
"DDNS": {
|
"DDNS": {
|
||||||
"Platform": 3, //1 Ali 2 Tencent 3 Namesilo
|
"Platform": 2, //1 Ali 2 Tencent 3 Namesilo
|
||||||
// 主域名
|
// 主域名
|
||||||
"Domain": "we965.com",
|
"Domain": "we965.cn",
|
||||||
// 子域名前缀
|
// 子域名前缀
|
||||||
"SubDomainArray": [ "git", "webutil", "dev" ],
|
"SubDomainArray": [ "git", "webutil", "dev" ],
|
||||||
// 记录类型
|
// 记录类型
|
||||||
@@ -24,17 +25,42 @@
|
|||||||
//间隔时间 秒
|
//间隔时间 秒
|
||||||
"time": "30"
|
"time": "30"
|
||||||
},
|
},
|
||||||
|
"SslDownload": {
|
||||||
|
"Enabled": true,
|
||||||
|
"Corn": "0/5 * * * * ?",
|
||||||
|
"Platform": 2,
|
||||||
|
"SavePath": "D:\\Paths\\ssl",
|
||||||
|
"ExpireDays": 10000,
|
||||||
|
"DownloadItems": [
|
||||||
|
{
|
||||||
|
"Domain": "git.we965.cn",
|
||||||
|
"FileName": "git.we965.cn.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "webutil.we965.cn",
|
||||||
|
"FileName": "webutil.we965.cn.pem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Domain": "dev.we965.cn",
|
||||||
|
"FileName": "dev.we965.cn.pem"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TencentCloud": {
|
||||||
|
"SecretId": "1111",
|
||||||
|
"SecretKey": "11111",
|
||||||
|
"Region": "ap-guangzhou",
|
||||||
|
"Dnspod": {
|
||||||
|
"Endpoint": "dnspod.tencentcloudapi.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AliCloud": {
|
||||||
|
"AccessKeyId": "1111",
|
||||||
|
"AccessKeySecret": "1111",
|
||||||
|
"RegionId": "cn-hangzhou",
|
||||||
|
"Endpoint": "1111"
|
||||||
|
},
|
||||||
"Namesilo": {
|
"Namesilo": {
|
||||||
"ApiKey": "1111"
|
"ApiKey": "1111"
|
||||||
},
|
|
||||||
"Dnspod": {
|
|
||||||
"Id": "1111",
|
|
||||||
"Key": "1111",
|
|
||||||
"Endpoint": "1111"
|
|
||||||
},
|
|
||||||
"Ali": {
|
|
||||||
"Id": "1111",
|
|
||||||
"Key": "1111",
|
|
||||||
"Endpoint": "1111"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user