Пример #1
0
    public void LoadFromFile_ThrowsIfPasswordIsNull()
    {
        // Arrange, Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("test.pfx", null, DefaultFlags));

        Assert.Equal("There was an error loading the certificate. No password was provided.", exception.Message);
    }
Пример #2
0
    public static void LoadDevelopment_ThrowsIfKeyDoesNotExist()
    {
        // Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadDevelopment("c:/inexistent.json", createIfMissing: false));

        Assert.Equal("Couldn't find the file 'c:/inexistent.json' and creation of a development key was not requested.", exception.Message);
    }
Пример #3
0
    public void LoadFromFile_ThrowsIfFileDoesNotExist()
    {
        // Arrange, Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("./nonexisting.pfx", "", DefaultFlags));

        Assert.Equal($"There was an error loading the certificate. The file './nonexisting.pfx' was not found.", exception.Message);
    }
        public static IIdentityServerBuilder ConfigureKey(this IIdentityServerBuilder identityServerBuilder, IConfiguration configuration)
        {
            if (configuration.GetValue <KeyKinds>("Type") != KeyKinds.KeysRotation)
            {
                identityServerBuilder.AddSigningCredentials();
                return(identityServerBuilder);
            }

            var builder = identityServerBuilder.AddKeysRotation(options => configuration.GetSection(nameof(KeyRotationOptions))?.Bind(options))
                          .AddRsaEncryptorConfiguration(options => configuration.GetSection(nameof(RsaEncryptorConfiguration))?.Bind(options));
            var dataProtectionsOptions = configuration.Get <DataProtectionOptions>();

            switch (dataProtectionsOptions.StorageKind)
            {
            case StorageKind.AzureStorage:
                builder.PersistKeysToAzureBlobStorage(new Uri(dataProtectionsOptions.StorageConnectionString));
                break;

            case StorageKind.EntityFramework:
                builder.PersistKeysToDbContext <OperationalDbContext>();
                break;

            case StorageKind.FileSytem:
                builder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionsOptions.StorageConnectionString));
                break;

            case StorageKind.Redis:
                var redis = ConnectionMultiplexer.Connect(dataProtectionsOptions.StorageConnectionString);
                if (string.IsNullOrEmpty(dataProtectionsOptions.RedisKey))
                {
                    builder.PersistKeysToStackExchangeRedis(redis);
                    break;
                }
                builder.PersistKeysToStackExchangeRedis(redis, dataProtectionsOptions.RedisKey);
                break;
            }
            var protectOptions = dataProtectionsOptions.KeyProtectionOptions;

            if (protectOptions != null)
            {
                switch (protectOptions.KeyProtectionKind)
                {
                case KeyProtectionKind.AzureKeyVault:
                    builder.ProtectKeysWithAzureKeyVault(protectOptions.AzureKeyVaultKeyId, protectOptions.AzureKeyVaultClientId, protectOptions.AzureKeyVaultClientSecret);
                    break;

                case KeyProtectionKind.X509:
                    if (!string.IsNullOrEmpty(protectOptions.X509CertificatePath))
                    {
                        var certificate = SigningKeysLoader.LoadFromFile(protectOptions.X509CertificatePath, protectOptions.X509CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet);
                        builder.ProtectKeysWithCertificate(certificate);
                        break;
                    }
                    builder.ProtectKeysWithCertificate(protectOptions.X509CertificateThumbprint);
                    break;
                }
            }
            return(identityServerBuilder);
        }
    public SigningCredentials LoadKey()
    {
        // We can't know for sure if there was a configuration section explicitly defined.
        // Check if the current configuration has any children and avoid failing if that's the case.
        // This will avoid failing when no configuration has been specified but will still fail if partial data
        // was defined.
        if (!_configuration.GetChildren().Any())
        {
            return(null);
        }

        var key = new KeyDefinition()
        {
            Type          = _configuration[nameof(KeyDefinition.Type)],
            FilePath      = _configuration[nameof(KeyDefinition.FilePath)],
            Password      = _configuration[nameof(KeyDefinition.Password)],
            Name          = _configuration[nameof(KeyDefinition.Name)],
            StoreLocation = _configuration[nameof(KeyDefinition.StoreLocation)],
            StoreName     = _configuration[nameof(KeyDefinition.StoreName)],
            StorageFlags  = _configuration[nameof(KeyDefinition.StorageFlags)]
        };

        if (bool.TryParse(_configuration[nameof(KeyDefinition.Persisted)], out var value))
        {
            key.Persisted = value;
        }

        switch (key.Type)
        {
        case KeySources.Development:
            var developmentKeyPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath ?? DefaultTempKeyRelativePath);
            var createIfMissing    = key.Persisted ?? true;
            _logger.LogInformation(LoggerEventIds.DevelopmentKeyLoaded, "Loading development key at '{developmentKeyPath}'.", developmentKeyPath);
            var developmentKey = new RsaSecurityKey(SigningKeysLoader.LoadDevelopment(developmentKeyPath, createIfMissing))
            {
                KeyId = "Development"
            };
            return(new SigningCredentials(developmentKey, "RS256"));

        case KeySources.File:
            var pfxPath      = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath);
            var storageFlags = GetStorageFlags(key);
            _logger.LogInformation(LoggerEventIds.CertificateLoadedFromFile, "Loading certificate file at '{CertificatePath}' with storage flags '{CertificateStorageFlags}'.", pfxPath, key.StorageFlags);
            return(new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromFile(pfxPath, key.Password, storageFlags)), "RS256"));

        case KeySources.Store:
            if (!Enum.TryParse <StoreLocation>(key.StoreLocation, out var storeLocation))
            {
                throw new InvalidOperationException($"Invalid certificate store location '{key.StoreLocation}'.");
            }
            _logger.LogInformation(LoggerEventIds.CertificateLoadedFromStore, "Loading certificate with subject '{CertificateSubject}' in '{CertificateStoreLocation}\\{CertificateStoreName}'.", key.Name, key.StoreLocation, key.StoreName);
            return(new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromStoreCert(key.Name, key.StoreName, storeLocation, GetCurrentTime())), "RS256"));

        default:
            throw new InvalidOperationException($"Invalid key type '{key.Type ?? "(null)"}'.");
        }
    }
Пример #6
0
    public void LoadFromFile_ThrowsIfPasswordIsIncorrect()
    {
        // Arrange, Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("test.pfx", "incorrect", DefaultFlags));

        Assert.Equal(
            $"There was an error loading the certificate. Either the password is incorrect or the process does not have permisions to store the key in the Keyset '{DefaultFlags}'",
            exception.Message);
    }
Пример #7
0
    public static void LoadFromStoreCert_ThrowsIfThereIsNoCertificateAvailable()
    {
        // Arrange
        var time = new DateTimeOffset(2018, 09, 25, 12, 0, 0, TimeSpan.Zero);

        // Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromStoreCert("Invalid", "My", StoreLocation.CurrentUser, time));

        Assert.Equal("Couldn't find a valid certificate with subject 'Invalid' on the 'CurrentUser\\My'", exception.Message);
    }
Пример #8
0
        public void Encrypt_retreive_cert_from_thumbrint()
        {
            var cert         = SigningKeysLoader.LoadFromFile("TestCert1.pfx", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet);
            var resolverMock = new Mock <Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver>();

            resolverMock.Setup(m => m.ResolveCertificate(It.IsAny <string>())).Returns(cert);
            var sut = new CertificateXmlEncryptor(cert.Thumbprint, resolverMock.Object, NullLoggerFactory.Instance);

            var result = sut.Encrypt(new XElement("test"));

            Assert.NotNull(result);
        }
Пример #9
0
    public static void LoadDevelopment_CreatesKeyIfItDoesNotExist()
    {
        // Arrange
        var path = "./tempkeyfolder/tempkey.json";

        if (File.Exists(path))
        {
            File.Delete(path);
        }

        // Act
        var key = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true);

        // Assert
        Assert.NotNull(key);
        Assert.True(File.Exists(path));
    }
Пример #10
0
    public static void LoadFromStoreCert_PrefersCertificatesCloserToExpirationDate()
    {
        try
        {
            SetupCertificates("./current.pfx", "./future.pfx");
            // Arrange
            var time = new DateTimeOffset(2020, 10, 29, 12, 0, 0, TimeSpan.Zero);

            // Act
            var certificate = SigningKeysLoader.LoadFromStoreCert("CN=SigningKeysLoaderTest", "My", StoreLocation.CurrentUser, time);

            // Assert
            Assert.NotNull(certificate);
            Assert.Equal("C54CD513088C23EC2AFD256874CC6C0F81EA9D5E", certificate.Thumbprint);
        }
        finally
        {
            CleanupCertificates();
        }
    }
Пример #11
0
    public static void LoadFromStoreCert_SkipsExpiredCertificates()
    {
        try
        {
            SetupCertificates("./expired.pfx", "./current.pfx", "./future.pfx");
            // Arrange
            var time = new DateTimeOffset(2024, 01, 01, 12, 0, 0, TimeSpan.Zero);

            // Act
            var certificate = SigningKeysLoader.LoadFromStoreCert("CN=SigningKeysLoaderTest", "My", StoreLocation.CurrentUser, time);

            // Assert
            Assert.NotNull(certificate);
            Assert.Equal("35840DD366107B89D2885A6B4F42CCBBAE6BA8E3", certificate.Thumbprint);
        }
        finally
        {
            CleanupCertificates();
        }
    }
Пример #12
0
    public static void LoadDevelopment_ReusesKeyIfExists()
    {
        // Arrange
        var path = "./tempkeyfolder/existing.json";

        if (File.Exists(path))
        {
            File.Delete(path);
        }
        var existingKey        = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true);
        var existingParameters = existingKey.ExportParameters(includePrivateParameters: true);

        // Act
        var currentKey        = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true);
        var currentParameters = currentKey.ExportParameters(includePrivateParameters: true);

        // Assert
        Assert.NotNull(currentKey);
        Assert.Equal(existingParameters.P, currentParameters.P);
        Assert.Equal(existingParameters.Q, currentParameters.Q);
    }
Пример #13
0
        public static IDataProtectionBuilder ConfigureDataProtection(this IDataProtectionBuilder builder, IConfiguration configuration)
        {
            var dataProtectionsOptions = configuration.Get <Aguacongas.TheIdServer.Models.DataProtectionOptions>();

            if (dataProtectionsOptions == null)
            {
                return(builder);
            }
            builder.AddKeyManagementOptions(options => configuration.GetSection(nameof(KeyManagementOptions))?.Bind(options));
            ConfigureEncryptionAlgorithm(builder, configuration);
            switch (dataProtectionsOptions.StorageKind)
            {
            case StorageKind.AzureStorage:
                builder.PersistKeysToAzureBlobStorage(new Uri(dataProtectionsOptions.StorageConnectionString));
                break;

            case StorageKind.EntityFramework:
                builder.PersistKeysToDbContext <OperationalDbContext>();
                break;

            case StorageKind.FileSytem:
                builder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionsOptions.StorageConnectionString));
                break;

            case StorageKind.Redis:
                var redis = ConnectionMultiplexer.Connect(dataProtectionsOptions.StorageConnectionString);
                if (string.IsNullOrEmpty(dataProtectionsOptions.RedisKey))
                {
                    builder.PersistKeysToStackExchangeRedis(redis);
                    break;
                }
                builder.PersistKeysToStackExchangeRedis(redis, dataProtectionsOptions.RedisKey);
                break;

            case StorageKind.Registry:
#pragma warning disable CA1416 // Validate platform compatibility
                builder.PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(dataProtectionsOptions.StorageConnectionString));
#pragma warning restore CA1416 // Validate platform compatibility
                break;
            }
            var protectOptions = dataProtectionsOptions.KeyProtectionOptions;
            if (protectOptions != null)
            {
                switch (protectOptions.KeyProtectionKind)
                {
                case KeyProtectionKind.AzureKeyVault:
                    builder.ProtectKeysWithAzureKeyVault(protectOptions.AzureKeyVaultKeyId, protectOptions.AzureKeyVaultClientId, protectOptions.AzureKeyVaultClientSecret);
                    break;

                case KeyProtectionKind.WindowsDpApi:
                    builder.ProtectKeysWithDpapi(protectOptions.WindowsDPAPILocalMachine);
                    break;

                case KeyProtectionKind.WindowsDpApiNg:
                    ConfigureWindowsDpApiNg(builder, protectOptions);
                    break;

                case KeyProtectionKind.X509:
                    if (!string.IsNullOrEmpty(protectOptions.X509CertificatePath))
                    {
                        var certificate = SigningKeysLoader.LoadFromFile(protectOptions.X509CertificatePath, protectOptions.X509CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet);
                        builder.ProtectKeysWithCertificate(certificate);
                        break;
                    }
                    builder.ProtectKeysWithCertificate(protectOptions.X509CertificateThumbprint);
                    break;
                }
            }

            return(builder);
        }