async def update( zone_id: int, form: ZoneCreateForm, zone_repo: ZoneRepo = Depends(ZoneRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: TokenPayload = Depends(ScopedTo("zone:update")), includes: List[str] = Query(None), ): data = only(dict(form), ["ip", "domain"]) if "domain" in data: data["domain"] = data["domain"].lower() existing_domain = zone_repo.first(domain=data["domain"]).results() if existing_domain and existing_domain.id != zone_id: abort_for_input("domain", "A Zone with that domain already exists") zone_repo.clear() if form.dns_server_id is not None: if form.dns_server_id is 0: data["dns_server_id"] = None elif dns_server_repo.exists(id=form.dns_server_id): dns_server = dns_server_repo.results() data["dns_server"] = dns_server zone = (zone_repo.loads(includes).get_or_fail(zone_id).update( data).includes(includes).data()) return ZoneResponse(zone=zone)
async def store( form: DnsRequestCreateForm, dns_request_repo: DnsRequestRepo = Depends(DnsRequestRepo()), zone_repo: ZoneRepo = Depends(ZoneRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: str = Depends(ScopedTo("dns-request:create")), ): dns_server_id = (dns_server_repo.first_or_fail( name=form.dns_server_name.lower()).results().id) zone = (zone_repo.filter( literal(form.name.lower()).contains( zone_repo.label("domain"))).first().results()) zone_id = zone.id if zone else None data = only(dict(form), ["name", "source_address", "source_port", "type", "protocol"]) data["name"] = data["name"].lower() data["type"] = data["type"].upper() data["dns_server_id"] = dns_server_id data["zone_id"] = zone_id dns_request = dns_request_repo.create(data).data() return DnsRequestResponse(dns_request=dns_request)
async def store( form: DnsServerCreateForm, dns_server_repo: DnsServerRepo = Depends(DnsServerRepo), token: TokenPayload = Depends(ScopedTo("dns-server:create")), ): if dns_server_repo.exists(name=form.name.lower()): abort(422, "Invalid Name") data = only(dict(form), ["name"]) data["name"] = data["name"].lower() item = dns_server_repo.create(data).data() return DnsServerResponse(dns_server=item)
async def index( sort_qs: SortQS = Depends(SortQS), pagination: PaginationQS = Depends(PaginationQS), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: TokenPayload = Depends(ScopedTo("dns-server:list")), search: str = Query(None), includes: List[str] = Query(None), ): includes = only(includes, ["zones"], values=True) pg, items = (dns_server_repo.loads(includes).includes(includes).search( search, searchable=["name", "id"]).paginate(pagination).data()) return DnsServersResponse(pagination=pg, dns_servers=items)
async def sync( api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo), token: TokenPayload = Depends(ScopedTo("api-token:syncable")), ): scopes = token.scopes if "api-token" in scopes or "api-token:syncable" in scopes: api_token = None dns_server = None if not dns_server_repo.exists(name=token.payload.dns_server_name.lower()): dns_server_repo.clear() logger.info("saving dns server from api token") dns_server = dns_server_repo.create( dict(name=token.payload.dns_server_name.lower()) ).results() else: dns_server = dns_server_repo.results() if not api_token_repo.loads("dns_server").exists(token=token.token): api_token_repo.clear() logger.info("saving api token from auth token") item = api_token_repo.create( dict( token=token.token, scopes=" ".join(scopes), dns_server=dns_server, expires_at=datetime.utcfromtimestamp(float(token.exp)), ) ).data() api_token_id = item.id item = ( api_token_repo.clear() .loads("dns_server") .get(api_token_id) .includes("dns_server") .data() ) else: logger.info("token already exists in database") item = api_token_repo.loads("dns_server").includes("dns_server").data() return ApiTokenResponse(api_token=item) else: raise HTTPException(403, detail="Not found")
async def store( form: ApiTokenCreateForm, api_token_repo: ApiTokenRepo = Depends(ApiTokenRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: TokenPayload = Depends(ScopedTo("api-token:create")), user: User = Depends(current_user), ): dns_server = dns_server_repo.first_or_fail(id=form.dns_server_id).results() scopes = [] for requested_scope in form.scopes.split(" "): request_scope_satisfied = False for user_token in token.scopes: # TODO: double check this, pretty lenient # if a:b in a:b:c if user_token in requested_scope: request_scope_satisfied = True if not request_scope_satisfied: logger.warning( f"[email protected]: Attempt to create unauthorized scope {requested_scope}" ) raise HTTPException(403, detail="unauthorized") else: scopes.append(requested_scope) # TODO: use better randomness token = create_bearer_token( data={ "sub": user.id, "scopes": " ".join(scopes), "dns_server_name": dns_server.name, }) data = { "scopes": " ".join(scopes), "token": str(token), "expires_at": form.expires_at, "dns_server_id": form.dns_server_id, } api_token = api_token_repo.create(data).data() return ApiTokenResponse(api_token=api_token)
async def show( dns_server: str, dns_server_repo: DnsServerRepo = Depends(DnsServerRepo), token: TokenPayload = Depends(ScopedTo("dns-server:show")), includes: List[str] = Query(None), ): includes = only(includes, ["zones"], values=True) dns_server_id_label = dns_server_repo.label("id") try: dns_server = int(dns_server) label = dns_server_id_label except ValueError: label = dns_server_repo.label("name") item = (dns_server_repo.loads(includes).filter( label == dns_server).first_or_fail().includes(includes).data()) return DnsServerResponse(dns_server=item)
async def update( dns_server: str, form: DnsServerCreateForm, dns_server_repo: DnsServerRepo = Depends(DnsServerRepo), token: TokenPayload = Depends(ScopedTo("dns-server:update")), ): data = only(dict(form), ["name"]) data["name"] = data["name"].lower() dns_server_id_label = dns_server_repo.label("id") try: dns_server = int(dns_server) label = dns_server_id_label except ValueError: label = dns_server_repo.label("name") item = (dns_server_repo.filter( label == dns_server).first_or_fail().update(data).data()) return DnsServerResponse(dns_server=item)
async def store( form: ZoneCreateForm, zone_repo: ZoneRepo = Depends(ZoneRepo()), dns_server_repo: DnsServerRepo = Depends(DnsServerRepo()), token: TokenPayload = Depends(ScopedTo("zone:create")), ): data = only(dict(form), ["ip", "domain"]) data["domain"] = data["domain"].lower() # Make sure domain is unique if zone_repo.exists(domain=data["domain"]): abort_for_input("domain", "A Zone with that domain already exists") zone_repo.clear() if form.dns_server_id: if dns_server_repo.exists(id=form.dns_server_id): data["dns_server_id"] = dns_server_repo.results().id zone = zone_repo.create(data).data() return ZoneResponse(zone=zone)
def seed_from_env(self): from bountydns.core.user import UserRepo from bountydns.core.zone import ZoneRepo from bountydns.core.dns_server import DnsServerRepo from bountydns.db.session import _scoped_session session = _scoped_session for i in range(9): i = str(i) user_data = {} email_key = f"SEED_USER_{i}_EMAIL" email = environ.get(email_key, None) password_key = f"SEED_USER_{i}_PASSWORD" password = environ.get(password_key, None) superuser_key = f"SEED_USER_{i}_SUPERUSER" is_superuser = int(environ.get(superuser_key, 0)) if email and password: email = email.lower() hashed_password = hash_password(password) repo = UserRepo(db=session) if not repo.exists(email=email): logger.info(f"seeding user {email}") user = factory("UserFactory", session=session).create( email=email, hashed_password=hashed_password, is_superuser=is_superuser, ) else: logger.info(f"seeded user {email} already exists") for i in range(9): i = str(i) name_key = f"SEED_DNS_SERVER_{i}_NAME" name = environ.get(name_key, None) if name: repo = DnsServerRepo(db=session) if not repo.exists(name=name): logger.info(f"seeding domain {name}") domain = factory("DnsServerFactory", session=session).create(name=name) for i in range(9): i = str(i) ip_key = f"SEED_ZONE_{i}_IP" domain_key = f"SEED_ZONE_{i}_DOMAIN" dns_server_name_key = f"SEED_ZONE_{i}_DNS_SERVER_NAME" ip = environ.get(ip_key, None) domain = environ.get(domain_key, None) if domain: domain = domain.lower() dns_server_name = environ.get(dns_server_name_key, None) if ip and domain: if dns_server_name: dns_server_repo = DnsServerRepo(db=session) if dns_server_repo.exists(name=dns_server_name): dns_server = dns_server_repo.results() else: logger.info( f"seeding dns server as zone dependency: {name}") dns_server = factory( "DnsServerFactory", session=session).create(name=dns_server_name) factory("ZoneFactory", session=session).create(ip=ip, domain=domain, dns_server=dns_server) else: repo = ZoneRepo(db=session) if not repo.exists(ip=ip, domain=domain): logger.info( f"seeding zone without dns server: {ip}, {domain}") factory("GlobalZoneFactory", session=session).create(ip=ip, domain=domain)