Add some CI for security testing
Some checks failed
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 16s
Datadog Static Analysis / Datadog Static Analyzer (push) Failing after 0s

This commit is contained in:
Tanishq Dubey 2025-02-20 20:58:44 -05:00
parent b2ed4cc4e5
commit 0a3abf439f
5 changed files with 144 additions and 39 deletions

View File

@ -0,0 +1,18 @@
on: [push]
name: Datadog Software Composition Analysis
jobs:
software-composition-analysis:
runs-on: ubuntu-latest
name: Datadog SBOM Generation and Upload
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check imported libraries are secure and compliant
id: datadog-software-composition-analysis
uses: DataDog/datadog-sca-github-action@main
with:
dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: datadoghq.com

View File

@ -0,0 +1,19 @@
on: [push]
name: Datadog Static Analysis
jobs:
static-analysis:
runs-on: ubuntu-latest
name: Datadog Static Analyzer
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check code meets quality and security standards
id: datadog-static-analysis
uses: DataDog/datadog-static-analyzer-github-action@v1
with:
dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: datadoghq.com
cpu_count: 2

View File

@ -1,32 +1,39 @@
from dataclasses import dataclass
from src.config.config import Configuration
from src.rendering import GENERIC_FILE_MAPPING
from src.rendering.markdown import render_markdown
from enum import Enum
from thumbhash import image_to_thumbhash
from PIL import Image
from datetime import datetime
import frontmatter
@dataclass
class ImageMetadata:
path: str
width: int
height: int
alt: str
thumbhash: str
# exif attributes
exif: dict
@dataclass
class MarkdownMetadata:
fontmatter: dict
content: str
preview: str
@dataclass
class FileMetadata:
path: str
first_hundred_chars: str
typeMeta: MarkdownMetadata | None
@dataclass
class TemplateFile:
name: str
path: str
proper_name: str
extension: str
categories: list[str]
date_modified: str
@ -37,10 +44,47 @@ class TemplateFile:
is_dir: bool
def format_date(timestamp):
return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d")
class TemplateHelpers:
def __init__(self, config: Configuration):
self.config: Configuration = config
def build_metadata_for_file(self, path: str, categories: list[str] = []):
"""Builds metadata for a file"""
file_path = self.config.content_dir / path
for k in categories:
if k == "image":
img = Image.open(file_path)
exif = img._getexif()
orientation = exif.get(274, 1) if exif else 1
width, height = img.width, img.height
if orientation in [5, 6, 7, 8]:
width, height = height, width
return ImageMetadata(
width=width,
height=height,
alt=file_path.name,
exif=img.info,
)
elif k == "document":
ret = None
with open(file_path, "r") as fdoc:
ret = FileMetadata(None)
if file_path.suffix[1:].lower() == "md":
ret.typeMeta = MarkdownMetadata({}, "", "")
ret.typeMeta.fontmatter = frontmatter.load(file_path)
ret.typeMeta.content = render_markdown(file_path)
ret.typeMeta.preview = ret.typeMeta.content[:100]
if "#" in ret.typeMeta.preview:
ret.typeMeta.preview = ret.typeMeta.preview.split("#")[0]
return ret
return None
def get_folder_contents(self, path: str = ""):
"""Returns the contents of a folder as a list of TemplateFile objects
@ -52,45 +96,25 @@ class TemplateHelpers:
for f in files:
t = TemplateFile(
name=f.name,
path=str(f.relative_to(self.config.content_dir)),
proper_name=f.stem,
extension=f.suffix.lower(),
categories=[],
date_modified=f.stat().st_mtime,
date_created=f.stat().st_ctime,
date_modified=format_date(f.stat().st_mtime),
date_created=format_date(f.stat().st_ctime),
size_kb=f.stat().st_size / 1024,
metadata=None,
dir_item_count=len(list(f.glob("*"))) if f.is_dir() else 0,
is_dir=f.is_dir(),
)
if f.is_file():
# Build metadata depending on the mapping in GENERIC_FILE_MAPPING
for k, v in GENERIC_FILE_MAPPING.items():
if f.suffix[1:].lower() in v:
t.categories.append(k)
if k == "image":
img = Image.open(f)
exif = img._getexif()
orientation = exif.get(274, 1) if exif else 1
width, height = img.width, img.height
if orientation in [5, 6, 7, 8]:
width, height = height, width
t.metadata = ImageMetadata(
path=str(f.relative_to(self.config.content_dir)),
width=width,
height=height,
alt=f.name,
thumbhash=image_to_thumbhash(img),
exif=img.info,
)
elif k == "document":
with open(f, "r") as fdoc:
t.metadata = FileMetadata(
path=str(f.relative_to(self.config.content_dir)),
first_hundred_chars=fdoc.read(100),
)
t.metadata = self.build_metadata_for_file(f, t.categories)
ret.append(t)
return ret
def get_sibling_content_files(self, path: str = ""):
search_contnet_path = self.config.content_dir / path
files = search_contnet_path.glob("*")

View File

@ -43,4 +43,4 @@ def generate_thumbnail(image_path, resize_percent, min_width):
img.save(thumbnail_io, format=img_format)
thumbnail_io.seek(0)
return (thumbnail_io, img_format)
return (thumbnail_io.getvalue(), img_format)

View File

@ -10,7 +10,39 @@ class RouteManager:
def __init__(self, config: Configuration):
self.config = config
def _ensure_route(self, path: str):
"""
Escapes the path for anything like
a path execution or injection attack
evaluates the path and ensures that it it does not
go above the self.content.content_dir
If any part of the path contains __, __{foldername}, or __{filename},
that is a hidden file or folder and should raise an exception
Any illegal path should raise an exception
"""
file_path: Path = self.config.content_dir / (path if path else "index.md")
print(file_path)
if file_path < self.config.content_dir:
raise Exception("Illegal path")
for part in file_path.parts:
if part.startswith("__"):
raise Exception("Illegal path")
def default_route(self, path: str):
try:
self._ensure_route(path)
print("all good")
print(path)
print("=============")
except Exception as e:
print(e)
return render_error_page(
403,
"Forbidden",
"You do not have permission to access this resource.",
self.config.templates_dir,
)
file_path: Path = self.config.content_dir / (path if path else "index.md")
return render_page(
file_path,
@ -24,20 +56,32 @@ class RouteManager:
if file_path.exists():
return send_file(file_path)
else:
return render_error_page(404, "Not Found", "The requested resource was not found on this server.", self.config.templates_dir)
return render_error_page(
404,
"Not Found",
"The requested resource was not found on this server.",
self.config.templates_dir,
)
@lru_cache(maxsize=128)
@lru_cache(maxsize=None)
def get_static(self, path: str):
file_path: Path = self.config.content_dir / path
if file_path.exists():
# Check to see if the file is an image, if it is, render a thumbnail
if file_path.suffix.lower() in [".jpg", ".jpeg", ".png", ".gif"]:
thumbnail_bytes, img_format = generate_thumbnail(str(file_path), 10, 300)
thumbnail_bytes, img_format = generate_thumbnail(
str(file_path), 10, 2048
)
return (
thumbnail_bytes.getvalue(),
thumbnail_bytes,
200,
{"Content-Type": f"image/{img_format.lower()}"},
)
return send_file(file_path)
else:
return render_error_page(404, "Not Found", "The requested resource was not found on this server.", self.config.templates_dir)
return render_error_page(
404,
"Not Found",
"The requested resource was not found on this server.",
self.config.templates_dir,
)