2021-02-06 22:36:34 +01:00
|
|
|
const glob = require("fast-glob");
|
|
|
|
const fs = require("fs");
|
2021-03-07 11:02:36 +01:00
|
|
|
const { pathToObject } = require("./crawler/sites-parser.js");
|
2021-02-06 22:36:34 +01:00
|
|
|
|
2021-02-13 11:44:11 +01:00
|
|
|
// Valor arbitrariamente alto para marcar webs con resultados pendientes
|
|
|
|
// y que aparezcan al final al ordenar de menos a más seguro.
|
|
|
|
const NO_SCORE = 9000;
|
|
|
|
|
2021-03-07 11:02:36 +01:00
|
|
|
// Fecha de lanzamiento de la plataforma en Unix timestamp.
|
|
|
|
const UNIX_TIME_RELEASE_DATE = 1611183600;
|
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
const getSafeScore = (value) => {
|
|
|
|
let safe = value.filter((v) => v.score > 69 && v.score < NO_SCORE).length;
|
|
|
|
let safeScore = (safe * 100) / value.length;
|
|
|
|
return safeScore.toFixed(0);
|
|
|
|
};
|
|
|
|
|
2021-07-22 13:38:40 +02:00
|
|
|
const getEmailScore = (value) => {
|
2021-07-22 19:38:45 +02:00
|
|
|
let safe = Object.values(value).filter((v) => v.spf.valid === true && v.dmarc.valid === true && v.dmarc.record.includes('p=reject')).length;
|
2021-07-22 21:35:06 +02:00
|
|
|
let emailScore = (safe * 100) / Object.values(value).length;
|
|
|
|
return emailScore.toFixed(0);
|
2021-07-22 13:38:40 +02:00
|
|
|
};
|
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
const filterByTerritorioId = (value, territorio_id) =>
|
|
|
|
value.filter((v) => v.territorio_id === territorio_id);
|
|
|
|
|
|
|
|
const filenameToData = (f) => ({
|
|
|
|
file: JSON.parse(fs.readFileSync(f, "utf8")),
|
|
|
|
id: /^_data.*\/(.*)\.json$/.exec(f)[1],
|
|
|
|
});
|
|
|
|
|
2021-02-06 22:36:34 +01:00
|
|
|
(function createGlobalDataFile() {
|
2021-02-13 21:26:38 +01:00
|
|
|
const territoriesLevel1 = glob.sync("_data/comunidades/*.json");
|
|
|
|
const territoriesLevel2 = glob.sync("_data/provincias/*.json");
|
|
|
|
|
|
|
|
const files = [
|
|
|
|
...territoriesLevel1,
|
|
|
|
...territoriesLevel2,
|
2021-02-06 22:36:34 +01:00
|
|
|
"_data/general.json",
|
2021-02-13 21:26:38 +01:00
|
|
|
];
|
|
|
|
|
2021-03-07 21:01:31 +01:00
|
|
|
const twitterSummary = JSON.parse(
|
|
|
|
fs.readFileSync(`_data/twitter/summary.json`, "utf8")
|
|
|
|
);
|
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
const all = files
|
|
|
|
.map(filenameToData)
|
|
|
|
.map(({ file, id }) => ({
|
|
|
|
territorio_id: id,
|
2021-02-06 22:36:34 +01:00
|
|
|
territorio: file.name,
|
|
|
|
webs: file.webs,
|
|
|
|
}))
|
|
|
|
.map(({ territorio_id, territorio, webs }) =>
|
2021-02-12 14:30:49 +01:00
|
|
|
webs.map((web) => ({
|
2021-02-06 22:36:34 +01:00
|
|
|
territorio_id,
|
|
|
|
territorio,
|
2021-02-12 14:30:49 +01:00
|
|
|
url: web.url,
|
|
|
|
name: web.name,
|
|
|
|
twitter: web.twitter,
|
2021-03-07 21:01:31 +01:00
|
|
|
twitter_mentions: twitterSummary[web.twitter] || 0,
|
2021-02-13 21:26:38 +01:00
|
|
|
tags: web.tags,
|
2021-02-06 22:36:34 +01:00
|
|
|
}))
|
|
|
|
)
|
|
|
|
.flat()
|
2021-02-07 16:23:12 +01:00
|
|
|
.map((obj) => {
|
|
|
|
let results;
|
|
|
|
try {
|
|
|
|
results = JSON.parse(
|
2021-07-27 00:51:42 +02:00
|
|
|
fs.readFileSync(`_data/results/${obj.url.replace(/\./g, "!")}.json`, "utf8")
|
2021-02-07 16:23:12 +01:00
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
// Los resultados aún no están disponibles.
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
...obj,
|
|
|
|
results,
|
|
|
|
};
|
|
|
|
})
|
2021-02-06 22:36:34 +01:00
|
|
|
.map((obj) => ({
|
|
|
|
...obj,
|
2021-02-07 16:23:12 +01:00
|
|
|
grade: obj.results?.grade,
|
2021-02-13 11:44:11 +01:00
|
|
|
score: obj.results?.score ?? NO_SCORE,
|
2021-02-07 16:23:12 +01:00
|
|
|
tests_passed: obj.results?.tests_passed,
|
2021-02-17 22:43:27 +01:00
|
|
|
tests_failed: obj.results?.tests_failed,
|
|
|
|
tests_quantity: obj.results?.tests_quantity,
|
2021-02-07 16:23:12 +01:00
|
|
|
state: obj.results?.state,
|
2021-02-06 22:36:34 +01:00
|
|
|
}));
|
|
|
|
|
|
|
|
fs.writeFileSync("_data/all.json", JSON.stringify(all));
|
2021-02-13 21:26:38 +01:00
|
|
|
|
|
|
|
const territories = territoriesLevel1
|
|
|
|
.map(filenameToData)
|
|
|
|
.map(({ file, id }) => ({
|
|
|
|
name: file.name,
|
|
|
|
id,
|
|
|
|
}))
|
|
|
|
.map(({ name, id }) => ({
|
|
|
|
name,
|
|
|
|
id,
|
|
|
|
safeScore: getSafeScore(filterByTerritorioId(all, id)),
|
|
|
|
subTerritories: territoriesLevel2
|
|
|
|
.map(filenameToData)
|
|
|
|
.filter(({ file }) => id === file.comunidad)
|
|
|
|
.map(({ file, id }) => ({ id, ...file }))
|
|
|
|
.map(({ name, id }) => ({
|
|
|
|
name,
|
2021-02-21 10:31:43 +01:00
|
|
|
id,
|
2021-02-13 21:26:38 +01:00
|
|
|
safeScore: getSafeScore(filterByTerritorioId(all, id)),
|
|
|
|
})),
|
|
|
|
}));
|
|
|
|
|
|
|
|
fs.writeFileSync("_data/territories.json", JSON.stringify(territories));
|
2021-02-06 22:36:34 +01:00
|
|
|
})();
|
|
|
|
|
2021-03-07 11:02:36 +01:00
|
|
|
(function createProgressFile() {
|
|
|
|
const historyDir = "_data/results/history";
|
|
|
|
let websWithProgress = glob
|
|
|
|
.sync(historyDir + "/*.json")
|
|
|
|
.map((path) => ({ path, file: pathToObject(path) }))
|
|
|
|
.filter(({ file }) => Array.isArray(file))
|
|
|
|
.map(({ path, file }) => ({
|
|
|
|
path,
|
|
|
|
file: file.filter(
|
|
|
|
(check) => check.end_time_unix_timestamp > UNIX_TIME_RELEASE_DATE
|
|
|
|
),
|
|
|
|
}))
|
|
|
|
.filter(({ file }) => file.length >= 2)
|
|
|
|
.map(({ path, file }) => ({
|
|
|
|
file,
|
|
|
|
path: path.substring(historyDir.length + 1),
|
|
|
|
}));
|
|
|
|
|
|
|
|
for (const { path, file } of websWithProgress) {
|
|
|
|
fs.writeFileSync(`_data/results/progress/${path}`, JSON.stringify(file));
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2021-07-27 00:51:42 +02:00
|
|
|
function createEmailSummaryFile() {
|
|
|
|
const result = {};
|
|
|
|
const sites = glob.sync("_data/results/dmarc/*.json");
|
|
|
|
for (const site of sites) {
|
|
|
|
const siteData = fs.readFileSync(site, "utf8");
|
|
|
|
if (siteData.length > 0) { // sites where dmarc analysis was not possible are empty
|
|
|
|
const siteName = /^_data\/results\/dmarc\/(.*)\.json$/.exec(site)[1].replace(/!/g, ".");
|
|
|
|
const siteData = JSON.parse(fs.readFileSync(site, "utf8"));
|
|
|
|
result[siteName] = siteData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
2021-01-13 22:31:38 +01:00
|
|
|
module.exports = function (eleventyConfig) {
|
2021-01-14 20:04:41 +01:00
|
|
|
eleventyConfig.addPassthroughCopy("assets");
|
|
|
|
eleventyConfig.addPassthroughCopy("images");
|
2021-01-16 18:03:36 +01:00
|
|
|
|
2021-01-18 17:21:18 +01:00
|
|
|
eleventyConfig.addFilter("color", (security) => {
|
2021-01-28 19:37:25 +01:00
|
|
|
if (security.tests_passed < 5) {
|
|
|
|
return "danger";
|
|
|
|
}
|
|
|
|
|
2021-01-25 13:39:16 +01:00
|
|
|
switch (security && security.grade && security.grade[0]) {
|
2021-02-06 22:36:34 +01:00
|
|
|
case "A":
|
|
|
|
case "B":
|
2021-01-20 19:07:52 +01:00
|
|
|
return "safe";
|
2021-02-06 22:36:34 +01:00
|
|
|
case "C":
|
|
|
|
case "D":
|
|
|
|
return "moderate";
|
|
|
|
case "E":
|
|
|
|
case "F":
|
|
|
|
return "severe";
|
2021-01-18 17:21:18 +01:00
|
|
|
default:
|
2021-01-20 19:08:52 +01:00
|
|
|
return "unknown";
|
2021-01-18 17:21:18 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
eleventyConfig.addFilter("abbr", (security) => {
|
|
|
|
let abbr = "";
|
2021-01-25 13:39:16 +01:00
|
|
|
switch (security && security.grade && security.grade[0]) {
|
2021-02-06 22:36:34 +01:00
|
|
|
case "A":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web es muy segura.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
2021-02-06 22:36:34 +01:00
|
|
|
case "B":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web es segura.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
2021-02-06 22:36:34 +01:00
|
|
|
case "C":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web podría mejorar su seguridad.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
2021-02-06 22:36:34 +01:00
|
|
|
case "D":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web debería mejorar su seguridad.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
2021-02-06 22:36:34 +01:00
|
|
|
case "E":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web es insegura.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
2021-02-06 22:36:34 +01:00
|
|
|
case "F":
|
2021-07-22 18:39:13 +02:00
|
|
|
abbr = "La web es muy insegura.";
|
2021-01-18 17:21:18 +01:00
|
|
|
break;
|
|
|
|
default:
|
2021-01-18 17:43:58 +01:00
|
|
|
return "Desconocido.";
|
2021-01-16 18:03:36 +01:00
|
|
|
}
|
2021-01-18 17:21:18 +01:00
|
|
|
|
2021-02-01 23:05:25 +01:00
|
|
|
abbr += ` Pasó ${security.tests_passed} de las ${security.tests_quantity} comprobaciones realizadas`;
|
2021-01-18 17:21:18 +01:00
|
|
|
return abbr;
|
2021-01-16 18:03:36 +01:00
|
|
|
});
|
2021-01-16 20:17:40 +01:00
|
|
|
|
2021-02-06 23:09:38 +01:00
|
|
|
eleventyConfig.addFilter("urlEncode", (value) => encodeURIComponent(value));
|
2021-02-06 22:36:34 +01:00
|
|
|
|
2021-02-06 23:09:38 +01:00
|
|
|
eleventyConfig.addFilter("testsPassedLt", (value, testsPassed) =>
|
|
|
|
value.filter((v) => v.tests_passed < testsPassed)
|
|
|
|
);
|
2021-02-06 22:36:34 +01:00
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
eleventyConfig.addFilter("scoreGt", (value, score) =>
|
|
|
|
value.filter((v) => v.score > score && v.score < NO_SCORE)
|
2021-02-13 11:44:11 +01:00
|
|
|
);
|
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
eleventyConfig.addFilter("tagged", (value, tag) =>
|
|
|
|
value.filter((v) => {
|
2021-02-13 11:44:11 +01:00
|
|
|
return v.tags && v.tags.indexOf(tag.name) >= 0;
|
|
|
|
})
|
2021-02-06 23:09:38 +01:00
|
|
|
);
|
|
|
|
|
2021-07-27 00:51:42 +02:00
|
|
|
const dmarcSummary = createEmailSummaryFile();
|
|
|
|
// make the dmarc summary available to the templates instead of writing it to disk
|
|
|
|
eleventyConfig.addCollection("dmarcSummary", () => dmarcSummary);
|
|
|
|
|
2021-07-22 13:38:40 +02:00
|
|
|
// Filters values with DMARC and SPF with specific valid option (true or false)
|
|
|
|
// Only values where SPF AND DMARC is valid, are considered valid
|
|
|
|
// Values where SPF OR DMARC is not valid, are considered invalid
|
2021-07-22 19:38:45 +02:00
|
|
|
// Only policy p=reject is considered valid/secure
|
2021-07-27 00:51:42 +02:00
|
|
|
eleventyConfig.addFilter("dmarc_valid", (value, valid=true) => {
|
|
|
|
const dmarcFilter = valid
|
|
|
|
? (web) => { const v = dmarcSummary[web.url]; return v.spf.valid === valid && v.dmarc.valid === valid && v.dmarc.record.includes('p=reject') }
|
|
|
|
: (web) => { const v = dmarcSummary[web.url]; return v.spf.valid === valid || v.dmarc.valid === valid || !v.dmarc.record.includes('p=reject') };
|
2021-07-22 21:35:06 +02:00
|
|
|
|
2021-07-27 00:51:42 +02:00
|
|
|
return value.filter(web => dmarcSummary[web.url])
|
|
|
|
.filter(dmarcFilter);
|
2021-07-22 21:35:06 +02:00
|
|
|
});
|
2021-07-22 13:38:40 +02:00
|
|
|
|
2021-07-21 21:54:37 +02:00
|
|
|
eleventyConfig.addFilter("dmarc_secure", (url) => {
|
|
|
|
const dmarc_info = dmarcSummary[url];
|
2021-07-22 21:35:06 +02:00
|
|
|
if (dmarc_info) {
|
|
|
|
return dmarc_info.spf.valid === true &&
|
|
|
|
dmarc_info.dmarc.valid === true &&
|
|
|
|
dmarc_info.dmarc.record.includes('p=reject');
|
|
|
|
}
|
2021-07-21 21:54:37 +02:00
|
|
|
});
|
|
|
|
|
2021-07-22 18:39:13 +02:00
|
|
|
eleventyConfig.addFilter("dnssec", (url) => {
|
|
|
|
const dmarc_info = dmarcSummary[url];
|
2021-07-22 21:35:06 +02:00
|
|
|
if (dmarc_info) {
|
|
|
|
return dmarc_info.dnssec;
|
|
|
|
}
|
2021-07-22 18:39:13 +02:00
|
|
|
});
|
|
|
|
|
2021-07-27 00:51:42 +02:00
|
|
|
eleventyConfig.addFilter("canonical", (url) => {
|
|
|
|
return url.replace(/^www\./, "")
|
|
|
|
.replace("http:", "")
|
|
|
|
.replace("https:", "")
|
|
|
|
.replace("/", "");
|
|
|
|
});
|
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
// % de webs seguras
|
|
|
|
eleventyConfig.addFilter("safeScore", getSafeScore);
|
2021-07-27 00:51:42 +02:00
|
|
|
|
2021-07-22 13:38:40 +02:00
|
|
|
// % de emails protegidos
|
|
|
|
eleventyConfig.addFilter("emailScore", getEmailScore);
|
2021-02-13 21:26:38 +01:00
|
|
|
|
|
|
|
eleventyConfig.addFilter("filterByTerritorioId", filterByTerritorioId);
|
2021-02-08 14:52:37 +01:00
|
|
|
|
2021-02-13 21:26:38 +01:00
|
|
|
eleventyConfig.addFilter("getSubTerritories", (value) =>
|
|
|
|
value.reduce(
|
|
|
|
(previous, current) => [...previous, ...current.subTerritories],
|
|
|
|
[]
|
|
|
|
)
|
2021-02-06 23:09:38 +01:00
|
|
|
);
|
2021-01-13 22:31:38 +01:00
|
|
|
};
|