예제 #1
0
 public AuditTests(AuditTestFixture fixture)
 {
     _fixture     = fixture;
     _client      = fixture.FhirClient;
     _auditLogger = _fixture.AuditLogger;
     _client.DeleteAllResources(ResourceType.Patient).Wait();
 }
예제 #2
0
        public async Task WhenCreatingAResource_GivenAClientWithNoAuthToken_TheServerShouldReturnUnauthorized()
        {
            FhirClient tempClient = Client.CreateClientForClientApplication(TestApplications.InvalidClient);

            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(UnauthorizedMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Unauthorized, fhirException.StatusCode);

            List <AuthenticationHeaderValue> wwwAuthenticationHeaderValues = fhirException.Headers.WwwAuthenticate.Where(h => h.Scheme == "Bearer").ToList();

            Assert.Single(wwwAuthenticationHeaderValues);

            Match matchResults = WwwAuthenticatePattern.Match(wwwAuthenticationHeaderValues.First().Parameter);

            Assert.Single(matchResults.Groups["authorization_uri"].Captures);
            var authorizationUri = matchResults.Groups["authorization_uri"].Captures[0].Value;

            Assert.Single(matchResults.Groups["realm"].Captures);
            var realm = matchResults.Groups["realm"].Captures[0].Value;

            Assert.Single(matchResults.Groups["resource_id"].Captures);
            var resourceId = matchResults.Groups["resource_id"].Captures[0].Value;

            Assert.Equal(AuthenticationSettings.Resource, realm);
            Assert.Equal(realm, resourceId);

            // We can only verify that this is a URI since a server with SmartOnFHIR enabled will not report the actual authorization server anywhere else.
            Assert.True(Uri.TryCreate(authorizationUri, UriKind.Absolute, out _));
        }
예제 #3
0
        private async Task ExecuteAndValidate(Func <FhirClient, Task> clientSetup, HttpStatusCode expectedStatusCode)
        {
            if (!_fixture.IsUsingInProcTestServer || !_fixture.FhirClient.SecuritySettings.SecurityEnabled)
            {
                // This test only works with the in-proc server with customized middleware pipeline and when security is enabled.
                return;
            }

            const string url = "Patient/123";

            // Create a new client with no token supplied.
            var client = new FhirClient(_fixture.CreateHttpClient(), ResourceFormat.Json);

            await clientSetup(client);

            FhirResponse <OperationOutcome> response = (await Assert.ThrowsAsync <FhirException>(() => client.ReadAsync <Patient>(url))).Response;

            string correlationId = response.Headers.GetValues(RequestIdHeaderName).FirstOrDefault();

            Assert.NotNull(correlationId);

            var expectedUri = new Uri($"http://localhost/{url}");

            Assert.Collection(
                _auditLogger.GetAuditEntriesByCorrelationId(correlationId),
                ae => ValidateExecutedAuditEntry(ae, "read", ResourceType.Patient, expectedUri, expectedStatusCode, correlationId));
        }
예제 #4
0
        public SmartProxyTestFixture()
        {
            string environmentUrl = Environment.GetEnvironmentVariable("TestEnvironmentUrl");

            // Only set up test fixture if running against remote server
            if (!string.IsNullOrWhiteSpace(environmentUrl))
            {
                var baseUrl = "https://localhost:" + Port;
                SmartLauncherUrl = baseUrl + "/index.html";

                Environment.SetEnvironmentVariable("FhirServerUrl", environmentUrl);
                Environment.SetEnvironmentVariable("ClientId", TestApplications.NativeClient.ClientId);
                Environment.SetEnvironmentVariable("DefaultSmartAppUrl", "/sampleapp/launch.html");

                var builder = WebHost.CreateDefaultBuilder()
                              .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddEnvironmentVariables();
                })
                              .UseStartup <SmartLauncher.Startup>()
                              .UseUrls(baseUrl);

                WebServer = builder.Build();
                WebServer.Start();

                HttpClient = new HttpClient {
                    BaseAddress = new Uri(environmentUrl),
                };

                FhirClient = new FhirClient(HttpClient, ResourceFormat.Json);
            }
        }
예제 #5
0
        public async Task WhenCreatingAResource_GivenAUserWithNoCreatePermissions_TheServerShouldReturnForbidden()
        {
            FhirClient    tempClient    = Client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);
            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(ForbiddenMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Forbidden, fhirException.StatusCode);
        }
예제 #6
0
        public async Task WhenCreatingAResource_GivenAClientWithWrongAudience_TheServerShouldReturnUnauthorized()
        {
            FhirClient    tempClient    = Client.CreateClientForClientApplication(TestApplications.WrongAudienceClient);
            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(UnauthorizedMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Unauthorized, fhirException.StatusCode);
        }
예제 #7
0
        public async Task WhenExportResources_GivenAUserWithNoExportPermissions_TheServerShouldReturnForbidden()
        {
            FhirClient tempClient = Client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.ExportAsync(_exportQueryParams));

            Assert.Equal(ForbiddenMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Forbidden, fhirException.StatusCode);
        }
예제 #8
0
        public async Task WhenCreatingAResource_GivenAClientWithInvalidAuthToken_TheServerShouldReturnUnauthorized()
        {
            FhirClient tempClient = Client.CreateClientForClientApplication(TestApplications.InvalidClient).Clone();

            tempClient.HttpClient.SetBearerToken(Invalidtoken);
            FhirException fhirException = await Assert.ThrowsAsync <FhirException>(async() => await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>()));

            Assert.Equal(UnauthorizedMessage, fhirException.Message);
            Assert.Equal(HttpStatusCode.Unauthorized, fhirException.StatusCode);
        }
예제 #9
0
        public async Task WhenGettingAResource_GivenAUserWithReadPermissions_TheServerShouldReturnSuccess()
        {
            FhirClient  tempClient      = Client.CreateClientForClientApplication(TestApplications.ServiceClient);
            Observation createdResource = await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            tempClient = Client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);
            FhirResponse <Observation> readResponse = await tempClient.ReadAsync <Observation>(ResourceType.Observation, createdResource.Id);

            Observation readResource = readResponse.Resource;

            Assert.Equal(createdResource.Id, readResource.Id);
            Assert.Equal(createdResource.Meta.VersionId, readResource.Meta.VersionId);
            Assert.Equal(createdResource.Meta.LastUpdated, readResource.Meta.LastUpdated);
        }
예제 #10
0
        public async Task GivenARequest_WhenInvalidAuthorizationTokenIsSupplied_ThenAuditLogEntriesShouldBeCreated()
        {
            await ExecuteAndValidate(
                () =>
            {
                FhirClient newClient = _client.Clone();

                newClient.HttpClient.SetBearerToken("invalid");

                return(newClient);
            },
                HttpStatusCode.Unauthorized,
                expectedAppId : null);
        }
        public static async Task <TResource[]> CreateResourcesAsync <TResource>(this FhirClient client, int count)
            where TResource : Resource, new()
        {
            TResource[] resources = new TResource[count];

            for (int i = 0; i < resources.Length; i++)
            {
                TResource resource = new TResource();

                resources[i] = await client.CreateAsync(resource);
            }

            return(resources);
        }
예제 #12
0
        public async Task GivenARequest_WhenNoAuthorizationTokenIsSupplied_ThenAuditLogEntriesShouldBeCreated()
        {
            await ExecuteAndValidate(
                () =>
            {
                FhirClient newClient = _client.Clone();

                newClient.HttpClient.DefaultRequestHeaders.Authorization = null;

                return(newClient);
            },
                HttpStatusCode.Unauthorized,
                expectedAppId : null);
        }
        public static async Task <TResource[]> CreateResourcesAsync <TResource>(this FhirClient client, params Action <TResource>[] resourceCustomizer)
            where TResource : Resource, new()
        {
            TResource[] resources = new TResource[resourceCustomizer.Length];

            for (int i = 0; i < resources.Length; i++)
            {
                TResource resource = new TResource();

                resourceCustomizer[i](resource);

                resources[i] = await client.CreateAsync(resource);
            }

            return(resources);
        }
        public static async Task DeleteAllResources(this FhirClient client, ResourceType resourceType, string searchUrl)
        {
            while (true)
            {
                Bundle bundle = await client.SearchAsync(resourceType, searchUrl, count : 100);

                if (!bundle.Entry.Any())
                {
                    break;
                }

                foreach (Bundle.EntryComponent entry in bundle.Entry)
                {
                    await client.DeleteAsync(entry.FullUrl);
                }
            }
        }
예제 #15
0
        public async Task WhenUpdatingAResource_GivenAUserWithUpdatePermissions_TheServerShouldReturnSuccess()
        {
            FhirClient  tempClient      = Client.CreateClientForUser(TestUsers.AdminUser, TestApplications.NativeClient);
            Observation createdResource = await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            tempClient = Client.CreateClientForUser(TestUsers.ReadWriteUser, TestApplications.NativeClient);
            FhirResponse <Observation> updateResponse = await tempClient.UpdateAsync(createdResource);

            Assert.Equal(System.Net.HttpStatusCode.OK, updateResponse.StatusCode);

            Observation updatedResource = updateResponse.Resource;

            Assert.NotNull(updatedResource);
            Assert.Equal(createdResource.Id, updatedResource.Id);
            Assert.NotEqual(createdResource.Meta.VersionId, updatedResource.Meta.VersionId);
            Assert.NotEqual(createdResource.Meta.LastUpdated, updatedResource.Meta.LastUpdated);
        }
예제 #16
0
        public async Task GivenABatchAndUserWithoutWrite_WhenPost_ThenAuditLogEntriesShouldBeCreated()
        {
            var batch = new Bundle
            {
                Type  = Bundle.BundleType.Batch,
                Entry = new List <Bundle.EntryComponent>
                {
                    new Bundle.EntryComponent
                    {
                        Resource = Samples.GetDefaultObservation().ToPoco(),
                        Request  = new Bundle.RequestComponent
                        {
                            Method = Bundle.HTTPVerb.POST,
                            Url    = "Observation",
                        },
                    },
                    new Bundle.EntryComponent
                    {
                        Request = new Bundle.RequestComponent
                        {
                            Method = Bundle.HTTPVerb.GET,
                            Url    = "Patient?name=peter",
                        },
                    },
                },
            };

            List <(string expectedActions, string expectedPathSegments, HttpStatusCode?expectedStatusCodes, ResourceType?resourceType)> expectedList = new List <(string, string, HttpStatusCode?, ResourceType?)>
            {
                ("batch", string.Empty, HttpStatusCode.OK, ResourceType.Bundle),
                ("create", "Observation", HttpStatusCode.Forbidden, ResourceType.Observation),
                ("search-type", "Patient?name=peter", HttpStatusCode.OK, ResourceType.Bundle),
            };

            FhirClient tempClient = _client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            await ExecuteAndValidateBundle(
                () => tempClient.PostBundleAsync(batch),
                expectedList,
                TestApplications.NativeClient.ClientId);
        }
예제 #17
0
        public async Task WhenHardDeletingAResource_GivenAUserWithHardDeletePermissions_TheServerShouldReturnSuccess()
        {
            FhirClient  tempClient      = Client.CreateClientForUser(TestUsers.WriteOnlyUser, TestApplications.NativeClient);
            Observation createdResource = await tempClient.CreateAsync(Samples.GetDefaultObservation().ToPoco <Observation>());

            tempClient = Client.CreateClientForUser(TestUsers.HardDeleteUser, TestApplications.NativeClient);

            // Hard-delete the resource.
            await tempClient.HardDeleteAsync(createdResource);

            tempClient = Client.CreateClientForUser(TestUsers.ReadOnlyUser, TestApplications.NativeClient);

            // Getting the resource should result in NotFound.
            await ExecuteAndValidateNotFoundStatus(() => tempClient.ReadAsync <Observation>(ResourceType.Observation, createdResource.Id));

            async Task <FhirException> ExecuteAndValidateNotFoundStatus(Func <Task> action)
            {
                FhirException exception = await Assert.ThrowsAsync <FhirException>(action);

                Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);
                return(exception);
            }
        }
예제 #18
0
        public async Task WhenExportResources_GivenAUserWithExportPermissions_TheServerShouldReturnSuccess()
        {
            FhirClient tempClient = Client.CreateClientForUser(TestUsers.ExportUser, TestApplications.NativeClient);

            await tempClient.ExportAsync(_exportQueryParams);
        }
예제 #19
0
 public AuditTests(AuditTestFixture fixture)
 {
     _fixture     = fixture;
     _client      = fixture.FhirClient;
     _auditLogger = _fixture.AuditLogger;
 }
 public static async Task DeleteAllResources(this FhirClient client, ResourceType resourceType)
 {
     await DeleteAllResources(client, resourceType, null);
 }