LINUX.ORG.RU
ФорумJob

[решено] Нужен человек пишущий на bash

 ,


2

2

Приветствую!

Нужно переписать скрипт работающий с https/ssl сертификатами на устройствах микротик. Скрипт работает в среде linux, выполняет задачу - получить(обновить) сертификаты (в частности у letsencript), авторизоваться на микротике по ssh ключу, добавить сертификаты в микротик(удалить старые, добавить новые), дальше удаляет сертификаты у себя. Скрипт работает с отдельным файлом конфигурации. Сейчас скрипт работает с одним устройством микротик(одним файлом конфигурации). Скрипт: letsencrypt-routeros.sh

#!/bin/bash
CONFIG_FILE=letsencrypt-routeros.settings

if [[ -z $1 ]] || [[ -z $2 ]] || [[ -z $3 ]] || [[ -z $4 ]] || [[ -z $5 ]]; then
echo -e "Usage: $0 or $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]\n"
source $CONFIG_FILE
else
ROUTEROS_USER=$1
ROUTEROS_HOST=$2
ROUTEROS_SSH_PORT=$3
ROUTEROS_PRIVATE_KEY=$4
DOMAIN=$5
fi

if [[ -z $ROUTEROS_USER ]] || [[ -z $ROUTEROS_HOST ]] || [[ -z $ROUTEROS_SSH_PORT ]] || [[ -z $ROUTEROS_PRIVATE_KEY ]] || [[ -z $DOMAIN ]]; then
echo "Check the config file $CONFIG_FILE or start with params: $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]"
echo "Please avoid spaces"
exit 1
fi

CERTIFICATE=/etc/letsencrypt/live/$DOMAIN/cert.pem
KEY=/etc/letsencrypt/live/$DOMAIN/privkey.pem
CHAIN=/etc/letsencrypt/live/$DOMAIN/chain.pem


#Create alias for RouterOS command
routeros="ssh -i $ROUTEROS_PRIVATE_KEY $ROUTEROS_USER@$ROUTEROS_HOST -p $ROUTEROS_SSH_PORT"

#Check connection to RouterOS
$routeros /system resource print
RESULT=$?

if [[ ! $RESULT == 0 ]]; then
echo -e "\nError in: $routeros"
echo "More info: https://wiki.mikrotik.com/wiki/Use_SSH_ ... key_login)"
exit 1
else
echo -e "\nConnection to RouterOS Successful!\n"
fi

if [ ! -f $CERTIFICATE ] && [ ! -f $KEY ]; then
echo -e "\nFile(s) not found:\n$CERTIFICATE\n$KEY\n"
echo -e "Please use CertBot Let'sEncrypt:"
echo "============================"
echo "certbot certonly --preferred-challenges=dns --manual -d $DOMAIN --manual-public-ip-logging-ok"
echo "or (for wildcard certificate):"
echo "certbot certonly --preferred-challenges=dns --manual -d *.$DOMAIN --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory"
echo "==========================="
echo -e "and follow instructions from CertBot\n"
exit 1
fi

# Remove previous certificate
$routeros /certificate remove [find name=$DOMAIN.pem_0]

# Create Certificate
# Delete Certificate file if the file exist on RouterOS
$routeros /file remove $DOMAIN.pem > /dev/null
# Upload Certificate to RouterOS
scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CERTIFICATE" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.pem"
sleep 2
# Import Certificate file
$routeros /certificate import file-name=$DOMAIN.pem passphrase=\"\"
# Delete Certificate file after import
$routeros /file remove $DOMAIN.pem

# Create Key
# Delete Certificate file if the file exist on RouterOS
$routeros /file remove $KEY.key > /dev/null
# Upload Key to RouterOS
scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$KEY" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN.key"
sleep 2
# Import Key file
$routeros /certificate import file-name=$DOMAIN.key passphrase=\"\"
# Delete Certificate file after import
$routeros /file remove $DOMAIN.key

# Create Chain
# Delete Chain file if the file exist on RouterOS
$routeros /file remove $DOMAIN-chain.pem> /dev/null
# Upload Chain to RouterOS
scp -q -P $ROUTEROS_SSH_PORT -i "$ROUTEROS_PRIVATE_KEY" "$CHAIN" "$ROUTEROS_USER"@"$ROUTEROS_HOST":"$DOMAIN-chain.pem"
sleep 2
# Import Chain file
$routeros /certificate import file-name=$DOMAIN-chain.pem passphrase=\"\"
# Delete Chain file after import
$routeros /file remove $DOMAIN-chain.pem

# Setup Certificate to SSTP Server
#$routeros /interface sstp-server server set certificate=$DOMAIN.pem_0
$routeros /ip service set www-ssl certificate=$DOMAIN.pem_0
$routeros /ip hotspot profile set hsprof1 login-by=https ssl-certificate=$DOMAIN.pem_0

exit 0
Файл конфигурации: letsencrypt-routeros.settings
ROUTEROS_USER=admin
ROUTEROS_HOST=10.0.254.254
ROUTEROS_SSH_PORT=22
ROUTEROS_PRIVATE_KEY=/opt/letsencrypt-routeros/id_dsa
DOMAIN=vpnserver.yourdomain.com
Пример выполнения скрипта:
uptime: 6w6d22h11m15s
version: 6.44 (stable)
build-time: Feb/25/2019 14:11:04
factory-software: 6.36.1
free-memory: 202.0MiB
total-memory: 256.0MiB
cpu: MIPS 1004Kc V2.15
cpu-count: 4
cpu-frequency: 880MHz
cpu-load: 6%
free-hdd-space: 4848.0KiB
total-hdd-space: 16.3MiB
write-sect-since-reboot: 19348
write-sect-total: 41673
bad-blocks: 0%
architecture-name: mmips
board-name: hEX
platform: MikroTik


Connection to RouterOS Successful!

certificates-imported: 1
private-keys-imported: 0
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0

certificates-imported: 0
private-keys-imported: 1
files-imported: 1
decryption-failures: 0
keys-with-no-certificate: 0

certificates-imported: 0
private-keys-imported: 0
files-imported: 0
decryption-failures: 0
keys-with-no-certificate: 0 
Нужно научить работать скрипт с несколькими файлами конфигурации вида letsencrypt-routeros_ХХ.settings(несколькими устройствами микротик) При этом скрипт должен !!!Только Один раз обращаться к серверу letsencript за обновлением серификатов(иначе ip инициатора забанят). Дальше поэтапно(именно поэтапно - с одним закончил перешел к следующему) обновляет все устройства в соответствии с файлами конфигурации, в файл лога пишет отчет о выполнении по каждому конфиг файлу, дальше удаляет серты у себя. Источник кода

(Не проверял) Во второй строке после шебанга:

[ -z "$CONFIG_FILE" ] && CONFIG_FILE=letsencrypt-routeros.settings

Дальше из шела или из крона запускается так:

CONFIG_FILE=/path/letsencrypt-routeros_XX.settings /path/letsencrypt-routeros.sh >>/path/letsencrypt-routeros.sh.log

Лог пишется в /path/letsencrypt-routeros.sh.log. Это ничего не стоит.

aleksey_tulinov ()
Ответ на: комментарий от aleksey_tulinov

aleksey_tulinov, и всего делов - добавить одну строчку?

volant ()
Ответ на: комментарий от volant

Заменить, вот эту строку после шебанга:

CONFIG_FILE=letsencrypt-routeros.settings

заменить на вот эту строку:

[ -z "$CONFIG_FILE" ] && CONFIG_FILE=letsencrypt-routeros.settings

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

aleksey_tulinov ()
Ответ на: комментарий от aleksey_tulinov

все понял, благодарю Вас! скайп nikvolant киньте, пожалуйста, сюда реквизиты(какие удобно) и сумму

volant ()
Ответ на: комментарий от aleksey_tulinov

не получается у меня - определенно чего то не догоняю...

вот начало конфига скрипта

#!/bin/bash
[ -z "$CONFIG_FILE" ] && CONFIG_FILE=letsencrypt-routeros.settings

if [[ -z $1 ]] || [[ -z $2 ]] || [[ -z $3 ]] || [[ -z $4 ]] || [[ -z $5 ]]; then
        echo -e "Usage: $0 or $0 [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]\n"
        source $CONFIG_FILE
else
        ROUTEROS_USER=$1
        ROUTEROS_HOST=$2
        ROUTEROS_SSH_PORT=$3
        ROUTEROS_PRIVATE_KEY=$4
        DOMAIN=$5

сам скрипт и конфиг файлы лежат в /opt/letsencrypt-routeros/ каталог добавил в path, вывод терминала:

root@nvr:~# echo $PATH
/opt/letsencrypt-routeros:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
файлы исполняемые, вывод терминала:
root@nvr:~#  ls -l /opt/letsencrypt-routeros
итого 16
-rwxr-xr-x 1 root root  158 сен 17 17:37 letsencrypt-routeros_01.settings
-rwxr-xr-x 1 root root  158 сен 17 17:38 letsencrypt-routeros_02.settings
-rwxr-xr-x 1 root root 3685 сен 18 09:56 letsencrypt-routeros.sh
-rw-r--r-- 1 root root    0 сен 17 17:53 letsencrypt-routeros.sh.log
-rw------- 1 root root  668 сен 16 21:45 vpn_key
если в терминале запускаю CONFIG_FILE=/path/letsencrypt-routeros_XX.settings /path/letsencrypt-routeros.sh получаю ошибку bash:
-bash: /path/letsencrypt-routeros.sh: Нет такого файла или каталога
если в терминале запущу скрипт с явным указанием пути, скрипт начинает выполняться, но спотыкается на 6й строке:
root@nvr:~# /opt/letsencrypt-routeros/letsencrypt-routeros.sh
Usage: /opt/letsencrypt-routeros/letsencrypt-routeros.sh or /opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]

/opt/letsencrypt-routeros/letsencrypt-routeros.sh: строка 6: letsencrypt-routeros.settings: Нет такого файла или каталога
Check the config file letsencrypt-routeros.settings or start with params: /opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]
Please avoid spaces
Что я делаю не так?

Пните, пожалуйста, в нужном направлении...

volant ()
Ответ на: комментарий от volant

/opt/letsencrypt-routeros/ - вместо /path/ letsencrypt-routeros.settings файл должен лежать в том же каталоге, что и скрипт letsencrypt-routeros.sh

engine ()

А если кто-то пишет на bash, стесняясь, то не подойдёт?

да-да, оффтоп, но с таким-то заголовком, да и тема уже решена

annerleen ★★★★ ()
Ответ на: комментарий от engine

понял, спасибо! начало запускаться, но все равно спотыкается на 6й строке

конфиг файлы имеют имя letsencrypt-routeros_01.settings, letsencrypt-routeros_02.settings и тд и лежат в одном каталоге со скриптом letsencrypt-routeros.sh

root@nvr:~# CONFIG_FILE=/opt/letsencrypt-routeros/letsencrypt-routeros_XX.settings /opt/letsencrypt-routeros/letsencrypt-routeros.sh
Usage: /opt/letsencrypt-routeros/letsencrypt-routeros.sh or /opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]

/opt/letsencrypt-routeros/letsencrypt-routeros.sh: строка 6: /opt/letsencrypt-routeros/letsencrypt-routeros_XX.settings: Нет такого файла или каталога
Check the config file /opt/letsencrypt-routeros/letsencrypt-routeros_XX.settings or start with params: /opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]
Please avoid spaces
volant ()
Ответ на: комментарий от engine

letsencrypt-routeros.settings файл должен лежать в том же каталоге, что и скрипт letsencrypt-routeros.sh

Как такового файла letsencrypt-routeros.settings в каталоге нет. В каталоге файлы вида letsencrypt-routeros_ХХ.settings

задача, что бы скрипт отрабатывал по нескольким конфиг файлам вида letsencrypt-routeros_ХХ.settings, а не по одному файлу letsencrypt-routeros.settings

volant ()
Ответ на: комментарий от volant

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

root@nvr:~# CONFIG_FILE=/opt/letsencrypt-routeros/letsencrypt-routeros_02.settings /opt/letsencrypt-routeros/letsencrypt-routeros.sh
Usage: /opt/letsencrypt-routeros/letsencrypt-routeros.sh or /opt/letsencrypt-routeros/letsencrypt-routeros.sh [RouterOS User] [RouterOS Host] [SSH Port] [SSH Private Key] [Domain]

ssh: connect to host 192.168.99.210 port 2231: Connection refused
а с маской в команде работать не хочет...

как поправить?

volant ()
Ответ на: комментарий от volant

Не надо копипастить команды с форума в шел под рутом, это плохо закончится.

letsencrypt-routeros_ХХ.settings - это не маска, маской было бы letsencrypt-routeros_*.settings, но шел работает с такими масками не так как кажется. Маска не передаётся в скрипт, перед запуском скрипта шел разворачивает маску в список файлов: `script.sh file_*` разворачивается в `script.sh file_01 file_03 file_07`, в зависимости от того какие файлы существуют на диске, затем скрипт вызывается с этими параметрами как если бы они были указаны вручную в командной строке. В переменной окружения такая подстановка работать не будет, но развернуть список файлов можно так:

for FILE in file_*; do  # "in $@" если файлы передаются параметрами
	# тут вместо echo $FILE вызов нужного скрипта
	echo $FILE
done

Я Вам советую создать тему в Admin и позадавать там вопросы, эти вещи так же возможно нагуглить, но Вас интересует не только модификация скрипта, а обновление сертификатов от letsencrypt в целом, я предполагаю, что это типовая задача коротую кто-то уже неоднократно решал и сможет либо ответить на Ваши вопросы, либо дать ссылку на описание всего процесса.

Если Вы всё же решите искать человека уверенно пищущего на баш - будьте осторожны, мало ли что, может Вам уверенно напишут баш-портянку, это не то, что обычно хотят получить. Судя по коментариям в этом топике Вы ищете системного администратора который наладит автоматическое обновление сертификатов.

aleksey_tulinov ()
Ответ на: комментарий от volant

Предлагаю помощь за 5 тыр) По срокам - за вечер управлюсь. В скайп отписал.

Mike_RM ()

Если установить vault, то задачу можно рещить обратным путем. Микротики могут делать запрос и получать ключ по json.

Nurmukh ★★ ()
Ответ на: комментарий от aleksey_tulinov

aleksey_tulinov, благодарю Вас за разъяснения!

но Вас интересует не только модификация скрипта, а обновление сертификатов от letsencrypt в целом

меня интересует только модификация скрипта. Обновление сертификата я настроил, сам скрипт, в его оригинальном варианте, протестировал - конечное устройство(микротик) получило файлы. В последнем приведенном мной примере, где скрипт отрабатывает, я просто закрыл порт ssh на конечном устройстве, что бы скрипт не достучался к нему.

Если Вы всё же решите искать человека уверенно пищущего на баш - будьте осторожны, мало ли что, может Вам уверенно напишут баш-портянку, это не то, что обычно хотят получить.

Хочу просить Вас дописать скрипт - на коммерческой основе, что бы он выполнял поставленную задачу - последовательно отрабатывал по конфиг файлам

volant ()

Примерное видение скрипта.

Для начала опеределяем переменную CONFIG_FILE_PATH=/path_to_folder/with_configs

Все конфиги лежат в данной папке, скрипт работает по файлам из данной директории.

Затем, создаем массив данных с кол-вом файлов и названием файлов в директории.

while IFS= read -r line; do
  CONFIG_ARRAY+=("$line")
done < <(ls "$CONFIG_FILE_PATH")

Проверяем корректность заполнения массива.

declare -p CONFIG_ARRAY

В отдельную функцию выводим запрос сертификатов с LetsEncrypt. Я так понимаю сертификаты запрашиваются в одном екземпляре и далее разбрасываются по всем микротикам.

Затем в отдельную функцию запихиваем функцию (здесь цикл) которая распихивает файлы по микротам. Отдельное логирование на каждый микрот в свой файл.

А вообще, для таких задач и ansible можно чутка поднять.

i3wm ()
Ответ на: комментарий от volant

Собственно, вопрос решен! Спасибо всем, кто помогал! Выложу здесь решение, возможно кому то пригодится.

В оригинал скрипта внесено изменение - закомментирована строка которая задаёт путь/имя файла с настройками: #CONFIG_FILE=letsencrypt-routeros.settings Для запуска скрипта letsencrypt-routeros.sh используется скрипт letsencrypt-routeros_xx.sh в котором через переменную окружения CONFIG_FILE передаётся имя/путь к файлу с настройками:

#!/bin/bash

export CONFIG_FILE=letsencrypt-routeros_01.settings;./letsencrypt-routeros.sh
export CONFIG_FILE=letsencrypt-routeros_02.settings;./letsencrypt-routeros.sh
export CONFIG_FILE=letsencrypt-routeros_03.settings;./letsencrypt-routeros.sh

И второй вариант скрипта letsencrypt-routeros_xx.sh, более удобный:

#!/bin/bash

path='.'
file_mask='*.settings'
for file in `find $path -type f -name "$file_mask" | sort -n`
do
    export CONFIG_FILE=$file;./letsencrypt-routeros.sh
done

Отдельное спасибо за помощь и разъяснения aleksey_tulinov!

volant ()
Ограничение на отправку комментариев: только для зарегистрированных пользователей, score>=0