Задачи Ansible повторное использование сеанса HTTP из модуля запросов Python

#python #ansible #ansible-inventory

Вопрос:

Задачи Ansible повторное использование сеанса HTTP из запросов Python

Сценарий:

  • Сложный процесс входа в веб-службу с несколькими перенаправлениями и очистками форм (через BeautifulSoup)
  • Файл скрипта Python, использующий модуль запросов с сеансом, для хранения маркеров и файлов cookie успеха для входа в систему для последующих вызовов API веб-службы

Цель:

  • Задача Ansible 1. Выполните скрипт Python для аутентификации веб-службы, верните сеанс HTTPS в Ansible
  • Задача Ansible 2..n: Выполнение API веб-служб с использованием встроенного uri модуля Ansible, используя сеанс HTTPS из

Мысли:

  • Честно говоря, я немного не понимаю, как эффективно структурировать это в Ansible. Возможно, было бы разумно рассмотреть весь скрипт Python для аутентификации в качестве модуля Ansible?

ПРИМЕР СКРИПТА АУТЕНТИФИКАЦИИ НА PYTHON (упрощенный)

 def main():
    import requests

    # Create Session for requests, store all cookies in this object
    https_session = requests.Session()

    if 'page_1' not in globals():
        page_1 = https_session.get(
            'https://login.test.com',
            allow_redirects=True
        )

    ...
    ...
    ...

    if 'redirect_8' not in globals():
        redirect_8 = https_session.post(
            'https://login.test.com/authenticate',
            allow_redirects=True,
        data = {
            "token": response_7['token']
            }
        )

    # Return the Cookie Jar
    return https_session.cookies


main()
 

ПРИМЕР ВЫЗОВА ANSIBLE:

 - name: test1
  script: login.py
  args:
        executable: python3
  environment:
        username: "{{ input_user }}"
        password: "{{ input_pwd }}"
  ignore_errors: yes
  register: login_test

- debug:
    msg: "{{ login_test }}.stdout"
 

ПРИМЕР ВОЗВРАТА К ANSIBLE:

 "
{
    "results": [
        {
            "changed": True,
            "rc": 0,
            "stdout": "<RequestsCookieJar[<Cookie TOKEN=wxyz-wxyz for .home.test.com/>, <Cookie USER_ID=123456789 for .home.test.com/>\n",
            "stdout_lines": [
                "<RequestsCookieJar[<Cookie TOKEN=wxyz-wxyz for .home.test.com/>, <Cookie USER_ID=123456789 for .home.test.com/>, "
            ],
            "stderr": "",
            "stderr_lines": [],
            "failed": False,
            "ansible_loop_var": "item",
        }
    ],
    "skipped": False,
    "changed": True,
    "msg": "All items completed",
}
.stdout"
 

Комментарии:

1. Может return json.dumps(https_session.cookies.get_dict()) быть, это правильный путь? Все еще не понимаю, в каком направлении двигаться / какие варианты доступны для этого варианта использования

Ответ №1:

Это можно было бы красиво завернуть в lookup плагин:

lookup_plugins/session_cookie.py :

 from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = """
  lookup: session_cookie
  author: Author
  options:
    username:
      type: string
      required: True
    password:
      type: string
      required: True
"""

from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
import requests

display = Display()

class LookupModule(LookupBase):
    def run(self, _terms, variables=None, **kwargs):
        self.set_options(var_options=variables, direct=kwargs)

        url_username=self.get_option('username')
        url_password=self.get_option('password')

        https_session = requests.Session()

        # do your custom sutff here
        https_session.get(
            'https://google.com',
            allow_redirects=True
        )

        # retrieve cookies from session an return them
        cookies = https_session.cookies.get_dict()

        return [cookies]


 

И тогда его можно будет использовать в сборнике игр, как это:

playbook.yml

 - name: Get session cookie
  hosts: localhost
  connection: local
  gather_facts: false
  vars:
    password: secret
    user: admin
    cookie: "{{ lookup('session_cookie', username=user, password=password) }}"
  tasks:
    - debug:
         msg: "{{ cookie['1P_JAR'] }}"

 

Запуск его вернет значение файла cookie из сеанса:

 ansible-playbook -i',' playbook.yaml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [Get session cookie] *****************************************************************************************************

TASK [debug] ******************************************************************************************************************
ok: [localhost] => {
    "msg": "2021-09-13-10"
}
 

Я заметил, что requests иногда не очень хорошо играл с разветвлением ansible, см. Проблему ansible, поэтому мне пришлось добавить это env export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES .