Files
2026-09-15 14:20:42 +02:00

110 lines
3.3 KiB
Python
Executable File

#!/usr/bin/env python
from tqdm import tqdm
import jinja2
import yaml
import json
from os.path import splitext, join
from os import listdir
from datetime import date
OUTPUT_ROOT = "output/"
CCSA_DIR ="CCSA/"
HTML_OUTPUT_DIR = "html/"
RSS_FEED = "rss.xml"
JSON_CATALOG = "CCSA.json"
BASE_URL = "https://0x29a.codeberg.pages/CCSA-DEMO/"
ccsa_html_template = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Co-op Cloud Security Advisory (DEMO) {{ ccsa_id }}</title>
</head>
<body>
<article>
<h1>Co-op Cloud Security Advisory (DEMO) {{ ccsa_id }}</h1>
<p><b>Recipe:</b>: {{ recipe }}</p>
<p><b>Affected Versions:</b> {% for version in versions %}<br/>{{ version }}{% endfor %}</p>
<p><b>Affected Images:</b> {% for image in images %}<br/>{{ image }}{% endfor %}</p>
<p><b>Upgrade paths:</b> {% for upgrade in upgrade_paths %}<br/>{{ upgrade }}{% endfor %}</p>
<p><b>Description:</b><br/>{{ description }}</p>
</article>
</body>
</html>"""
ccsa_html_index_template = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Co-op Cloud Security Advisories</title>
</head>
<body>
<h1>Co-op Cloud Security Advisories</h1>
{% for ccsa in ccsas %}
<article>
<p><a href="{{ ccsa.ccsa_id }}.html">{{ ccsa.ccsa_id }}</a>: {{ ccsa.recipe }} {{ ccsa.short }}</p>
</article>
{% endfor %}
</body>
</html>"""
ccsa_rss_template = """<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Co-op Cloud Security Advisories (DEMO)</title>
<link>{{ base_url }}</link>
<description>Running feed of Security Advisories related to Co-op Cloud</description>
{% for ccsa in ccsas %}
<item>
<title>{{ ccsa.ccsa_id }}</title>
<link>{{ ccsa.url }}</link>
<description>{{ ccsa.recipe }} {{ ccsa.short }} {% for upgrade in ccsa.upgrade_paths %} <br/>{{ upgrade }} {% endfor %}</description>
<pubDate>{{ ccsa.date }}</pubDate>
</item>
{% endfor %}
</channel>
</rss>
"""
class ForceDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, date):
return str(obj)
return super().default(obj)
environment = jinja2.Environment()
html_template = environment.from_string(ccsa_html_template)
rss_template = environment.from_string(ccsa_rss_template)
index_template = environment.from_string(ccsa_html_index_template)
ccsas = []
print("parsing CCSAs and writing html advisories")
for f in tqdm(listdir(CCSA_DIR)):
ccsa_yml_path = join(CCSA_DIR, f)
with open(ccsa_yml_path) as fd:
ccsa = yaml.safe_load(fd.read())
ccsa["ccsa_id"] = splitext(f)[0]
html_file_name = f'{ccsa["ccsa_id"]}.html'
ccsa["url"] = f"{BASE_URL}/{html_file_name}"
ccsa["upgrade_paths"] = [f"{v} -> {u}" for v,u in zip(ccsa["versions"], ccsa["upgrade_to"])]
with open(join(OUTPUT_ROOT, html_file_name), "w") as fd:
fd.write(html_template.render(base_url=BASE_URL, **ccsa))
ccsas.append(ccsa)
print("creating RSS feed")
with open(join(OUTPUT_ROOT, RSS_FEED), "w") as fd:
fd.write(rss_template.render(base_url=BASE_URL, ccsas=ccsas))
print("creating json catalog")
with open(join(OUTPUT_ROOT, JSON_CATALOG), "w") as fd:
fd.write(json.dumps(ccsas, cls=ForceDateTimeEncoder))
print("creating index")
with open(join(OUTPUT_ROOT, "index.html"), "w") as fd:
fd.write(index_template.render(ccsas=ccsas))
print("complete")