/// <summary>
        /// Save certificates and account data to a directory.
        /// Certificates are stored in the .pfx (PKCS #12) format in a subdirectory of <paramref name="directory"/>.
        /// Account key information is stored in a JSON format in a different subdirectory of <paramref name="directory"/>.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="directory">The root directory for storing information. Information may be stored in subdirectories.</param>
        /// <param name="pfxPassword">Set to null or empty for passwordless .pfx files.</param>
        /// <returns></returns>
        public static ILettuceEncryptServiceBuilder PersistDataToDirectory(
            this ILettuceEncryptServiceBuilder builder,
            DirectoryInfo directory,
            string?pfxPassword)
        {
            if (builder is null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            if (directory is null)
            {
                throw new ArgumentNullException(nameof(directory));
            }

            var otherFileSystemRepoServices = builder
                                              .Services
                                              .Where(d => d.ServiceType == typeof(ICertificateRepository) &&
                                                     d.ImplementationInstance != null &&
                                                     d.ImplementationInstance.GetType() == typeof(FileSystemCertificateRepository));

            foreach (var serviceDescriptor in otherFileSystemRepoServices)
            {
                var otherRepo = (FileSystemCertificateRepository)serviceDescriptor.ImplementationInstance !;
                if (otherRepo.RootDir.Equals(directory))
                {
                    if (otherRepo.PfxPassword != pfxPassword)
                    {
                        throw new ArgumentException($"Another file system repo has been configured for {directory}, but with a different password.");
                    }
                    return(builder);
                }
            }

            var implementationInstance = new FileSystemCertificateRepository(directory, pfxPassword);

            builder.Services
            .AddSingleton <ICertificateRepository>(implementationInstance)
            .AddSingleton <ICertificateSource>(implementationInstance);

            builder.Services.TryAddSingleton <IAccountStore>(services => new FileSystemAccountStore(directory,
                                                                                                    services.GetRequiredService <ILogger <FileSystemAccountStore> >(),
                                                                                                    services.GetRequiredService <ICertificateAuthorityConfiguration>()));

            return(builder);
        }
    /// <summary>
    /// Persists certificates to configured key vault.
    /// </summary>
    /// <param name="builder">A LettuceEncrypt service builder.</param>
    /// <param name="configure">Configuration for KeyVault connections.</param>
    /// <returns>The original LettuceEncrypt service builder.</returns>
    public static ILettuceEncryptServiceBuilder PersistCertificatesToAzureKeyVault(
        this ILettuceEncryptServiceBuilder builder,
        Action <AzureKeyVaultLettuceEncryptOptions> configure)
    {
        var services = builder.Services;

        services
        .AddSingleton <ICertificateClientFactory, CertificateClientFactory>()
        .AddSingleton <ISecretClientFactory, SecretClientFactory>();

        services.TryAddSingleton <AzureKeyVaultCertificateRepository>();
        services.TryAddSingleton <IAccountStore, AzureKeyVaultAccountStore>();
        services.TryAddEnumerable(
            ServiceDescriptor.Singleton <ICertificateRepository, AzureKeyVaultCertificateRepository>(x =>
                                                                                                     x.GetRequiredService <AzureKeyVaultCertificateRepository>()));
        services.TryAddEnumerable(
            ServiceDescriptor.Singleton <ICertificateSource, AzureKeyVaultCertificateRepository>(x =>
                                                                                                 x.GetRequiredService <AzureKeyVaultCertificateRepository>()));

        services.AddSingleton <IConfigureOptions <AzureKeyVaultLettuceEncryptOptions> >(s =>
        {
            var config = s.GetService <IConfiguration?>();
            return(new ConfigureOptions <AzureKeyVaultLettuceEncryptOptions>(o =>
                                                                             config?.Bind("LettuceEncrypt:AzureKeyVault", o)));
        });

        var options = services
                      .AddOptions <AzureKeyVaultLettuceEncryptOptions>()
                      .Configure(configure);

#if FEATURE_VALIDATE_DATA_ANNOTATIONS
        options.ValidateDataAnnotations();
#endif

        return(builder);
    }
 /// <summary>
 /// Persists certificates to configured key vault.
 /// </summary>
 /// <param name="builder">A LettuceEncrypt service builder.</param>
 /// <returns>The original LettuceEncrypt service builder.</returns>
 public static ILettuceEncryptServiceBuilder PersistCertificatesToAzureKeyVault(
     this ILettuceEncryptServiceBuilder builder)
 => builder.PersistCertificatesToAzureKeyVault(_ => { });