in amazon-inspector-image-scanner/amazon-inspector-image-scanner-agent/src/main/java/com/amazon/inspector/teamcity/ScanBuildProcessAdapter.java [96:249]
private void ScanRequestHandler(Map<String, String> runnerParameters) throws Exception {
String teamcityDirPath = build.getCheckoutDirectory().getAbsolutePath();
String sbomgenPath = runnerParameters.get(SBOMGEN_PATH);
String sbomgenSource = runnerParameters.get(SBOMGEN_SELECTION);
String archivePath = runnerParameters.get(ARCHIVE_PATH);
String dockerUsername = runnerParameters.get(DOCKER_USERNAME);
String dockerPassword = runnerParameters.get(DOCKER_PASSWORD);
String roleArn = runnerParameters.get(ROLE_ARN);
String region = runnerParameters.get(REGION);
String awsAccessKeyId = runnerParameters.get(AWS_ACCESS_KEY_ID);
String awsSecretKey = runnerParameters.get(AWS_SECRET_KEY);
String awsProfileName = runnerParameters.get(AWS_PROFILE_NAME);
boolean isThresholdEnabled = Boolean.parseBoolean(runnerParameters.get(IS_THRESHOLD_ENABLED));
publicProgressLogger.message("Threshold: " + isThresholdEnabled);
String activeSbomgenPath = sbomgenPath;
if (null != sbomgenSource && !sbomgenSource.equals("manual")) {
publicProgressLogger.message("Automatic SBOMGen Sourcing selected, downloading now...");
activeSbomgenPath = SbomgenDownloader.getBinary(sbomgenSource);
} else {
publicProgressLogger.message("Using manually provided path to inspector-sbomgen.");
}
String sbom = new SbomgenRunner(activeSbomgenPath, archivePath, dockerUsername, dockerPassword).run();
JsonElement metadata = JsonParser.parseString(sbom).getAsJsonObject().get("metadata");
JsonObject component = null;
if (metadata != null && metadata.getAsJsonObject().get("component") != null) {
component = metadata.getAsJsonObject().get("component").getAsJsonObject();
}
String imageSha = getImageSha(sbom);
publicProgressLogger.message("Sending SBOM to Inspector for validation");
AmazonWebServicesCredentials awsCredentials = null;
if ((awsAccessKeyId != null && !awsAccessKeyId.isEmpty()) && (awsSecretKey != null && !awsSecretKey.isEmpty())) {
awsCredentials = AmazonWebServicesCredentials.builder()
.AWSAccessKeyId(awsAccessKeyId)
.AWSSecretKey(awsSecretKey)
.build();
}
String responseData = new SdkRequests(region, awsCredentials, awsProfileName, roleArn).requestSbom(sbom);
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
SbomData sbomData = SbomData.builder().sbom(gson.fromJson(responseData, Sbom.class)).build();
String sbomFileName = String.format("%s-%s-sbom.json", build.getProjectName(),
build.getBuildNumber()).replaceAll("[ #]", "");
String sbomPath = String.format("%s/%s", teamcityDirPath, sbomFileName);
writeSbomDataToFile(gson.toJson(sbomData.getSbom()), sbomPath);
CsvConverter converter = new CsvConverter(sbomData);
String csvVulnFileName = String.format("%s-%s-vuln.csv", build.getProjectName(),
build.getBuildNumber()).replaceAll("[ #]", "");
String csvDockerFileName = String.format("%s-%s-docker.csv", build.getProjectName(),
build.getBuildNumber()).replaceAll("[ #]", "");
String csvVulnPath = String.format("%s/%s", teamcityDirPath, csvVulnFileName);
String csvDockerPath = String.format("%s/%s", teamcityDirPath, csvDockerFileName);
progressLogger.message("Converting SBOM Results to CSV.");
SbomOutputParser parser = new SbomOutputParser(sbomData);
parser.parseVulnCounts();
String sanitizedArchiveName = null;
String componentName = null;
if (component != null && component.get("name") != null) {
componentName = component.get("name").getAsString();
}
if (componentName != null && componentName.endsWith(".tar")) {
sanitizedArchiveName = sanitizeFilePath("file://" + componentName);
} else {
sanitizedArchiveName = archivePath;
}
converter.routeVulnerabilities();
String csvVulnContent = converter.convertVulnerabilities(sanitizedArchiveName, imageSha, runnerParameters.get("teamcity.build.id"), SbomOutputParser.vulnCounts);
if (csvVulnContent != null) {
FileUtils.writeStringToFile(new File(csvVulnPath), csvVulnContent);
artifactsWatcher.addNewArtifactsPath(csvVulnPath);
}
String csvDockerContent = converter.convertDocker(sanitizedArchiveName, imageSha, runnerParameters.get("teamcity.build.id"), SbomOutputParser.dockerCounts);
if (csvDockerContent != null) {
FileUtils.writeStringToFile(new File(csvDockerPath), csvDockerContent);
artifactsWatcher.addNewArtifactsPath(csvDockerPath);
}
String[] splitName = sanitizedArchiveName.split(":");
String tag = null;
if (splitName.length > 1) {
tag = splitName[1];
}
String baseUrl = buildBaseUrl();
String sbomUrl = sanitizeUrl(String.format("%s/%s", baseUrl, sbomFileName));
String vulnCsvUrl = sanitizeUrl(String.format("%s/%s", baseUrl, csvVulnFileName));
String dockerCsvUrl = sanitizeUrl(String.format("%s/%s", baseUrl, csvDockerFileName));
String artifactsUrl = baseUrl.replace(":id", "?buildTab=artifacts").replace("repository/download", "buildConfiguration");
HtmlData htmlData = HtmlData.builder()
.artifactsPath(artifactsUrl)
.updatedAt(new SimpleDateFormat("MM/dd/yyyy, hh:mm:ss aa").format(Calendar.getInstance().getTime()))
.imageMetadata(ImageMetadata.builder()
.id(splitName[0])
.tags(tag)
.sha(imageSha)
.build())
.docker(HtmlConversionUtils.convertDocker(sbomData.getSbom().getVulnerabilities(),
sbomData.getSbom().getComponents()))
.vulnerabilities(HtmlConversionUtils.convertVulnerabilities(sbomData.getSbom().getVulnerabilities(),
sbomData.getSbom().getComponents()))
.build();
String htmlJarPath = new File(HtmlJarHandler.class.getProtectionDomain().getCodeSource().getLocation()
.toURI()).getPath();
HtmlJarHandler htmlJarHandler = new HtmlJarHandler(htmlJarPath);
String htmlPath = htmlJarHandler.copyHtmlToDir(teamcityDirPath);
String html = gson.toJson(htmlData);
new HtmlGenerator(htmlPath).generateNewHtml(html);
artifactsWatcher.addNewArtifactsPath(htmlPath);
artifactsWatcher.addNewArtifactsPath(sbomPath);
String serverUrl = String.format("http://%s",
build.getSharedBuildParameters().getAllParameters().get("env.BUILD_URL").split("/")[2]);
progressLogger.message("Prefixing file paths with the Server URL from settings, currently: " + serverUrl);
progressLogger.message("Build Artifacts: " + baseUrl.replace(":id", "?buildTab=artifacts").replace("repository/download", "buildConfiguration"));
progressLogger.message("Files can also be downloaded from the artifacts tab.");
progressLogger.message(SbomOutputParser.aggregateCounts.toString());
boolean doesBuildPass = true;
if (!isThresholdEnabled) {
progressLogger.message("Ignoring results due to thresholds being disabled.");
} else {
doesBuildPass = !doesBuildFail(SbomOutputParser.aggregateCounts.getCounts());
}
if (!isThresholdEnabled) {
scanRequestSuccessHandler();
} else if (isThresholdEnabled && doesBuildPass) {
scanRequestSuccessHandler();
} else {
scanRequestFailureHandler();
}
}