Авторизация токена JWT с использованием запросов Python для DockerHub - PullRequest
2 голосов
/ 17 марта 2019

Я обнаружил, что редактирование full_description репозитория DockerHub можно сделать с помощью JavaScript API , и подумал, что это было бы забавным предлогом для изучения пакета requests для python. JavaScript API определенно работает, например, используя этот простой образ докера .

API JS в основном делает

  1. Отправьте запрос POST на https://hub.docker.com/v2/users/login с именем пользователя и паролем. Сервер отвечает token.
  2. Отправьте PATCH запрос на определенный https://hub.docker.com/v2/repositories/{user or org}/{repo}, убедившись, что заголовок имеет Authorization: JWT {token}, и в этом случае с телом содержимого {"full_description":"...value..."}.

Что беспокоит, так это то, что запрос PATCH на стороне python получает ответ 200 от сервера (если вы намеренно установили неверный токен авторизации, вы получите отказ, как и ожидалось). Но его ответ на самом деле содержит текущую информацию (а не пропатченную информацию).

Единственные "открытия", которые я сделал:

  • Если вы добавите отладочный журнал , есть 301. Но это тот же URL для стороны javascript, так что это не имеет значения?

    send: b'{"full_description": "TEST"}'
    reply: 'HTTP/1.1 301 MOVED PERMANENTLY\r\n'
    
  • Маркер, полученный с помощью POST в requests, такой же, как если бы я GET - auth.docker.io, как описано в Получение токена на предъявителя раздел здесь . В частности , я не указал пароль (только что сделал curl -X GET ...). Это не так. Они разные, я не знаю, как я думал, что они были одинаковыми.

Этот второй заставляет меня чувствовать, что я пропускаю шаг. Как мне нужно расшифровать токен или что-то? Я не знаю, что еще с этим делать, особенно ответ 200 от PATCH, несмотря на отсутствие изменений.

код:

import json
from textwrap import indent
import requests


if __name__ == "__main__":
    username = "<< SET THIS VALUE >>"
    password = "<< SET THIS VALUE >>"
    repo = "<< SET THIS VALUE >>"

    base_url = "https://hub.docker.com/v2"
    login_url = f"{base_url}/users/login"
    repo_url = f"{base_url}/repositories/{username}/{repo}"

    # NOTE: if I use a `with requests.Session()`, then I'll get
    # CSRF Failed: CSRF token missing or incorrect
    # Because I think that csrftoken is only valid for login page (?)
    # Get login token and create authorization header
    print("==> Logging into DockerHub")
    tok_req = requests.post(login_url, json={"username": username, "password": password})
    token = tok_req.json()["token"]
    headers = {"Authorization": f"JWT {token}"}

    print(f"==> Sending PATCH request to {repo_url}")
    payload = {"full_description": "TEST"}
    patch_req = requests.patch(repo_url, headers=headers, json=payload)
    print(f"    Response (status code: {patch_req.status_code}):")
    print(indent(json.dumps(patch_req.json(), indent=2), "    "))
...