понедельник, 2 августа 2021 г.

Nginx прокси и простой bash wrapper для cURL

$ inv get /


{

    "equipment": [

        [

            "novac",

            "thiem",

            "monolith",

            "vega",

            "whale"

        ]

    ]

}

В предыдущем посте я рассказывал как написал простую инвенторку с Flask API и сбилдил ее в Github CI/CD в Docker контейнер, huh?

Сегодня напишем простой wrapper на bash для того, чтобы с этой инвенторкой работать. Так же закончим начатое и настроим прокси.

Сразу к делу. Пост получится малюсенький. 

Сам скрипт: https://github.com/MelHiour/vyos_onbox_scripts/blob/main/inventory.sh

В общем, все прошло успешно и я пользуюсь этим "приложением". Единственное что не очень удобно это пользовать curl. Уж очень длинные получаются команды. Пару человек сказало, что это не юзабельно, что в целом близко к правде.

Можно использовать HTTPie, но я не могу его легко поставить на VyOS. А как раз основной машиной, на которой я этой инвенторкой пользуюсь это VyOS.

Второй момент это безопасность. Конечно нужно прикрутить авторизацию и включить HTTPS.

Nginx reverse proxy

1. Создаем сеть в docker, в которую войдут два контейнера - simple_inventtory и nginx.

docker network create INVENTORY

2. Запускаем наш контейнер в этой сети --net=INVENTORY

cat /srv/simple_inventory/run 

docker run --name simple_inventory \

-d --net=INVENTORY \

-p 5000:5000/tcp \

-v /srv/simple_inventory/data:/app/data \

melhiour1/simple_inventory

3. Создаем конфигурация для NGINX прокси.

Nginx контейнер будет слушать на порту 3000 с включенным SSL. Так же включена базовая аутентификация. Видно что прокси будет отправлять запросы по имени контейнера на порт 5000.

cat /srv/nginx/simple_inventory/conf/nginx.conf

server {

  server_name blah.labnfun.ru;

  listen 3000;

  ssl on;

  ssl_certificate /etc/nginx/conf.d/cert.pem;

  ssl_certificate_key /etc/nginx/conf.d/key.pem;

  client_max_body_size 128M;  

  location / {

     auth_basic          'Credentials please';

     auth_basic_user_file /etc/nginx/conf.d/auth;

     proxy_pass           http://simple_inventory:5000;

  }

}


4. Создаем директорию passwd и создаем логин/пароль

mkdir passwd 

sudo htpasswd -c simple_inventory melhiour


5. У меня есть свои SSL сертификаты на которые я просто делаю симлинк. Структура папок должна получиться такой.

/srv/nginx/simple_inventory/

├── certs

│   ├── cert.pem -> /etc/letsencrypt/live/blah.labnfun.ru/cert.pem

│   └── key.pem -> /etc/letsencrypt/live/blah.labnfun.ru/privkey.pem

├── conf

│   └── nginx.conf

└── passwd

    └── simple_inventory



6. Создаем файлик с командой запуска. Запихиваем контейнер в ту же сеть, где крутиться simple_inventory и подтыкиваем все нужные файлики конфигурации.

docker run --name nginx_simple_inventory \

-d \

--net=INVENTORY \

-v /srv/nginx/simple_inventory/conf:/etc/nginx/conf.d \

-v /srv/nginx/simple_inventory/certs/cert.pem:/etc/nginx/conf.d/cert.pem \

-v /srv/nginx/simple_inventory/certs/key.pem:/etc/nginx/conf.d/key.pem \

-v /srv/nginx/simple_inventory/passwd/simple_inventory:/etc/nginx/conf.d/auth \

-p 3000:3000 \

--restart always \

nginx

7. Запускаем и тестируем. Теперь нужно передавать username в curl, ну и использовать https.

[root@whale ~]# bash /srv/nginx/simple_inventory/run 

458972a8e518c4e7e9659933e958fbcd96d8842cf467af82581dd37455838b61


[root@whale ~]# curl -k -u melhiour https://localhost:3000/inventory/

Enter host password for user 'melhiour':

{"equipment":[["novac","thiem","monolith","vega","whale","public"]]}

Wrapper для curl

Напоминаю, что я буду использовать VyOS, поэтому некоторые пути могут показаться странными, но это не важно. Линукс и есть линукс.

1. Создаем файл .netrc и вписываем в него логин и пароль для нужного хоста. Это позволит не вводить пароль каждый раз.

cat .netrc 

machine whale

    login melhiour

    password ijerkln898erj

2. Создаем сам файл скрипта, добавляем прав на запуск и делаем симлинк для того, чтобы каждый раз не запускать из директории.

touch /config/scripts/inventory.sh

chmod +x /config/scripts/inventory.sh

sudo ln -s /config/scripts/inventory.sh /usr/local/bin/inv

3. Сам скрипт. Нужно поменять _INVENTORY_PATH на нужный и можно пользоваться. Это не что иное как простая подстановка аргументов в нужные команды в зависимости от операции. Плюс json из ответа форматируется python модулем.

cat /config/scripts/inventory.sh


#!/bin/bash

# Usage:

# inv [get|post|put|delete] [json_data(put&post only)] [endpoint]

#

# Exampes:

# inv get /

# inv put '{"type":"VM","os":"Centos"}' /whale

# inv delete /whale


_INVENTORY_PATH=https://whale:3000/inventory


if [ "$1" == "get" ]; then

    curl -kn --silent $_INVENTORY_PATH$2 | python -m json.tool

elif [ "$1" == "post" ]; then

    curl -kn --silent --header "Content-Type:application/json" --request POST --data "$2" $_INVENTORY_PATH$3 | python -m json.tool

elif [ "$1" == "put" ]; then

    curl -kn --silent --header "Content-Type:application/json" --request PUT --data "$2" $_INVENTORY_PATH$3 | python -m json.tool

elif [ "$1" == "delete" ]; then

    curl -kn --silent --header "Content-Type:application/json" --request DELETE $_INVENTORY_PATH$2 | python -m json.tool

else

    echo 'Operation is not supported. Please use [get|put|delete|post]'

fi

А теперь сравним как это работает. Чем сложнее команда, тем очевиднее удобство.

inv get /


$ curl -kn --silent https://whale:3000/inventory/ | python -m json.tool

{

    "equipment": [

        [

            "novac",

            "thiem",

            "monolith",

            "vega",

            "whale"

        ]

    ]

}



$ inv get /

{

    "equipment": [

        [

            "novac",

            "thiem",

            "monolith",

            "vega",

            "whale"

        ]

    ]

}

inv post '{"data"}' /

$ curl -kn --silent --header "Content-Type: application/json" --request POST --data '{"name":"test","eth0":"10.10.10.2/30","eth2":["10.20.30.3/24","10.10.12.2/30"],"type":"firewall","os":"VyOS"}' https://whale:3000/inventory/ | python -m json.tool

{

    "name": "test"

}



$ inv post '{"name":"test1","eth0":"10.10.10.2/30","eth2":["10.20.30.3/24","10.10.12.2/30"],"type":"firewall","os":"VyOS"}' /

{

    "name": "test1"

}



inv delete /endpoint

$ curl -kn --silent --header --request DELETE https://whale:3000/inventory/test | python -m json.tool

{

    "eth0": "10.10.10.2/30",

    "eth2": [

        "10.20.30.3/24",

        "10.10.12.2/30"

    ],

    "name": "test",

    "os": "VyOS",

    "type": "firewall"

}


$ inv delete /test1

{

    "eth0": "10.10.10.2/30",

    "eth2": [

        "10.20.30.3/24",

        "10.10.12.2/30"

    ],

    "name": "test1",

    "os": "VyOS",

    "type": "firewall"

}


Скрипт супер простой, но "юзабилити" увеличивает значительно.

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

Отправить комментарий