forked from mirrors/thatmattlove-hyperglass
add structured data configuration options & external RPKI validation
This commit is contained in:
parent
40b957ee21
commit
4b92b670c9
6 changed files with 137 additions and 8 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
59
docs/docs/structured-data.mdx
Normal file
59
docs/docs/structured-data.mdx
Normal 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
|
||||
```
|
||||
|
|
@ -18,6 +18,7 @@ module.exports = {
|
|||
"ui",
|
||||
"api",
|
||||
"messages",
|
||||
"structured-data",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
31
hyperglass/configuration/models/structured.py
Normal file
31
hyperglass/configuration/models/structured.py
Normal 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
35
hyperglass/external/rpki.py
vendored
Normal 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
|
||||
Loading…
Add table
Reference in a new issue