Skip to content

Commit

Permalink
LNK-3044: Log Forging Query Dispatch (#526)
Browse files Browse the repository at this point in the history
### 🛠 Description of Changes

Please provide a high-level overview of the changes included in this PR.

### 🧪 Testing Performed

Please describe the testing that was performed on the changes included
in this PR.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Enhanced logging security by sanitizing patient and facility
identifiers in various log messages and audit notes.
  
- **Bug Fixes**
- Improved error handling to ensure sanitized values are logged during
exceptions.

- **Documentation**
- Updated logging statements to reflect the inclusion of sanitization
for sensitive information across multiple components.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
edward-miller-lcg authored Oct 30, 2024
2 parents 938f422 + 98aeb82 commit 6e930ce
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 37 deletions.
13 changes: 7 additions & 6 deletions DotNet/QueryDispatch/Domain/Managers/PatientDispatchManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using LantanaGroup.Link.Shared.Application.Models;
using LantanaGroup.Link.Shared.Application.Models.Kafka;
using LantanaGroup.Link.Shared.Application.Repositories.Interfaces;
using LantanaGroup.Link.Shared.Application.Services.Security;
using Quartz;
using QueryDispatch.Application.Settings;

Expand Down Expand Up @@ -44,7 +45,7 @@ public async Task<string> createPatientDispatch(PatientDispatchEntity patientDis
//_datastore.Add(patientDispatch);
await _repository.AddAsync(patientDispatch);

_logger.LogInformation($"Created patient dispatch for patient id {patientDispatch.PatientId} in facility {patientDispatch.FacilityId}");
_logger.LogInformation($"Created patient dispatch for patient id {HtmlInputSanitizer.Sanitize(patientDispatch.PatientId)} in facility {HtmlInputSanitizer.Sanitize(patientDispatch.FacilityId)}");

await ScheduleService.CreateJobAndTrigger(patientDispatch, await _schedulerFactory.GetScheduler());

Expand All @@ -60,7 +61,7 @@ public async Task<string> createPatientDispatch(PatientDispatchEntity patientDis
Action = AuditEventType.Create,
EventDate = DateTime.UtcNow,
Resource = typeof(PatientDispatchEntity).Name,
Notes = $"Created patient dispatch for patient id {patientDispatch.PatientId} in facility {patientDispatch.FacilityId}"
Notes = $"Created patient dispatch for patient id {HtmlInputSanitizer.Sanitize(patientDispatch.PatientId)} in facility {HtmlInputSanitizer.Sanitize(patientDispatch.FacilityId)}"
};

_producer.Produce(nameof(KafkaTopic.AuditableEventOccurred), new Message<string, AuditEventMessage>
Expand All @@ -75,8 +76,8 @@ public async Task<string> createPatientDispatch(PatientDispatchEntity patientDis
}
catch (Exception ex)
{
_logger.LogError($"Create patient dispatch exception for patient id {patientDispatch.PatientId} in facility {patientDispatch.FacilityId}.", ex);
throw new ApplicationException($"Failed to create patient dispatch record for patient id {patientDispatch.PatientId} in facility {patientDispatch.FacilityId}.");
_logger.LogError($"Create patient dispatch exception for patient id {HtmlInputSanitizer.Sanitize(patientDispatch.PatientId)} in facility {HtmlInputSanitizer.Sanitize(patientDispatch.FacilityId)}.", ex);
throw new ApplicationException($"Failed to create patient dispatch record for patient id {HtmlInputSanitizer.Sanitize(patientDispatch.PatientId)} in facility {HtmlInputSanitizer.Sanitize(patientDispatch.FacilityId)}.");
}
}

Expand All @@ -89,7 +90,7 @@ public async Task<bool> deletePatientDispatch(string facilityId, string patientI
{
await _repository.RemoveAsync(entity);
}
_logger.LogInformation($"Deleted Patient Dispatch record for patient id {patientId} in facility {facilityId}");
_logger.LogInformation($"Deleted Patient Dispatch record for patient id {HtmlInputSanitizer.Sanitize(patientId)} in facility {HtmlInputSanitizer.Sanitize(facilityId)}");


var headers = new Headers
Expand Down Expand Up @@ -121,7 +122,7 @@ public async Task<bool> deletePatientDispatch(string facilityId, string patientI
}
catch (Exception ex)
{
_logger.LogError(ex, "Patient dispatch delete exception for patientId {patientId} in facility {facilityId}", patientId, facilityId);
_logger.LogError(ex, "Patient dispatch delete exception for patientId {patientId} in facility {facilityId}", HtmlInputSanitizer.Sanitize(patientId), HtmlInputSanitizer.Sanitize(facilityId));

return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using LantanaGroup.Link.Shared.Application.Models;
using LantanaGroup.Link.Shared.Application.Models.Kafka;
using LantanaGroup.Link.Shared.Application.Repositories.Interfaces;
using LantanaGroup.Link.Shared.Application.Services.Security;
using Quartz;
using QueryDispatch.Application.Settings;

Expand Down Expand Up @@ -63,7 +64,7 @@ public async Task SaveConfigEntity(QueryDispatchConfigurationEntity config, List

await _repository.UpdateAsync(config, cancellationToken);

_logger.LogInformation($"Updated query dispatch configuration for facility {config.FacilityId}");
_logger.LogInformation($"Updated query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}");



Expand All @@ -88,8 +89,8 @@ public async Task SaveConfigEntity(QueryDispatchConfigurationEntity config, List
}
catch (Exception ex)
{
_logger.LogError($"Failed to update query dispatch configuration for facility {config.FacilityId}.", ex);
throw new ApplicationException($"Failed to update query dispatch configuration for facility {config.FacilityId}.");
_logger.LogError($"Failed to update query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}.", ex);
throw new ApplicationException($"Failed to update query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}.");
}
}

Expand All @@ -101,7 +102,7 @@ public async Task AddConfigEntity(QueryDispatchConfigurationEntity config, Cance
{
await _repository.AddAsync(config, cancellationToken);

_logger.LogInformation($"Created query dispatch configuration for facility {config.FacilityId}");
_logger.LogInformation($"Created query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}");


var auditMessage = new AuditEventMessage
Expand All @@ -125,8 +126,8 @@ public async Task AddConfigEntity(QueryDispatchConfigurationEntity config, Cance
}
catch (Exception ex)
{
_logger.LogError($"Failed to create query dispatch configuration for facility {config.FacilityId}.", ex);
throw new ApplicationException($"Failed to create query dispatch configuration for facility {config.FacilityId}.");
_logger.LogError($"Failed to create query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}.", ex);
throw new ApplicationException($"Failed to create query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(config.FacilityId)}.");
}
}

Expand All @@ -147,7 +148,7 @@ public async Task DeleteConfigEntity(string facilityId, CancellationToken cancel
}
await _repository.DeleteAsync(config.Id, cancellationToken);

_logger.LogInformation($"Deleted query dispatch configuration for facility {facilityId}");
_logger.LogInformation($"Deleted query dispatch configuration for facility {HtmlInputSanitizer.Sanitize(facilityId)}");


var auditMessage = new AuditEventMessage
Expand All @@ -174,8 +175,8 @@ public async Task DeleteConfigEntity(string facilityId, CancellationToken cancel
}
catch (Exception ex)
{
_logger.LogError($"Failed to delete query dispatch configuration for facilityId {facilityId}", ex);
throw new ApplicationException($"Failed to delete query dispatch configuration for facilityId {facilityId}");
_logger.LogError($"Failed to delete query dispatch configuration for facilityId {HtmlInputSanitizer.Sanitize(facilityId)}", ex);
throw new ApplicationException($"Failed to delete query dispatch configuration for facilityId {HtmlInputSanitizer.Sanitize(facilityId)}");
}
}

Expand Down
13 changes: 7 additions & 6 deletions DotNet/QueryDispatch/Domain/Managers/ScheduledReportManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using LantanaGroup.Link.Shared.Application.Models;
using LantanaGroup.Link.Shared.Application.Models.Kafka;
using LantanaGroup.Link.Shared.Application.Repositories.Interfaces;
using LantanaGroup.Link.Shared.Application.Services.Security;
using Quartz;
using QueryDispatch.Application.Settings;

Expand Down Expand Up @@ -46,7 +47,7 @@ public async Task<string> createScheduledReport(ScheduledReportEntity scheduledR

await _scheduledReportRepository.AddAsync(scheduledReport);

_logger.LogInformation($"Created schedule report for faciltiy {scheduledReport.FacilityId}");
_logger.LogInformation($"Created schedule report for faciltiy {HtmlInputSanitizer.Sanitize(scheduledReport.FacilityId)}");

var headers = new Headers
{
Expand Down Expand Up @@ -77,8 +78,8 @@ public async Task<string> createScheduledReport(ScheduledReportEntity scheduledR
}
catch (Exception ex)
{
_logger.LogError($"Failed to create scheduled report for facility {scheduledReport.FacilityId}.", ex);
throw new ApplicationException($"Failed to create scheduled report for facility {scheduledReport.FacilityId}.");
_logger.LogError($"Failed to create scheduled report for facility {HtmlInputSanitizer.Sanitize(scheduledReport.FacilityId)}.", ex);
throw new ApplicationException($"Failed to create scheduled report for facility {HtmlInputSanitizer.Sanitize(scheduledReport.FacilityId)}.");
}
}

Expand Down Expand Up @@ -128,7 +129,7 @@ public async Task UpdateScheduledReport(ScheduledReportEntity existingReport, Sc

await _scheduledReportRepository.UpdateAsync(existingReport);

_logger.LogInformation($"Update scheduled report type {newReportPeriod.ReportType} for facility id {existingReport.FacilityId}");
_logger.LogInformation($"Update scheduled report type {HtmlInputSanitizer.Sanitize(newReportPeriod.ReportType)} for facility id {HtmlInputSanitizer.Sanitize(existingReport.FacilityId)}");

var headers = new Headers
{
Expand Down Expand Up @@ -158,8 +159,8 @@ public async Task UpdateScheduledReport(ScheduledReportEntity existingReport, Sc
}
catch (Exception ex)
{
_logger.LogError($"Failed to update scheduled report for facility id {existingReport.FacilityId}.", ex);
throw new ApplicationException($"Failed to update scheduled report for facility id {existingReport.FacilityId}.");
_logger.LogError($"Failed to update scheduled report for facility id {HtmlInputSanitizer.Sanitize(existingReport.FacilityId)}.", ex);
throw new ApplicationException($"Failed to update scheduled report for facility id {HtmlInputSanitizer.Sanitize(existingReport.FacilityId)}.");
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion DotNet/QueryDispatch/Jobs/QueryDispatchJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using QueryDispatch.Application.Settings;
using LantanaGroup.Link.QueryDispatch.Application.Interfaces;
using QueryDispatch.Domain.Managers;
using LantanaGroup.Link.Shared.Application.Services.Security;

namespace LanatanGroup.Link.QueryDispatch.Jobs
{
Expand Down Expand Up @@ -79,7 +80,7 @@ public async Task Execute(IJobExecutionContext context)

_acquisitionProducer.Flush();

_logger.LogInformation($"Produced Data Acquisition Requested event for facilityId: {patientDispatchEntity.FacilityId}");
_logger.LogInformation($"Produced Data Acquisition Requested event for facilityId: {HtmlInputSanitizer.Sanitize(patientDispatchEntity.FacilityId)}");

await patientDispatchMgr.deletePatientDispatch(patientDispatchEntity.FacilityId, patientDispatchEntity.PatientId);

Expand Down
13 changes: 7 additions & 6 deletions DotNet/QueryDispatch/Listeners/PatientEventListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using LantanaGroup.Link.Shared.Application.Models;
using LantanaGroup.Link.Shared.Application.Models.Kafka;
using LantanaGroup.Link.Shared.Application.Repositories.Interfaces;
using LantanaGroup.Link.Shared.Application.Services.Security;
using QueryDispatch.Application.Settings;
using QueryDispatch.Domain.Managers;
using System.Text;
Expand Down Expand Up @@ -107,7 +108,7 @@ await _patientEventConsumer.ConsumeWithInstrumentation(async (result, cancellati
throw new DeadLetterException("Correlation Id missing");
}

_logger.LogInformation($"Consumed Patient Event for: Facility '{consumeResult.Message.Key}'. PatientId '{value.PatientId}' with a event type of {value.EventType}");
_logger.LogInformation($"Consumed Patient Event for: Facility '{HtmlInputSanitizer.Sanitize(consumeResult.Message.Key)}'. PatientId '{HtmlInputSanitizer.Sanitize(value.PatientId)}' with a event type of {HtmlInputSanitizer.Sanitize(value.EventType)}");

//ScheduledReportEntity scheduledReport = getScheduledReportQuery.Execute(consumeResult.Message.Key);
ScheduledReportEntity scheduledReport = await scheduledReportRepository.FirstOrDefaultAsync(x => x.FacilityId == consumeResult.Message.Key);
Expand All @@ -125,21 +126,21 @@ await _patientEventConsumer.ConsumeWithInstrumentation(async (result, cancellati

if (dispatchSchedule == null)
{
throw new TransientException($"Query dispatch configuration missing for facility {consumeResult.Message.Key}");
throw new TransientException($"Query dispatch configuration missing for facility {HtmlInputSanitizer.Sanitize(consumeResult.Message.Key)}");
}

DispatchSchedule dischargeDispatchSchedule = dispatchSchedule.DispatchSchedules.FirstOrDefault(x => x.Event == QueryDispatchConstants.EventType.Discharge);

if (dischargeDispatchSchedule == null)
{
throw new TransientException($"'Discharge' query dispatch configuration missing for facility {consumeResult.Message.Key}");
throw new TransientException($"'Discharge' query dispatch configuration missing for facility {HtmlInputSanitizer.Sanitize(consumeResult.Message.Key)}");
}

PatientDispatchEntity patientDispatch = _queryDispatchFactory.CreatePatientDispatch(consumeResult.Message.Key, value.PatientId, value.EventType, correlationId, scheduledReport, dischargeDispatchSchedule);

if (patientDispatch.ScheduledReportPeriods == null || patientDispatch.ScheduledReportPeriods.Count == 0)
{
throw new TransientException($"No active scheduled report periods found for facility {consumeResult.Message.Key}");
throw new TransientException($"No active scheduled report periods found for facility {HtmlInputSanitizer.Sanitize(consumeResult.Message.Key)}");
}

await patientDispatchMgr.createPatientDispatch(patientDispatch);
Expand All @@ -148,12 +149,12 @@ await _patientEventConsumer.ConsumeWithInstrumentation(async (result, cancellati
}
catch (DeadLetterException ex)
{
_deadLetterExceptionHandler.HandleException(consumeResult, ex, consumeResult.Key);
_deadLetterExceptionHandler.HandleException(consumeResult, ex, HtmlInputSanitizer.Sanitize(consumeResult.Key));
_patientEventConsumer.Commit(consumeResult);
}
catch (TransientException ex)
{
_transientExceptionHandler.HandleException(consumeResult, ex, consumeResult.Key);
_transientExceptionHandler.HandleException(consumeResult, ex, HtmlInputSanitizer.Sanitize(consumeResult.Key));
_patientEventConsumer.Commit(consumeResult);
}
catch (Exception ex)
Expand Down
Loading

0 comments on commit 6e930ce

Please sign in to comment.