部分linux下root用户自动安装ca证书

This commit is contained in:
老九 2021-11-11 22:32:10 +08:00
parent 5f97c381ab
commit ec7515dfda
10 changed files with 251 additions and 50 deletions

View File

@ -0,0 +1,77 @@
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.IO;
namespace FastGithub.HttpServer
{
abstract class CaCertInstallerOfLinux : ICaCertInstaller
{
const string OS_RELEASE_FILE = "/etc/os-release";
/// <summary>
/// 更新工具文件名
/// </summary>
public abstract string CertUpdateFileName { get; }
/// <summary>
/// 证书根目录
/// </summary>
public abstract string RootCertPath { get; }
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public abstract bool IsSupported();
/// <summary>
/// 安装ca证书
/// </summary>
/// <param name="caCertFilePath">证书文件路径</param>
/// <param name="logger"></param>
public void Install(string caCertFilePath, ILogger logger)
{
if (Environment.UserName != "root")
{
logger.LogWarning($"无法自动安装CA证书{caCertFilePath}因为没有root权限");
return;
}
try
{
Directory.CreateDirectory(this.RootCertPath);
var destCertFilePath = Path.Combine(this.RootCertPath, "fastgithub.crt");
File.Copy(caCertFilePath, destCertFilePath, overwrite: true);
Process.Start(this.CertUpdateFileName).WaitForExit();
}
catch (Exception ex)
{
logger.LogWarning(ex.Message, "自动安装证书异常");
}
}
/// <summary>
/// 是否为某个发行版
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
protected bool IsReleasName(string name)
{
if (File.Exists(OS_RELEASE_FILE) == false)
{
return false;
}
var releaseLines = File.ReadAllLines(OS_RELEASE_FILE);
if (releaseLines.Length == 0)
{
return false;
}
var nameLine = releaseLines[0];
return nameLine.Contains(name);
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace FastGithub.HttpServer
{
class CaCertInstallerOfLinuxCentOS : CaCertInstallerOfLinux
{
public override string RootCertPath => "/etc/pki/ca-trust/source/anchors";
public override string CertUpdateFileName => "update-ca-trust";
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public override bool IsSupported()
{
return OperatingSystem.IsLinux() && base.IsReleasName("CentOS");
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace FastGithub.HttpServer
{
class CaCertInstallerOfLinuxDebain : CaCertInstallerOfLinux
{
public override string RootCertPath => "/usr/local/share/ca-certificates";
public override string CertUpdateFileName => "update-ca-certificates";
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public override bool IsSupported()
{
return OperatingSystem.IsLinux() && base.IsReleasName("Debain");
}
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace FastGithub.HttpServer
{
sealed class CaCertInstallerOfLinuxUbuntu : CaCertInstallerOfLinuxDebain
{
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public override bool IsSupported()
{
return OperatingSystem.IsLinux() && base.IsReleasName("Ubuntu");
}
}
}

View File

@ -0,0 +1,27 @@
using Microsoft.Extensions.Logging;
using System;
namespace FastGithub.HttpServer
{
sealed class CaCertInstallerOfMacOS : ICaCertInstaller
{
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public bool IsSupported()
{
return OperatingSystem.IsMacOS();
}
/// <summary>
/// 安装ca证书
/// </summary>
/// <param name="caCertFilePath">证书文件路径</param>
/// <param name="logger"></param>
public void Install(string caCertFilePath, ILogger logger)
{
logger.LogWarning($"请手动安装CA证书然后设置信任CA证书{caCertFilePath}");
}
}
}

View File

@ -0,0 +1,51 @@
using Microsoft.Extensions.Logging;
using System;
using System.Security.Cryptography.X509Certificates;
namespace FastGithub.HttpServer
{
sealed class CaCertInstallerOfWindows : ICaCertInstaller
{
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
public bool IsSupported()
{
return OperatingSystem.IsWindows();
}
/// <summary>
/// 安装ca证书
/// </summary>
/// <param name="caCertFilePath">证书文件路径</param>
/// <param name="logger"></param>
public void Install(string caCertFilePath, ILogger logger)
{
try
{
using var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
var caCert = new X509Certificate2(caCertFilePath);
var subjectName = caCert.Subject[3..];
foreach (var item in store.Certificates.Find(X509FindType.FindBySubjectName, subjectName, false))
{
if (item.Thumbprint != caCert.Thumbprint)
{
store.Remove(item);
}
}
if (store.Certificates.Find(X509FindType.FindByThumbprint, caCert.Thumbprint, true).Count == 0)
{
store.Add(caCert);
}
store.Close();
}
catch (Exception)
{
logger.LogWarning($"请手动安装CA证书{caCertFilePath}到“将所有的证书都放入下列存储”\\“受信任的根证书颁发机构”");
}
}
}
}

View File

@ -18,6 +18,7 @@ namespace FastGithub.HttpServer
private const string CACERT_PATH = "cacert";
private const int KEY_SIZE_BITS = 2048;
private readonly IMemoryCache serverCertCache;
private readonly IEnumerable<ICaCertInstaller> certInstallers;
private readonly ILogger<CertService> logger;
@ -34,12 +35,16 @@ namespace FastGithub.HttpServer
/// <summary>
/// 证书服务
/// </summary>
/// <param name="serverCertCache"></param>
/// <param name="certInstallers"></param>
/// <param name="logger"></param>
public CertService(
IMemoryCache serverCertCache,
IEnumerable<ICaCertInstaller> certInstallers,
ILogger<CertService> logger)
{
this.serverCertCache = serverCertCache;
this.certInstallers = certInstallers;
this.logger = logger;
Directory.CreateDirectory(CACERT_PATH);
}
@ -68,17 +73,10 @@ namespace FastGithub.HttpServer
/// </summary>
public void InstallAndTrustCaCert()
{
if (OperatingSystem.IsWindows())
var installer = this.certInstallers.FirstOrDefault(item => item.IsSupported());
if (installer != null)
{
this.InstallAndTrustCaCertAtWindows();
}
else if (OperatingSystem.IsLinux())
{
this.logger.LogWarning($"请根据具体linux发行版手动安装CA证书{this.CaCerFilePath}");
}
else if (OperatingSystem.IsMacOS())
{
this.logger.LogWarning($"请手动安装CA证书然后设置信任CA证书{this.CaCerFilePath}");
installer.Install(this.CaCerFilePath, this.logger);
}
else
{
@ -113,38 +111,6 @@ namespace FastGithub.HttpServer
}
}
/// <summary>
/// 安装CA证书
/// </summary>
private void InstallAndTrustCaCertAtWindows()
{
try
{
using var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
var caCert = new X509Certificate2(this.CaCerFilePath);
var subjectName = caCert.Subject[3..];
foreach (var item in store.Certificates.Find(X509FindType.FindBySubjectName, subjectName, false))
{
if (item.Thumbprint != caCert.Thumbprint)
{
store.Remove(item);
}
}
if (store.Certificates.Find(X509FindType.FindByThumbprint, caCert.Thumbprint, true).Count == 0)
{
store.Add(caCert);
}
store.Close();
}
catch (Exception)
{
this.logger.LogWarning($"请手动安装CA证书{this.CaCerFilePath}到“将所有的证书都放入下列存储”\\“受信任的根证书颁发机构”");
}
}
/// <summary>
/// 获取颁发给指定域名的证书
/// </summary>

View File

@ -0,0 +1,23 @@
using Microsoft.Extensions.Logging;
namespace FastGithub.HttpServer
{
/// <summary>
/// CA证书安装器
/// </summary>
interface ICaCertInstaller
{
/// <summary>
/// 是否支持
/// </summary>
/// <returns></returns>
bool IsSupported();
/// <summary>
/// 安装ca证书
/// </summary>
/// <param name="caCertFilePath">证书文件路径</param>
/// <param name="logger"></param>
void Install(string caCertFilePath,ILogger logger);
}
}

View File

@ -1,6 +1,5 @@
using FastGithub.HttpServer;
using Microsoft.Extensions.DependencyInjection;
namespace FastGithub
{
/// <summary>
@ -18,9 +17,14 @@ namespace FastGithub
return services
.AddMemoryCache()
.AddHttpForwarder()
.AddSingleton<CertService>()
.AddSingleton<CertService>()
.AddSingleton<ICaCertInstaller, CaCertInstallerOfMacOS>()
.AddSingleton<ICaCertInstaller, CaCertInstallerOfWindows>()
.AddSingleton<ICaCertInstaller, CaCertInstallerOfLinuxCentOS>()
.AddSingleton<ICaCertInstaller, CaCertInstallerOfLinuxDebain>()
.AddSingleton<ICaCertInstaller, CaCertInstallerOfLinuxUbuntu>()
.AddSingleton<HttpProxyMiddleware>()
.AddSingleton<RequestLoggingMiddleware>()
.AddSingleton<RequestLoggingMiddleware>()
.AddSingleton<HttpReverseProxyMiddleware>();
}
}

View File

@ -1,7 +1,4 @@
set output=./publish
if exist "%output%" rd /S /Q "%output%"
dotnet publish -c Release -o "%output%/fastgithub_win-x64" ./FastGithub.UI/FastGithub.UI.csproj
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained -r win-x64 -o "%output%/fastgithub_win-x64" ./FastGithub/FastGithub.csproj
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained -r linux-x64 -o "%output%/fastgithub_linux-x64" ./FastGithub/FastGithub.csproj
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained -r linux-arm64 -o "%output%/fastgithub_linux-arm64" ./FastGithub/FastGithub.csproj
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true --self-contained -r osx-x64 -o "%output%/fastgithub_osx-x64" ./FastGithub/FastGithub.csproj
dotnet publish -c Release /p:PublishSingleFile=true /p:PublishTrimmed=false --self-contained -r linux-x64 -o "%output%/fastgithub_linux-x64" ./FastGithub/FastGithub.csproj