Skip to content

Instantly share code, notes, and snippets.

@greenido
Last active February 26, 2024 12:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greenido/e2eceff5ea69fa94a84c74ed308bd74a to your computer and use it in GitHub Desktop.
Save greenido/e2eceff5ea69fa94a84c74ed308bd74a to your computer and use it in GitHub Desktop.
Fetch JFrog Xray violations into CSV so you can use them in an external monitoring/logging tool
//
// Fetch Xray Data into CSV and later any DB/Logging/Monitoring tool you wish.
//
// @author: Ido Green | @greenido
// @date: March 2020
//
// @see:
// https://greenido.wordpress.com/2019/12/04/how-to-build-an-integration-with-jfrog-xray/
// https://greenido.wordpress.com/2020/02/12/continuous-software-updates/
//
// https://csvkit.readthedocs.io/en/latest/
//
// init project
const fs = require("fs");
var request = require("request");
require('dotenv').config()
// TODO: change these values in your .env file to meet your credentials
const BASE_URL = process.env.BASE_URL;
const USERNAME = process.env.XRAY_USER;
const PASSWORD = process.env.XRAY_PASS;
//
// Fetch violations from Xray
// TODO: change the 'watch_name' to a watch that is defined at your Xray
//
function fetchViolations() {
// Create the base64 auth string
let auth = 'Basic ' + Buffer.from(USERNAME + ':' + PASSWORD).toString('base64');
// Using the REST API on: /api/v1/violations
// With an example payload for specific watch_name.
var options = {
method: "POST",
url: "http://" + BASE_URL + "/api/v1/violations",
headers: {
"Content-Type": "application/json",
Authorization: auth
},
body: JSON.stringify({
"filters": { "watch_name": "step3-create-docker-image-product" },
"pagination": { "order_by": "updated", "limit": 25, "offset": 1 }
})
};
request(options, function(error, response) {
if (error) {
console.log("😳 ERROR with fetching violations: ");
console.log(error);
return;
}
console.log("Status code: "+ response.statusCode);
if (response.statusCode == 200) {
let resJson = JSON.parse(response.body);
console.log("🏵 Total Violations: " + resJson.total_violations);
console.log("Violations: " + response.body);
// Now let's convert the JSON to CSV and save it
exportJson2Csv(resJson);
}
});
}
//
// Export the JSON to CSV
//
function exportJson2Csv(jsonInput) {
var json = jsonInput.violations;
var fields = [
"description",
"severity",
"type",
"infected_component",
"created",
"watch_name",
"issue_id",
"violation_details_url",
"impacted_artifacts"
];
var replacer = function(key, value) {
if (value === null || value === undefined) {
// handle null cases in Xray response
return "";
} else {
if ( (key.indexOf("infected_component") > -1 ||
key.indexOf("impacted_artifacts" > -1)) &&
Array.isArray(value)) {
// We have an array to save in one cell
value = value.join(" -- ");
return value;
}
else if (key.indexOf("violation_details_url") > -1 ) {
// let's save it in a seperate file so we can run on it later to add more details.
saveDetailedUrl(value);
return value;
}
}
// This will make sure we aren't breaking our CSV
value = value.replace(/,/g, ';');
value = value.replace(/\"/g, "'");
return value;
};
// Building the CSV output
var csv = json.map(function(row) {
return fields
.map(function(fieldName) {
let cellValue = replacer(fieldName, row[fieldName]);
let desc = row[fieldName];
return JSON.stringify(cellValue);
})
.join(",");
});
// Add header column
csv.unshift(fields.join(","));
csv = csv.join("\r\n");
//
// save it to a CSV file
//
let curTime = new Date().getTime();
fs.writeFile("./xray-violations-" + curTime + ".csv", csv, err => {
if (err) {
console.log("😳 Error writing CSV file", err);
} else {
console.log("🥎 Successfully wrote the CSV file");
}
});
}
//
// Saving the details url on a file we can use in the next script (with another process).
//
function saveDetailedUrl(detailUrl) {
fs.appendFile("./xray-violations-details-urls-" + curTime + ".txt", detailUrl + "\n", err => {
if (err) {
console.log("😳 Error writing detailUrl: ", err);
}
// else { console.log("🥎 Successfully wrote detailUrl:" + detailUrl); }
});
}
//
// Let's start the work
//
fetchViolations();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment