private async Task <(JArray resources, List <CheckResult> checks)> ParseResourcesAndChecks(JArray[] rawData, AuditMetadata auditMeta) { var checksResults = new List <CheckResult>(); var resources = new Dictionary <string, JToken>(); foreach (var jArray in rawData) { foreach (var item in jArray) { // failure in processing one check-result should not impact the rest try { var controlItem = item["ControlItem"]; var checkId = $"azsk.{controlItem["ControlID"].Value<string>()}"; var id = await this.cache.GetOrAddItem(checkId, () => new Check { Id = checkId, Severity = this.ToSeverity(controlItem["ControlSeverity"].Value <string>()), Category = item["FeatureName"].Value <string>(), Description = $"{controlItem["Description"].Value<string>()}{Environment.NewLine}{controlItem["Rationale"].Value<string>()}", Remediation = controlItem["Recommendation"].Value <string>(), }); var checkResult = this.ToCheckResult(item); checkResult.AuditId = auditMeta.AuditId; checkResult.ExternalCheckId = checkId; checkResult.InternalCheckId = id; checksResults.Add(checkResult); if (item["ResourceContext"] != null) { resources.TryAdd(checkResult.ComponentId, item["ResourceContext"]); } } catch (Exception ex) { Logger.Warning(ex, "Failed to process one of check results in {AuditId}", auditMeta.AuditId); } } } var resourcesArray = new JArray(resources.Select(i => i.Value)); return(resourcesArray, checksResults); }
private async Task <Audit> NormalizeRawData(JArray[] rawData, AuditBlob auditBlob, AuditMetadata auditMetadata) { var(scope, id, name) = this.GetSubscriptionMeta(rawData); var(resources, checks) = await this.ParseResourcesAndChecks(rawData, auditMetadata); var azMetadata = new JObject { { "scanner", JToken.FromObject(auditBlob.ParentContainer.Metadata) }, { "audit", JToken.FromObject(auditMetadata) }, { "subscription", new JObject { { "scope", scope }, { "id", id }, { "name", name }, { "resources", resources }, } }, }; var auditDate = DateTimeOffset.FromUnixTimeSeconds(auditMetadata.Timestamp).DateTime; var audit = new Audit { Id = auditMetadata.AuditId, Date = auditDate, ScannerId = $"{auditBlob.ParentContainer.Metadata.Type}/{auditBlob.ParentContainer.Metadata.Id}", ComponentId = $"/subscriptions/{id}", ComponentName = name, CheckResults = checks, MetadataAzure = new MetadataAzure { AuditId = auditMetadata.AuditId, Date = auditDate, JSON = azMetadata.ToString(Formatting.None), }, }; return(audit); }