LINUX.ORG.RU
решено ФорумAdmin

Помощь изогнутым рукам: валидация параметров команды в Bash

 ,


3

2

Есть куча команд, которые страшно выполнить неправильно.

Для конкретики выберу только одну: страшно сделать ssh-copy-id без параметра -i (путь до ключа), где путь до ключа - один из заранее определенного набора (~/.ssh/valid_key_1.rsa.pub, ~/.ssh/valid_key_2.rsa.pub).

Можно ли как-нибудь в баше сделать так, чтобы он валидировал все вводимые команды, и если ssh-copy-id запущен с неверными параметрами - не давал бы выполнить такую команду?

★★★★☆

cmd="la-la-la some-hacker-command"
case "$cmd" in
    la-la-la)
        echo "OK"
    ;;
    *)
        echo "ERROR: your command is incorect: ${cmd}"
    ;;
esac
joy4eg ★★★★★
()

А еще посмотри в сторону clish/klish

joy4eg ★★★★★
()

т.е. в данном конкретном случае ты боишься нечаянно закинуть.ssh/identity.pub на удалённый хост?

zolden ★★★★★
()

Откуда bash знает, какие параметры ssh-copy-id правильные?

Я так понимаю, команды запускаются скриптом. Можно:

1) Останавливать скрипт после первой команды, выполнившейся с ненулевым кодом возврата: set -e.

2) Запретить неинициализированные переменные: set -u

Вообще, почитай man set, там почти все параметры полезны при криворукости.

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

у разных хостов разные ключи. Ключи присылают заказчики, когда дают доступ по ssh до сервера. Я боюсь случайно закинуть одному заказчику ключ другого заказчика. Например, если вообще не указать -i, то ssh будет автоматически искать подходящий ключ, и это совсем не всегда будет id_rsa.pub

вообще, это был чисто пример, чтобы было о чем говорить. rm -rf /* я боюсь не меньше. Иногда руки печатают удивительные вещи, которых ты на самом деле совершенно не хочешь :)

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от mtk

Откуда bash знает, какие параметры ssh-copy-id правильные?

ну естественно для проверки нужно написать скрипт.

как бы объяснить по аналогии. Вот в системах контроля версий есть pre-commit-hook, который не позволяет коммиту закоммититься, если скрипт отработал и вернул лошь.

я хочу найти такую же фичу для баша. pre-execute-hook. Чтобы команда свалилась моему скрипту, я в этом скрипте распарсил параметры и если они неверные - вернул сообщение об ошибке башу. И чтобы баш мне соответственно написал это сообщение об ошибке «извините, вы забыли указать параметр -i, поэтому я вашу команду выполнять не стану».

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от stevejobs

pre-execute-hook

Насчет bash не знаю, но в zsh есть хуки: precmd, preexec. Их используют преимущественно для обновления prompt/title, например: oh-my-zsh.

Можно сделать как-то так:

#!/bin/zsh
autoload -U add-zsh-hook

function ssh-copy-id-validate() {
  # здесь проверка валидности $@ для ssh-copy-id
}

# остальные валидаторы
...

function preexec_validate() {
  case "$1" in
    ssh-copy-id)
      ssh-copy-id-validate "$@"
      ;;
    # здесь остальные валидаторы
}

add-zsh-hook preexec preexec_validate
Осталось понять, как прерывать выполнение невалидных команд.

mtk
()
Последнее исправление: mtk (всего исправлений: 1)
Ответ на: комментарий от mtk

Вот рабочий прототип:

#!/bin/zsh
autoload -U add-zsh-hook

# допустим, мы хотим избежать выполнения mycmd при $1!=$2
function mycmd() {
  if (($1!=$2)); then
    echo "forbidden"
  else
    echo "$@"
  fi
}

# запретить исполнение mycmd если $1!=$2
function mycmd_validate() {
  # извлекаем первые два аргумента
  local arg1=$(echo "$cmd" | cut -d ' ' -f2)
  local arg2=$(echo "$cmd" | cut -d ' ' -f3)
  if (($arg1!=$arg2)); then
    echo "$@: invalid mycmd invocation"
    exit 1
  fi
}

# запретить исполнение rm если $1 начинается на 'a'
function rm_validate() {
  # извлекаем первый аргумент
  local arg1=$(echo "$cmd" | cut -d ' ' -f2)
  if [[ $arg1 == a* ]]; then
    echo "$@: invalid rm invocation"
    exit 1
  fi
}

function preexec_validate() {
  # команда со всеми аргументами содержится в $2
  local cmd=$2
  # извлекаем название команды
  local arg0=$(echo "$cmd" | cut -d ' ' -f1)
  case "$arg0" in
    mycmd)
      mycmd_validate "$cmd"
      ;;
    rm)
      rm_validate "$cmd"
      ;;
  esac
}

add-zsh-hook preexec preexec_validate

# Тест
mycmd 1 1 # OK
mycmd 1 2 # FAIL

rm b # OK
rm a # FAIL
Запрещаем исполнение mycmd если $1!=$2, запрещаем вызов rm если аргумент начинается с символа 'a'. Ничего лучше чем делать «exit 1» при ишибке валидации не придумал.

mtk
()

Кстати, возникла идея опен-сорц проекта: понаписать таких валидаторов на все популярные команды, и выложить на гитхаб (под названием krivye_ruki.git). Пусть комьюнити добавляет свои валидаторы.

Например, криворукий админ пробует ввести:

rm -rf a *
а шелл его переспрашивает:
$USER, did you meant "rm -rf a*" [Y/N]?
To disable this warning in future, add "IGNORE_RULE_RM106=1" to ~/.zshrc

mtk
()
Последнее исправление: mtk (всего исправлений: 1)
Ответ на: комментарий от mtk
$USER, did you meant "rm -rf a*" [Y]es/[N]o/[I]gnore?

и добавлять в ~/.zshrc автоматически

stevejobs ★★★★☆
() автор топика

Есть куча команд, которые страшно выполнить неправильно.

начни делать бекапы.

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

Кстати, возникла идея опен-сорц проекта: понаписать таких валидаторов на все популярные команды, и выложить на гитхаб (под названием krivye_ruki.git)

вы нашли друг друга…

emulek
()
Ответ на: комментарий от stevejobs
 # .bashrc
function ssh-copy-id
{
  # Валидируешь параметры
  # ...
  # 

  if [[ "$parameters" == "valid" ]]; then
    command ssh-copy-id $@
  else
    echo "Идите нафиг"
  fi
}

Не?
И работает даже на bash. Сам так сделал wrapper для rsync, правда пока только с одним набором аргументов.

nexfwall ★★★★
()
Последнее исправление: nexfwall (всего исправлений: 2)
Ответ на: комментарий от stevejobs

Я боюсь случайно закинуть одному заказчику ключ другого заказчика.

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

а так да, некоторые есть команды весьма забавные, например crontab -e/-r, но тут уж как повезет, ну или не повезет. очень помогает логирование в putty - по нему иногда можно отследить содержимое файлов или то какие именно изменения были сделаны.

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

представь: тебе для соединения с сервером дали публичный и приватный ключ. Это значит, что у кого-то еще есть тот же самый приватный ключ. И тут ты случайно заливаешь его на сервер другого заказчика. Получается, один заказчик сможет зайти на сервер другого заказчика. А они конкуренты, и он с радостью там всё отформатирует.

stevejobs ★★★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.