public async Task ExpectFullKeyManagerExplicitAwsStoreRetrieveToSucceed()
        {
            var config = new S3XmlRepositoryConfig(S3IntegrationTests.BucketName) { KeyPrefix = "RealXmlKeyManager1/" };
            await s3Cleanup.ClearKeys(S3IntegrationTests.BucketName, config.KeyPrefix);

            var serviceCollection = new ServiceCollection();
            serviceCollection.AddDataProtection()
                             .PersistKeysToAwsS3(s3Client, config);
            using (var serviceProvider = serviceCollection.BuildServiceProvider())
            {
                var keyManager = new XmlKeyManager(serviceProvider.GetRequiredService<IOptions<KeyManagementOptions>>(),
                                                   serviceProvider.GetRequiredService<IActivator>());

                var activationDate = new DateTimeOffset(new DateTime(1980, 1, 1));
                var expirationDate = new DateTimeOffset(new DateTime(1980, 6, 1));
                keyManager.CreateNewKey(activationDate, expirationDate);

                IReadOnlyCollection<IKey> keys = keyManager.GetAllKeys();

                Assert.Equal(1, keys.Count);
                Assert.Equal(activationDate, keys.Single().ActivationDate);
                Assert.Equal(expirationDate, keys.Single().ExpirationDate);
                Assert.NotNull(keys.Single().Descriptor);
            }
        }
        public async Task ExpectProtectRoundTripToSucceed()
        {
            var s3Config = new S3XmlRepositoryConfig(S3IntegrationTests.BucketName)
            {
                KeyPrefix = "CombinedXmlKeyManager3/"
            };
            await s3Cleanup.ClearKeys(S3IntegrationTests.BucketName, s3Config.KeyPrefix);

            var kmsConfig = new KmsXmlEncryptorConfig(KmsIntegrationTests.KmsTestingKey);

            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton(s3Client);
            serviceCollection.AddSingleton(kmsClient);
            serviceCollection.AddDataProtection()
            .SetApplicationName(KmsIntegrationTests.ApplicationName)
            .PersistKeysToAwsS3(s3Config)
            .ProtectKeysWithAwsKms(kmsConfig);
            using (var serviceProvider = serviceCollection.BuildServiceProvider())
            {
                var prov = serviceProvider.GetRequiredService <IDataProtectionProvider>().CreateProtector("bob");

                var plaintext = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
                var encrypted = prov.Protect(plaintext);
                var decrypted = prov.Unprotect(encrypted);
                Assert.Equal(plaintext, decrypted);
            }
        }
        public void ExpectSuccessfulCopy()
        {
            config.Bucket                                        = "somebucket";
            config.KeyPrefix                                     = "keypref";
            config.MaxS3QueryConcurrency                         = 4;
            config.StorageClass                                  = S3StorageClass.Glacier;
            config.ServerSideEncryptionMethod                    = ServerSideEncryptionMethod.AWSKMS;
            config.ServerSideEncryptionCustomerMethod            = ServerSideEncryptionCustomerMethod.AES256;
            config.ServerSideEncryptionCustomerProvidedKey       = "key";
            config.ServerSideEncryptionCustomerProvidedKeyMd5    = "md5";
            config.ServerSideEncryptionKeyManagementServiceKeyId = "keyid";
            config.ClientSideCompression                         = !config.ClientSideCompression;
            config.ValidateETag                                  = !config.ValidateETag;
            config.ValidateMd5Metadata                           = !config.ValidateMd5Metadata;

            var copy = new S3XmlRepositoryConfig();

            copy.CopyFrom(config);

            Assert.Equal(config.Bucket, copy.Bucket);
            Assert.Equal(config.KeyPrefix, copy.KeyPrefix);
            Assert.Equal(config.MaxS3QueryConcurrency, copy.MaxS3QueryConcurrency);
            Assert.Equal(config.StorageClass, copy.StorageClass);
            Assert.Equal(config.ServerSideEncryptionMethod, copy.ServerSideEncryptionMethod);
            Assert.Equal(config.ServerSideEncryptionCustomerMethod, copy.ServerSideEncryptionCustomerMethod);
            Assert.Equal(config.ServerSideEncryptionCustomerProvidedKey, copy.ServerSideEncryptionCustomerProvidedKey);
            Assert.Equal(config.ServerSideEncryptionCustomerProvidedKeyMd5, copy.ServerSideEncryptionCustomerProvidedKeyMd5);
            Assert.Equal(config.ServerSideEncryptionKeyManagementServiceKeyId, copy.ServerSideEncryptionKeyManagementServiceKeyId);
            Assert.Equal(config.ClientSideCompression, copy.ClientSideCompression);
            Assert.Equal(config.ValidateETag, copy.ValidateETag);
            Assert.Equal(config.ValidateMd5Metadata, copy.ValidateMd5Metadata);
        }
Example #4
0
        public async Task ExpectFullKeyManagerStoreRetrieveToSucceed()
        {
            var s3Config = new S3XmlRepositoryConfig(S3IntegrationTests.BucketName)
            {
                KeyPrefix = "CombinedXmlKeyManager2/"
            };
            await s3Cleanup.ClearKeys(S3IntegrationTests.BucketName, s3Config.KeyPrefix);

            var kmsConfig = new KmsXmlEncryptorConfig(KmsIntegrationTests.ApplicationName, KmsIntegrationTests.KmsTestingKey);

            var serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton(s3Client);
            serviceCollection.AddSingleton(kmsClient);
            serviceCollection.AddDataProtection()
            .PersistKeysToAwsS3(s3Config)
            .ProtectKeysWithAwsKms(kmsConfig);
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var keyManager = new XmlKeyManager(serviceProvider.GetRequiredService <IXmlRepository>(),
                                               serviceProvider.GetRequiredService <IAuthenticatedEncryptorConfiguration>(),
                                               serviceProvider);

            var activationDate = new DateTimeOffset(new DateTime(1980, 1, 1));
            var expirationDate = new DateTimeOffset(new DateTime(1980, 6, 1));

            keyManager.CreateNewKey(activationDate, expirationDate);

            IReadOnlyCollection <IKey> keys = keyManager.GetAllKeys();

            Assert.Equal(1, keys.Count);
            Assert.Equal(activationDate, keys.Single().ActivationDate);
            Assert.Equal(expirationDate, keys.Single().ExpirationDate);
        }
Example #5
0
        public void ExpectBuilderAdditionsConfig(bool withClient)
        {
            var services = new List <ServiceDescriptor>();

            builder.Setup(x => x.Services).Returns(svcCollection.Object);
            svcCollection.Setup(x => x.GetEnumerator()).Returns(() => services.GetEnumerator());
            svcCollection.Setup(x => x.Add(It.IsAny <ServiceDescriptor>()))
            .Callback <ServiceDescriptor>(sd => { services.Add(sd); });

            // An empty collection seems to be enough to run what is eventually ConfigurationBinder.Bind, since there is no way to mock the options configure call
            // ReSharper disable once CollectionNeverUpdated.Local
            var configChildren = new List <IConfigurationSection>();
            Mock <IConfiguration> configMock = repository.Create <IConfiguration>();

            configMock.Setup(x => x.GetChildren()).Returns(configChildren);

            // Repeat call to ensure cumulative calls work
            if (withClient)
            {
                builder.Object.PersistKeysToAwsS3(client.Object, configMock.Object);
                builder.Object.PersistKeysToAwsS3(client.Object, configMock.Object);
            }
            else
            {
                builder.Object.PersistKeysToAwsS3(configMock.Object);
                builder.Object.PersistKeysToAwsS3(configMock.Object);
                provider.Setup(x => x.GetService(typeof(IAmazonS3))).Returns(client.Object);
            }

            Assert.Equal(1, services.Count(x => x.ServiceType == typeof(IMockingWrapper)));

            // IConfigureOptions is designed & expected to be present multiple times, so expect two after two calls
            Assert.Equal(2, services.Count(x => x.ServiceType == typeof(IConfigureOptions <KeyManagementOptions>)));
            Assert.Equal(2, services.Count(x => x.ServiceType == typeof(IConfigureOptions <S3XmlRepositoryConfig>)));

            Assert.Equal(ServiceLifetime.Singleton, services.Single(x => x.ServiceType == typeof(IMockingWrapper)).Lifetime);
            Assert.Equal(ServiceLifetime.Singleton, services.First(x => x.ServiceType == typeof(IConfigureOptions <KeyManagementOptions>)).Lifetime);
            Assert.Equal(ServiceLifetime.Singleton, services.First(x => x.ServiceType == typeof(IConfigureOptions <S3XmlRepositoryConfig>)).Lifetime);

            // Ensure we run equivalent config for the actual configuration object
            var configureObject = services.First(x => x.ServiceType == typeof(IConfigureOptions <S3XmlRepositoryConfig>)).ImplementationInstance;
            var optionsObject   = new S3XmlRepositoryConfig();

            ((IConfigureOptions <S3XmlRepositoryConfig>)configureObject).Configure(optionsObject);

            provider.Setup(x => x.GetService(typeof(ILoggerFactory))).Returns(loggerFactory.Object);
            provider.Setup(x => x.GetService(typeof(IOptions <S3XmlRepositoryConfig>))).Returns(snapshot.Object);
            loggerFactory.Setup(x => x.CreateLogger(typeof(S3XmlRepository).FullName)).Returns(repository.Create <ILogger <S3XmlRepository> >().Object);
            snapshot.Setup(x => x.Value).Returns(optionsObject);

            var configure = services.First(x => x.ServiceType == typeof(IConfigureOptions <KeyManagementOptions>)).ImplementationFactory(provider.Object);
            var options   = new KeyManagementOptions();

            ((IConfigureOptions <KeyManagementOptions>)configure).Configure(options);
            Assert.IsType <S3XmlRepository>(options.XmlRepository);
        }
Example #6
0
 public S3IntegrationTests()
 {
     // Expectation that local SDK has been configured correctly, whether via VS Tools or user config files
     s3Client = new AmazonS3Client(RegionEndpoint.EUWest1);
     // Override the default for ease of debugging. Explicitly turn on for compression tests.
     config = new S3XmlRepositoryConfig(BucketName)
     {
         ClientSideCompression = false
     };
     xmlRepo   = new S3XmlRepository(s3Client, new DirectOptions <S3XmlRepositoryConfig>(config));
     s3Cleanup = new CleanupS3(s3Client);
 }
        public async Task ExpectApplicationIsolationToThrow(string app1, string app2, bool throws)
        {
            var s3Config = new S3XmlRepositoryConfig(S3IntegrationTests.BucketName)
            {
                KeyPrefix = "CombinedXmlKeyManager4/"
            };
            await s3Cleanup.ClearKeys(S3IntegrationTests.BucketName, s3Config.KeyPrefix);

            var kmsConfig = new KmsXmlEncryptorConfig(KmsIntegrationTests.KmsTestingKey);

            var plaintext = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            byte[] encrypted;

            {
                var serviceCollection = new ServiceCollection();
                serviceCollection.AddSingleton(s3Client);
                serviceCollection.AddSingleton(kmsClient);
                serviceCollection.AddDataProtection()
                .SetApplicationName(app1)
                .PersistKeysToAwsS3(s3Config)
                .ProtectKeysWithAwsKms(kmsConfig);
                using (var serviceProvider = serviceCollection.BuildServiceProvider())
                {
                    var prov = serviceProvider.GetRequiredService <IDataProtectionProvider>().CreateProtector("bob");

                    encrypted = prov.Protect(plaintext);
                }
            }

            {
                var serviceCollection = new ServiceCollection();
                serviceCollection.AddSingleton(s3Client);
                serviceCollection.AddSingleton(kmsClient);
                serviceCollection.AddDataProtection()
                .SetApplicationName(app2)
                .PersistKeysToAwsS3(s3Config)
                .ProtectKeysWithAwsKms(kmsConfig);
                using (var serviceProvider = serviceCollection.BuildServiceProvider())
                {
                    var prov = serviceProvider.GetRequiredService <IDataProtectionProvider>().CreateProtector("bob");

                    if (throws)
                    {
                        Assert.Throws <CryptographicException>(() => prov.Unprotect(encrypted));
                    }
                    else
                    {
                        Assert.NotNull(prov.Unprotect(encrypted));
                    }
                }
            }
        }
        private static S3XmlRepositoryConfig ToNewS3Config(JObject config)
        {
            var newConfig = new S3XmlRepositoryConfig(config[nameof(S3XmlRepositoryConfig.Bucket)].Value <string>());

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.KeyPrefix), out JToken keyprefix))
            {
                newConfig.KeyPrefix = keyprefix.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.MaxS3QueryConcurrency), out JToken concurrency))
            {
                newConfig.MaxS3QueryConcurrency = concurrency.Value <int>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.StorageClass), out JToken storageClass))
            {
                newConfig.StorageClass = S3StorageClass.FindValue(storageClass.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionMethod), out JToken serverSideEncryptionMethod))
            {
                newConfig.ServerSideEncryptionMethod = ServerSideEncryptionMethod.FindValue(serverSideEncryptionMethod.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerMethod), out JToken serverSideEncryptionCustomerMethod))
            {
                newConfig.ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.FindValue(serverSideEncryptionCustomerMethod.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerProvidedKey), out JToken serverSideEncryptionCustomerProvidedKey))
            {
                newConfig.ServerSideEncryptionCustomerProvidedKey = serverSideEncryptionCustomerProvidedKey.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerProvidedKeyMd5), out JToken serverSideEncryptionCustomerProvidedKeyMd5))
            {
                newConfig.ServerSideEncryptionCustomerProvidedKeyMd5 = serverSideEncryptionCustomerProvidedKeyMd5.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionKeyManagementServiceKeyId), out JToken serverSideEncryptionKeyManagementServiceKeyId))
            {
                newConfig.ServerSideEncryptionKeyManagementServiceKeyId = serverSideEncryptionKeyManagementServiceKeyId.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ClientSideCompression), out JToken clientSideCompression))
            {
                newConfig.ClientSideCompression = clientSideCompression.Value <bool>();
            }

            return(newConfig);
        }
Example #9
0
        public byte[] CreateS3(byte[] toEncrypt, string protector, S3XmlRepositoryConfig config)
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddDataProtection()
            .PersistKeysToAwsS3(s3Client, config);

            var serviceProvider = serviceCollection.BuildServiceProvider();

            using (serviceProvider as IDisposable)
            {
                var prov = serviceProvider.GetRequiredService <IDataProtectionProvider>().CreateProtector(protector);

                return(prov.Protect(toEncrypt));
            }
        }
Example #10
0
        public void ExpectBuilderAdditions(bool withClient)
        {
            var services = new List <ServiceDescriptor>();

            builder.Setup(x => x.Services).Returns(svcCollection.Object);
            svcCollection.Setup(x => x.Count).Returns(() => services.Count);
            svcCollection.Setup(x => x.Add(It.IsAny <ServiceDescriptor>())).Callback <ServiceDescriptor>(sd => services.Add(sd));
            svcCollection.Setup(x => x[It.IsAny <int>()]).Returns <int>(index => services[index]);
            svcCollection.Setup(x => x.RemoveAt(It.IsAny <int>())).Callback <int>(index => services.RemoveAt(index));

            var config = new S3XmlRepositoryConfig("bucket");

            // Repeat call to ensure cumulative calls work
            if (withClient)
            {
                builder.Object.PersistKeysToAwsS3(client.Object, config);
                builder.Object.PersistKeysToAwsS3(client.Object, config);
            }
            else
            {
                builder.Object.PersistKeysToAwsS3(config);
                builder.Object.PersistKeysToAwsS3(config);
                provider.Setup(x => x.GetService(typeof(IAmazonS3))).Returns(client.Object);
            }

            Assert.Equal(1, services.Count(x => x.ServiceType == typeof(IMockingWrapper)));
            Assert.Equal(1, services.Count(x => x.ServiceType == typeof(IXmlRepository)));

            Assert.Equal(ServiceLifetime.Singleton, services.Single(x => x.ServiceType == typeof(IMockingWrapper)).Lifetime);
            Assert.Equal(ServiceLifetime.Singleton, services.Single(x => x.ServiceType == typeof(IXmlRepository)).Lifetime);

            provider.Setup(x => x.GetService(typeof(ILoggerFactory))).Returns(loggerFactory.Object);
            loggerFactory.Setup(x => x.CreateLogger(typeof(S3XmlRepository).FullName)).Returns(repository.Create <ILogger <S3XmlRepository> >().Object);

            Assert.IsType <S3XmlRepository>(services.Single(x => x.ServiceType == typeof(IXmlRepository)).ImplementationFactory(provider.Object));
        }
Example #11
0
#pragma warning disable S3242 // JObject is more descriptive than 'more general' IDictionary
        private static (string ControlValue, byte[] ToEncrypt, string Protector, string ApplicationName, S3XmlRepositoryConfig S3Config, KmsXmlEncryptorConfig KmsConfig) ToOldConfig(JObject config)
#pragma warning restore S3242
        {
            var controlValue   = config[ConfigType].Value <string>();
            var protectData    = Convert.FromBase64String(config[DataToProtect].Value <string>());
            var protectorValue = config[ProtectorKey].Value <string>();

            var old = new S3XmlRepositoryConfig(config[nameof(S3XmlRepositoryConfig.Bucket)].Value <string>());

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.KeyPrefix), out JToken keyprefix))
            {
                old.KeyPrefix = keyprefix.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.MaxS3QueryConcurrency), out JToken concurrency))
            {
                old.MaxS3QueryConcurrency = concurrency.Value <int>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.StorageClass), out JToken storageClass))
            {
                old.StorageClass = S3StorageClass.FindValue(storageClass.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionMethod), out JToken serverSideEncryptionMethod))
            {
                old.ServerSideEncryptionMethod = ServerSideEncryptionMethod.FindValue(serverSideEncryptionMethod.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerMethod), out JToken serverSideEncryptionCustomerMethod))
            {
                old.ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.FindValue(serverSideEncryptionCustomerMethod.Value <string>());
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerProvidedKey), out JToken serverSideEncryptionCustomerProvidedKey))
            {
                old.ServerSideEncryptionCustomerProvidedKey = serverSideEncryptionCustomerProvidedKey.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionCustomerProvidedKeyMd5), out JToken serverSideEncryptionCustomerProvidedKeyMd5))
            {
                old.ServerSideEncryptionCustomerProvidedKeyMd5 = serverSideEncryptionCustomerProvidedKeyMd5.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ServerSideEncryptionKeyManagementServiceKeyId), out JToken serverSideEncryptionKeyManagementServiceKeyId))
            {
                old.ServerSideEncryptionKeyManagementServiceKeyId = serverSideEncryptionKeyManagementServiceKeyId.Value <string>();
            }

            if (config.TryGetValue(nameof(S3XmlRepositoryConfig.ClientSideCompression), out JToken clientSideCompression))
            {
                old.ClientSideCompression = clientSideCompression.Value <bool>();
            }

            string applicationName = null;

            if (config.TryGetValue(ApplicationNameKey, out JToken appName))
            {
                applicationName = appName.Value <string>();
            }

            string kmsApplicationName = null;

            if (config.TryGetValue(KmsApplicationNameKey, out JToken kmsAppName))
            {
                kmsApplicationName = kmsAppName.Value <string>();
            }

            string keyIdentifier = null;

            if (config.TryGetValue(nameof(KmsXmlEncryptorConfig.KeyId), out JToken keyId))
            {
                keyIdentifier = keyId.Value <string>();
            }

            KmsXmlEncryptorConfig kmsConfig = null;

            if (!string.IsNullOrEmpty(kmsApplicationName) && !string.IsNullOrEmpty(keyIdentifier))
            {
                kmsConfig = new KmsXmlEncryptorConfig(kmsApplicationName, keyIdentifier);
            }

            return(controlValue, protectData, protectorValue, applicationName, old, kmsConfig);
        }
Example #12
0
        public byte[] CreateS3AndKms(byte[] toEncrypt, string protector, string applicationName, S3XmlRepositoryConfig s3Config, KmsXmlEncryptorConfig kmsConfig)
        {
            var serviceCollection = new ServiceCollection();

            serviceCollection.AddDataProtection()
            .SetApplicationName(applicationName)
            .ProtectKeysWithAwsKms(kmsClient, kmsConfig)
            .PersistKeysToAwsS3(s3Client, s3Config);

            var serviceProvider = serviceCollection.BuildServiceProvider();

            using (serviceProvider as IDisposable)
            {
                var prov = serviceProvider.GetRequiredService <IDataProtectionProvider>().CreateProtector(protector);

                return(prov.Protect(toEncrypt));
            }
        }
 public S3XmlRepositoryConfigTests()
 {
     config = new S3XmlRepositoryConfig("somebucket");
 }