Политика паролей (далее — политика) определяет набор требований к генерируемым паролям. Stronghold позволяет настраивать пользовательские политики и использовать их вместо политики по умолчанию.

Политики паролей не связаны с политиками доступа. У них похожие названия, но разное назначение.

Stronghold использует модель настройки политик паролей, совместимую с Vault 1.5+.

Использование политик паролей в Stronghold

В Stronghold политики паролей используются для следующих целей:

  • Генерация через API паролей, соответствующих определенной политике.
  • Настройка автоматической генерации паролей механизмами секретов. Политики паролей поддерживаются не всеми механизмами секретов. Перед настройкой политики для механизма проверьте его документацию.
  • Проверка пароля, создаваемого пользователем с помощью метода аутентификации userpass.

Структура и синтаксис политики

Политики паролей задаются в формате HCL или JSON.

В политике описываются:

  • Длина пароля (задается в параметре length).

  • Одно или несколько правил, которым должен соответствовать пароль. Каждое правило описывается в поле rule. Stronghold допускает использование в политиках правил charset.

    Политика должна содержать как минимум одно правило charset. Политика без правила charset будет отклонена.

Пример политики:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
}

Эта политика для генерации пароля длиной 20 символов только из строчных латинских букв.

Параметр length

Параметр length задаёт длину генерируемого пароля.

Особенности:

  • тип — int;
  • параметр обязателен;
  • значение должно быть не меньше 4.

Правило charset

Правило charset задаёт набор символов и, при необходимости, минимальное количество символов (min-chars) из этого набора, которое должно присутствовать в пароле.

Если политика содержит несколько правил charset, Stronghold до начала генерации пароля объединяет все наборы символов и удаляет дубликаты (например, если указаны наборы abcde и cdefg, для генерации будет использоваться итоговый набор abcdefg). При этом сгенерированный пароль всё равно проверяется на соответствие каждому правилу charset отдельно.

После объединения и удаления дубликатов итоговый charset, из которого генерируются пароли-кандидаты, не должен содержать более 256 символов.

Параметры правила charset

В правиле charset используются следующие параметры:

Имя параметраТипЗначение по умолчаниюОписание
charsetstringСтроковое представление набора символов. Поддерживаются строки в кодировке UTF-8. Все символы должны быть печатными
min-charsint0Минимальное число символов из charset, которое должно присутствовать в пароле

Если min-chars не указан или равен 0, набор символов будет использоваться при генерации, но не будет накладывать на итоговый пароль обязательного требования.

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

length = 20

rule "charset" {
  charset = "abcde"
  min-chars = 1
}

rule "charset" {
  charset = "01234"
  min-chars = 1
}

Эта политика генерирует пароль длиной 20 символов из объединённого набора abcde01234. При этом пароль должен содержать как минимум один символ из abcde и как минимум один символ из 01234.

Примеры политик

Пароль 20 символов, только наборы символов без обязательного минимума:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
}

rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
}

rule "charset" {
  charset = "0123456789"
}

rule "charset" {
  charset = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
}

Пароль 20 символов, минимум одна прописная буква, одна строчная буква и одна цифра:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}

rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  min-chars = 1
}

rule "charset" {
  charset = "0123456789"
  min-chars = 1
}

Пароль 20 символов, минимум одна прописная буква, одна строчная буква, одна цифра и один символ из полного ASCII-набора специальных символов:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}

rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  min-chars = 1
}

rule "charset" {
  charset = "0123456789"
  min-chars = 1
}

rule "charset" {
  charset = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
  min-chars = 1
}

Пароль 20 символов, минимум одна прописная буква, одна строчная буква, одна цифра и один символ из набора !@#$:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}

rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  min-chars = 1
}

rule "charset" {
  charset = "0123456789"
  min-chars = 1
}

rule "charset" {
  charset = "!@#$"
  min-chars = 1
}

Политика паролей по умолчанию

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

Политика по умолчанию требует:

  • 20 символов в пароле (для метода userpass8 символов);
  • минимум одну прописную букву;
  • минимум одну строчную букву;
  • минимум одну цифру;
  • минимум один символ тире (-).

Пример политики по умолчанию:

length = 20

rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}

rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  min-chars = 1
}

rule "charset" {
  charset = "0123456789"
  min-chars = 1
}

rule "charset" {
  charset = "-"
  min-chars = 1
}

Управление политиками

Создание и редактирование политики

Для создания или редактирования политики паролей используйте POST-метод /sys/policies/password/:name.

Пример создания политики из файла в формате HCL:

d8 stronghold write sys/policies/password/my-policy policy=@my-policy.hcl

Пример передачи политики напрямую при создании:

d8 stronghold write sys/policies/password/my-policy policy=- <<EOF
length = 20
rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz0123456789"
}
EOF

Чтобы убедиться, что политика создана, используйте команду:

d8 stronghold read sys/policies/password/my-policy

Пример создания политики через API:

curl \
  --request POST \
  --header "X-Vault-Token: ..." \
  --data my-policy.json \
  https://stronghold.example.com/v1/sys/policies/password/my-policy

Получение списка политик

Для получения списка созданных политик используйте GET-метод /sys/policies/password.

Пример:

d8 stronghold read sys/policies/password

Пример получения списка политик через API:

curl \
  --header "X-Vault-Token: ..." \
  --request LIST \
  https://stronghold.example.com/v1/sys/policies/password

Получение информации о политике

Для получения информации о конкретной политике используйте GET-метод /sys/policies/password/:name.

Пример:

d8 stronghold read sys/policies/password/my-policy

Пример получения информации о конкретной политике через API:

curl \
  --header "X-Vault-Token: ..." \
  https://stronghold.example.com/v1/sys/policies/password/my-policy

Удаление политики

Для удаления политики паролей используйте DELETE-метод /sys/policies/password/:name.

Пример:

d8 stronghold delete sys/policies/password/my-policy

Пример удаления политики через API:

curl \
  --header "X-Vault-Token: ..." \
  --request DELETE \
  https://stronghold.example.com/v1/sys/policies/password/my-policy

Генерация паролей через API

Вы можете вручную генерировать пароли, соответствующие определенной политике. Используйте для этого метод /sys/policies/password/:name/generate, где вместо :name укажите название политики, которой должен соответствовать пароль.

Пример:

d8 stronghold read sys/policies/password/my-policy/generate

Пример генерации пароля через API:

curl \
  --header "X-Vault-Token: ..." \
  https://stronghold.example.com/v1/sys/policies/password/my-policy/generate

Принципы и особенности генерации паролей

Stronghold сначала генерирует пароль-кандидат из объединённого набора символов, полученного из всех правил charset, описанных в политике. Повторяющиеся символы из разных наборов удаляются из объединённого набора. После этого Stronghold проверяет пароль-кандидат на соответствие всем правилам, описанным в политике.

Генерация пароля-кандидата

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

Для генерации пароля-кандидата используются:

  1. Криптографически стойкий генератор случайных чисел.
  2. Набор символов charset, из которого выбираются символы.
  3. Длина пароля.

На высоком уровне процесс выглядит так:

  1. Stronghold получает N случайных значений, где N равно длине пароля.
  2. Каждое значение интерпретируется как индекс символа в массиве charset.
  3. По этим индексам выбираются символы.
  4. Из выбранных символов собирается пароль-кандидат.
  5. Полученный пароль проверяется на соответствие всем правилам, описанным в политике.

Например, нужно сгенерировать пароль длиной 8 из набора символов abcdefghij.

Stronghold получил следующие случайные значения:

[3, 2, 0, 8, 7, 3, 5, 1]

Эти значения соответствуют индексам символов в charset:

[3, 2, 0, 8, 7, 3, 5, 1] => [d, c, a, i, h, d, f, b]

В результате получается пароль-кандидат dcaihdfb.

Предотвращение смещения

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

Например, если генератор возвращает значения в диапазоне 0–255, а длина charset не делит 256 без остатка, первые символы набора могут встречаться чаще.

Рассмотрим упрощённый пример. Пусть charset равен abcdefghij, то есть содержит 10 символов. Пусть генератор возвращает значения в диапазоне 0–25.

В этом случае:

  • значения 0–9 соответствуют всем 10 символам;
  • значения 10–19 снова соответствуют всем 10 символам;
  • значения 20–25 соответствуют только первым 6 символам.

Из-за этого символы abcdef будут выбираться чаще, чем ghij.

Чтобы избежать такого поведения, Stronghold вычисляет максимальное допустимое значение, которое можно безопасно использовать для индексации charset. Для этого примера максимальное допустимое значение будет равно 19. В этом случае все значения от 0 до 19 включительно дают ровно по 2 попадания на каждый символ. Если случайное число превышает это значение, оно отбрасывается, и генерация продолжается. За счёт этого длина итогового пароля не уменьшается, а распределение символов остаётся корректным.

Особенности производительности

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

Общую оценку можно представить так:

скорость генерации пароля = (время генерации одного пароля-кандидата) * (число сгенерированных паролей-кандидатов)

Количество попыток зависит от того, насколько вероятно, что очередной пароль-кандидат не пройдёт проверку по всем правилам.

Практически это означает следующее:

  • чем больше ограничений по min-chars, тем выше вероятность повторной генерации;
  • чем меньше размер обязательного поднабора символов, тем ниже вероятность быстро получить подходящий пароль;
  • с ростом длины пароля вероятность выполнить часть требований увеличивается, но растёт и стоимость самой генерации.

Особенно заметное снижение производительности возникает, если одно из правил требует хотя бы один символ из очень маленького набора, например !@#$, а общий charset при этом значительно больше.

Чтобы оценить производительность конкретной политики, протестируйте её через API генерации паролей в вашем окружении Stronghold.