Beispiel #1
0
def resolve_recursive_set_members(_,
                                  info: GraphQLResolveInfo,
                                  set_names: List[str],
                                  depth: int = 0,
                                  sources: Optional[List[str]] = None,
                                  exclude_sets: Optional[List[str]] = None,
                                  sql_trace: bool = False):
    """Resolve an recursiveSetMembers query"""
    query_resolver = QueryResolver(
        info.context['request'].app.state.preloader,
        info.context['request'].app.state.database_handler)
    if sql_trace:
        query_resolver.enable_sql_trace()
    set_names_set = {i.upper() for i in set_names}
    exclude_sets_set = {i.upper()
                        for i in exclude_sets} if exclude_sets else set()
    query_resolver.set_query_sources(sources)
    for set_name in set_names_set:
        results = query_resolver.members_for_set_per_source(
            set_name,
            exclude_sets=exclude_sets_set,
            depth=depth,
            recursive=True)
        for source, members in results.items():
            yield dict(rpslPk=set_name, rootSource=source, members=members)
    if sql_trace:
        info.context['sql_queries'] = query_resolver.retrieve_sql_trace()
Beispiel #2
0
def resolve_as_set_prefixes(_,
                            info: GraphQLResolveInfo,
                            set_names: List[str],
                            sources: Optional[List[str]] = None,
                            ip_version: Optional[int] = None,
                            exclude_sets: Optional[List[str]] = None,
                            sql_trace: bool = False):
    """Resolve an asSetPrefixes query"""
    query_resolver = QueryResolver(
        info.context['request'].app.state.preloader,
        info.context['request'].app.state.database_handler)
    if sql_trace:
        query_resolver.enable_sql_trace()
    set_names_set = {i.upper() for i in set_names}
    exclude_sets_set = {i.upper()
                        for i in exclude_sets} if exclude_sets else set()
    query_resolver.set_query_sources(sources)
    for set_name in set_names_set:
        prefixes = list(
            query_resolver.routes_for_as_set(set_name,
                                             ip_version,
                                             exclude_sets=exclude_sets_set))
        yield dict(rpslPk=set_name, prefixes=prefixes)
    if sql_trace:
        info.context['sql_queries'] = query_resolver.retrieve_sql_trace()
Beispiel #3
0
def create_resolve_info(schema,
                        request_string,
                        variables=None,
                        return_type=None):
    exe_context = create_execution_context(schema, request_string, variables)
    parent_type = get_operation_root_type(schema, exe_context.operation)
    field_asts = get_field_asts_from_execution_context(exe_context)

    field_ast = field_asts[0]
    field_name = field_ast.name.value

    if return_type is None:
        field_def = get_field_def(schema, parent_type, field_name)
        if not field_def:
            return Undefined
        return_type = field_def.type

    # The resolve function's optional third argument is a context value that
    # is provided to every resolve function within an execution. It is commonly
    # used to represent an authenticated user, or request-specific caches.
    return GraphQLResolveInfo(
        field_name,
        field_asts,
        return_type,
        parent_type,
        Path(None, 0, None),
        schema,
        exe_context.fragments,
        exe_context.root_value,
        exe_context.operation,
        exe_context.variable_values,
        exe_context.context_value,
        exe_context.is_awaitable,
    )
Beispiel #4
0
 def _create_resolve_info(self, field_name, field_asts, return_type, parent_type):
     return GraphQLResolveInfo(
         field_name,
         field_asts,
         return_type,
         parent_type,
         Path(None, 0, None),
         schema=self.root_info.schema,
         fragments=self.root_info.fragments,
         root_value=self.root_info.root_value,
         operation=self.root_info.operation,
         variable_values=self.root_info.variable_values,
         context=self.root_info.context,
         is_awaitable=self.root_info.is_awaitable,
     )
Beispiel #5
0
def _rpsl_db_query_to_graphql_out(query: RPSLDatabaseQuery,
                                  info: GraphQLResolveInfo):
    """
    Given an RPSL database query, execute it and clean up the output
    to be suitable to return to GraphQL.

    Main changes are:
    - Enum handling
    - Adding the asn and prefix fields if applicable
    - Ensuring the right fields are returned as a list of strings or a string
    """
    database_handler = info.context['request'].app.state.database_handler
    if info.context.get('sql_trace'):
        if 'sql_queries' not in info.context:
            info.context['sql_queries'] = [repr(query)]
        else:
            info.context['sql_queries'].append(repr(query))

    for row in database_handler.execute_query(query, refresh_on_error=True):
        graphql_result = {
            snake_to_camel_case(k): v
            for k, v in row.items() if k != 'parsed_data'
        }
        if 'object_text' in row:
            graphql_result['objectText'] = remove_auth_hashes(
                row['object_text'])
        if 'rpki_status' in row:
            graphql_result['rpkiStatus'] = row['rpki_status']
        if row.get('ip_first') is not None and row.get('prefix_length'):
            graphql_result['prefix'] = row['ip_first'] + '/' + str(
                row['prefix_length'])
        if row.get('asn_first') is not None and row.get(
                'asn_first') == row.get('asn_last'):
            graphql_result['asn'] = row['asn_first']

        object_type = resolve_rpsl_object_type(row)
        for key, value in row.get('parsed_data', dict()).items():
            if key == 'auth':
                value = [remove_auth_hashes(v) for v in value]
            graphql_type = schema.graphql_types[object_type][key]
            if graphql_type == 'String' and isinstance(value, list):
                value = '\n'.join(value)
            graphql_result[snake_to_camel_case(key)] = value
        yield graphql_result
Beispiel #6
0
def resolve_rpsl_objects(_, info: GraphQLResolveInfo, **kwargs):
    """
    Resolve a `rpslObjects` query. This query has a considerable
    number of parameters, each of which is applied to an RPSL
    database query.
    """
    low_specificity_kwargs = {
        'object_class', 'rpki_status', 'scope_filter_status', 'sources',
        'sql_trace'
    }
    # A query is sufficiently specific if it has other fields than listed above,
    # except that rpki_status is sufficient if it is exclusively selecting on
    # valid or invalid.
    low_specificity = all([
        not (set(kwargs.keys()) - low_specificity_kwargs),
        kwargs.get('rpki_status', []) not in [[RPKIStatus.valid],
                                              [RPKIStatus.invalid]],
    ])
    if low_specificity:
        raise ValueError('Your query must be more specific.')

    if kwargs.get('sql_trace'):
        info.context['sql_trace'] = True

    query = RPSLDatabaseQuery(
        column_names=_columns_for_graphql_selection(info),
        ordered_by_sources=False,
        enable_ordering=False)

    if 'record_limit' in kwargs:
        query.limit(kwargs['record_limit'])
    if 'rpsl_pk' in kwargs:
        query.rpsl_pks(kwargs['rpsl_pk'])
    if 'object_class' in kwargs:
        query.object_classes(kwargs['object_class'])
    if 'asn' in kwargs:
        query.asns_first(kwargs['asn'])
    if 'text_search' in kwargs:
        query.text_search(kwargs['text_search'])
    if 'rpki_status' in kwargs:
        query.rpki_status(kwargs['rpki_status'])
    else:
        query.rpki_status([RPKIStatus.not_found, RPKIStatus.valid])
    if 'scope_filter_status' in kwargs:
        query.scopefilter_status(kwargs['scope_filter_status'])
    else:
        query.scopefilter_status([ScopeFilterStatus.in_scope])

    all_valid_sources = set(get_setting('sources', {}).keys())
    if get_setting('rpki.roa_source'):
        all_valid_sources.add(RPKI_IRR_PSEUDO_SOURCE)
    sources_default = set(get_setting('sources_default', []))

    if 'sources' in kwargs:
        query.sources(kwargs['sources'])
    elif sources_default and sources_default != all_valid_sources:
        query.sources(list(sources_default))

    # All other parameters are generic lookup fields, like `members`
    for attr, value in kwargs.items():
        attr = attr.replace('_', '-')
        if attr in lookup_fields:
            query.lookup_attrs_in([attr], value)

    ip_filters = [
        'ip_exact', 'ip_less_specific', 'ip_more_specific',
        'ip_less_specific_one_level', 'ip_any'
    ]
    for ip_filter in ip_filters:
        if ip_filter in kwargs:
            getattr(query, ip_filter)(IP(kwargs[ip_filter]))

    return _rpsl_db_query_to_graphql_out(query, info)
Beispiel #7
0
 async def check_auth(obj: Any, info: GraphQLResolveInfo,
                      **kwargs: Any) -> Any:  # type: ignore
     if not info.context.get("auth", False):
         await authenticate(info.context["request"])
         info.context["auth"] = True
     return await f(obj, info, **kwargs)