예제 #1
0
        public async Task TestGetManagedCertificates()
        {
            var filter = new ManagedCertificateFilter();
            var result = await _client.GetManagedCertificates(filter);

            Assert.IsNotNull(result, $"Fetched {result.Count} managed sites");
        }
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null)
        {
            var list = await _itemManager.GetAll(filter);


            if (filter?.IncludeExternal == true)
            {
                if (_pluginManager?.CertificateManagerProviders?.Any() == true)
                {
                    // TODO: cache providers/results
                    // check if we have any external sources of managed certificates
                    foreach (var p in _pluginManager.CertificateManagerProviders)
                    {
                        if (p != null)
                        {
                            var pluginType = p.GetType();
                            var providers  = p.GetProviders(pluginType);
                            foreach (var cp in providers)
                            {
                                var certManager = p.GetProvider(pluginType, cp.Id);
                                var certs       = await certManager.GetManagedCertificates(filter);

                                list.AddRange(certs);
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.WriteLine("Failed to create provider from plugin [Certificate Manager] ");
                        }
                    }
                }
            }

            return(list);
        }
예제 #3
0
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null)
        {
            var list = await _itemManager.GetManagedCertificates(filter);


            if (filter?.IncludeExternal == true)
            {
                if (_pluginManager?.CertificateManagerProviders?.Any() == true)
                {
                    // TODO: cache providers/results
                    // check if we have any external sources of managed certificates
                    foreach (var p in _pluginManager.CertificateManagerProviders)
                    {
                        var providers = p.GetProviders();
                        foreach (var cp in providers)
                        {
                            var certManager = p.GetProvider(cp.Id);
                            var certs       = await certManager.GetManagedCertificates(filter);

                            list.AddRange(certs);
                        }
                    }
                }
            }

            return(list);
        }
예제 #4
0
        private async void Export_Click(object sender, RoutedEventArgs e)
        {
            var filter   = new ManagedCertificateFilter {
            };
            var settings = new ExportSettings {
            };

            var dialog = new SaveFileDialog();

            // prompt user for save file location and perform export to json file
            dialog.FileName   = $"certifytheweb_export_{DateTime.Now.ToString("yyyyMMdd")}.json";
            dialog.DefaultExt = "json";
            dialog.Filter     = "Json files (*.json)|*.json|All files (*.*)|*.*";

            if (dialog.ShowDialog() == true)
            {
                var savePath = dialog.FileName;

                settings.EncryptionSecret = txtSecret.Password;
                var export = await MainViewModel.GetSettingsExport(filter, settings, false);

                var json = JsonConvert.SerializeObject(export, new JsonSerializerSettings {
                    Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore
                });
                System.IO.File.WriteAllText(savePath, json);

                (App.Current as App).ShowNotification("Export completed OK", App.NotificationType.Success);
            }
        }
예제 #5
0
        public async Task <List <ManagedCertificate> > GetAll(ManagedCertificateFilter filter = null)
        {
#if DEBUG
            // filter.PageIndex = 0;
            // filter.PageSize = 100;
#endif

            var items = await LoadAllManagedCertificates(filter);

            if (filter != null)
            {
                if (!string.IsNullOrEmpty(filter.Id))
                {
                    items = items.Where(i => i.Id.ToLowerInvariant().Trim() == filter.Id.ToLowerInvariant().Trim());
                }

                if (!string.IsNullOrEmpty(filter.Name))
                {
                    items = items.Where(i => i.Name.ToLowerInvariant().Trim() == filter.Name.ToLowerInvariant().Trim());
                }

                if (!string.IsNullOrEmpty(filter.Keyword))
                {
                    items = items.Where(i => i.Name.ToLowerInvariant().Contains(filter.Keyword.ToLowerInvariant()));
                }

                if (!string.IsNullOrEmpty(filter.ChallengeType))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeType == filter.ChallengeType));
                }

                if (!string.IsNullOrEmpty(filter.ChallengeProvider))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeProvider == filter.ChallengeProvider));
                }

                if (!string.IsNullOrEmpty(filter.StoredCredentialKey))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeCredentialKey == filter.StoredCredentialKey));
                }

                //TODO: IncludeOnlyNextAutoRenew
                if (filter.MaxResults > 0)
                {
                    items = items.Take(filter.MaxResults);
                }
            }

            return(items.ToList());
        }
예제 #6
0
        public async Task TestGetManagedCertificate()
        {
            //get full list
            var filter = new ManagedCertificateFilter {
                MaxResults = 10
            };
            var results = await _client.GetManagedCertificates(filter);

            Assert.IsTrue(results.Count > 0, "Got one or more managed sites");

            //attempt to get single item
            var site = await _client.GetManagedCertificate(results[0].Id);

            Assert.IsNotNull(site, $"Fetched single managed site details");
        }
예제 #7
0
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter)
        {
            var response = await PostAsync("managedcertificates/search/", filter);

            var serializer = new JsonSerializer();

            using (var sr = new StreamReader(await response.Content.ReadAsStreamAsync()))
                using (var reader = new JsonTextReader(sr))
                {
                    var managedCertificateList = serializer.Deserialize <List <ManagedCertificate> >(reader);
                    foreach (var s in managedCertificateList)
                    {
                        s.IsChanged = false;
                    }
                    return(managedCertificateList);
                }
        }
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null, bool reloadAll = true)
        {
            // Don't reload settings unless we need to or we are unsure if any items have changed
            if (!_managedCertificatesCache.Any() || IsSingleInstanceMode == false || reloadAll)
            {
                await LoadAllManagedCertificates();
            }

            // filter and convert dictionary to list TODO: use db instead of in memory filter?
            var items = _managedCertificatesCache.Values.AsQueryable();

            if (filter != null)
            {
                if (!string.IsNullOrEmpty(filter.Name))
                {
                    items = items.Where(i => i.Name.ToLowerInvariant().Trim() == filter.Name.ToLowerInvariant().Trim());
                }

                if (!string.IsNullOrEmpty(filter.Keyword))
                {
                    items = items.Where(i => i.Name.ToLowerInvariant().Contains(filter.Keyword.ToLowerInvariant()));
                }

                if (!string.IsNullOrEmpty(filter.ChallengeType))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeType == filter.ChallengeType));
                }

                if (!string.IsNullOrEmpty(filter.ChallengeProvider))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeProvider == filter.ChallengeProvider));
                }

                if (!string.IsNullOrEmpty(filter.StoredCredentialKey))
                {
                    items = items.Where(i => i.RequestConfig.Challenges != null && i.RequestConfig.Challenges.Any(t => t.ChallengeCredentialKey == filter.StoredCredentialKey));
                }

                //TODO: IncludeOnlyNextAutoRenew
                if (filter.MaxResults > 0)
                {
                    items = items.Take(filter.MaxResults);
                }
            }
            return(new List <ManagedCertificate>(items));
        }
예제 #9
0
        private async void Export_Click(object sender, RoutedEventArgs e)
        {
            var filter   = new ManagedCertificateFilter {
            };
            var settings = new ExportSettings {
            };

            var dialog = new SaveFileDialog();

            // prompt user for save file location and perform export to json file
            dialog.FileName = $"certifytheweb_export_{DateTime.Now.ToString("yyyyMMdd")}.json";

            if (dialog.ShowDialog() == true)
            {
                var savePath = dialog.FileName;

                var export = await MainViewModel.GetSettingsExport(filter, settings, false);

                var json = JsonConvert.SerializeObject(export);
                System.IO.File.WriteAllText(savePath, json);

                (App.Current as App).ShowNotification("Export completed OK", App.NotificationType.Success);
            }
        }
예제 #10
0
        public async Task <List <ManagedCertificate> > Search(ManagedCertificateFilter filter)
        {
            DebugLog();

            return(await _certifyManager.GetManagedCertificates(filter));
        }
예제 #11
0
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null)
        {
            var list = new List <ManagedCertificate>();

            if (await IsPresent())
            {
                var directorySearch = new DirectoryInfo(_settingsPath);
                var configFiles     = directorySearch.GetFiles("order.json", SearchOption.AllDirectories);

                foreach (var config in configFiles)
                {
                    try
                    {
                        var cfg = JsonConvert.DeserializeObject <ConfigSettings>(File.ReadAllText(config.FullName));

                        var managedCert = new ManagedCertificate
                        {
                            Id         = "posh-acme://" + cfg.Id,
                            Name       = cfg.FriendlyName,
                            ItemType   = ManagedCertificateType.SSL_ExternallyManaged,
                            SourceId   = Definition.Id,
                            SourceName = Definition.Title,
                            //  CertificateThumbprintHash = lastSuccess?.Thumbprint,
                            DateRenewed            = cfg.RenewAfter,
                            DateExpiry             = cfg.CertExpires,
                            LastRenewalStatus      = cfg.Status == "valid" ? RequestState.Success : (cfg.Status != null ? RequestState.Error : (RequestState?)null),
                            DateLastRenewalAttempt = config.LastWriteTime,
                            RequestConfig          = new CertRequestConfig
                            {
                                PrimaryDomain           = cfg.MainDomain,
                                SubjectAlternativeNames = cfg.SANs
                            },
                            DomainOptions = new System.Collections.ObjectModel.ObservableCollection <DomainOption>
                            {
                                new DomainOption {
                                    Domain = cfg.MainDomain, IsPrimaryDomain = true, IsManualEntry = true, IsSelected = true
                                }
                            }
                        };

                        if (managedCert.RequestConfig.SubjectAlternativeNames != null)
                        {
                            var domains = managedCert.RequestConfig.SubjectAlternativeNames.Where(d => d != managedCert.RequestConfig.PrimaryDomain).Distinct();
                            foreach (var d in domains)
                            {
                                managedCert.DomainOptions.Add(new DomainOption {
                                    Domain = d, IsManualEntry = true, IsPrimaryDomain = false
                                });
                            }
                        }

                        managedCert.IsChanged = false;
                        list.Add(managedCert);
                    }
                    catch (Exception exp)
                    {
                        System.Diagnostics.Debug.WriteLine($"Failed to parse config: [{config}] " + exp);
                    }
                }
            }
            return(list);
        }
예제 #12
0
        public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null)
        {
            var list = new List <ManagedCertificate>();

            if (await IsPresent())
            {
                var directorySearch = new DirectoryInfo(Path.Combine(_settingsPath, "renewal"));

                if (directorySearch.Exists)
                {
                    var configFiles = directorySearch.GetFiles("*.conf", SearchOption.AllDirectories);

                    foreach (var config in configFiles)
                    {
                        try
                        {
                            var id = config.Name.Replace(".conf", "");

                            var managedCert = new ManagedCertificate
                            {
                                Id         = "certbot://" + id,
                                Name       = id,
                                ItemType   = ManagedCertificateType.SSL_ExternallyManaged,
                                SourceId   = Definition.Id,
                                SourceName = Definition.Title
                            };

                            var certFile = new FileInfo(Path.Combine(_settingsPath, "live", id, "cert.pem"));
                            if (certFile.Exists)
                            {
                                try
                                {
                                    var cert       = Certify.Management.CertificateManager.ReadCertificateFromPem(certFile.FullName);
                                    var parsedCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(cert.GetEncoded()); managedCert.DateStart = cert.NotBefore;
                                    managedCert.DateExpiry                = cert.NotAfter;
                                    managedCert.DateRenewed               = cert.NotBefore;
                                    managedCert.DateLastRenewalAttempt    = cert.NotBefore;
                                    managedCert.CertificateThumbprintHash = parsedCert.Thumbprint;
                                    managedCert.CertificatePath           = certFile.FullName;
                                    managedCert.LastRenewalStatus         = RequestState.Success;

                                    if (cert.NotAfter < DateTime.Now.AddDays(29))
                                    {
                                        // assume certs with less than 30 days left have failed to renew
                                        managedCert.LastRenewalStatus     = RequestState.Error;
                                        managedCert.RenewalFailureMessage = "Check certbot configuration. This certificate will expire in less than 30 days and has not yet automatically renewed.";
                                    }

                                    managedCert.RequestConfig = new CertRequestConfig
                                    {
                                        PrimaryDomain = parsedCert.SubjectName.Name
                                    };

                                    var sn = ((System.Collections.ArrayList)cert.GetSubjectAlternativeNames());

                                    List <string> sans = new List <string>();
                                    foreach (System.Collections.ArrayList s in sn)
                                    {
                                        sans.Add(s[1].ToString());
                                    }

                                    managedCert.RequestConfig.SubjectAlternativeNames = sans.ToArray();

                                    managedCert.DomainOptions = new System.Collections.ObjectModel.ObservableCollection <DomainOption>
                                    {
                                        new DomainOption {
                                            Domain          = managedCert.RequestConfig.PrimaryDomain,
                                            IsPrimaryDomain = true,
                                            IsManualEntry   = true,
                                            IsSelected      = true
                                        }
                                    };
                                }
                                catch (Exception exp)
                                {
                                    System.Diagnostics.Debug.WriteLine("Failed to parse cert: " + exp);
                                }
                            }

                            //var cfg = ParseIni(File.ReadAllText(config.FullName));

                            managedCert.IsChanged = false;
                            list.Add(managedCert);
                        }
                        catch (Exception exp)
                        {
                            System.Diagnostics.Debug.WriteLine($"Failed to parse config: [{config}] " + exp);
                        }
                    }
                }
            }
            return(list);
        }
예제 #13
0
 public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null) => await _itemManager.GetManagedCertificates(filter, true);
예제 #14
0
 public async Task <List <ManagedCertificate> > GetManagedCertificates(ManagedCertificateFilter filter = null)
 {
     return(await this._itemManager.GetManagedCertificates(filter, true));
 }
예제 #15
0
        /// <summary>
        /// Export the managed certificates and related settings for the given filter
        /// </summary>
        /// <param name="filter"></param>
        /// <returns>Package of exported settings</returns>
        public async Task <ImportExportPackage> PerformExport(ManagedCertificateFilter filter, ExportSettings settings, bool isPreview)
        {
            var salt = Guid.NewGuid().ToString();

            var export = new ImportExportPackage
            {
                SourceName           = Environment.MachineName,
                ExportDate           = DateTime.Now,
                SystemVersion        = Certify.Management.Util.GetAppVersion(),
                EncryptionSalt       = salt,
                EncryptionValidation = new EncryptedContent
                {
                    Content = EncryptBytes(Encoding.ASCII.GetBytes("Secret"), settings.EncryptionSecret, salt),
                    Scheme  = EncryptionScheme
                }
            };

            // export managed certs, related certificate files, stored credentials

            // deployment tasks with local script or path references will need to copy the scripts separately. Need a summary of items to copy.

            var managedCerts = await _itemManager.GetAll(filter);

            export.Content = new ImportExportContent
            {
                ManagedCertificates    = managedCerts,
                CertificateFiles       = new List <EncryptedContent>(),
                Scripts                = new List <EncryptedContent>(),
                CertificateAuthorities = new List <CertificateAuthority>(),
                StoredCredentials      = new List <StoredCredential>()
            };


            // for each managed cert, export the current certificate files (if present)
            foreach (var c in managedCerts)
            {
                if (!string.IsNullOrEmpty(c.CertificatePath) && System.IO.File.Exists(c.CertificatePath))
                {
                    var certBytes = System.IO.File.ReadAllBytes(c.CertificatePath);

                    var encryptedBytes = EncryptBytes(certBytes, settings.EncryptionSecret, export.EncryptionSalt);
                    var content        = new EncryptedContent {
                        Filename = c.CertificatePath, Scheme = EncryptionScheme, Content = encryptedBytes
                    };

                    export.Content.CertificateFiles.Add(content);
                }

                if (c.PreRequestTasks?.Any() == true)
                {
                    export.Content.Scripts.AddRange(GetTaskScriptsAndContent(c.PreRequestTasks, settings.EncryptionSecret, export.EncryptionSalt));
                }

                if (c.PostRequestTasks?.Any() == true)
                {
                    export.Content.Scripts.AddRange(GetTaskScriptsAndContent(c.PostRequestTasks, settings.EncryptionSecret, export.EncryptionSalt));
                }
            }


            // for each managed cert, check used stored credentials (DNS challenges or deployment tasks)
            var allCredentials = await _credentialsManager.GetCredentials();

            var usedCredentials = new List <StoredCredential>();

            if (settings.ExportAllStoredCredentials)
            {
                usedCredentials.AddRange(allCredentials);
            }
            else
            {
                foreach (var c in managedCerts)
                {
                    // gather credentials used by cert
                    if (c.CertificatePasswordCredentialId != null)
                    {
                        if (!usedCredentials.Any(u => u.StorageKey == c.CertificatePasswordCredentialId))
                        {
                            usedCredentials.Add(allCredentials.Find(a => a.StorageKey == c.CertificatePasswordCredentialId));
                        }
                    }

                    // gather credentials used by tasks
                    var allTasks = new List <Config.DeploymentTaskConfig>();

                    if (c.PreRequestTasks != null)
                    {
                        allTasks.AddRange(c.PreRequestTasks);
                    }

                    if (c.PostRequestTasks != null)
                    {
                        allTasks.AddRange(c.PostRequestTasks);
                    }

                    if (allTasks.Any())
                    {
                        var usedTaskCredentials = allTasks
                                                  .Select(t => t.ChallengeCredentialKey)
                                                  .Distinct()
                                                  .Where(t => allCredentials.Any(ac => ac.StorageKey == t));

                        foreach (var used in usedTaskCredentials)
                        {
                            if (!usedCredentials.Any(u => u.StorageKey == used))
                            {
                                usedCredentials.Add(allCredentials.FirstOrDefault(u => u.StorageKey == used));
                            }
                        }
                    }
                }
            }

            // decrypt each used stored credential, re-encrypt and base64 encode secret
            foreach (var c in usedCredentials)
            {
                var decrypted = await _credentialsManager.GetUnlockedCredential(c.StorageKey);

                if (decrypted != null)
                {
                    var encBytes = EncryptBytes(Encoding.UTF8.GetBytes(decrypted), settings.EncryptionSecret, export.EncryptionSalt);
                    c.Secret = Convert.ToBase64String(encBytes);
                }
            }

            export.Content.StoredCredentials = usedCredentials;

            // for each managed cert, check and summarise used local scripts

            // copy acme-dns settings

            // export acme accounts?
            return(export);
        }
예제 #16
0
        private async Task <IQueryable <ManagedCertificate> > LoadAllManagedCertificates(ManagedCertificateFilter filter)
        {
            var managedCertificates = new List <ManagedCertificate>();

            var watch = Stopwatch.StartNew();

            // FIXME: this query should called only when absolutely required as the result set may be very large
            if (File.Exists(_dbPath))
            {
                var sql = "SELECT id, json FROM manageditem";

                if (filter?.PageIndex != null && filter?.PageSize != null)
                {
                    sql += $" LIMIT {filter.PageSize} OFFSET {filter.PageIndex}";
                    //sql += $" WHERE id NOT IN (SELECT id FROM manageditem ORDER BY id ASC LIMIT {filter.PageSize * filter.PageIndex}) ORDER BY id ASC LIMIT {filter.PageIndex}";
                }

                using (var db = new SQLiteConnection(_connectionString))
                    using (var cmd = new SQLiteCommand(sql, db))
                    {
                        await db.OpenAsync();

                        using (var reader = await cmd.ExecuteReaderAsync())
                        {
                            while (await reader.ReadAsync())
                            {
                                var itemId = (string)reader["id"];

                                var managedCertificate = JsonConvert.DeserializeObject <ManagedCertificate>((string)reader["json"]);

                                // in some cases users may have previously manipulated the id, causing
                                // duplicates. Correct the ID here (database Id is unique):
                                if (managedCertificate.Id != itemId)
                                {
                                    managedCertificate.Id = itemId;
                                    Debug.WriteLine("LoadSettings: Corrected managed site id: " + managedCertificate.Name);
                                }

                                managedCertificates.Add(managedCertificate);
                            }
                            reader.Close();
                        }
                    }

                foreach (var site in managedCertificates)
                {
                    site.IsChanged = false;
                }
            }

            Debug.WriteLine($"LoadAllManagedCertificates[SQLite] took {watch.ElapsedMilliseconds}ms for {managedCertificates.Count} records");
            return(managedCertificates.AsQueryable());
        }
예제 #17
0
        /// <summary>
        /// Perform full export of app configuration
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="settings"></param>
        /// <param name="isPreview">If true, export is a preview only</param>
        /// <returns></returns>
        public async Task <ImportExportPackage> GetSettingsExport(ManagedCertificateFilter filter, ExportSettings settings, bool isPreview)
        {
            var pkg = await _certifyClient.PerformExport(new ExportRequest { Filter = filter, Settings = settings, IsPreviewMode = isPreview });

            return(pkg);
        }