Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for BGPKIT ROAS lookup API #1

Merged
merged 2 commits into from
Feb 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Each returning item has the following field:

### BGPKIT Broker

Origianl Rust version BGPKIT Broker code available at: <https://github.com/bgpkit/bgpkit-broker>
Original Rust version BGPKIT Broker code available at: <https://github.com/bgpkit/bgpkit-broker>

Example:
```python
Expand All @@ -80,4 +80,42 @@ Available fields:
- `collector`: collector name, e.g. `rrc00` or `route-views2`
- `data_type`: `rib` or `update`
- `order`: order by timestamp, `asc` or `desc`, default

### BGPKIT ROAS Lookup

BGPKIT ROAS lookup API provides lookup for historical RPKI ROAS data lookup. The following example shows a query that
asks for all the validated ROA payload for RIPE NCC on the date of `2018-01-01`.

```python
import bgpkit
roas = bgpkit.Roas()
data = roas.query(debug=True, asn=3333, date="2018-01-01")
for entry in data:
print(entry)
assert len(data) == 10
```

```
{'tal': 'ripencc', 'prefix': '193.0.0.0/21', 'asn': 3333, 'max_len': 21, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.10.0/23', 'asn': 3333, 'max_len': 23, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.12.0/23', 'asn': 3333, 'max_len': 23, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.18.0/23', 'asn': 3333, 'max_len': 23, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.20.0/23', 'asn': 3333, 'max_len': 23, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.22.0/23', 'asn': 3333, 'max_len': 23, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '193.0.24.0/22', 'asn': 3333, 'max_len': 26, 'date_ranges': [['2017-01-14', '2018-12-27'], ['2019-01-03', '2019-06-24']]}
{'tal': 'ripencc', 'prefix': '193.0.24.0/24', 'asn': 3333, 'max_len': 24, 'date_ranges': [['2017-02-25', '2018-12-27'], ['2019-01-03', '2019-06-24']]}
{'tal': 'ripencc', 'prefix': '2001:610:240::/42', 'asn': 3333, 'max_len': 42, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
{'tal': 'ripencc', 'prefix': '2001:67c:2e8::/48', 'asn': 3333, 'max_len': 48, 'date_ranges': [['2015-03-10', '2016-01-26'], ['2016-01-30', '2018-12-27'], ['2019-01-03', '2019-10-21'], ['2019-10-23', '2020-02-23'], ['2020-02-25', '2020-04-05'], ['2020-04-07', '2020-08-02'], ['2020-08-04', '2021-04-21'], ['2021-04-23', '2021-04-24'], ['2021-04-28', '2022-02-26']]}
```

Available query fields:

- `Roas()`
- `api_url`: the base URL for the BGPKIT ROAS instance. Default: `https://api.roas.bgpkit.com`
- `query()`
- `prefix`: prefix to query in `str`
- `asn`: AS number to query in `int`
- `tal`: trust anchor to query in `str`, available values: `ripencc`, `arin`, `apnic`, `afrinic`, `lacnic`
- `date`: date to query, format: `YYYY-MM-DD`, e.g. `2022-01-01`
- `max_len`: filter results to only VRP's with specific max length
- `debug`: boolean toggle to display debug information, default `False`
1 change: 1 addition & 0 deletions bgpkit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .bgpkit_parser import Parser
from .bgpkit_broker import Broker
from .bgpkit_roas import Roas
3 changes: 2 additions & 1 deletion bgpkit/bgpkit_broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import requests as requests


def check_type(value: any, ty: type) -> bool:
try:
ty(value)
Expand All @@ -20,7 +21,7 @@ class BrokerItem:

class Broker:

def __init__(self, api_url: str = "https://api.broker.bgpkit.com/v1", page_size: int=100):
def __init__(self, api_url: str = "https://api.broker.bgpkit.com/v1", page_size: int = 100):
self.base_url = api_url.strip()
self.page_size = int(page_size)

Expand Down
80 changes: 80 additions & 0 deletions bgpkit/bgpkit_roas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from dataclasses import dataclass
from typing import Optional, List

import requests as requests


def check_type(value: any, ty: type) -> bool:
try:
ty(value)
return True
except ValueError:
raise ValueError("invalid option input")


@dataclass
class RoasItem:
prefix: str
asn: int
tal: str
date_ranges: List[List[str]]


@dataclass
class RoasRes:
limit: int
count: int
data: List[RoasItem]
next_page_num: Optional[int]
next_page: Optional[str]
error: Optional[str]


class Roas:

def __init__(self, api_url: str = "https://api.roas.bgpkit.com"):
self.base_url = api_url.strip()

def query(self,
prefix: str = None,
asn: int = None,
tal: str = None,
date: str = None,
max_len: int = None,
debug: bool = False,
) -> [RoasItem]:

if not (prefix or asn or tal or date or max_len):
print("ERROR: must specify at least one query parameter: prefix, asn, tal, date, max_len")
return []

params = []
if prefix:
check_type(prefix, str)
params.append(f"prefix={prefix}")
if asn:
check_type(asn, int)
params.append(f"asn={asn}")
if tal:
check_type(tal, str)
params.append(f"tal={tal}")
if date:
check_type(date, str)
params.append(f"date={date}")
if max_len:
check_type(max_len, int)
params.append(f"max_len={max_len}")

api_url = f"{self.base_url}/lookup?" + "&".join(params)
data_items = []
if debug:
print(api_url)
res = RoasRes(**requests.get(api_url).json())
while res.data:
data_items.extend(res.data)
if res.next_page:
res = RoasRes(**requests.get(res.next_page).json())
else:
break

return data_items
15 changes: 12 additions & 3 deletions bgpkit/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@ def test_parser(self):

def test_broker(self):
broker = bgpkit.Broker()
items = broker.query(start_ts=1634693400, end_ts=1634693400)
items = broker.query(start_ts=1643760000, end_ts=1643761200)
for item in items:
print(item)
print(len(items))
assert len(items) == 58

elems = bgpkit.Parser(items[0].url).parse_all()
assert len(elems) == 222467
# elems = bgpkit.Parser(items[0].url).parse_all()
# assert len(elems) == 222467

def test_roas(self):
roas = bgpkit.Roas()
data = roas.query(debug=True, asn=3333, date="2018-01-01")
for entry in data:
print(entry)
assert len(data) == 10

assert len(roas.query()) == 0
10 changes: 9 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import setuptools

# read the contents of your README file
from pathlib import Path
this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text()

setuptools.setup(
name='pybgpkit',
version='0.0.1',
version='0.0.2.post1',
description='BGPKIT tools Python bindings',
url='https://github.com/bgpkit/pybgpkit',
author='Mingwei Zhang',
author_email='[email protected]',
packages=setuptools.find_packages(),
include_package_data=True,
long_description=long_description,
long_description_content_type='text/markdown',
install_requires=[
# available on pip
'pybgpkit-parser==0.0.1',
'requests',
],
entry_points={'console_scripts': [
]}
Expand Down