Example #1
0
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)
Example #2
0
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)
Example #3
0
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)
Example #4
0
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)
Example #5
0
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")
Example #6
0
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)
Example #7
0
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)
Example #8
0
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)
Example #9
0
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)
Example #10
0
    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)