Browse Source

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

老九 3 years ago
parent
commit
ec7515dfda

+ 77 - 0
FastGithub.HttpServer/CaCertInstallerOfLinux.cs

@@ -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);
+        }
+    }
+}

+ 20 - 0
FastGithub.HttpServer/CaCertInstallerOfLinuxCentOS.cs

@@ -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");
+        }
+    }
+}

+ 20 - 0
FastGithub.HttpServer/CaCertInstallerOfLinuxDebain.cs

@@ -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");
+        }
+    }
+}

+ 16 - 0
FastGithub.HttpServer/CaCertInstallerOfLinuxUbuntu.cs

@@ -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");
+        }
+    }
+}

+ 27 - 0
FastGithub.HttpServer/CaCertInstallerOfMacOS.cs

@@ -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}");
+        }
+    }
+}

+ 51 - 0
FastGithub.HttpServer/CaCertInstallerOfWindows.cs

@@ -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}到“将所有的证书都放入下列存储”\\“受信任的根证书颁发机构”");
+            }
+        }
+    }
+}

+ 8 - 42
FastGithub.HttpServer/CertService.cs

@@ -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>

+ 23 - 0
FastGithub.HttpServer/ICaCertInstaller.cs

@@ -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);
+    }
+}

+ 7 - 3
FastGithub.HttpServer/ServiceCollectionExtensions.cs

@@ -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>();
         }
     }

+ 2 - 5
publish.cmd

@@ -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