using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace CDP { public class AuditFunctions { private readonly ILogger _logger; public static string FileAuditContainer = "FileAudits"; public static string UserAuditContainer = "UserAudits"; public static string GroupAuditContainer = "GroupAudits"; public static string TenantAuditContainer = "TenantAudits"; public AuditFunctions(ILogger logger) { _logger = logger; } [Function("GetAuditLogForFile")] public async Task GetAuditLogForFile([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req) { _logger.LogInformation("GetAuditLogForFile invoked"); // Convert the JSON payload to a string string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(requestBody)) return new BadRequestObjectResult(new { error = true, message = "The body is empty" }); _logger.LogInformation(requestBody); GetAuditLogForFileDto dto = JsonConvert.DeserializeObject(requestBody); if (dto == null) return new BadRequestObjectResult(new { error = true, message = "Parse error." }); List ad = await AuditDB.GetAuditRecordsBetweenDates(dto.FileId, DateTime.MinValue, DateTime.MaxValue, CDPLite.FileAuditContainer); return new OkObjectResult(ad); } [Function("GetAuditLogForUser")] public async Task GetAuditLogForUser([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req) { _logger.LogInformation("GetAuditLogForUser invoked"); // Convert the JSON payload to a string string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(requestBody)) return new BadRequestObjectResult(new { error = true, message = "The body is empty" }); _logger.LogInformation(requestBody); GetAuditLogForUserDto dto = JsonConvert.DeserializeObject(requestBody); if (dto == null) return new BadRequestObjectResult(new { error = true, message = "Parse error." }); string userId = Helpers.HashAndShortenText(dto.Email.ToLower()); List ad = await AuditDB.GetAuditRecordsBetweenDates(userId, DateTime.MinValue, DateTime.MaxValue, UserAuditContainer); return new OkObjectResult(ad); } [Function("GetAuditLogForGroup")] public async Task GetAuditLogForGroup([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req) { _logger.LogInformation("GetAuditLogForGroup invoked"); // Convert the JSON payload to a string string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(requestBody)) return new BadRequestObjectResult(new { error = true, message = "The body is empty" }); _logger.LogInformation(requestBody); GetAuditLogForGroupDto dto = JsonConvert.DeserializeObject(requestBody); if (dto == null) return new BadRequestObjectResult(new { error = true, message = "Parse error." }); List ad = await AuditDB.GetAuditRecordsBetweenDates(dto.GroupId, DateTime.MinValue, DateTime.MaxValue, GroupAuditContainer); return new OkObjectResult(ad); } [Function("GetAuditLogForTenant")] public async Task GetAuditLogForTenant([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req) { _logger.LogInformation("GetAuditLogForGroup invoked"); // Convert the JSON payload to a string string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(requestBody)) return new BadRequestObjectResult(new { error = true, message = "The body is empty" }); _logger.LogInformation(requestBody); GetAuditLogForTenantDto dto = JsonConvert.DeserializeObject(requestBody); if (dto == null) return new BadRequestObjectResult(new { error = true, message = "Parse error." }); List ad = await AuditDB.GetAuditRecordsBetweenDates(dto.AppKey, DateTime.MinValue, DateTime.MaxValue, TenantAuditContainer); return new OkObjectResult(ad); } [Function("AddAccessViolation")] public async Task AddAccessViolation([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req) { _logger.LogInformation("AddAccessViolation invoked"); // Convert the JSON payload to a string string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (string.IsNullOrEmpty(requestBody)) return false; _logger.LogInformation(requestBody); AddAccessViolationDto dto = JsonConvert.DeserializeObject(requestBody); if (dto == null) return false; string message = string.Format($"Access violation recorded for file {dto.FileName}"); string action = "Access Violation"; await AddAudits(dto.AppKey, dto.FileId, dto.FileName, "", "", action, message); return true; } public static async Task AddAuditsEvent(string appKey, string fileId, string fileName, string userId, string groupid, string action, string message) { using (var mt = new MethodTimer("AddAuditsEventMessage")) { if (string.IsNullOrEmpty(appKey) || string.IsNullOrEmpty(fileId) || string.IsNullOrEmpty(action) || string.IsNullOrEmpty(message)) return ""; AuditEventMetadata auditEvent = new AuditEventMetadata { FileId = fileId, FileName = fileName, UserId = userId, GroupId = groupid, Action = action, Message = message }; string jobId = Guid.NewGuid().ToString(); string jobMeta = JsonConvert.SerializeObject(auditEvent); Job job = new Job { AppKey = appKey, EventType = JobType.AddAudits, Id = jobId, JobMetadata = jobMeta }; await MetaProcessor.PublishJob(job); return jobId; } } public static async Task AddAudits(string appKey, string fileId, string fileName, string userId, string groupid, string action, string message) { if (string.IsNullOrEmpty(appKey) || string.IsNullOrEmpty(fileId) || string.IsNullOrEmpty(action) || string.IsNullOrEmpty(message)) { Console.WriteLine(string.Format("something weird? appKey, fileId, action, message: {0} {1} {2} {3}", appKey, fileId, action, message)); return; } AuditRecord faRec = new FileAuditRecord() { AppKey = appKey, FileId = fileId, FileName = fileName, UserId = userId, GroupId = groupid, Action = action, Message = message, EventTime = DateTime.UtcNow, }; Console.WriteLine("Adding File Audit Record"); await AuditDB.AppendRecord(faRec.id, faRec, FileAuditContainer); AuditRecord faRecTenant = new TenantAuditRecord() { AppKey = appKey, FileId = fileId, FileName = fileName, UserId = userId, GroupId = groupid, Action = action, Message = message, EventTime = DateTime.UtcNow, }; await AuditDB.AppendRecord(faRecTenant.id, faRecTenant, TenantAuditContainer); if (!string.IsNullOrEmpty(groupid)) { AuditRecord faRecGroup = new GroupAuditRecord() { AppKey = appKey, FileId = fileId, FileName = fileName, UserId = userId, GroupId = groupid, Action = action, Message = message, EventTime = DateTime.UtcNow, }; await AuditDB.AppendRecord(faRecGroup.id, faRecGroup, GroupAuditContainer); } AuditRecord faRecUser = new UserAuditRecord() { AppKey = appKey, FileId = fileId, FileName = fileName, UserId = userId, GroupId = groupid, Action = action, Message = message, EventTime = DateTime.UtcNow, }; await AuditDB.AppendRecord(faRecUser.id, faRecUser, UserAuditContainer); } /// /// Adds the audit record on a background thread. /// private static async Task AddFileAudit(AuditRecord far) { await AuditDB.AppendRecord(far.id, far, FileAuditContainer); } private static async Task AddUserAudit(AuditRecord far) { await AuditDB.AppendRecord(far.id, far, UserAuditContainer); } private static async Task AddTenantAudit(AuditRecord far) { await Task.Run(async () => { try { await AuditDB.AppendRecord(far.id, far, TenantAuditContainer); } catch (Exception e) { } }); } private static async Task AddGroupAudit(AuditRecord far) { await Task.Run(async () => { try { await AuditDB.AppendRecord(far.id, far, GroupAuditContainer); } catch (Exception e) { } }); } } }