Пример #1
0
        static int SslCertListCollector(ConsoleService c, string cmdName, string str)
        {
            ConsoleParam[] args =
            {
                new ConsoleParam("[dnsZonesDir]", ConsoleService.Prompt, "dnsZonesDir: ", ConsoleService.EvalNotEmpty, null),
                new ConsoleParam("OUT",           ConsoleService.Prompt, "outDir: ",      ConsoleService.EvalNotEmpty, null),
                new ConsoleParam("HASH"),
            };
            ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);

            string dirZonesDir = vl.DefaultParam.StrValue;
            string outDir      = vl["OUT"].StrValue;
            string hashliststr = vl["HASH"].StrValue;

            string[] hashlist = hashliststr._Split(StringSplitOptions.RemoveEmptyEntries, ";", "/", ",", ":", " ");

            var dirList = Lfs.EnumDirectory(dirZonesDir, false);

            if (dirList.Where(x => x.IsFile && (IgnoreCaseTrim)Lfs.PathParser.GetExtension(x.Name) == ".dns").Any() == false)
            {
                // 指定されたディレクトリに *.dns ファイルが 1 つもない場合は子ディレクトリ名をソートして一番大きいものを選択する
                dirZonesDir = dirList.OrderByDescending(x => x.Name).Where(x => x.IsDirectory).Select(x => x.FullPath).First();
            }

            Con.WriteLine($"Target directory: '{dirZonesDir}'");

            // 1. DNS ゾーンファイルを入力してユニークな FQDN レコードの一覧を生成する
            DnsFlattenUtil flat = new DnsFlattenUtil();

            foreach (FileSystemEntity ent in Lfs.EnumDirectory(dirZonesDir, true))
            {
                if (ent.IsFile)
                {
                    string fn = ent.FullPath;
                    fn._Print();

                    flat.InputZoneFile(Lfs.PathParser.GetFileNameWithoutExtension(fn), Lfs.ReadDataFromFile(fn).Span);
                }
            }

            // 2. FQDN の一覧を入力して FQDN と IP アドレスのペアの一覧を生成する
            DnsIpPairGeneratorUtil pairGenerator = new DnsIpPairGeneratorUtil(100, flat.FqdnSet);

            List <SniHostnameIpAddressPair> list = pairGenerator.ExecuteAsync()._GetResult().ToList();

            // 3. FQDN と IP アドレスのペアの一覧を入力して SSL 証明書一覧を出力する
            SslCertCollectorUtil col = new SslCertCollectorUtil(1000, list);

            IReadOnlyList <SslCertCollectorItem> ret = col.ExecuteAsync()._GetResult();

            if (hashlist.Length >= 1)
            {
                List <SslCertCollectorItem> filtered = new List <SslCertCollectorItem>();
                ret.Where(x => hashlist.Where(y => y._IsSameHex(x.CertHashSha1)).Any())._DoForEach(x => filtered.Add(x));
                ret = filtered;
            }

            ret = ret.OrderBy(x => x.FriendName._NonNullTrim()._Split(StringSplitOptions.RemoveEmptyEntries, ".").Reverse()._Combine("."), StrComparer.IgnoreCaseTrimComparer).ToList();

            // 結果表示
            Con.WriteLine($"Results: {ret.Count} endpoints");

            // 結果保存
            string csv = ret._ObjectArrayToCsv(withHeader: true);

            XmlAndXsd xmlData = Util.GenerateXmlAndXsd(ret);

            string dir = outDir;

            Lfs.WriteDataToFile(Lfs.PathParser.Combine(dir, xmlData.XmlFileName), xmlData.XmlData, flags: FileFlags.AutoCreateDirectory);
            Lfs.WriteDataToFile(Lfs.PathParser.Combine(dir, xmlData.XsdFileName), xmlData.XsdData, flags: FileFlags.AutoCreateDirectory);
            Lfs.WriteStringToFile(Lfs.PathParser.Combine(dir, "csv.csv"), csv, flags: FileFlags.AutoCreateDirectory, writeBom: true);

            return(0);
        }
Пример #2
0
    static int SslCertChecker(ConsoleService c, string cmdName, string str)
    {
        ConsoleParam[] args =
        {
            new ConsoleParam("[dnsZonesDir]", ConsoleService.Prompt, "dnsZonesDir: ", ConsoleService.EvalNotEmpty, null),
        };
        ConsoleParamValueList vl = c.ParseCommandList(cmdName, str, args);

        string dirZonesDir = vl.DefaultParam.StrValue;//@"C:\Users\yagi\Desktop\dnstest";//

        var dirList = Lfs.EnumDirectory(dirZonesDir, false);

        if (dirList.Where(x => x.IsFile && (IgnoreCaseTrim)Lfs.PathParser.GetExtension(x.Name) == ".dns").Any() == false)
        {
            // 指定されたディレクトリに *.dns ファイルが 1 つもない場合は子ディレクトリ名をソートして一番大きいものを選択する
            dirZonesDir = dirList.OrderByDescending(x => x.Name).Where(x => x.IsDirectory).Select(x => x.FullPath).First();
        }

        //Con.WriteLine($"Target directory: '{dirZonesDir}'");

        // 1. DNS ゾーンファイルを入力してユニークな FQDN レコードの一覧を生成する
        DnsFlattenUtil flat = new DnsFlattenUtil();

        foreach (FileSystemEntity ent in Lfs.EnumDirectory(dirZonesDir, true))
        {
            if (ent.IsFile)
            {
                string fn = ent.FullPath;
                //fn._Print();

                flat.InputZoneFile(Lfs.PathParser.GetFileNameWithoutExtension(fn), Lfs.ReadDataFromFile(fn).Span);
            }
        }

        // 2. FQDN の一覧を入力して FQDN と IP アドレスのペアの一覧を生成する
        DnsIpPairGeneratorUtil pairGenerator = new DnsIpPairGeneratorUtil(100, flat.FqdnSet);

        List <SniHostnameIpAddressPair> list = pairGenerator.ExecuteAsync()._GetResult().ToList();

        List <int> ports_FastDebug = new();

        ports_FastDebug.Add(443);

        // 3. FQDN と IP アドレスのペアの一覧を入力して SSL 証明書一覧を出力する
        SslCertCollectorUtil col = new SslCertCollectorUtil(1000, list,
                                                            new SslCertCollectorUtilSettings
        {
            //TryCount = 1,
            //PotentialHttpsPorts = portsTmp,
            DoNotIgnoreLetsEncrypt = true,
            Silent = true,
        });

        long startTick = Time.Tick64;

        IReadOnlyList <SslCertCollectorItem> ret = col.ExecuteAsync()._GetResult();

        long endTick = Time.Tick64;

        DateTimeOffset now        = DtOffsetNow;
        DateTimeOffset threshold2 = now.AddDays(20);

        // 証明書が古くなっていれば警告を出す
        // IP アドレスごとに整理
        SortedDictionary <string, List <SslCertCollectorItem> > dictSoon    = new SortedDictionary <string, List <SslCertCollectorItem> >(StrComparer.IpAddressStrComparer);
        SortedDictionary <string, List <SslCertCollectorItem> > dictExpired = new SortedDictionary <string, List <SslCertCollectorItem> >(StrComparer.IpAddressStrComparer);

        foreach (var item in ret.Where(x => x.IpAddress._IsFilled()))
        {
            var span = item.CertNotAfter - item.CertNotBefore;

            // もともと有効期限が 約 3 年間よりも長い証明書が登録されている場合は、意図的に登録されているオレオレ証明書であるので、更新対象としてマークしない
            if (span < Consts.Numbers.MaxCertExpireSpanTargetForUpdate)
            {
                // 古いかどうか確認
                if (item.CertNotAfter < threshold2)
                {
                    if (item.CertNotAfter < now)
                    {
                        // すでに有効期限超過
                        var o = dictExpired._GetOrNew(item.IpAddress !, () => new List <SslCertCollectorItem>());
                        o.Add(item);
                    }
                    else
                    {
                        // 有効期限 間もなく
                        var o = dictSoon._GetOrNew(item.IpAddress !, () => new List <SslCertCollectorItem>());
                        o.Add(item);
                    }
                }
            }
        }

        dictSoon.Values._DoForEach(x => x._DoSortBy(x => x.OrderBy(x => x.FriendName, StrComparer.FqdnReverseStrComparer).OrderBy(x => x.SniHostName, StrComparer.FqdnReverseStrComparer).OrderBy(x => x.Port)));

        int soonHosts    = dictSoon.Count();
        int expiredHosts = dictExpired.Count();

        Con.WriteLine();

        Con.WriteLine("----");

        if (soonHosts >= 1)
        {
            Con.WriteLine($"Result: WARNING: Total {soonHosts} host's SSL certificates are expiring soon. Please check!", flags: LogFlags.Heading);
        }
        else
        {
            Con.WriteLine($"Result: OK: No host's SSL certificates are expiring soon. Good.", flags: LogFlags.Heading);
        }
        Con.WriteLine("", flags: LogFlags.Heading);

        if (expiredHosts >= 1)
        {
            Con.WriteLine($"Result: Info: Total {expiredHosts} host's SSL certificates are already expired.", flags: LogFlags.Heading);
        }
        else
        {
            Con.WriteLine($"Result: Info: No host's SSL certificates are already expired.", flags: LogFlags.Heading);
        }
        Con.WriteLine("", flags: LogFlags.Heading);


        Con.WriteLine($" Total SniHostnameIpAddressPairs: {list.Count._ToString3()}", flags: LogFlags.Heading);
        Con.WriteLine($" Total SslCertCollectorItems: {ret.Count._ToString3()}", flags: LogFlags.Heading);
        Con.WriteLine($" Took time: {(endTick - startTick)._ToTimeSpanMSecs()._ToTsStr()}", flags: LogFlags.Heading);
        Con.WriteLine();

        if (soonHosts >= 1)
        {
            CoresLib.Report_SimpleResult += $" (WARN! Expiring Soon: {soonHosts} hosts)";

            Con.WriteLine();
            Con.WriteLine("=========== WARN: Expiring Soon Hosts Summary ===========");


            int index = 0;
            foreach (var host in dictSoon)
            {
                string ip    = host.Key;
                string fqdns = host.Value.Select(x => x.FriendName).Distinct(StrCmpi)._OrderByValue(StrComparer.FqdnReverseStrComparer)._Combine(", ");

                index++;
                Con.WriteLine($"Host #{index}/{dictSoon.Count}: IP = '{ip}', FQDNs = '{fqdns}'");
            }

            Con.WriteLine();
        }


        if (expiredHosts >= 1)
        {
            Con.WriteLine();
            Con.WriteLine("=========== INFO: Already Expired Hosts Summary ===========");


            int index = 0;
            foreach (var host in dictExpired)
            {
                string ip    = host.Key;
                string fqdns = host.Value.Select(x => x.FriendName).Distinct(StrCmpi)._OrderByValue(StrComparer.FqdnReverseStrComparer)._Combine(", ");

                index++;
                Con.WriteLine($"Host #{index}/{dictExpired.Count}: IP = '{ip}', FQDNs = '{fqdns}'");
            }

            Con.WriteLine();
        }


        if (soonHosts >= 1)
        {
            string printStr = dictSoon._ObjectToJson();

            Con.WriteLine();
            Con.WriteLine("=========== WARN: Expiring Soon Certificates Details ===========");
            Con.WriteLine(printStr);
            Con.WriteLine();
        }


        if (expiredHosts >= 1)
        {
            string printStr = dictExpired._ObjectToJson();

            Con.WriteLine();
            Con.WriteLine("=========== INFO: Already Expired Certificates Details ===========");
            Con.WriteLine(printStr);
            Con.WriteLine();
        }

        return(0);
    }