それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

adguard home のAPIを叩いて設定を更新する-python

adguard home には APIがある。

python のpip が提供されている。

https://pypi.org/project/adguardhome/

使ってみる(準備)

プロジェクトとpython環境を作成する

mkdir adg
cd adg
pyenv local 3.9.8
pyenv exec python -V
pyenv exec pip install pip --upgrade
pyenv exec pipenv install
pyenv exec pipenv shell

パッケージを入れる

pipenv install adguardhome

使ってみる(ハローワールド)

Hello Worldの代わりに、AdGuard Home のバージョンを取得してみる。

version_sample.py

from adguardhome import AdGuardHome
import os
import asyncio

async def main():

    pw = os.environ.get('adguard_home_pass')
    id = os.environ.get('adguard_home_user')
    async with AdGuardHome("192.168.2.2", port=80,username=id,password=pw) as adguard:

        version = await adguard.version()
        print("AdGuard version:", version)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

実行

$ adguard_home_pass=xxx_login_password_xxx adguard_home_user=admin python3 version_sample.py
AdGuard version: v0.107.5

これでバージョンを取得できるので、APIが呼び出せることがわかる。

HTTPSを有効にする

POSTを使って、API経由で設定を更新してみる。

certbotで作った証明書と秘密鍵を投入してみる。

秘密鍵と証明書はBase64エンコードする必要があるので、そのまま突っ込んでも動かないため、エンコード処理ををした。

sample_enable_tls.py

import base64
import json
import os

from adguardhome import AdGuardHome
import asyncio

async def main():

    """"
        AdGuard Home にCertbotで更新された証明書と鍵を入れる。
    """
    pw = os.environ.get('adguard_home_pass')
    id = os.environ.get('adguard_home_user')
    key_path = os.environ.get('certbot_key_path')
    cert_path = os.environ.get('certbot_fullchain_path')
    async with AdGuardHome("192.168.2.2", port=80,username=id,password=pw) as adguard:

        version = await adguard.version()
        print("AdGuard version:", version)
        await adguard.request('tls/configure',method='POST',data=json.dumps({'enabled':False}))
        #
        key = "\n".join(map(str.strip, open(key_path,'r').readlines()))
        key = str(base64.b64encode(key.encode('utf-8')),'utf-8')
        #
        cert = "\n".join(map(str.strip,open(cert_path,'r').readlines()))
        cert = str(base64.b64encode(cert.encode('utf-8')),'utf-8')
        data = {
            "port_https":         443,
            "port_dns_over_tls":  853,
            "port_dns_over_quic": 784,
            "enabled": True,
            "key_type": "RSA",
            "private_key": key,
            "certificate_chain": cert,
        }
        ret = await adguard.request('tls/configure',method='POST',data=json.dumps(data))
        print(ret)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    

これでAPI経由で、証明書を更新できる。

仕組み

python で作られたパッケージのソース・コードを見たところ、リクエストを投げているだけだった。

仕組みは単純である。

認証はBasic認証

curl -u username:password http://adguard-home.lan:80/

APIは、指定のURLに指定のJSONを投げ込む

バージョン確認は、/control/status にGETリクエストを送るだけである。

curl -u username:password http://adguard-home.lan:80/control/status

これなら、pythonとpipを持ち出さなくても、簡単にcurl でリクエスを作成できそうである。

APIについて

APIは OpenAPI形式でSwaggerの定義ファイルが、公式レポジトリに公開されている

使ったバージョンのAPIは次のとおりである。→https://github.com/AdguardTeam/AdGuardHome/blob/master/openapi/openapi.yaml

参考資料

Python: AdGuard Home API Client

AdGuard Home OpenAPI