Example #1
0
        public AuditHelperTests()
        {
            _fhirRequestContext.Uri.Returns(Uri);
            _fhirRequestContext.CorrelationId.Returns(CorrelationId);

            _fhirRequestContextAccessor.FhirRequestContext = _fhirRequestContext;

            _auditEventTypeMapping.GetAuditEventType(ControllerName, AnonymousActionName).Returns((string)null);
            _auditEventTypeMapping.GetAuditEventType(ControllerName, NonAnonymousActionName).Returns(AuditEventType);

            _httpContext.Connection.RemoteIpAddress = CallerIpAddress;

            _claimsExtractor.Extract().Returns(Claims);

            _auditHelper = new AuditHelper(_fhirRequestContextAccessor, _auditEventTypeMapping, _auditLogger, NullLogger <AuditHelper> .Instance, _auditHeaderReader);
        }
Example #2
0
        public async Task Invoke(HttpContext context)
        {
            try
            {
                // Call the next delegate/middleware in the pipeline
                await _next(context);
            }
            finally
            {
                var statusCode = (HttpStatusCode)context.Response.StatusCode;

                // The authorization middleware runs before MVC middleware and therefore,
                // information related to route and audit will not be populated if authentication fails.
                // Handle such condition and populate them here if possible.
                if (_fhirRequestContextAccessor.FhirRequestContext.RouteName == null &&
                    (statusCode == HttpStatusCode.Unauthorized || statusCode == HttpStatusCode.Forbidden))
                {
                    RouteData routeData = context.GetRouteData();

                    if (routeData?.Values != null)
                    {
                        routeData.Values.TryGetValue("controller", out object controllerName);
                        routeData.Values.TryGetValue("action", out object actionName);
                        routeData.Values.TryGetValue(KnownActionParameterNames.ResourceType, out object resourceType);

                        IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

                        fhirRequestContext.AuditEventType = _auditEventTypeMapping.GetAuditEventType(
                            controllerName?.ToString(),
                            actionName?.ToString());
                        fhirRequestContext.ResourceType = resourceType?.ToString();
                    }
                }
            }
        }
Example #3
0
        private void ExecuteAndValidateFilter(string auditEventTypeFromMapping, string expectedAuditEventType)
        {
            _auditEventTypeMapping.GetAuditEventType(ControllerName, ActionName).Returns(auditEventTypeFromMapping);

            _filterAttribute.OnActionExecuting(_actionExecutingContext);

            Assert.NotNull(_fhirRequestContextAccessor.FhirRequestContext.AuditEventType);
            Assert.Equal(expectedAuditEventType, _fhirRequestContextAccessor.FhirRequestContext.AuditEventType);
            Assert.Equal(RouteName, _fhirRequestContextAccessor.FhirRequestContext.RouteName);
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

            fhirRequestContext.RouteName = context.ActionDescriptor?.AttributeRouteInfo?.Name;

            // Set the resource type based on the route data
            RouteData routeData = context.RouteData;

            if (routeData?.Values != null)
            {
                if (routeData.Values.TryGetValue(KnownActionParameterNames.ResourceType, out object resourceType))
                {
                    fhirRequestContext.ResourceType = resourceType?.ToString();
                }
            }

            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                fhirRequestContext.AuditEventType = _auditEventTypeMapping.GetAuditEventType(
                    controllerActionDescriptor.ControllerName,
                    controllerActionDescriptor.ActionName);

                // If this is a request from the batch and transaction route, we need to examine the payload to set the AuditEventType
                if (fhirRequestContext.AuditEventType == AuditEventSubType.BundlePost)
                {
                    if (context.ActionArguments.TryGetValue(KnownActionParameterNames.Bundle, out object value))
                    {
                        if (!(value is Hl7.Fhir.Model.Bundle bundle))
                        {
                            return;
                        }

                        switch (bundle.Type)
                        {
                        case Hl7.Fhir.Model.Bundle.BundleType.Batch:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Batch;
                            break;

                        case Hl7.Fhir.Model.Bundle.BundleType.Transaction:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Transaction;
                            break;
                        }
                    }
                }
            }

            if (context.HttpContext.Request.Headers.TryGetValue(KnownHeaders.PartiallyIndexedParamsHeaderName, out var headerValues))
            {
                fhirRequestContext.IncludePartiallyIndexedSearchParams = true;
            }

            base.OnActionExecuting(context);
        }
Example #5
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

            fhirRequestContext.RouteName = context.ActionDescriptor?.AttributeRouteInfo?.Name;

            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

            if (controllerActionDescriptor != null)
            {
                fhirRequestContext.AuditEventType = _auditEventTypeMapping.GetAuditEventType(
                    controllerActionDescriptor.ControllerName,
                    controllerActionDescriptor.ActionName);
            }
        }
        public async Task GivenRouteNameNotSetAndAuthXFailed_WhenInvoked_ThenAuditLogShouldBeLogged(HttpStatusCode statusCode)
        {
            const string resourceType = "Patient";

            _auditEventTypeMapping.GetAuditEventType(ControllerName, ActionName).Returns(DefaultAuditEventType);

            _httpContext.Response.StatusCode = (int)statusCode;

            RouteData routeData = SetupRouteData(ControllerName, ActionName);

            routeData.Values.Add("typeParameter", resourceType);

            await _fhirRequestContextBeforeAuthenticationMiddleware.Invoke(_httpContext);

            Assert.Equal(DefaultAuditEventType, _fhirRequestContext.AuditEventType);
            Assert.Equal(resourceType, _fhirRequestContext.ResourceType);
        }
Example #7
0
        private void Log(AuditAction auditAction, string controllerName, string actionName, HttpStatusCode?statusCode, string resourceType, HttpContext httpContext, IClaimsExtractor claimsExtractor)
        {
            string auditEventType = _auditEventTypeMapping.GetAuditEventType(controllerName, actionName);

            // Audit the call if an audit event type is associated with the action.
            if (auditEventType != null)
            {
                IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

                _auditLogger.LogAudit(
                    auditAction,
                    operation: auditEventType,
                    resourceType: resourceType,
                    requestUri: fhirRequestContext.Uri,
                    statusCode: statusCode,
                    correlationId: fhirRequestContext.CorrelationId,
                    callerIpAddress: httpContext.Connection?.RemoteIpAddress?.ToString(),
                    callerClaims: claimsExtractor.Extract());
            }
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            EnsureArg.IsNotNull(context, nameof(context));
            IDicomRequestContext dicomRequestContext = _dicomRequestContextAccessor.DicomRequestContext;

            dicomRequestContext.RouteName = context.ActionDescriptor?.AttributeRouteInfo?.Name;

            // Set StudyInstanceUid, SeriesInstanceUid, and SopInstanceUid based on the route data
            RouteData routeData = context.RouteData;

            if (routeData?.Values != null)
            {
                // Try to get StudyInstanceUid
                if (routeData.Values.TryGetValue(KnownActionParameterNames.StudyInstanceUid, out object studyInstanceUid))
                {
                    dicomRequestContext.StudyInstanceUid = studyInstanceUid.ToString();

                    // Try to get SeriesInstanceUid only if StudyInstanceUid was successfully fetched.
                    if (routeData.Values.TryGetValue(KnownActionParameterNames.SeriesInstanceUid, out object seriesInstanceUid))
                    {
                        dicomRequestContext.SeriesInstanceUid = seriesInstanceUid.ToString();

                        // Try to get SopInstanceUid only if StudyInstanceUid and SeriesInstanceUid were fetched successfully.
                        if (routeData.Values.TryGetValue(KnownActionParameterNames.SopInstanceUid, out object sopInstanceUid))
                        {
                            dicomRequestContext.SopInstanceUid = sopInstanceUid.ToString();
                        }
                    }
                }
            }

            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                dicomRequestContext.AuditEventType = _auditEventTypeMapping.GetAuditEventType(
                    controllerActionDescriptor.ControllerName,
                    controllerActionDescriptor.ActionName);
            }

            base.OnActionExecuting(context);
        }
        private void ExecuteAndValidateFilter(
            string auditEventTypeFromMapping,
            string expectedAuditEventType,
            ResourceType?resourceType = null)
        {
            _auditEventTypeMapping.GetAuditEventType(ControllerName, ActionName).Returns(auditEventTypeFromMapping);

            _filterAttribute.OnActionExecuting(_actionExecutingContext);

            Assert.NotNull(_dicomRequestContextAccessor.DicomRequestContext.AuditEventType);
            Assert.Equal(expectedAuditEventType, _dicomRequestContextAccessor.DicomRequestContext.AuditEventType);
            Assert.Equal(RouteName, _dicomRequestContextAccessor.DicomRequestContext.RouteName);

            if (resourceType != null)
            {
                switch (resourceType)
                {
                case ResourceType.Study:
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.StudyInstanceUid, StudyInstanceUid);
                    break;

                case ResourceType.Series:
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.StudyInstanceUid, StudyInstanceUid);
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.SeriesInstanceUid, SeriesInstanceUid);
                    break;

                case ResourceType.Instance:
                case ResourceType.Frames:
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.StudyInstanceUid, StudyInstanceUid);
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.SeriesInstanceUid, SeriesInstanceUid);
                    Assert.Equal(_dicomRequestContextAccessor.DicomRequestContext.SopInstanceUid, SopInstanceUid);
                    break;

                default:
                    break;
                }
            }
        }
Example #10
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

            fhirRequestContext.RouteName = context.ActionDescriptor?.AttributeRouteInfo?.Name;

            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                fhirRequestContext.AuditEventType = _auditEventTypeMapping.GetAuditEventType(
                    controllerActionDescriptor.ControllerName,
                    controllerActionDescriptor.ActionName);

                // If this is a request from the batch and transaction route, we need to examine the payload to set the AuditEventType
                if (fhirRequestContext.AuditEventType == AuditEventSubType.BundlePost)
                {
                    if (context.ActionArguments.TryGetValue(KnownActionParameterNames.Bundle, out object value))
                    {
                        if (!(value is Hl7.Fhir.Model.Bundle bundle))
                        {
                            return;
                        }

                        switch (bundle.Type)
                        {
                        case Hl7.Fhir.Model.Bundle.BundleType.Batch:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Batch;
                            break;

                        case Hl7.Fhir.Model.Bundle.BundleType.Transaction:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Transaction;
                            break;
                        }
                    }
                }
            }
        }
Example #11
0
        private void Log(AuditAction auditAction, string controllerName, string actionName, HttpStatusCode?statusCode, string resourceType, HttpContext httpContext, IClaimsExtractor claimsExtractor)
        {
            IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext;

            // fhirRequestContext.AuditEventType will not be set in the case of an unauthorized call because the filter that sets it will not be executed
            string auditEventType = string.IsNullOrWhiteSpace(fhirRequestContext.AuditEventType) ? _auditEventTypeMapping.GetAuditEventType(controllerName, actionName) : fhirRequestContext.AuditEventType;

            // Audit the call if an audit event type is associated with the action.
            if (auditEventType != null)
            {
                _auditLogger.LogAudit(
                    auditAction,
                    operation: auditEventType,
                    resourceType: resourceType,
                    requestUri: fhirRequestContext.Uri,
                    statusCode: statusCode,
                    correlationId: fhirRequestContext.CorrelationId,
                    callerIpAddress: httpContext.Connection?.RemoteIpAddress?.ToString(),
                    callerClaims: claimsExtractor.Extract(),
                    customHeaders: _auditHeaderReader.Read(httpContext));
            }
        }
Example #12
0
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.RequestContext;

            fhirRequestContext.RouteName = context.ActionDescriptor?.AttributeRouteInfo?.Name;

            // Set the resource type based on the route data
            RouteData routeData = context.RouteData;

            if (routeData?.Values != null)
            {
                if (routeData.Values.TryGetValue(KnownActionParameterNames.ResourceType, out object resourceType))
                {
                    fhirRequestContext.ResourceType = resourceType?.ToString();
                }
            }

            if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)
            {
                // if controllerActionDescriptor.ActionName is CustomError then retain the AuditEventType from previous context
                // e.g. In case of 500 error - we want to make sure we log the AuditEventType of the original request for which the error occurred in RequestMetric.
                fhirRequestContext.AuditEventType = KnownRoutes.CustomError.Contains(controllerActionDescriptor.ActionName, StringComparison.OrdinalIgnoreCase) ? fhirRequestContext.AuditEventType : _auditEventTypeMapping.GetAuditEventType(
                    controllerActionDescriptor.ControllerName,
                    controllerActionDescriptor.ActionName);

                // If this is a request from the batch and transaction route, we need to examine the payload to set the AuditEventType
                if (fhirRequestContext.AuditEventType == AuditEventSubType.BundlePost)
                {
                    if (context.ActionArguments.TryGetValue(KnownActionParameterNames.Bundle, out object value))
                    {
                        if (!(value is Hl7.Fhir.Model.Bundle bundle))
                        {
                            return;
                        }

                        switch (bundle.Type)
                        {
                        case Hl7.Fhir.Model.Bundle.BundleType.Batch:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Batch;
                            break;

                        case Hl7.Fhir.Model.Bundle.BundleType.Transaction:
                            fhirRequestContext.AuditEventType = AuditEventSubType.Transaction;
                            break;
                        }
                    }
                }
            }

            if (context.HttpContext.Request.Headers.TryGetValue(KnownHeaders.PartiallyIndexedParamsHeaderName, out var headerValues))
            {
                fhirRequestContext.IncludePartiallyIndexedSearchParams = true;
            }

            base.OnActionExecuting(context);
        }