using System; using System.Linq; using System.Net; using System.Web; using System.Threading.Tasks; using AutopilotMonitor.Functions.Helpers; using AutopilotMonitor.Functions.Services; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; namespace AutopilotMonitor.Functions.Functions.Vulnerability { /// /// Returns the full software inventory for a tenant from the SoftwareInventory table. /// Galactic Admin only. Query param: ?tenantId=... /// public class GetSoftwareInventoryFunction { private readonly ILogger _logger; private readonly TableStorageService _storageService; private readonly GalacticAdminService _galacticAdminService; public GetSoftwareInventoryFunction( ILogger logger, TableStorageService storageService, GalacticAdminService galacticAdminService) { _logger = logger; _storageService = storageService; _galacticAdminService = galacticAdminService; } [Function("GetSoftwareInventory")] public async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "vulnerability/software-inventory")] HttpRequestData req) { try { // Galactic Admin only — enforced by PolicyEnforcementMiddleware var userIdentifier = TenantHelper.GetUserIdentifier(req); var query = HttpUtility.ParseQueryString(req.Url.Query); var tenantId = query["tenantId"]; if (string.IsNullOrEmpty(tenantId)) { var badRequest = req.CreateResponse(HttpStatusCode.BadRequest); await badRequest.WriteAsJsonAsync(new { success = false, message = "tenantId query parameter is required" }); return badRequest; } var inventory = await _storageService.GetSoftwareInventoryAsync(tenantId); var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteAsJsonAsync(new { success = true, tenantId, total = inventory.Count, matched = inventory.Count(i => !string.IsNullOrEmpty(i["cpeUri"]?.ToString())), unmatched = inventory.Count(i => string.IsNullOrEmpty(i["cpeUri"]?.ToString())), inventory }); return response; } catch (Exception ex) { _logger.LogError(ex, "Failed to get software inventory"); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteStringAsync("Internal server error"); return errorResponse; } } } }