1
0
Fork 1
mirror of https://github.com/thatmattlove/hyperglass.git synced 2026-01-17 08:48:05 +00:00

add structured data configuration options & external RPKI validation

This commit is contained in:
checktheroads 2020-06-06 01:22:14 -07:00
parent 40b957ee21
commit 4b92b670c9
6 changed files with 137 additions and 8 deletions

View file

@ -79,14 +79,15 @@ cors_origins: [localhost:3000, 192.0.2.1]
From the top level, the following subsections may be defined and configured:
| Section | Description | All Options |
| :--------- | :-------------------------------------------------- | :-----------------------------------------: |
| `cache` | Redis server & cache timeout settings. | <PageLink to="/docs/cache">➡️</PageLink> |
| `docs` | API documentation settings. | <PageLink to="/docs/api">➡️</PageLink> |
| `logging` | File, syslog, and webhook settings. | <PageLink to="/docs/logging">➡️</PageLink> |
| `messages` | Customize almost all user-facing UI & API messages. | <PageLink to="/docs/messages">➡️</PageLink> |
| `queries` | Enable, disable, or configure query types. | <PageLink to="/docs/queries">➡️</PageLink> |
| `web` | Web UI & branding settings. | <PageLink to="/docs/ui">➡️</PageLink> |
| Section | Description | All Options |
| :----------- | :-------------------------------------------------- | :------------------------------------------------: |
| `cache` | Redis server & cache timeout settings. | <PageLink to="/docs/cache">➡️</PageLink> |
| `docs` | API documentation settings. | <PageLink to="/docs/api">➡️</PageLink> |
| `logging` | File, syslog, and webhook settings. | <PageLink to="/docs/logging">➡️</PageLink> |
| `messages` | Customize almost all user-facing UI & API messages. | <PageLink to="/docs/messages">➡️</PageLink> |
| `queries` | Enable, disable, or configure query types. | <PageLink to="/docs/queries">➡️</PageLink> |
| `structured` | Configure structured data features. | <PageLink to="/docs/structured-data">➡️</PageLink> |
| `web` | Web UI & branding settings. | <PageLink to="/docs/ui">➡️</PageLink> |
## Adding Devices

View file

@ -0,0 +1,59 @@
---
id: structured-data
title: Structured Data
sidebar_label: Structured Data
description: Configure structured data parameters
---
<div class="table--full-width" />
The `structured` subsection contains multiple subsections of its own:
| Section | Description | All Options |
| :------------ | :--------------------------------- | :---------------------------------------: |
| `communities` | Include or exclude BGP communities | <PageLink to="#communities">➡️</PageLink> |
| `rpki` | Configure RPKI validation | <PageLink to="#rpki">➡️</PageLink> |
## `communities`
| Parameter | Type | Default | Description |
| :-------- | :----: | :------: | :------------------------------------------------------------------------------------------------------------------------------------ |
| `mode` | String | `'deny'` | `'deny'` denies any matching patterns and permits anything else. `'permit'` only permits matching patterns and denies everything else |
| `items` | List | `[]` | List of regular expression patterns to match |
:::note Regular Expressions with YAML
If you're using any regex patterns with special characters, you'll probably need to wrap the patterns in single quotes, to denote a raw string. For example:
```yaml
normal_string: Normal String
raw_string: '^Raw\sString$'
```
:::
## `rpki`
| Parameter | Type | Default |
| :-------- | :----: | :--------: |
| `mode` | String | `'router'` |
### `router` mode
`router` mode uses the RPKI state from the perspective of the router. This means if your network is not using Origin Validation, the RPKI state will be shown as "Not Verified". Otherwise, the corresponding RPKI state will be shown.
### `external` mode
`external` mode takes each prefix, the last ASN in the `AS_PATH` and requests the RPKI validation state via the [Cloudflare RPKI Portal](https://rpki.cloudflare.com/).
## Example
```yaml title="hyperglass.yaml"
structured:
communities:
mode: permit
items:
- '65000:\d+'
- '65[1-4]00:\d+'
rpki:
mode: external
```

View file

@ -18,6 +18,7 @@ module.exports = {
"ui",
"api",
"messages",
"structured-data",
],
},
{

View file

@ -23,6 +23,7 @@ from hyperglass.configuration.models.cache import Cache
from hyperglass.configuration.models.logging import Logging
from hyperglass.configuration.models.queries import Queries
from hyperglass.configuration.models.messages import Messages
from hyperglass.configuration.models.structured import Structured
class Params(HyperglassModel):
@ -113,6 +114,7 @@ class Params(HyperglassModel):
logging: Logging = Logging()
messages: Messages = Messages()
queries: Queries = Queries()
structured: Structured = Structured()
web: Web = Web()
class Config:

View file

@ -0,0 +1,31 @@
"""Structured data configuration variables."""
# Standard Library
from typing import List
# Third Party
from pydantic import StrictInt, StrictStr, constr
# Project
from hyperglass.models import HyperglassModel
class StructuredCommunities(HyperglassModel):
"""Control structured data response for BGP communties."""
mode: constr(regex=r"(permit|deny)") = "deny"
items: List[StrictStr] = []
class StructuredRpki(HyperglassModel):
"""Control structured data response for RPKI state."""
mode: constr(regex=r"(router|external)") = "router"
max_age: StrictInt = 24
class Structured(HyperglassModel):
"""Control structured data responses."""
communities: StructuredCommunities = StructuredCommunities()
rpki: StructuredRpki = StructuredRpki()

35
hyperglass/external/rpki.py vendored Normal file
View file

@ -0,0 +1,35 @@
"""Validate RPKI state via Cloudflare GraphQL API."""
from hyperglass.log import log
from hyperglass.external._base import BaseExternal
RPKI_STATE_MAP = {"Invalid": 0, "Valid": 1, "NotFound": 2, "DEFAULT": 3}
RPKI_NAME_MAP = {v: k for k, v in RPKI_STATE_MAP.items()}
def rpki_state(prefix, asn):
"""Get RPKI state and map to expected integer."""
log.debug("Validating RPKI State for {p} via AS{a}", p=prefix, a=asn)
state = 3
query = 'query GetValidation {{ validation(prefix: "{prefix}", asn: {asn}) {{ state }} }}'.format( # noqa: E501
prefix=prefix, asn=asn
)
try:
with BaseExternal(base_url="https://rpki.cloudflare.com") as client:
response = client._post("/api/graphql", data={"query": query})
validation_state = (
response.get("data", {}).get("validation", {}).get("state", "DEFAULT")
)
state = RPKI_STATE_MAP[validation_state]
except Exception:
state = 3
log.debug(
"RPKI Validation State for {p} via AS{a} is {s}",
p=prefix,
a=asn,
s=RPKI_NAME_MAP[state],
)
return state