import base64 import hashlib from typing import Optional from sqlalchemy.orm import Mapped, mapped_column, relationship from app.brm.brn import BRN from app.extensions import db from app.models import AbstractConfiguration, AbstractResource from app.models.base import Group class Onion(AbstractConfiguration): @property def brn(self) -> BRN: return BRN( group_id=self.group_id, product="eotk", provider="*", resource_type="onion", resource_id=self.onion_name ) group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False) domain_name = db.Column(db.String(255), nullable=False) onion_public_key = db.Column(db.LargeBinary, nullable=False) onion_private_key = db.Column(db.LargeBinary, nullable=False) tls_public_key = db.Column(db.LargeBinary, nullable=False) tls_private_key = db.Column(db.LargeBinary, nullable=False) group = db.relationship("Group", back_populates="onions") @property def onion_name(self) -> str: p = self.onion_public_key[32:] h = hashlib.sha3_256() h.update(b".onion checksum") h.update(p) h.update(b"\x03") checksum = h.digest() result = bytearray(p) result.extend(checksum[0:2]) result.append(0x03) onion = base64.b32encode(result).decode("utf-8").strip("=") return onion.lower() class Eotk(AbstractResource): group_id: Mapped[int] = mapped_column(db.Integer(), db.ForeignKey("group.id")) instance_id: Mapped[Optional[str]] provider: Mapped[str] region: Mapped[str] group: Mapped[Group] = relationship("Group", back_populates="eotks") @property def brn(self) -> BRN: return BRN( group_id=self.group_id, provider=self.provider, product="eotk", resource_type="instance", resource_id=self.region )