diff --git a/network/dyndns_api.rst b/network/dyndns_api.rst index afbd952..7a84803 100644 --- a/network/dyndns_api.rst +++ b/network/dyndns_api.rst @@ -7,7 +7,7 @@ DNS dynamique avec l'api d'online.net et de python :category: network :slug: dyndns_online :authors: Milka64 -:summary: Comment faire du DNS dynamique avec online.net et python +:summary: Comment faire du DNS dynamique avec Scaleway et python :status: draft @@ -22,20 +22,21 @@ J'ai bien commencé à chercher des solution de dynDNS mais je me suis vite rend Ensuite, je me suis dit que j'allais me monter un bind auto-hebergé mais par manque de temps, j'ai mis cette solution de coté. -Et par le plus grand des hasard en mettant à jour une entrée DNS, je me suis rendu compte qu'Online avait une API pour gérer ses services. +Et par le plus grand des hasard en mettant à jour une entrée DNS, je me suis rendu compte que Scaleway avait une API pour gérer ses services. Dyndns.py --------- J'ai donc écrit `ce petit script `_ (qui est utilisable par tous) dont je vais détailler les differentes parties. -fonction args +Il n'y a besoin que du token de l'api (disponible `ici `_) + +Fonction args ~~~~~~~~~~~~~ -Parse les argument du scripts +Elle parse les argument du scripts, et permets d'avoir un `--help`. .. code-block:: python - :linenos: def get_args(): """ @@ -53,24 +54,138 @@ Parse les argument du scripts return parser.parse_args() -fonction clear +Fonction clear ~~~~~~~~~~~~~~ -Éfface les version innutilisé +Efface les versions innutilisé: -fonction update +.. code-block:: python + + def clear_versions(args, session): + """ + clear inactive versions + """ + all_versions = session.get("https://api.online.net/api/v1/domain/" + args.domain + "/version").json() + versions_to_remove = [x for x in session.get("https://api.online.net/api/v1/domain/" + args.domain + "/version").json() if not x['active']] + for version in versions_to_remove: + if args.verbose: + print("Deleting : " + version['name']) + api_session.delete("https://api.online.net/api/v1/domain/" + args.domain + "/version/" + version["uuid_ref"]) + + +Fonction update ~~~~~~~~~~~~~~~ Crée une nouvelle zone, la peuple (avec les entrées de la version active) et l'active. -main +.. code-block:: python + + def create_new_version(args, records, records_to_update): + """ + Create new zone version with name YYYYMMDDhhmm + """ + new_name = datetime.now().strftime("%Y%m%d%H%M") + if args.verbose: + print("Generating new zone called : " + new_name) + url = "https://api.online.net/api/v1/domain/" + args.domain + "/version" + data = { + 'name' : new_name + } + res = api_session.post(url, data) + if "error" in res.json(): + exit(res.json()['error_description']) + id_to_update = res.json()["uuid_ref"] + url = "https://api.online.net/api/v1/domain/" + args.domain + "/version/" + id_to_update + "/zone" + for record in records: + if record['name'] in records_to_update: + record['data'] = public_ip + data = { + 'name' : record['name'], + 'type' : record['type'], + 'ttl' : record['ttl'], + 'data' : record['data'], + 'priority' : 0, + } + res = api_session.post(url, data) + if "error" in res.json(): + exit(res['error_description']) + url = "https://api.online.net/api/v1/domain/" + args.domain + "/version/" + id_to_update + "/enable" + res = api_session.patch(url) + try: + res_json = res.json() + except: + res_json = {} + if "error" in res_json: + exit(res['error_description']) + +Main ~~~~ Appelé lors de l'éxecution du scipt + +.. code-block:: python + + if __name__ == "__main__": + + ## PARSE AGRS ## + args = get_args() + + ## Check if Token is present + if not args.token: + exit("token is required") + + ## Get public IP ## + try: + public_ip = requests.get(args.url).text + except: + exit("Can't get public IP") + if not public_ip: + exit("Can't get public IP") + if args.verbose: + print("Public IP is : " + public_ip) + + ## Init api session ## + api_session = requests.session() + api_session.headers['Authorization'] = 'Bearer ' + args.token + + ## Check api connection ## + try: + response = api_session.get("https://api.online.net/api/v1/domain/list") + except: + exit("Can't connect to api") + if "error" in response.json(): + exit(response.json()['error_description']) + + + ## Get records and compare IP ## + records = api_session.get("https://api.online.net/api/v1/domain/" + args.domain + "/zone").json() + if "error" in records: + exit(records['error_description']) + + records_to_update = args.records.split(',') + + old_ip = [x['data'] for x in records if x['name'] in records_to_update and not public_ip in x["data"]] + + if not old_ip: + exit() + + else: + create_new_version(args, records, records_to_update) + + ## Clear inactive versions ## + if args.clean: + clear_versions(args, api_session) + BONUS : acme.sh + api online ---------------------------- -En me documentant sur l'api d'online, je me suis rendu compte qu'acme.sh permet d'utiliser l'api d'Online. +En me documentant sur l'api d'online, je me suis rendu compte qu'acme.sh permet d'utiliser l'api de Scaleway. +Jusqu'à présent je mettais à jour mes certificats à la main tous les 3 mois (avec quelques raté à l'occasion...). +Il n'y a juste besoin du token. + +.. code-block:: console + + $ acme.sh --issue --dns dns_online -d 0w.tf -d "*.0w.tf" --reloadcmd "nginx -s reload" --server letsencrypt --force