public override async Task <bool> ReportPackageSourceAudit() { if (!AuditOptions.ContainsKey("GitHubReportOwner") || !AuditOptions.ContainsKey("GitHubReportName") || !AuditOptions.ContainsKey("GitHubToken")) { throw new ArgumentException("The GitHubReportOwner, GitHubReportName, and GitHubReportOwner audit options must be present."); } if (AuditOptions.ContainsKey("GitHubReportTitle")) { IssueTitle = (string)AuditOptions["GitHubReportTitle"]; } else { IssueTitle = string.Format("[DevAudit] {2} audit on {0} {1}", DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString(), Source.PackageManagerLabel); } GitHubClient client; client = new GitHubClient(new ProductHeaderValue("DevAudit")); client.Credentials = new Credentials((string)AuditOptions["GitHubToken"]); Repository repository; try { repository = await client.Repository.Get((string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"]); } catch (Exception) { AuditEnvironment.Warning("Could not get repository {0}/{1}.", (string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"]); } NewIssue issue = new NewIssue(IssueTitle); BuildPackageSourceAuditReport(); issue.Body = IssueText.ToString(); try { Issue i = await client.Issue.Create((string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"], issue); AuditEnvironment.Info("Created issue #{0} {1} in GitHub repository {2}/{3}.", i.Number, IssueTitle, (string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"]); } catch (AggregateException ae) { AuditEnvironment.Error(ae, "Error creating new issue for repository {0}/{1}.", (string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"]); return(false); } catch (Exception e) { AuditEnvironment.Error(e, "Error creating new issue for repository {0}/{1}.", (string)AuditOptions["GitHubReportOwner"], (string)AuditOptions["GitHubReportName"]); return(false); } return(true); }
public override async Task <bool> ReportPackageSourceAudit() { if (!this.AuditOptions.ContainsKey("GitLabReportUrl") || !this.AuditOptions.ContainsKey("GitLabReportName") || !this.AuditOptions.ContainsKey("GitLabToken")) { throw new ArgumentException("A required audit option for the GitLab environment is missing."); } HostUrl = (string)this.AuditOptions["GitLabReportUrl"]; Token = (string)this.AuditOptions["GitLabToken"]; ProjectName = (string)this.AuditOptions["GitLabReportName"]; GitLabClient client = null; try { this.AuditEnvironment.Info("Connecting to project {0} at {1}", ProjectName, HostUrl); client = new GitLabClient(HostUrl, Token); IEnumerable <Project> projects = await client.Projects.Owned(); Project = projects.Where(p => p.Name == ProjectName).FirstOrDefault(); this.AuditEnvironment.Info("Connected to project {0}.", Project.PathWithNamespace); } catch (AggregateException ae) { AuditEnvironment.Error(ae, "Could not get project {0} at url {1}.", ProjectName, HostUrl); return(false); } catch (Exception e) { AuditEnvironment.Error(e, "Could not get project {0} at url {1}.", ProjectName, HostUrl); return(false); } if (Project == null) { AuditEnvironment.Error("Could not find the project {0}.", Project.Name); return(false); } if (!Project.IssuesEnabled) { AuditEnvironment.Error("Issues are not enabled for the project {0}/{1}.", Project.Owner, Project.Name); return(false); } if (AuditOptions.ContainsKey("GitLabReportTitle")) { IssueTitle = (string)AuditOptions["GitLabReportTitle"]; } else { IssueTitle = string.Format("[DevAudit] {2} audit on {0} {1}", DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString(), Source.PackageManagerLabel); } BuildPackageSourceAuditReport(); try { IssueCreate ic = new IssueCreate { ProjectId = Project.Id, Title = IssueTitle, Description = IssueText.ToString() }; Issue issue = await client.Issues.CreateAsync(ic); if (issue != null) { AuditEnvironment.Success("Created issue #{0} '{1}' in GitLab project {2}/{3} at host url {4}.", issue.IssueId, issue.Title, Project.Owner, ProjectName, HostUrl); return(true); } else { AuditEnvironment.Error("Error creating new issue for project {0} at host url {1}. The issue object is null.", ProjectName, HostUrl); return(false); } } catch (AggregateException ae) { AuditEnvironment.Error(ae, "Error creating new issue for project {0} at host url {1}.", ProjectName, HostUrl); return(false); } catch (Exception e) { AuditEnvironment.Error(e, "Error creating new issue for project {0} at host url {1}.", ProjectName, HostUrl); return(false); } }
public override async Task <bool> ReportPackageSourceAudit() { HttpClient.DefaultRequestHeaders.Accept.Clear(); HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var r = await HttpClient.GetStringAsync("/api/v2/applications?publicId=" + IQServerAppId); var apps = JsonConvert.DeserializeObject <IQServerApplications>(r); if (apps.Applications.Length == 0) { AuditEnvironment.Error("The app id {0} does not exist on the IQ Server at {1}.", IQServerAppId, IQServerUrl.ToString()); return(false); } IQServerInternalAppId = apps.Applications.First().Id; SBom.AppendFormat("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<bom xmlns=\"http://cyclonedx.org/schema/bom/1.1\" version=\"1\" serialNumber=\"urn:uuid:{0}\"\nxmlns:v=\"http://cyclonedx.org/schema/ext/vulnerability/1.0\">\n\t<components>\n", Guid.NewGuid().ToString("D")); int packages_count = Source.Vulnerabilities.Count; int packages_processed = 0; int c = 0; foreach (var pv in Source.Vulnerabilities.OrderByDescending(sv => sv.Value.Count(v => v.PackageVersionIsInRange))) { IPackage package = pv.Key; List <IVulnerability> package_vulnerabilities = pv.Value; var purl = string.IsNullOrEmpty(package.Group) ? string.Format("pkg:nuget/{0}@{1}", package.Name, package.Version) : string.Format("pkg:nuget/{0}/{1}@{2}", package.Group, package.Name, package.Version); SBom.AppendLine("\t\t<component type =\"library\">"); if (!string.IsNullOrEmpty(package.Group)) { SBom.AppendFormat("\t\t\t<group>{0}</group>\n", package.Group); } SBom.AppendFormat("\t\t\t<name>{0}</name>\n", package.Name); SBom.AppendFormat("\t\t\t<version>{0}</version>\n", package.Version); SBom.AppendFormat("\t\t\t<purl>{0}</purl>\n", purl); if ((package_vulnerabilities.Count() != 0) && (package_vulnerabilities.Count(v => v.PackageVersionIsInRange) > 0)) { SBom.AppendLine("\t\t\t<v:vulnerabilities>"); var matched_vulnerabilities = package_vulnerabilities.Where(v => v.PackageVersionIsInRange).ToList(); int matched_vulnerabilities_count = matched_vulnerabilities.Count; matched_vulnerabilities.ForEach(v => { SBom.AppendFormat("\t\t\t\t<v:vulnerability ref=\"{0}\">\n", purl); SBom.AppendFormat("\t\t\t\t\t<v:id>{0}</v:id>\n", v.CVE != null && v.CVE.Length > 0 ? v.CVE.First() : v.Id); SBom.AppendLine("\t\t\t\t</v:vulnerability>"); c++; }); SBom.AppendLine("\t\t\t</v:vulnerabilities>"); } SBom.AppendLine("\t\t</component>"); packages_processed++; } SBom.AppendLine("\t</components>\n</bom>"); AuditEnvironment.Debug("SBOM:\n{0}", SBom.ToString()); HttpClient.DefaultRequestHeaders.Accept.Clear(); //HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); var req = string.Format("/api/v2/scan/applications/{0}/sources/devaudit", IQServerInternalAppId); var content = new StringContent(SBom.ToString(), Encoding.UTF8, "application/xml"); var response = await HttpClient.PostAsync(req, content); if (!response.IsSuccessStatusCode) { return(false); } string json = await response.Content.ReadAsStringAsync(); AuditEnvironment.Debug("JSON response from IQ Server at {0}: {1}", IQServerUrl.ToString(), json); var status = JsonConvert.DeserializeObject <IQServerStatus>(json); AuditEnvironment.Info("IQ Server report complete. {0} components with {1} vulnerabilities submitted. Scan status is at: {2}{3}", packages_count, c, IQServerUrl.ToString(), status.statusUrl); return(true); }
public override Task <bool> ReportPackageSourceAudit() { if (!AuditOptions.ContainsKey("BitBucketReportAccount") || !AuditOptions.ContainsKey("BitBucketReportName") || !AuditOptions.ContainsKey("BitBucketKey")) { throw new ArgumentException("The BitBucketReportAccount, BitBucketReportName, and BitBucketReportKey audit options must be present."); } string key = (string)AuditOptions["BitBucketKey"]; string[] k = key.Split('|'); if (k.Count() != 2) { throw new ArgumentException("The BitBucketReportKey audit option must have the format consumer_key|secret."); } string consumer = k[0], secret = k[1]; string account = (string)AuditOptions["BitBucketReportAccount"]; string repository = (string)AuditOptions["BitBucketReportName"]; if (AuditOptions.ContainsKey("BitBucketReportTitle")) { IssueTitle = (string)AuditOptions["BitBucketReportTitle"]; } else { IssueTitle = string.Format("[DevAudit] {0} audit on {1} {2}", Source.PackageManagerLabel, DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString()); } SharpBucketV2 sharp_bucket = new SharpBucketV2(); sharp_bucket.OAuth2LeggedAuthentication(consumer, secret); RepositoriesEndPoint repository_endpoint = sharp_bucket.RepositoriesEndPoint(account, repository); IssuesResource r; try { r = repository_endpoint.IssuesResource(); } catch (Exception e) { AuditEnvironment.Error(e, "Could not get issues resource for repository {0}/{1}.", account, repository); return(Task.FromResult(false)); } BuildPackageSourceAuditReport(); Issue issue = new Issue() { title = IssueTitle, content = IssueText.ToString(), status = "new", priority = "major", kind = "bug" }; try { Issue i = r.PostIssue(issue); if (i == null) { AuditEnvironment.Error("Could not post issue to repository {0}/{1}.", account, repository); return(Task.FromResult(false)); } else { AuditEnvironment.Success("Created issue {0} at {1}.", i.title, i.resource_uri); } } catch (Exception e) { AuditEnvironment.Error(e, "Could not post issue to repository {0}/{1}.", account, repository); return(Task.FromResult(false)); } return(Task.FromResult(true)); }