Files
gdit-back/models.py

192 lines
6.6 KiB
Python

from datetime import datetime
from enum import Enum
from typing import Optional
from sqlalchemy import (
Boolean,
Column,
DateTime,
ForeignKey,
Integer,
String,
Text,
UniqueConstraint,
create_engine,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
Base = declarative_base()
class VulnerabilitySeverity(Enum):
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
UNSPECIFIED = "unspecified"
class IgnoreType(Enum):
IMAGE = "image"
FILE = "file"
PROJECT = "project"
class Project(Base):
__tablename__ = "projects"
id = Column(Integer, primary_key=True)
gitlab_id = Column(Integer, unique=True, nullable=False)
name = Column(String(255), nullable=False)
path = Column(String(255), nullable=False)
web_url = Column(String(500), nullable=False)
last_scanned = Column(DateTime, nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
files = relationship("File", back_populates="project", cascade="all, delete-orphan")
ignore_rules = relationship(
"IgnoreRule", back_populates="project", cascade="all, delete-orphan"
)
class File(Base):
__tablename__ = "files"
id = Column(Integer, primary_key=True)
project_id = Column(Integer, ForeignKey("projects.id"), nullable=False)
file_path = Column(String(500), nullable=False)
branch = Column(String(100), nullable=False)
file_type = Column(String(50), nullable=False) # docker-compose, dockerfile, gitlab-ci
last_scanned = Column(DateTime, nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
project = relationship("Project", back_populates="files")
image_usages = relationship("FileImageUsage", back_populates="file", cascade="all, delete-orphan")
__table_args__ = (
UniqueConstraint("project_id", "file_path", "branch", name="unique_file_branch"),
)
class Image(Base):
__tablename__ = "images"
id = Column(Integer, primary_key=True)
image_name = Column(String(500), nullable=False)
tag = Column(String(100), nullable=True)
registry = Column(String(255), nullable=True)
full_image_name = Column(String(1000), nullable=False, unique=True)
last_seen = Column(DateTime, default=datetime.utcnow)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
vulnerabilities = relationship(
"Vulnerability", back_populates="image", cascade="all, delete-orphan"
)
file_usages = relationship(
"FileImageUsage", back_populates="image", cascade="all, delete-orphan"
)
class FileImageUsage(Base):
__tablename__ = "file_image_usages"
id = Column(Integer, primary_key=True)
file_id = Column(Integer, ForeignKey("files.id"), nullable=False)
image_id = Column(Integer, ForeignKey("images.id"), nullable=False)
first_seen = Column(DateTime, default=datetime.utcnow)
last_seen = Column(DateTime, default=datetime.utcnow)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
file = relationship("File", back_populates="image_usages")
image = relationship("Image", back_populates="file_usages")
__table_args__ = (
UniqueConstraint("file_id", "image_id", name="unique_file_image"),
)
class Vulnerability(Base):
__tablename__ = "vulnerabilities"
id = Column(Integer, primary_key=True)
image_id = Column(Integer, ForeignKey("images.id"), nullable=False)
scan_job_id = Column(Integer, ForeignKey("scan_jobs.id"), nullable=True)
vulnerability_id = Column(String(100), nullable=False)
severity = Column(String(20), nullable=False)
title = Column(String(500), nullable=True)
description = Column(Text, nullable=True)
cvss_score = Column(String(10), nullable=True)
published_date = Column(DateTime, nullable=True)
fixed_version = Column(String(100), nullable=True)
scan_date = Column(DateTime, default=datetime.utcnow)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
image = relationship("Image", back_populates="vulnerabilities")
scan_job = relationship("ScanJob", back_populates="vulnerabilities")
__table_args__ = (
UniqueConstraint(
"image_id", "vulnerability_id", name="unique_image_vulnerability"
),
)
class IgnoreRule(Base):
__tablename__ = "ignore_rules"
id = Column(Integer, primary_key=True)
project_id = Column(Integer, ForeignKey("projects.id"), nullable=True)
ignore_type = Column(String(20), nullable=False)
target = Column(String(1000), nullable=False)
reason = Column(Text, nullable=True)
created_by = Column(String(100), nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
project = relationship("Project", back_populates="ignore_rules")
class ScanJob(Base):
__tablename__ = "scan_jobs"
id = Column(Integer, primary_key=True)
job_type = Column(String(50), nullable=False) # discovery, vulnerability
status = Column(String(20), nullable=False) # pending, running, completed, failed
project_id = Column(Integer, ForeignKey("projects.id"), nullable=True)
started_at = Column(DateTime, nullable=True)
completed_at = Column(DateTime, nullable=True)
error_message = Column(Text, nullable=True)
results_summary = Column(Text, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
vulnerabilities = relationship("Vulnerability", back_populates="scan_job", cascade="all, delete-orphan")
DATABASE_URL = "sqlite:///./gitlab_docker_tracker.db"
engine = create_engine(DATABASE_URL, echo=False)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def create_tables():
Base.metadata.create_all(bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()