public void GetAllElements_EmptyOrNonexistentDirectory_ReturnsEmptyCollection()
    {
        WithUniqueTempRegKey(regKey =>
        {
            // Arrange
            var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance);

            // Act
            var allElements = repository.GetAllElements();

            // Assert
            Assert.Equal(0, allElements.Count);
        });
    }
    public void RegistryKey_Property()
    {
        WithUniqueTempRegKey(regKey =>
        {
            // Arrange
            var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance);

            // Act
            var retVal = repository.RegistryKey;

            // Assert
            Assert.Equal(regKey, retVal);
        });
    }
    public void StoreElements_ThenRetrieve_SeesAllElements()
    {
        WithUniqueTempRegKey(regKey =>
        {
            // Arrange
            var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance);

            // Act
            repository.StoreElement(new XElement("element1"), friendlyName: null);
            repository.StoreElement(new XElement("element2"), friendlyName: null);
            repository.StoreElement(new XElement("element3"), friendlyName: null);
            var allElements = repository.GetAllElements();

            // Assert
            var orderedNames = allElements.Select(el => el.Name.LocalName).OrderBy(name => name);
            Assert.Equal(new[] { "element1", "element2", "element3" }, orderedNames);
        });
    }
Example #4
0
        /// <summary>
        /// https://github.com/dotnet/aspnetcore/blob/d8906c8523f071371ce95d4e2d2fdfa89858047e/src/DataProtection/DataProtection/src/KeyManagement/XmlKeyManager.cs#L105
        /// </summary>
        /// <returns></returns>
        internal IXmlRepository GetFallbackKeyRepositoryEncryptorPair()
        {
            IXmlRepository key;
            var            forAzureWebSites = DefaultKeyStorageDirectories.Instance.GetKeyStorageDirectoryForAzureWebSites();

            if (forAzureWebSites != null)
            {
                key = new FileSystemXmlRepository(forAzureWebSites, this._loggerFactory);
            }
            else
            {
                var storageDirectory = DefaultKeyStorageDirectories.Instance.GetKeyStorageDirectory();
                if (storageDirectory != null)
                {
                    key = new FileSystemXmlRepository(storageDirectory, this._loggerFactory);
                }
                else
                {
                    RegistryKey registryKey = null;
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                    {
                        registryKey = RegistryXmlRepository.DefaultRegistryKey;
                    }

                    if (registryKey != null)
                    {
                        var defaultRegistryKey = RegistryXmlRepository.DefaultRegistryKey;
                        key = new RegistryXmlRepository(defaultRegistryKey, this._loggerFactory);
                    }
                    else
                    {
                        throw new Exception(
                                  "Is not possible to determine which folder are the protection keys. NetDevPack.Security.JwtSigningCredentials.Store.FileSystem or NetDevPack.Security.JwtSigningCredentials.Store.EntityFrameworkCore");
                    }
                }
            }
            return(key);
        }
    public void StoreElement_WithValidFriendlyName_UsesFriendlyName()
    {
        WithUniqueTempRegKey(regKey =>
        {
            // Arrange
            var element    = XElement.Parse("<element1 />");
            var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance);

            // Act
            repository.StoreElement(element, "valid-friendly-name");

            // Assert
            var valueNames = regKey.GetValueNames();
            var valueName  = valueNames.Single(); // only one value should've been created

            // value name should be "valid-friendly-name"
            Assert.Equal("valid-friendly-name", valueName, StringComparer.OrdinalIgnoreCase);

            // value contents should be "<element1 />"
            var parsedElement = XElement.Parse(regKey.GetValue(valueName) as string);
            XmlAssert.Equal("<element1 />", parsedElement);
        });
    }
    public void StoreElement_WithInvalidFriendlyName_CreatesNewGuidAsName(string friendlyName)
    {
        WithUniqueTempRegKey(regKey =>
        {
            // Arrange
            var element    = XElement.Parse("<element1 />");
            var repository = new RegistryXmlRepository(regKey, NullLoggerFactory.Instance);

            // Act
            repository.StoreElement(element, friendlyName);

            // Assert
            var valueNames = regKey.GetValueNames();
            var valueName  = valueNames.Single(); // only one value should've been created

            // value name should be "{GUID}"
            Guid parsedGuid = Guid.Parse(valueName as string);
            Assert.NotEqual(Guid.Empty, parsedGuid);

            // value contents should be "<element1 />"
            var parsedElement = XElement.Parse(regKey.GetValue(valueName) as string);
            XmlAssert.Equal("<element1 />", parsedElement);
        });
    }
Example #7
0
        internal KeyValuePair <IXmlRepository, IXmlEncryptor> GetFallbackKeyRepositoryEncryptorPair()
        {
            IXmlRepository repository = null;
            IXmlEncryptor  encryptor  = null;

            // If we're running in Azure Web Sites, the key repository goes in the %HOME% directory.
            var azureWebSitesKeysFolder = _keyStorageDirectories.GetKeyStorageDirectoryForAzureWebSites();

            if (azureWebSitesKeysFolder != null)
            {
                _logger.UsingAzureAsKeyRepository(azureWebSitesKeysFolder.FullName);

                // Cloud DPAPI isn't yet available, so we don't encrypt keys at rest.
                // This isn't all that different than what Azure Web Sites does today, and we can always add this later.
                repository = new FileSystemXmlRepository(azureWebSitesKeysFolder, _loggerFactory);
            }
            else
            {
                // If the user profile is available, store keys in the user profile directory.
                var localAppDataKeysFolder = _keyStorageDirectories.GetKeyStorageDirectory();
                if (localAppDataKeysFolder != null)
                {
                    if (OSVersionUtil.IsWindows())
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.

                        // If the user profile is available, we can protect using DPAPI.
                        // Probe to see if protecting to local user is available, and use it as the default if so.
                        encryptor = new DpapiXmlEncryptor(
                            protectToLocalMachine: !DpapiSecretSerializerHelper.CanProtectToCurrentUserAccount(),
                            loggerFactory: _loggerFactory);
                    }
                    repository = new FileSystemXmlRepository(localAppDataKeysFolder, _loggerFactory);

                    if (encryptor != null)
                    {
                        _logger.UsingProfileAsKeyRepositoryWithDPAPI(localAppDataKeysFolder.FullName);
                    }
                    else
                    {
                        _logger.UsingProfileAsKeyRepository(localAppDataKeysFolder.FullName);
                    }
                }
                else
                {
                    // Use profile isn't available - can we use the HKLM registry?
                    RegistryKey regKeyStorageKey = null;
                    if (OSVersionUtil.IsWindows())
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.
                        regKeyStorageKey = RegistryXmlRepository.DefaultRegistryKey;
                    }
                    if (regKeyStorageKey != null)
                    {
                        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // Hint for the platform compatibility analyzer.
                        regKeyStorageKey = RegistryXmlRepository.DefaultRegistryKey;

                        // If the user profile isn't available, we can protect using DPAPI (to machine).
                        encryptor  = new DpapiXmlEncryptor(protectToLocalMachine: true, loggerFactory: _loggerFactory);
                        repository = new RegistryXmlRepository(regKeyStorageKey, _loggerFactory);

                        _logger.UsingRegistryAsKeyRepositoryWithDPAPI(regKeyStorageKey.Name);
                    }
                    else
                    {
                        // Final fallback - use an ephemeral repository since we don't know where else to go.
                        // This can only be used for development scenarios.
                        repository = new EphemeralXmlRepository(_loggerFactory);

                        _logger.UsingEphemeralKeyRepository();
                    }
                }
            }

            return(new KeyValuePair <IXmlRepository, IXmlEncryptor>(repository, encryptor));
        }
        private static IEnumerable <IServiceDescriptor> GetDefaultServicesWindows(ServiceDescriber describe)
        {
            List <ServiceDescriptor> descriptors = new List <ServiceDescriptor>();

            // Are we running in Azure Web Sites?
            DirectoryInfo azureWebSitesKeysFolder = TryGetKeysFolderForAzureWebSites();

            if (azureWebSitesKeysFolder != null)
            {
                // We'll use a null protector at the moment until the
                // cloud DPAPI service comes online.
                descriptors.AddRange(new[]
                {
                    describe.Singleton <IXmlEncryptor, NullXmlEncryptor>(),
                    describe.Instance <IXmlRepository>(new FileSystemXmlRepository(azureWebSitesKeysFolder))
                });
            }
            else
            {
                // Are we running with the user profile loaded?
                DirectoryInfo localAppDataKeysFolder = TryGetLocalAppDataKeysFolderForUser();
                if (localAppDataKeysFolder != null)
                {
                    descriptors.AddRange(new[]
                    {
                        describe.Instance <IXmlEncryptor>(new DpapiXmlEncryptor(protectToLocalMachine: false)),
                        describe.Instance <IXmlRepository>(new FileSystemXmlRepository(localAppDataKeysFolder))
                    });
                }
                else
                {
                    // If we've reached this point, we have no user profile loaded.

                    RegistryXmlRepository hklmRegXmlRepository = RegistryXmlRepository.GetDefaultRepositoryForHKLMRegistry();
                    if (hklmRegXmlRepository != null)
                    {
                        // Have WAS and IIS created an auto-gen key folder in the HKLM registry for us?
                        // If so, use it as the repository, and use DPAPI as the key protection mechanism.
                        // We use same-machine DPAPI since we already know no user profile is loaded.
                        descriptors.AddRange(new[]
                        {
                            describe.Instance <IXmlEncryptor>(new DpapiXmlEncryptor(protectToLocalMachine: true)),
                            describe.Instance <IXmlRepository>(hklmRegXmlRepository)
                        });
                    }
                    else
                    {
                        // Fall back to DPAPI for now
                        return(new[] {
                            describe.Instance <IDataProtectionProvider>(new DpapiDataProtectionProvider(DataProtectionScope.LocalMachine))
                        });
                    }
                }
            }

            // We use CNG CBC + HMAC by default.
            descriptors.AddRange(new[]
            {
                describe.Singleton <IAuthenticatedEncryptorConfigurationFactory, CngCbcAuthenticatedEncryptorConfigurationFactory>(),
                describe.Singleton <ITypeActivator, TypeActivator>(),
                describe.Singleton <IKeyManager, XmlKeyManager>(),
                describe.Singleton <IDataProtectionProvider, DefaultDataProtectionProvider>()
            });

            return(descriptors);
        }