Skip to content

Commit

Permalink
Merge pull request #1 from bgpkit/feature-roas-sdk
Browse files Browse the repository at this point in the history
Add support for BGPKIT ROAS lookup API
  • Loading branch information
digizeph authored Feb 26, 2022
2 parents c35abde + 57f5eb1 commit 2b80c0d
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 6 deletions.
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

0 comments on commit 2b80c0d

Please sign in to comment.