routeur / Pear

Pear is a script for gathering info from an ASNumber
MIT License
9 stars 2 forks source link

replacing direct API call by peerindDB local sync #10

Open darcosion opened 1 year ago

darcosion commented 1 year ago

Since the new PeeringDB policy, the API call managment was modified (see here : https://docs.peeringdb.com/howto/api_keys/ )

Every session have a rate limit of 50~60s, so it's impossible to use Pear normally now.

I suggest to use peeringdb python package which offer a local copy of peeringDB as proposed here : http://peeringdb.github.io/peeringdb-py/

note : It is important to do regularly database sync with peeringdb sync.

darcosion commented 1 year ago

A priori, une fois le module python peeringdb installé via sudo pip3 install peeringdb, on a la possibilité de récupérer le contenu d'un objet ASN :

from peeringdb import config, resource
from peeringdb.client import Client

pdb = Client()

net = pdb.tags.net              # type wrap

asn_example = net.all().filter(asn=2906).first()

kado @routeur

darcosion commented 1 year ago

A priori, trouver des facilités sur la base d'un AS pourrait se faire car la règle pour trouver quelque chose semble être :

>>> # on récupère les info d'un AS juste pour s'assurer qu'il existe
>>> a = pdb.all(resource.Network).filter(asn=174)
>>> print(a)
<QuerySet [<Network: Cogent Communications, Inc.>]>
>>> # on récupère via un queryset sur un autre modèle de resources les éléments : 
>>> b = pdb.all(resource.NetworkFacility).filter(local_asn=174)
>>> b
<QuerySet [<NetworkFacility: Cogent Communications, Inc. @ Interxion Frankfurt (FRA1-15)>, <NetworkFacility: Cogent Communications, Inc. @ Interxion Paris 1 (Aubervilliers Cedex)>, <NetworkFacility: Cogent Communications, Inc. @ Equinix LD8 - London, Docklands>, <NetworkFacility: Cogent Communications, Inc. @ Interxion Amsterdam Science Park Campus (AMS9)>, <NetworkFacility: Cogent Communications, Inc. @ Telehouse - Frankfurt>, <NetworkFacility: Cogent Communications, Inc. @ Interxion Dusseldorf (DUS1, DUS2)>, <NetworkFacility: Cogent Communications, Inc. @ CoreSite - Los Angeles (LA1) One Wilshire>, <NetworkFacility: Cogent Communications, Inc. @ Equinix AT2/AT3 - Atlanta>, <NetworkFacility: Cogent Communications, Inc. @ Equinix DC1-DC15, DC21 - Ashburn>, <NetworkFacility: Cogent Communications, Inc. @ Equinix CH1/CH2/CH4 - Chicago>, <NetworkFacility: Cogent Communications, Inc. @ Equinix DA1 - Dallas>, <NetworkFacility: Cogent Communications, Inc. @ Equinix LA1 - Los Angeles>, <NetworkFacility: Cogent Communications, Inc. @ Equinix NY1 - New York, Newark>, <NetworkFacility: Cogent Communications, Inc. @ Equinix SV1/SV5/SV10 - Silicon Valley, San Jose>, <NetworkFacility: Cogent Communications, Inc. @ Equinix MI1 - Miami, NOTA>, <NetworkFacility: Cogent Communications, Inc. @ Equinix TR1 - Toronto>, <NetworkFacility: Cogent Communications, Inc. @ Equinix SK1 - Stockholm, Bromma>, <NetworkFacility: Cogent Communications, Inc. @ Equinix FR5 - Frankfurt, KleyerStrasse>, <NetworkFacility: Cogent Communications, Inc. @ Equinix FR7 - Frankfurt, Gutleutstrasse>, <NetworkFacility: Cogent Communications, Inc. @ Equinix FR1 - No longer operational>, '...(remaining elements truncated)...']>
darcosion commented 1 year ago

Les objets Carrier ajoutés récemment semblent souvent crash. Je fait un drop tables et un sync à nouveau pour avoir une DB neuve. A voir si cela suffit et/ou s'il faut considérer cela comme une opération à réaliser régulièrement.

btw, j'ai découvert qu'on pouvait stocker la peeringdb n'importe où :

@:~$ peeringdb config show
orm:
  backend: django_peeringdb
  database:
    engine: sqlite3
    host: ''
    name: peeringdb.sqlite3
    password: ''
    port: 0
    user: ''
  migrate: true
  secret_key: ''
sync:
  api_key: ''
  only: []
  password: ''
  strip_tz: 1
  timeout: 0
  url: https://www.peeringdb.com/api
  user: ''

note : ne pas faire plusieurs sync d'affilé : Exception: 429 Internal error: Too Many Requests

darcosion commented 1 year ago

A priori, la méthode similaire pour obtenir les info d'un AS serait :

@:~$ peeringdb whois AS3031
# depuis l'AS on récupère son ORG ID pour avoir tous les AS affiliés
@:~$ peeringdb whois ORG3593

Ensuite, on conserve le code de requêtage de CAIDA car l'API est toujours ouverte : https://github.com/routeur/Pear/blob/e93d71c44f65018986cd1928854ad342e1e7b404/Pear.py#L157-L166

darcosion commented 1 year ago

Cette documentation semble complète sur le sujet : https://docs.peeringdb.com/presentation/20220225-Apricot-1-2-GUI-API-with-exercises.pdf

darcosion commented 1 year ago

J'ai trouvé une information assez complexe et pas du tout publique sur le mode de fonctionnement local de peeringdb.

Peeringdb utilise un backend Django, ce qui signifie qu'il y a l'ORM django qui entre en jeu. Donc quand ils mettent à jour la forme de la DB, il y a des objets Django que l'on appelle les models qui resprésentent le format des table, colonnes, etc... en base de donnée et in fine les données à manipuler qu'il faut mettre à jour.

DONC QUAND UN peeringdb sync crash avec une erreur python, une chose à faire absolument avant tout :

pip3 install --upgrade peeringdb
pip3 install --upgrade django-peeringdb

Là, je viens de le faire et j'ai vu ça :

Installing collected packages: django-peeringdb
  Attempting uninstall: django-peeringdb
    Found existing installation: django-peeringdb 2.14.1
    Uninstalling django-peeringdb-2.14.1:
      Successfully uninstalled django-peeringdb-2.14.1
Successfully installed django-peeringdb-3.0.0

Clairement, c'était nécessaire et ça a tout débloqué.

darcosion commented 1 year ago

J'ai trouvé comment obtenir la liste des AS appartenant à la même organisation qu'un AS, démonstration avec netflix :

>>> asn_example = get_as.net.all().filter(asn=2906).first()
>>> asn_example
<Network: Netflix>
>>> asn_example.org_id
6483
>>> asn_netflix_list = get_as.net.all().filter(org_id=asn_example.org_id)
>>> asn_netflix_list
<QuerySet [<Network: Netflix>, <Network: Netflix Streaming Services>, <Network: Netflix AS55095>]>