Хранение паролей всегда было головной болью. В классическом варианте у вас есть пользователь, который очень старается не забыть жутко секретный «qwerty123» и информационная система, которая хранит хеш от этого пароля. Хорошая система еще и заботливо солит хеши, чтобы отравить жизнь нехорошим людям, которые могут украсть базу с хешированными паролями. Тут все понятно. Какие-то пароли храним в голове, а какие-то засовываем в зашифрованном виде в keepass.

Все меняется, когда мы убираем из схемы человека, который старательно вводит ключ с бумажки. При взаимодействии двух информационных систем, на клиентской стороне в любом случае должен храниться пароль в открытом для системы виде, чтобы его можно было передать и сравнить с эталонным хешем. И вот на этом этапе админы обычно открывают местный филиал велосипедостроительного завода и начинают старательно прятать, обфусцировать и закапывать секретный ключ в коде скриптов. Многие из этих вариантов не просто бесполезны, но и опасны. Я попробую предложить удобное и безопасное решение этой проблемы для python. И чуть затронем powershell.

Как делать не надо


Всем знакома концепция «временного скриптика». Вот буквально только данные по-быстрому распарсить из базы и удалить. А потом внезапно выясняется, что скрипт уже из dev-зоны мигрировал куда-то в продакшен. И тут начинают всплывать неприятные сюрпризы от изначальной «одноразовости».

Чаще всего встречается вариант в стиле:

db_login = 'john.doe'
password = 'password!'

Проблема в том, что здесь пароль светится в открытом виде и достаточно просто обнаруживается среди залежей старых скриптов автоматическим поиском. Чуть более сложный вариант идет по пути security through obscurity, с хранением пароля в зашифрованном виде прямо в коде. При этом расшифровка обратно должна выполняться тут же, иначе клиент не сможет предъявить этот пароль серверной стороне. Такой способ спасет максимум от случайного взгляда, но любой серьезный разбор кода вручную позволит без проблем вытащить секретный ключ. Код ниже спасет только от таких «shoulder surfers»:

>>> import base64
>>> print base64.b64encode("password")
cGFzc3dvcmQ=
>>> print base64.b64decode("cGFzc3dvcmQ=")
password

Самый неприятный сценарий — использования систем контроля версии, например git, для таких файлов с чувствительной информацией. Даже, если автор решит вычистить все пароли — они останутся в истории репозитория. Фактически, если вы запушили в git файл с секретными данными — можете автоматически считать их скомпрометированными и немедленно начинать процедуру замены всех затронутых credentials.

Использование системного хранилища


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

  • KDE4 & KDE5 KWallet (требуется dbus)
  • Freedesktop Secret Service — множество DE, включая GNOME (требуется secretstorage)
  • Windows Credential Locker
  • macOS Keychain

Также можно использовать альтернативные бэкенды или написать свой, если уж совсем что-то странное требуется.

Сравним сложность атаки


При хранении пароля непосредственно в скрипте нужно:

  1. Похитить сам код (легко)
  2. Деобфусцировать при необходимости (легко)

При использовании локального keyring злоумышленнику нужно:

  1. Похитить сам код (легко)
  2. Деобфусцировать при необходимости (легко)
  3. Скомпрометировать локальную машину, залогинившись под атакуемым пользователем (сложно)

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

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


import argparse
import getpass
import keyring


def parse_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("-n", "--newpass", required=False, help="Set new password", action="store_true")
    arguments = parser.parse_args()
    return arguments


def fake_db_connection():
    # Функция, имитирующая подключение к базе данных или что-то подобное
    db_name = 'very_important_db'
    db_host = '147.237.0.71'
    passwd = keyring.get_password(systemname, username)

    print('Connecting to db: {}'.format(db_name))
    print('Using very secret password from vault: {}'.format(passwd))
    print('Doing something important...')
    print('Erasing the database...')
    print('Task completed')


# Объявляем дефолтные переменные
systemname = 'important_database'
username = 'meklon'

args = parse_arguments()

# Записываем в хранилище пароль, если активирован параметр --newpass
if args.newpass:
    # Безопасно запрашиваем ввод пароля в CLI
    password = getpass.getpass(prompt="Enter secret password:")

    # Пишем полученный пароль в хранилище ключей
    try:
        keyring.set_password(systemname, username, password)
    except Exception as error:
        print('Error: {}'.format(error))

# Подключаемся к базе с помощью пароля из системного хранилища
fake_db_connection()


Безопасный ввод пароля


Еще один частый вариант утечки секретных паролей — история командной строки. Использование стандартного input здесь недопустимо:

age = input("What is your age? ")
print "Your age is: ", age
type(age)

>>output
What is your age? 100
Your age is:  100
type 'int'>

В примере выше я уже упоминал библиотеку getpass:

# Безопасно запрашиваем ввод пароля в CLI
password = getpass.getpass(prompt="Enter secret password:")

Ввод данных при ее использовании аналогичен классическому *nix подходу при входе в систему. Ни в какие системные логи данные не пишутся и не отображаются на экране.

Немного о Powershell


Для Powershell правильным вариантом является использование штатного Windows Credential Locker.
Реализуется это модулем CredentialManager.

Пример использования:

Install-Module CredentialManager -force
New-StoredCredential -Target $url -Username $ENV:Username -Pass ....
Get-StoredCredential -Target .... 

Комментарии (81)


  1. KorP
    14.01.2019 11:50
    +1

    С пол года как перешёл на использование keyring, пока претензий нет


  1. virtual_hack2root
    14.01.2019 11:57
    +1

    Я думаю, что стандартный, подход в DevOps заколючется как раз не в раскрытии приватной информации, с последующей ее защитой с помощью keyring, а в том, чтобы изначально параметризовать скрипты, (причем — любые: bash, powershell, python, Docker, и т.д.), с помощью настраиваемых переменных окружения, и предоставлении доступа к ним через Web IDE / Web UI и программный доступ по API для параметризации. Данный подход реализован в GitLab, Azure, Google Cloud, Digital Ocean, GitHub


    1. Meklon
      14.01.2019 11:59

      Подожди, ну вот у нас есть взаимодействие Machine2Machine. Одна сторона у тебя в любом случае должна иметь пароль. Оператора, который вобьет его интерактивно нет. Пароль в виде параметра скрипта как-то несекьюрно использовать. Как минимум будет светиться в history.


      1. virtual_hack2root
        14.01.2019 12:01
        +1

        Не будет, так так там будет светиться что-то вроде ${CI_GITLAB_PASSWORD}, а не пароль, а само значение ${CI_GITLAB_PASSWORD} можно забить как на источнике так и на целевой машине.


        1. Meklon
          14.01.2019 12:02

          А CI_GITLAB_PASSWORD где физически хранится?


          1. virtual_hack2root
            14.01.2019 12:03

            в переменных окружения для выполняемого процесса


            1. Meklon
              14.01.2019 12:14

              А переменные привязаны к локальной машине?


              1. virtual_hack2root
                14.01.2019 12:28

                Нет, это завилит от конкретого pipeline, и CI, они настраиваются в конфигураторе конкретного CI, и фактически работают внутри контейнера, и могут располагаться как в облаке, так и на конкретной машине, на которой запущен агент CI, то есть это полностью зависит от того, как сконфигурирован конкретный агент (Azure, GitlLab, Jenkins позволяют установку локальных агентов не в облако а на конкретную машину, в зависимости от настроек агента, агент может либо требовать совместную настройку Docker-а, если работает в режиме ВМ, Docker/Docker Swarm ноды/ ноды кластера Kubertenes (GlitLab), либо нет, если работает в режиме remote shell, с прямым доступом к локальной оболочке ОС), так что с точки зрения Azure, GitHub и Google Cloud, происходит передача информации ("возьми пароль из переменной окружения x для подключения к БД у") вместо ("возьми пароль x для подключения к БД у")


                Пример (там есть пример настройки БД):


                Testing a Phoenix application with GitLab CI/CD


                Обрати внимение на


                variables:
                  POSTGRES_DB: test_test
                  POSTGRES_HOST: postgres
                  POSTGRES_USER: postgres
                  POSTGRES_PASSWORD: "postgres"
                  MIX_ENV: "test"

                их можно заменить на переменные окружения


                variables:
                  POSTGRES_DB: $CI_POSTGRES_DB
                  POSTGRES_HOST: $CI_POSTGRES_HOST
                  POSTGRES_USER: $CI_POSTGRES_USER
                  POSTGRES_PASSWORD: $CI_POSTGRES_PASSWORD
                  MIX_ENV: $CI_MIX_ENV


                1. Meklon
                  14.01.2019 12:59

                  Ага, спасибо, почитаю. Хотя, имхо, сложность компрометации эквивалентна варианту с keyring.


                1. skovpen
                  15.01.2019 17:22

                  и что произойдёт, если в пуллреквесте будет в CI-скрипте добавлена строчка злоумышленником?

                  echo $CI_POSTGRES_PASSWORD


                  1. gecube
                    15.01.2019 17:32

                    Вы просто мерж реквест не принимаете и все довольны.


                    1. skovpen
                      15.01.2019 17:35
                      +1

                      Много Вы проектов видели, где пуллреквест проверяется CI только после ручного просмотра?


                      1. gecube
                        15.01.2019 17:41

                        Вы имеете в виду, что пуллреквест тоже прогоняется через CI — и это риск утечки данных?
                        Ну, да, есть такое, но проблема в Gitlab (одно из решений) решается следующими способами:


                        • переменную можно объявить как protected
                        • это дает возможность видеть ее ТОЛЬКО на protected runner (нужно их завести и пометить)
                        • и нужно пометить ветки как protected и назначить права на пользователей (кто куда может пушить код).
                        • далее аккуратно принимать мерж реквесты.

                        Ну, и коли Вы не доверяете своей команде разработчиков, которая и так скорее всего имеет доступ на продакшн и может залить любой вредоносный код (гораздо посерьезнее, чем просто отображение пароля к продовой базе), то у Вас проблемы ГОРАЗДО более серьезные, чем утечка паролей...


                        1. skovpen
                          15.01.2019 17:50

                          я больше про opensource и публичные репозитории.


                          1. gecube
                            15.01.2019 21:29

                            Публичными репозиториями вообще опасно пользоваться. Та же история с leftpad. Поэтому они вне контекста разговора.


            1. worldmind
              14.01.2019 18:30

              И кто устанавливает эти переменные окружения?
              Если конфиг с открытым паролем, то это хуже предложенного способа.


              1. virtual_hack2root
                14.01.2019 18:53
                +1

                пароли устанавливает тот же человек, который настраивает пайплайн сборки, но не в скриптах, а в переменных окружения, используемых при сборке, взаимодействие узлов может осуществляеться в таком случает через использование пременных окружения из защифроманной памяти виртуальной машины (Google Cloud).


                1. worldmind
                  14.01.2019 19:25

                  > а в переменных окружения, используемых при сборке

                  это только ждля случая с докером годиться


              1. Tangeman
                14.01.2019 22:51

                Если конфиг с открытым паролем, то это хуже предложенного способа.

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


    1. Sap_ru
      14.01.2019 18:47
      +6

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


      1. virtual_hack2root
        14.01.2019 18:59

        Конечно я использую изляцию Docker-a, например, eсли использовать, к примеру Google Cloud Computing + Docker, то очень быстно выяснится, что


        1) вся ВМ, все диски, все свапы — шифруются,
        2) при использовании Docker-a внутри Google Cloud Computing, кроме всего прочего, удается решить проблему с разделением переменных окружения дочерними процессами, и самих данных в соседние процессы путем изоляции с помошью контейнеров.
        3) при падении или компрометации отдельных компонент, взаимодействующих с внешним миром либо нет, тчень просто перезапустить или изолировать процесс и заменить его на другой


        1. Sap_ru
          14.01.2019 23:47
          +1

          А как решается утечка переменные внутри докера через дочерние процессы? Пременные же в любом случае наследуются, нет? И если у вас упадёт нечто дочернее и сбросит, например отладочные логи с перменными окружения, которые выйдут за пределы контейнера, то туда могут все ключи/пароли попасть и это может никто не заметить? Шифрование тут не поможет — это логи и они пути их неисповедимы, а критически важной ифнормации в них быть не должно.
          Или какой-то софт внутри контейнера уязвимый, который может ключи элементарно получить и передать. Он бы этих ключей/паролей и не видел, а тут вот они — в переменных окружения.
          Не понимаю, как именно гарантируется непердача переменный окружения за пределы контейнера в общем случае.
          Или я что-то в принципиально не понимаю?


          1. gecube
            15.01.2019 02:06

            В любом случае пароли хранятся в ОЗУ. Вопрос только в том сколько уровней абстракции нужно пройти, чтобы добраться до них. Короче — рутовый доступ к хост-машине с докером эквивалентен полному обладанию всеми секретами на ней.
            А убежать из контейнера в хостовое окружение — ну, надо постараться (хоть и потенциально возможно, что при запуске привилегированных контейнеров, что при наличии уязвимостей в самом ядре ОС)
            Сами переменные окружения это не так плохо, но можно лучше. Например, подготавливать файл с секретами при старте контейнера, потом его грохать. Нет окружения — нет проблем.
            И ещё — а зачем нам вообще говорить о дочерних процессах? Если злоумышленник влез внутрь контейнера, то ок, это уже проблема. Независимо от наличия дочерних процессов.

            Ещё могу вспомнить, что коллеги из Авито с подобной бякой боролись. И придумали свой велосипед, весьма неплохой


            1. Sap_ru
              17.01.2019 00:08
              +1

              Остаются логи. Т.к. перменные окружения любят класть в логи краш-дампы, т.к. масса проблем может быть вызвана именно ими.
              Я как раз думал через переменные кличи передавать и решил не делать этого именно для контейнеров, т.к. там я не контролирую дальнейшее распространение окружения. Максимум — между двумя своми приложениями/скриптами, где я могу гарантированно переопредлить переменные среды сразу после вытаскивания чувтсвительной информации.


              1. gecube
                17.01.2019 00:19

                Логи остаются проблемой независимо от переменных окружения, т.к. разработчики (в частности, джависты) любят многомегабайтные простыни стектрейсов, а там может быть что угодно… Поэтому маскирование чувствительной информации — is a must.


                1. rraderio
                  17.01.2019 10:23

                  А как вы маскируете чувствительную информацию? в приложении?


                  1. gecube
                    17.01.2019 10:46

                    В приложухе — нет, не получится. Только если настроить несколько уровней logger'а.

                    Более удобно — сделать это на уровне хранилища логов (того же graylog), но это вычислительно дорого. Но можно просто вшивать в каждое сообщение с потенциально чувствительной информацией некий флаг (нужно доработать приложуху) и на входе в хранилище логов его фильтровать — тогда терпимо.

                    Т.е. итого — есть хранилище логов. Есть фильтрация на входе. Есть несколько потоков данных в интерфейсе: полный (для сотрудников ИБ и доверенных лиц) и очищенный (для всех остальных, кому нужен доступ).


  1. Meklon
    14.01.2019 12:01

    Кстати, подскажите, кто сталкивался с вариантами токенов для скриптов вживую? Мне рассказывали, но руками не трогал.


    1. worldmind
      14.01.2019 16:20

      ты про всякие oauth токены?


      1. Meklon
        14.01.2019 16:30

        Типа того. Ниже уже Hashicorp предложили с динамическими паролями. Смущает только то, что очень молодой проект. У них релиз 1.01 месяц назад был.


        1. worldmind
          14.01.2019 18:35

          С токенами тему чуток мутноватая (вроде считается секурнее, но я как-то не уверен, что сильно), я пару лет назад юзал гугловое апи чуток, в моём случае схема была такая (их там много вариантов) — юзер вводил свой логин/пароль в формочку гугла, а гугл в ответ возвращал приложению пару токенов, один быстропротухающий, а второй для обновления первого и в принципе приложение могло работать уже без участия юзера, но токены эти всё равно надо где-то хранить, если утечка одного первого токена ещё терпима, то если утекут оба, то считай утёк пароль, хотя токены вероятно чуток меньше доступов имеют.


          1. enkaro
            14.01.2019 21:41

            Вы описываете jwt (JSON Web Token).
            Если утечет второй токен, сменится пароль и работающее взаимодействие (m2m или живая сессия) сломается.
            Перестанут ходить данные и придется повторно себя аутентифицировать через пароль, ключ API и т.д.


            1. worldmind
              15.01.2019 09:46

              Ровно также если утечёт пароль — после его смены он перестанет работать.


              1. enkaro
                15.01.2019 11:12

                Отличие в том, что утекает сессионная Кука, а не пароль или ключ API


          1. mayorovp
            15.01.2019 11:35
            +1

            Главный доступ, которого токены, как правило, не имеют — доступ к смене пароля. Даже если злоумышленник может делать от имени пользователя что угодно — он всё равно не может «угнать» аккаунт. Как только пользователь заметит неладное — он зайдёт в аккаунт через браузер и инвалидирует все токены.

            По крайней мере, именно так эта схема должна работать.


            1. gecube
              15.01.2019 16:51

              И еще идеально, когда токен привязывается к устройству (или ip, или любому другому критерию), чтобы для любого другого устройства (ip, другого критерия) нужно было 100% выписывать новый токен.


              1. mayorovp
                15.01.2019 17:03

                Привязка к ip будет означать постоянные разлогины при переключении с мобильной сети на домашний Wi-Fi. Другой критерий точно так же угоняется и подделывается.


                1. gecube
                  15.01.2019 17:13

                  Ну, расскажите, пожалуйста, нам как работает схема с токенами приложений в гугл gmail, например. Это реально интересный и полезный кейс.
                  Я — честно, не разбирался глубоко. Но могу предположить, что токены, которые мы видим при подключении приложении либо действительно могут быть переиспользованы, либо являются одноразовыми, и тогда на оконечном устройстве появляется что-то типа куки. И которая уже дальше и является ключом шифрования. Ну, может еще как-то текущее время завязано.
                  Всей этой криптографией и безопасностью интересовался давно, поэтому выпал из тренда.


                  1. mayorovp
                    15.01.2019 17:20

                    gmail я отдельно не исследовал, но при использовании токенов сейчас, как правило, используется простейшая схема — bearer token, токен «на предъявителя» без каких бы то ни было дополнительных криптозащит. Однако, у них ограничивается область возможного использования.


                    1. gecube
                      15.01.2019 17:34

                      ОКей. Спасибо. Т.е. единственная защита от увода bearer token заключается в том, что


                      • best practice выписывать уникальный bearer token на каждого потребителя сервиса (что дает нам возможность их селективно блочить, т.е. отзывать bearer token)
                      • энтропия и длина bearer token должна быть достаточной, чтобы его нельзя было сбрутить (т.е. для операций с ним — защита на уровне протокола от сниффинга + защита на уровне сервера по rate limit запросов, включающих токен).


        1. gecube
          15.01.2019 09:17

          Hashicorp нормально делает. И хорошие (полезные и качественные) продукты. И энтерпрайз поддержка у них, если надо. Мои рекомендации.

          Также хочу сказать, что без контекста номер версии ни о чем. Вспомним, как многие вендоры переходили с одной системы нумерации версий на другую. Как например, ОпенСусе прыгнули с 13 сразу на 42. Ваш К.О. или файрфокс аналогичный фортель выкинул…


  1. immaculate
    14.01.2019 12:07

    В проектах на Django использую библиотеку django-environ. При этом информация для соединения с базой данных берется либо из переменных окружения, либо из файла .env. Например, DATABASE_URL=mysql://username:password@localhost/project.


    Для деплоя использую ansible c паролями, зашифрованными посредством Ansible Vault: в файлах ansible хранятся зашифрованные переменные, пароль шифрования хранится в отдельном файле на сервере CD. Таким образом, пароли в открытом виде никогда не попадают в репозиторий с исходным кодом.


    1. Meklon
      14.01.2019 13:10

      А для puppet/foreman/katello какое решение наиболее кошерно?


      1. selivanov_pavel
        15.01.2019 02:27

        Внизу в комментах git-crypt упоминали, но в отличие от ansible vault зашифрованные файлы лежат только в git-репозитории, а локально они остаются в открытом виде.


      1. nox1725
        15.01.2019 11:03

        Для Puppet — однозначно Hiera, она умеет шифровать данные в eyaml


    1. selivanov_pavel
      15.01.2019 02:24

      Ещё в ansible можно использовать разные environments для разных наборов хостов. Для dev пароли будут в открытом виде user:qwerty, а для prod — зашифрованные vault.


  1. nonname
    14.01.2019 15:41

    Это будет работать пока у нас есть конкретные машины, в контейнерных средах это не работает. Лучше всего использовать что-то вроде Hashicorp Vault, хранить пароли там, а уже доставлять их в приложение можно разными способами, как обращением из кода приложения с сессионным ключом прямо в vault, так и внешними инструментами, доставляя пароль при деплое в те же env переменные или через secrets (k8s, rancher, etc..), ну или в систему управления конфигурациями, если она используется в CD. Плюсом такого подхода будет единое место хранения паролей.


    1. worldmind
      14.01.2019 16:22
      +1

      Думаю можно дать ссылку, вроде свободная лицензия.


      1. nad_oby
        15.01.2019 00:47

        Как раз сейчас ковыряю vault для хранения и генерации всего, что связано с аутентификацией.
        Пока глубоко не нырнул, полёт нормальный.


  1. arheops
    14.01.2019 16:59

    Обясните мне, что компроментирует пароль в коде, если он действителен только для конкретного набора хостов?
    Ну к тому же mysql
    При взломе хоста имхо вас кейринг тоже не спасет.


    1. virtual_hack2root
      14.01.2019 19:04

      во многих сложных системах, безусловно, есть не только внутренние хосты, видимые со специально оговоренных IP-адресов, но и внешние, либо динамическим списком IP-адресов, вот в таком случае, велик шанс, что злоумышленнику, получившему валидную пару логин-пароль удастя получить контроль над БД на уровне сервиса, предроставляющего доступ извне, путем подмены IP-адреса, либо MTM, либо несколькими другими способами, (0-Day, и т.д.)


    1. enkaro
      14.01.2019 21:46

      Для CredentialManager есть mimikatz, который доставляется на конечную машину, к примеру, через metasploit.
      Получаются все нужные данные.
      Дальше уже дело «прямоты» рук администратора mysql.
      Прописал только конкретные IP, молодец, но есть варианты.
      Прописал вместо IP %,… к без вариантов.


  1. VGoudkov
    14.01.2019 17:04

    Если копнуть чуть глубже — в полный, так сказать enterprise — то есть несколько крупных и дорогих программных продуктов, специализирующихся на управлении паролями. Работает для конечных пользователей администраторов систем и для отдельных приложений, включая централизованную замену по расписанию во всём зоопарке, распечатку на бумагу для хранения в сейфе у CTO, логирование всего и вся и прочие приятности. Стоит денег, но закрывает многие требования и сценарии из области ИБ и прочих обязательных требований. В редких случаях спасает от серьёзных финансовых последствий.


    1. Meklon
      14.01.2019 18:13

      Полностью согласен. Предложишь варианты?)


      1. anonymous
        15.01.2019 02:35

        CyberArk PAS, например.


        1. gecube
          15.01.2019 09:16

          Имхо, не работает. Весь этот «энтерпрайз» такое себе.
          И сразу вопрос, если cyberark так хорош, то чего все свои велосипеды строят?
          Пример — avito поверх hashicorp vault


      1. VGoudkov
        16.01.2019 16:36

        По CyberArk я в своё время был сертифицированный инженер :) В принципе, такие вещи начинаются с Gartner Magic Quadrant (например тут), и выбираешь вендора. Потом смотришь функционал на сайтах (нужно что-то типа CLI / application-to-application password management). Потом к толстым системным интеграторам, которые у вендора на сайте заявлены как партнёры, за ценником и PoC (Proof Of Concept, он же пилот). Обычно такие штуки всё равно через партнёров продаются, так что напрямую скорее всего не получится.


    1. enkaro
      14.01.2019 21:34

      Поддержу с просьбой.


      1. anonymous
        15.01.2019 02:38

        CyberArk PAS, например.


  1. TimsTims
    14.01.2019 17:21

    только после входа пользователя в систему

    Но ведь есть ещё другие скрипты, которые запускаются по расписанию на сервере. И если мы говорим про всякие powershell, то это Windows server, а значит там не будет автоматического логина на сервер, а значит скрипт который лежит в планировщике, или в сервисах не сможет получить доступ к хранилищу...


    1. Meklon
      14.01.2019 18:16
      +2

      Скрипт может работать под технологической учётной записью. И vault будет использоваться именно ее, а не живого админа.


      1. virtual_hack2root
        14.01.2019 19:09

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


      1. TimsTims
        15.01.2019 10:01

        Это понятно, что ТУЗ будет, но вы написали что сначала под этой ТУЗ надо авторизоваться("только после входа в систему"). Т.е. при каждом обновлении сервера и каждой перезагрузке нужно будет авторизоваться на сервере.


  1. The_Kf
    14.01.2019 19:15

    Для PowerShell на Windows есть и ещё варианты — можно шифровать пароль сертификатом (лежащим в стандартном хранилище сертификатов, разумеется) или просто аутентифицироваться прям этим сертом.


  1. geisha
    14.01.2019 20:11
    +1

    Спасибо, не думал, что всё так просто. Заменил b64decode на keyring в скриптике и он молча отработал. Вопрос: полное отсутствие функции получения списка паролей — это из-за требований совместимости, хитрая защита или просто так случилось?


  1. Jek_Rock
    14.01.2019 20:56

    Как вы прячете секреты из истории комманд в Windows и Linux? Например, если нужно консольным клиентом подключиться к базе.


    1. Meklon
      14.01.2019 21:15
      +1

      Системные варианты ввода пароля. В посте getpass описан. Для bash тоже есть аналогичный безопасный ввод. Надо выключить echo для команды с ключом -s:

      #!/bin/bash
      # Read Password
      echo -n Password: 
      read -s password
      echo
      # Run Command
      echo $password
      


      В powershell будет что-то вроде:

      $SecurePassword = Read-Host -Prompt "Enter password" -AsSecureString


    1. nikoloza
      15.01.2019 17:30

      Начните команду с пробела и он не будет писаться в лог.
      Актуально для bash с HISTCONTROL=ignorespace


  1. Gasoid
    14.01.2019 23:49
    +1

    все переменные вынести в конфиги, конфиги генерить уже на хосте, пароли хранить отдельно в CI/Vault/Env


    ну и cur.fetchall() очень плохо, а если там 1млн записей?


    1. Meklon
      14.01.2019 23:52

      ну и cur.fetchall() очень плохо, а если там 1млн записей?

      SQL не моя сильная сторона, признаю. Не использую как-то… Это всего лишь пример)


  1. batment
    15.01.2019 00:48

    Есть еще git-crypt, который позволяет держать зашифрованные файлы с секретами в гите, и расшифровывать только когда нужно. Но он требует вдумчивого использования, чтобы расшифрованные файлы ненароком куда-нибудь не утекли.


  1. fear86
    15.01.2019 01:02

    Поднимайте все узлы в изолированной сети, монтируйте файловую систему в readonly с noexec, используйте ротацию паролей с небольшим ttl. И спите спокойно ))

    ps: Всегда помните, что приложения открытые в мир по умолчанию уязвимы. И главный вопрос не «что делать если сломают?», а «что делать когда сломают?». Этот план должен быть составлен и проработан, для уменьшений деструктивных последствий атаки.


  1. selivanov_pavel
    15.01.2019 02:19

    Linux-овый keyring работает через PAM, и только если пользователь при входе вводил пароль, насколько я понимаю с участием этого самого пароля. Если используется какой-нибудь способ входа без пароля — то keyring остаётся закрытым. Так что на сервере неприменимо.

    ИМХО всё чувствительное надо выносить в отдельный конфиги, которые раскладываются из ansible vault, harshicorp vault и всяких прочих AWS KMS.


    1. gecube
      15.01.2019 09:19

      Т.е. скорее вопрос в том, что если нужно сетевое хранилище данных, то keyring не подойдёт (или к нему удаленно можно цепляться?)


      1. selivanov_pavel
        15.01.2019 09:44

        Удалённо цеплять тоже нельзя, но главное, что его не получится использовать для работающей в фоне службы на сервере. Он для десктопных приложений. По крайней мере в Linux, не знаю как насчёт Windows и MacOS.


        1. Meklon
          15.01.2019 10:08

          Почему нельзя? Запускаем скрипт от технологической учетки machine01. Делаем set_passwd. Все. Теперь в этой учетке есть пароль и можно таскать его скриптами через get_passwd.


          1. selivanov_pavel
            15.01.2019 10:32

            В системе хранится только солёный хеш пароля, в /etc/shadow для локальных пользователей. Получить сам пароль пользователя PAM модуль может только при вводе этого пароля пользователем при логине.

            В этом и весь смысл keyring: не получится получить доступ к зашифрованным данным, даже если удалось получить доступ к файлам. Нужно получить ещё и пароль пользователя.


            1. Meklon
              15.01.2019 10:59

              Твою мать( Спасибо. А неинтерактивно как это решить? В виде демонов/скриптов для m2m? Если без стороннего ПО.


              1. selivanov_pavel
                15.01.2019 11:21

                Как убрать пароли в открытом виде из исходников? Обычно это решается вынесением паролей в конфиг либо environment, и раскладыванием этого конфига или environment снаружи средствами CI, configuration management(ansible/puppet/...) или что там у вас есть. Ну и строгими разрешениями, чтобы прочитать этот файл мог только пользователь соответствующей службы, а не любой пользователь на хосте(неактуально для контейнеров).

                Для ленивых — можно по каким-то признакам определять, работает приложение в dev или prod среде, и считывать соответствующий config.dev.yml либо config.prod.yml. Первый при этом не так страшно положить в исходники, а второй всё-же должен появляться на хосте в процессе деплоя, руками или автоматикой. А, ну и добавить config.prod.yml в .gitignore на всякий пожарный.


                1. Meklon
                  15.01.2019 11:30

                  Благодарю.


  1. AlexPancho
    15.01.2019 10:37

    мой способ не самый надежный, но довольно простой — хранить пароли в питон-файле, файл добавить в исключение гит (или что там у вас), импортировать в рабочий файл.

    #Примерно так
    import nsfw
    user_pass = nsfw.userpass01
    

    Естественно, так можно хранить целые словари логинов-паролей, и доставать значение по ключам.