public HttpResponseMessage PostGenerateCertificate(CertificateGenerationDetailsViewModel details)
        {
            var certificateData = SelfSignedCertificate.GenerateSelfSigned(
                details.SubjectName,
                details.IssuerName,
                details.NotBefore,
                details.NotAfter,
                details.PrivateKeyPassword,
                details.HashAlgorithm
                );

            var certificatePathString = HttpContext.Current.Server.MapPath("~/app_data/Certificates");
            var certificateFileName   = Guid.NewGuid().ToString() + ".pfx";
            var certificateFilePath   = Path.Combine(certificatePathString, certificateFileName);

            SelfSignedCertificate.Save(certificateFilePath, certificateData);

            ComponentSpace.SAML2.SAMLController.Configuration.LocalIdentityProviderConfiguration.LocalCertificatePassword = details.PrivateKeyPassword;
            // TODO : Consider a cleaner method of combining paths here.
            ComponentSpace.SAML2.SAMLController.Configuration.LocalIdentityProviderConfiguration.LocalCertificateFile = Path.Combine("app_data", Path.Combine("Certificates", certificateFileName));

            var result = CertificateToViewModel(ComponentSpace.SAML2.SAMLController.CertificateManager.GetLocalIdentityProviderSignatureCertificates("default", null).FirstOrDefault());

            ComponentSpace.SAML2.Configuration.SAMLConfigurationFile.Save(ComponentSpace.SAML2.SAMLController.Configuration);

            var jsonText = JsonConvert.SerializeObject(result);

            var response = new HttpResponseMessage(HttpStatusCode.OK);

            response.Content = new StringContent(jsonText, Encoding.UTF8, "application/json");

            return(response);
        }
        public async Task AuthorizedRoute_WithCertificateAuthenticationInHeader_ShouldSucceed()
        {
            // Arrange
            const string subjectKey = "subject", issuerKey = "issuer";

            _testServer.AddConfigKeyValue(subjectKey, "CN=known-subject");
            _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((issuerKey, "CN=known-issuername")));
            _testServer.AddService(
                new CertificateAuthenticationValidator(
                    new CertificateAuthenticationConfigBuilder()
                    .WithSubject(X509ValidationLocation.Configuration, subjectKey)
                    .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey)
                    .Build()));

            _testServer.AddFilter(new CertificateAuthenticationFilter());

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName("known-issuername", "known-subject"))
                using (HttpClient client = _testServer.CreateClient())
                {
                    var request = new HttpRequestMessage(HttpMethod.Get, NoneAuthenticationController.Route);

                    string base64String = Convert.ToBase64String(clientCertificate.Export(X509ContentType.Pkcs12), Base64FormattingOptions.None);
                    request.Headers.Add("X-ARR-ClientCert", base64String);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Assert
                        Assert.NotEqual(HttpStatusCode.Unauthorized, response.StatusCode);
                    }
                }
        }
Esempio n. 3
0
        public async Task CertificateAuthorizedRoute_WithBypassAttribute_SkipsAuthentication(string route)
        {
            // Arrange
            const string issuerKey = "issuer";

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName("issuer", "subject"))
            {
                var options = new TestApiServerOptions()
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(issuerKey, "CN=issuer"))
                    .AddClientCertificate(clientCertificate)
                    .AddSingleton(certificateValidator)
                    .AddMvc(opt => opt.Filters.AddCertificateAuthentication());
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(route);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    }
                }
            }
        }
        public async Task CertificateAuthenticationOption_GetHealthAuthenticated_ResultsOk()
        {
            // Arrange
            string subject = $"subject-{Guid.NewGuid()}";

            var authenticatedProjectArguments =
                new WebApiProjectOptions()
                .WithCertificateSubjectAuthentication($"CN={subject}");

            using (var project = await WebApiProject.StartNewAsync(authenticatedProjectArguments, _outputWriter))
                using (var certificate = SelfSignedCertificate.CreateWithSubject(subject))
                {
                    project.TearDownOptions = TearDownOptions.KeepProjectDirectory;
                    var clientCertificate = Convert.ToBase64String(certificate.RawData);

                    // Act
                    using (HttpResponseMessage response =
                               await project.Health.GetAsync(
                                   request => request.Headers.Add("X-ARR-ClientCert", clientCertificate)))
                    {
                        // Assert
                        Assert.NotNull(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    }
                }
        }
        public async Task AuthorizedRoute_WithCertificateAuthentication_ShouldFailWithUnauthorized_WhenClientCertificateSubjectNameDoesntMatch()
        {
            // Arrange
            string subjectKey = "subject", subjectValue = $"subject-{Guid.NewGuid()}";

            _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((subjectKey, subjectValue)));
            _testServer.AddService(
                new CertificateAuthenticationValidator(
                    new CertificateAuthenticationConfigBuilder()
                    .WithSubject(X509ValidationLocation.SecretProvider, subjectKey)
                    .Build()));

            _testServer.AddFilter(new CertificateAuthenticationFilter());

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithSubject("unrecognized-subject-name"))
            {
                _testServer.SetClientCertificate(clientCertificate);
                using (HttpClient client = _testServer.CreateClient())
                {
                    var request = new HttpRequestMessage(
                        HttpMethod.Get,
                        NoneAuthenticationController.Route);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Arrange
                        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
                    }
                }
            }
        }
Esempio n. 6
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationViaConfigurationSecretProviderAndCustom_ShouldFailWithUnauthorized_WhenAnyClientCertificateValidationDoesntSucceeds(
            string subjectName,
            string issuerName,
            string thumbprintNoise,
            bool expected)
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName(issuerName, subjectName))
            {
                _testServer.AddConfigKeyValue(SubjectKey, "CN=subject");
                _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((IssuerKey, "CN=issuer")));
                _testServer.AddService(
                    new CertificateAuthenticationValidator(
                        new CertificateAuthenticationConfigBuilder()
                        .WithSubject(X509ValidationLocation.Configuration, SubjectKey)
                        .WithIssuer(X509ValidationLocation.SecretProvider, IssuerKey)
                        .WithThumbprint(new StubX509ValidationLocation(clientCertificate.Thumbprint + thumbprintNoise), ThumbprintKey)
                        .Build()));

                _testServer.SetClientCertificate(clientCertificate);
                using (HttpClient client = _testServer.CreateClient())
                {
                    var request = new HttpRequestMessage(HttpMethod.Get, AuthorizedRoute);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Assert
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }
Esempio n. 7
0
        public async Task AuthorizedRoute_WithCertificateAuthentication_ShouldFailWithUnauthorized_WhenClientCertificateSubjectNameDoesntMatch()
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithSubject("unrecognized-subject-name"))
            {
                var options = new TestApiServerOptions()
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.SecretProvider, SubjectKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(SubjectKey, "CN=subject"))
                    .AddClientCertificate(clientCertificate)
                    .AddSingleton(certificateValidator);
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(CertificateAuthenticationOnMethodController.AuthorizedGetRoute);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Arrange
                        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
                    }
                }
            }
        }
Esempio n. 8
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationOnAppServiceHeader_ShouldSucceeds_WhenClientCertificateSubjectNameMatches(string actualSubject)
        {
            // Arrange
            _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((SubjectKey, $"CN={actualSubject}")));
            _testServer.AddService(
                new CertificateAuthenticationValidator(
                    new CertificateAuthenticationConfigBuilder()
                    .WithSubject(X509ValidationLocation.SecretProvider, SubjectKey)
                    .Build()));

            const string expectedSubject = "known-subject";

            using (HttpClient client = _testServer.CreateClient())
                using (var cert = SelfSignedCertificate.CreateWithSubject(expectedSubject))
                {
                    var    request           = new HttpRequestMessage(HttpMethod.Get, AuthorizedRoute);
                    string clientCertificate = Convert.ToBase64String(cert.RawData);
                    request.Headers.Add("X-ARR-ClientCert", clientCertificate);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Arrange
                        bool equalSubject   = expectedSubject == actualSubject;
                        bool isUnauthorized = response.StatusCode == HttpStatusCode.Unauthorized;
                        Assert.True(equalSubject != isUnauthorized, "Client certificate with the same subject name should result in an OK HTTP status code");
                    }
                }
        }
        private async Task ConfigureSigningCertificate(string spoId)
        {
            // Set custom signing key
            string password = Guid.NewGuid().ToString();
            string certName = "SelfSigned federation metadata";
            SelfSignedCertificate selfSignedCert = new SelfSignedCertificate(password, certName);
            Guid keyIDPrivateCert = Guid.NewGuid();

            var privateKey = new Beta.KeyCredential()
            {
                CustomKeyIdentifier = selfSignedCert.CustomKeyIdentifier,
                EndDateTime         = selfSignedCert.EndDateTime,
                KeyId         = keyIDPrivateCert,
                StartDateTime = selfSignedCert.StartDateTime,
                Type          = "AsymmetricX509Cert",
                Usage         = "Sign",
                Key           = selfSignedCert.PrivateKey
            };

            var publicKey = new Beta.KeyCredential()
            {
                CustomKeyIdentifier = selfSignedCert.CustomKeyIdentifier,
                EndDateTime         = selfSignedCert.EndDateTime,
                KeyId         = Guid.NewGuid(),
                StartDateTime = selfSignedCert.StartDateTime,
                Type          = "AsymmetricX509Cert",
                Usage         = "Verify",
                Key           = selfSignedCert.PublicKey
            };

            var keyCredentials = new List <Beta.KeyCredential>()
            {
                privateKey,
                publicKey
            };

            var passwordCredentials = new List <Beta.PasswordCredential>()
            {
                new Beta.PasswordCredential()
                {
                    CustomKeyIdentifier = selfSignedCert.CustomKeyIdentifier,
                    KeyId         = keyIDPrivateCert,
                    EndDateTime   = selfSignedCert.EndDateTime,
                    StartDateTime = selfSignedCert.StartDateTime,
                    SecretText    = password
                }
            };

            var spKeyCredentials = new Beta.ServicePrincipal
            {
                KeyCredentials      = keyCredentials,
                PasswordCredentials = passwordCredentials,
                PreferredTokenSigningKeyThumbprint = selfSignedCert.Thumbprint
            };

            await _galleryAppsRepository.ConfigureSelfSignedCertificate(spKeyCredentials, spoId);
        }
        public async Task SiteCertificateRoundTrip()
        {
            var testCert = SelfSignedCertificate.Make(new DateTime(2020, 5, 24), new DateTime(2020, 5, 26));;

            await PersistenceService.PersistSiteCertificateAsync(testCert);

            var retrievedCert = (LetsEncryptX509Certificate)await PersistenceService.GetPersistedSiteCertificateAsync();

            Assert.AreEqual(testCert.RawData, retrievedCert.RawData);
        }
Esempio n. 11
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationViaConfigurationAndSecretProvider_ShouldFailWithUnauthorized_WhenAnyClientCertificateValidationDoesntSucceeds(
            string subjectValue,
            string issuerValue,
            bool expected)
        {
            // Arrange
            const string subjectKey = "subject", issuerKey = "issuer";

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName(issuerValue, subjectValue))
            {
                var options = new TestApiServerOptions()
                              .ConfigureAppConfiguration(config => config.AddInMemoryCollection(new []
                {
                    new KeyValuePair <string, string>(subjectKey, "CN=known-subject")
                }))
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.Configuration, subjectKey)
                            .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(issuerKey, "CN=known-issuername"))
                    .AddClientCertificate(clientCertificate)
                    .AddSingleton(certificateValidator)
                    .AddMvc(opt => opt.Filters.AddCertificateAuthentication());
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(NoneAuthenticationController.GetRoute);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }
Esempio n. 12
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationViaConfiguration_ShouldFailWithUnauthorized_WhenAnyClientCertificateValidationDoesntSucceeds(
            string subjectName,
            string issuerName,
            string thumbprintNoise,
            bool expected)
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName(issuerName, subjectName))
            {
                var options = new TestApiServerOptions()
                              .ConfigureAppConfiguration(config => config.AddInMemoryCollection(new []
                {
                    new KeyValuePair <string, string>(SubjectKey, "CN=subject"),
                    new KeyValuePair <string, string>(IssuerKey, "CN=issuer"),
                    new KeyValuePair <string, string>(ThumbprintKey, clientCertificate.Thumbprint + thumbprintNoise)
                }))
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.Configuration, SubjectKey)
                            .WithIssuer(X509ValidationLocation.Configuration, IssuerKey)
                            .WithThumbprint(X509ValidationLocation.Configuration, ThumbprintKey)
                            .Build());

                    services.AddSingleton(certificateValidator)
                    .AddClientCertificate(clientCertificate);
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(CertificateAuthenticationOnMethodController.AuthorizedGetRoute);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }
        public async Task AuthorizedRoute_WithCertificateAuthenticationViaSecretProvider_ShouldFailWithUnauthorized_WhenAnyClientCertificateValidationDoesntSucceeds(
            string subjectValue,
            string issuerValue,
            bool expected)
        {
            // Arrange
            const string subjectKey = "subject", issuerKey = "issuer";

            _testServer.AddService <ISecretProvider>(
                new InMemorySecretProvider(
                    (subjectKey, "CN=known-subject"),
                    (issuerKey, "CN=known-issuername")));

            _testServer.AddService(
                new CertificateAuthenticationValidator(
                    new CertificateAuthenticationConfigBuilder()
                    .WithSubject(X509ValidationLocation.SecretProvider, subjectKey)
                    .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey)
                    .Build()));

            _testServer.AddFilter(new CertificateAuthenticationFilter());

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName(issuerValue, subjectValue))
            {
                _testServer.SetClientCertificate(clientCertificate);
                using (HttpClient client = _testServer.CreateClient())
                {
                    var request = new HttpRequestMessage(
                        HttpMethod.Get,
                        NoneAuthenticationController.Route);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Assert
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }
Esempio n. 14
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationInHeader_ShouldSucceed()
        {
            // Arrange
            const string subjectKey = "subject", issuerKey = "issuer";

            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName("known-issuername", "known-subject"))
            {
                var options = new TestApiServerOptions()
                              .ConfigureAppConfiguration(config => config.AddInMemoryCollection(new []
                {
                    new KeyValuePair <string, string>(subjectKey, "CN=known-subject")
                }))
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.Configuration, subjectKey)
                            .WithIssuer(X509ValidationLocation.SecretProvider, issuerKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(issuerKey, "CN=known-issuername"))
                    .AddSingleton(certificateValidator)
                    .AddMvc(opt => opt.Filters.AddCertificateAuthentication());
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    string base64String = Convert.ToBase64String(clientCertificate.Export(X509ContentType.Pkcs12), Base64FormattingOptions.None);
                    var    request      = HttpRequestBuilder
                                          .Get(NoneAuthenticationController.GetRoute)
                                          .WithHeader("X-ARR-ClientCert", base64String);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.NotEqual(HttpStatusCode.Unauthorized, response.StatusCode);
                    }
                }
            }
        }
        public HttpResponseMessage PutIdentityProvider(IdentityProviderConfigurationViewModel idpConfig)
        {
            var certificateData = SelfSignedCertificate.GenerateSelfSigned(
                idpConfig.IdpCertificateParameters.SubjectName,
                idpConfig.IdpCertificateParameters.IssuerName,
                idpConfig.IdpCertificateParameters.NotBefore,
                idpConfig.IdpCertificateParameters.NotAfter,
                idpConfig.IdpCertificateParameters.PrivateKeyPassword,
                idpConfig.IdpCertificateParameters.HashAlgorithm
                );

            var certificatePathString = HttpContext.Current.Server.MapPath("~/app_data/Certificates");
            var certificateFileName   = Guid.NewGuid().ToString() + ".pfx";
            var certificateFilePath   = Path.Combine(certificatePathString, certificateFileName);

            SelfSignedCertificate.Save(certificateFilePath, certificateData);

            var newConfiguration = new ComponentSpace.SAML2.Configuration.SAMLConfiguration();

            var localIdp = new ComponentSpace.SAML2.Configuration.LocalIdentityProviderConfiguration();

            localIdp.Name        = idpConfig.IdpName;
            localIdp.Description = idpConfig.IdpDescription;
            localIdp.LocalCertificatePassword = idpConfig.IdpCertificateParameters.PrivateKeyPassword;
            // TODO : Consider a cleaner method of combining paths here.
            localIdp.LocalCertificateFile = Path.Combine("app_data", Path.Combine("Certificates", certificateFileName));
            newConfiguration.LocalIdentityProviderConfiguration = localIdp;

            ComponentSpace.SAML2.SAMLController.Configurations.Add("default", newConfiguration);
            ComponentSpace.SAML2.Configuration.SAMLConfigurationFile.Save(ComponentSpace.SAML2.SAMLController.Configuration);

            var result = "ok";

            var jsonText = JsonConvert.SerializeObject(result);

            var response = new HttpResponseMessage(HttpStatusCode.OK);

            response.Content = new StringContent(jsonText, Encoding.UTF8, "application/json");

            return(response);
        }
Esempio n. 16
0
        public async Task CertificateAuthorizedRoute_EmitsSecurityEventsWhenRequested_RunsAuthentication()
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithSubject("unrecognized-subject-name"))
            {
                var spySink = new InMemorySink();
                var options = new TestApiServerOptions()
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.SecretProvider, SubjectKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(SubjectKey, "CN=subject"))
                    .AddClientCertificate(clientCertificate)
                    .AddSingleton(certificateValidator);
                })
                              .ConfigureHost(host => host.UseSerilog((context, config) => config.WriteTo.Sink(spySink)));

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(CertificateAuthenticationOnMethodController.AuthorizedGetRouteEmitSecurityEvents);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
                        IEnumerable <LogEvent> logEvents = spySink.DequeueLogEvents();
                        Assert.Contains(logEvents, logEvent =>
                        {
                            string message = logEvent.RenderMessage();
                            return(message.Contains("EventType") && message.Contains("Security"));
                        });
                    }
                }
            }
        }
Esempio n. 17
0
        public async Task AuthorizedRoute_WithCertificateAuthentication_ShouldFailWithUnauthorized_WhenClientCertificateThumbprintDoesntMatch(
            string thumbprintNoise,
            bool expected)
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.Create())
            {
                const string thumbprintKey = "thumbprint";

                var options = new TestApiServerOptions()
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithThumbprint(X509ValidationLocation.SecretProvider, thumbprintKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(thumbprintKey, clientCertificate.Thumbprint + thumbprintNoise))
                    .AddSingleton(certificateValidator)
                    .AddClientCertificate(clientCertificate)
                    .AddMvc(opt => opt.Filters.AddCertificateAuthentication());
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    var request = HttpRequestBuilder.Get(NoneAuthenticationController.GetRoute);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Assert
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }
Esempio n. 18
0
        public async Task AuthorizedRoute_WithCertificateAuthenticationOnAppServiceHeader_ShouldSucceeds_WhenClientCertificateSubjectNameMatches(string actualSubject)
        {
            // Arrange
            const string expectedSubject = "known-subject";

            using (var cert = SelfSignedCertificate.CreateWithSubject(expectedSubject))
            {
                var options = new TestApiServerOptions()
                              .ConfigureServices(services =>
                {
                    var certificateValidator =
                        new CertificateAuthenticationValidator(
                            new CertificateAuthenticationConfigBuilder()
                            .WithSubject(X509ValidationLocation.SecretProvider, SubjectKey)
                            .Build());

                    services.AddSecretStore(stores => stores.AddInMemory(SubjectKey, $"CN={actualSubject}"))
                    .AddSingleton(certificateValidator);
                });

                await using (var server = await TestApiServer.StartNewAsync(options, _logger))
                {
                    string clientCertificate = Convert.ToBase64String(cert.RawData);
                    var    request           = HttpRequestBuilder
                                               .Get(CertificateAuthenticationOnMethodController.AuthorizedGetRoute)
                                               .WithHeader("X-ARR-ClientCert", clientCertificate);

                    // Act
                    using (HttpResponseMessage response = await server.SendAsync(request))
                    {
                        // Arrange
                        bool equalSubject   = expectedSubject == actualSubject;
                        bool isUnauthorized = response.StatusCode == HttpStatusCode.Unauthorized;
                        Assert.True(equalSubject != isUnauthorized, "Client certificate with the same subject name should result in an OK HTTP status code");
                    }
                }
            }
        }
Esempio n. 19
0
        public async Task CertificateAuthorizedRoute_WithBypassAttribute_SkipsAuthentication(string route)
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.CreateWithIssuerAndSubjectName("issuer", "subject"))
            {
                _testServer.SetClientCertificate(clientCertificate);
                _testServer.AddFilter(new CertificateAuthenticationFilter());
                _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((IssuerKey, "CN=issuer")));
                _testServer.AddService(
                    new CertificateAuthenticationValidator(
                        new CertificateAuthenticationConfigBuilder()
                        .WithIssuer(X509ValidationLocation.SecretProvider, IssuerKey)
                        .Build()));

                using (HttpClient client = _testServer.CreateClient())
                    // Act
                    using (HttpResponseMessage response = await client.GetAsync(route))
                    {
                        // Assert
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    }
            }
        }
        public async Task AuthorizedRoute_WithCertificateAuthentication_ShouldFailWithUnauthorized_WhenClientCertificateThumbprintDoesntMatch(
            string thumbprintNoise,
            bool expected)
        {
            // Arrange
            using (X509Certificate2 clientCertificate = SelfSignedCertificate.Create())
            {
                const string thumbprintKey = "thumbprint";

                _testServer.AddService <ISecretProvider>(new InMemorySecretProvider((thumbprintKey, clientCertificate.Thumbprint + thumbprintNoise)));
                _testServer.AddService(
                    new CertificateAuthenticationValidator(
                        new CertificateAuthenticationConfigBuilder()
                        .WithThumbprint(X509ValidationLocation.SecretProvider, thumbprintKey)
                        .Build()));

                _testServer.AddFilter(new CertificateAuthenticationFilter());

                _testServer.SetClientCertificate(clientCertificate);
                using (HttpClient client = _testServer.CreateClient())
                {
                    var request = new HttpRequestMessage(
                        HttpMethod.Get,
                        NoneAuthenticationController.Route);

                    // Act
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        // Arrange
                        Assert.True(
                            (HttpStatusCode.Unauthorized == response.StatusCode) == expected,
                            $"Response HTTP status code {(expected ? "should" : "shouldn't")} be 'Unauthorized' but was '{response.StatusCode}'");
                    }
                }
            }
        }