# Занятие 14: Безопасность / Профили пользователей

> Исходная страница в нативном Markdown: Безопасность / Профили пользователей

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

<!-- Generated by scripts/generate_skeleton.py. -->

> [!NOTE]
> Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
> **HTML source:** [pgpro_14_profile.html](https://edu.postgrespro.ru/16/pgpro-16/pgpro_14_profile.html)
> **Archive:** [PGPRO-handouts-16.zip](https://edu.postgrespro.ru/16/PGPRO-handouts-16.zip)
> **Страниц PDF:** 16

## Page 1: Безопасность / Профили пользователей {#source-page-001}

### Авторские права

© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
### Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
### Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
### Отказ от ответственности

Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.

## Page 2: Темы {#source-page-002}

- Запрет простых паролей
- Профили пользователей

## Page 3: Запрет простых паролей {#source-page-003}

**Модуль passwordcheck**

## Page 4: Модуль passwordcheck {#source-page-004}

  - user123
  - passwordcheck
  - R0cvjyfdnbrf+
  - passwordcheck
- Проверка надежности паролей пользователей
  - CREATE ROLE
  - ALTER ROLE
  - \\password

### Комментарии преподавателя

Модуль passwordcheck проверяет надежность паролей, задаваемых командами CREATE ROLE и ALTER ROLE, а также устанавливаемых метакомандой \\password в psql.

Модуль должен быть загружен с помощью shared\_preload\_libraries или командой LOAD.

Модуль passwordcheck проверяет, что пароль:

● содержит не менее 8 символов;

● содержит и буквы, и иные символы;

● не содержит имя роли.

Модуль не предусматривает конфигурационных настроек.

<https://postgrespro.ru/docs/enterprise/16/passwordcheck#PASSWORDCHE> CK

## Page 5: Модуль passwordcheck {#source-page-005}

```sh
student$ psql
```
Расширение passwordcheck требует загрузки одноименной разделяемой библиотеки:
```sql
=> ALTER SYSTEM SET shared_preload_libraries = 'passwordcheck';
```
```sql
ALTER SYSTEM
```
После подключения библиотеки необходимо перезапустить СУБД.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql
```
Создадим базу данных и роль:
```sql
=> CREATE DATABASE pgpro_profile;
```
```sql
CREATE DATABASE
```
```sql
=> CREATE ROLE bob LOGIN;
```
```sql
CREATE ROLE
```
Запишем в дополнительный конфигурационный файл правило для парольной аутентификации нового пользователя при подключении к БД pgpro\_profile:
```text
/var/lib/pgpro/ent-16/pg_hba.conf.d/pgpro_profile.conf
```
```text
# TYPE  DATABASE       USER   ADDRESS  METHOD
host    pgpro_profile  bob    all      scram-sha-256
```
```sql
=> SELECT pg_reload_conf();
```
```text
 pg_reload_conf
----------------
 t
(1 row)
```
Проверим, можно ли установить пользователю нестойкий пароль bob123:
```sql
=> ALTER ROLE bob PASSWORD 'bob123';
```
```text
ERROR:  password is too short
```
Теперь попробуем установить сложный пароль:
```sql
=> ALTER ROLE bob PASSWORD 'GGU2015ujlf';
```
```sql
ALTER ROLE
```
Удалим модуль passwordcheck и снова перезапустим СУБД.
```sql
=> ALTER SYSTEM RESET shared_preload_libraries;
```
```sql
ALTER SYSTEM
```
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```

## Page 6: Профили пользователей {#source-page-006}

**Профиль**
- Попытки входа
- Время жизни пароля
- Уровень сложности пароля

## Page 7: Профиль {#source-page-007}

**Профиль ограничивает использование системы пользователем**
  - количество неудачных попыток входа
  - время жизни пароля и время неактивности
  - уровень сложности пароля
- По умолчанию к ролям применяется профиль default
  - не устанавливает никаких ограничений, но это можно изменить
- Управление профилями
  - суперпользователи или роли, включенные в pg\_manage\_profiles

### Комментарии преподавателя

Ядро Postgres Pro обеспечивает гораздо более гибкое управление парольными политиками, чем простое расширение passwordcheck.

Профиль ограничивает использование базы данных и устанавливает парольную политику для ролей. Профили определяются на уровне кластера баз данных и назначаются ролям. Новый профиль создает команда CREATE PROFILE, изменяет — ALTER PROFILE, удаляет — DROP PROFILE.

Профиль назначается при создании роли или командой ALTER ROLE. Новым ролям по умолчанию назначается профиль default. Исходно профиль default не устанавливает ограничений, но их можно добавить командой ALTER PROFILE. Если роли назначен профиль, отличный от default, рассмотренный выше модуль passwordcheck не работает.

Управлять профилями с помощью указанных команд разрешено только суперпользователям или пользователям, включенным в предустановленную роль pg\_manage\_profiles.

<https://postgrespro.ru/docs/enterprise/16/sql-createprofile>

## Page 8: Попытки входа {#source-page-008}

**FAILED\\\_LOGIN\\\_ATTEMPTS**
  - количество неудачных попыток входа до блокировки пользователя
  - ALTER ROLE ... ACCOUNT UNLOCK
- FAILED\_AUTH\_KEEP\_TIME
  - время в днях до сброса счетчика неудачных попыток

### Комментарии преподавателя

Параметр профиля FAILED\_LOGIN\_ATTEMPTS ограничивает количество неудачных попыток входа. По превышении этого количества пользователь блокируется. Суперпользователь может разблокировать заблокированную роль командой ALTER ROLE с предложением ACCOUNT UNLOCK.

Параметр профиля FAILED\_AUTH\_KEEP\_TIME задает время в днях с момента первой неудачной попытки входа; при попытке входа по истечении этого времени счетчик неудачных попыток сбрасывается, а пользователь разблокируется.

## Page 9: Время жизни пароля {#source-page-009}

![Source slide page 9: Время жизни пароля](images/page-009.png){#source-figure-009 caption="Source slide page 9: Время жизни пароля"}


### Комментарии преподавателя

Параметр профиля PASSWORD\_LIFE\_TIME задает период в днях, в течение которого пароль действителен. При установленном для роли атрибуте VALID UNTIL будет выбираться наиболее короткий срок действия пароля, исходя из этих двух значений.

Если установлен PASSWORD\_GRACE\_TIME, действие пароля продлевается, но в течение этого периода выдаются предупреждение о необходимости смены пароля. Если пароль так и не был изменен, последующие попытки входа в сеанс будут отвергнуты.

Параметр профиля USER\_INACTIVE\_TIME задает максимальный период в днях с момента последнего входа пользователя, в течение которого пользователь должен снова войти в сеанс. В противном случае пользователь блокируется.

## Page 10: Уровень сложности пароля {#source-page-010}

**PASSWORD\\\_MIN\\\_UNIQUE\\\_CHARS**
  - минимальное количество уникальных символов
- PASSWORD\_MIN\_LEN
  - минимальная длина
- PASSWORD\_REQUIRE\_COMPLEX
  - проверка надежности пароля
- PASSWORD\_REUSE\_TIME и PASSWORD\_REUSE\_MAX
  - время в днях и количество смен паролей, после которых старый пароль
  - можно использовать повторно

### Комментарии преподавателя

Параметры профиля PASSWORD\_MIN\_UNIQUE\_CHARS и PASSWORD\_MIN\_LEN ограничивают минимальное количество уникальных символов в пароле и его минимальную длину.

Параметр PASSWORD\_REQUIRE\_COMPLEX требует, чтобы пароль содержал и буквы, и небуквенные символы, а также не содержал имя пользователя.

Параметры профиля PASSWORD\_REUSE\_TIME и PASSWORD\_REUSE\_MAX определяют, когда пароль может быть использован повторно: для этого должно пройти указанное время и пароль должен быть сменен указанное количество раз.

## Page 11: Профили пользователей {#source-page-011}

```sh
student$ psql -d pgpro_profile
```
Пока ничего не мешает пользователю установить простой пароль:
```sql
=> ALTER ROLE bob PASSWORD 'bob';
```
```sql
ALTER ROLE
```
Создадим профиль:
```sql
=> CREATE PROFILE IF NOT EXISTS prof LIMIT
  PASSWORD_LIFE_TIME 60
  PASSWORD_GRACE_TIME 7
  PASSWORD_MIN_LEN 8
  PASSWORD_REQUIRE_COMPLEX;
```
```sql
CREATE PROFILE
```
Этот профиль определяет, что пароль необходимо менять через 60 дней. Еще в течение 7 дней будут выводиться предупреждения о необходимости поменять пароль.
Минимальная длина пароля — 8 символов, причем пароль должен содержать как буквы, так и другие символы, а имя пользователя не должно входить в пароль.
Назначим роли bob профиль prof:
```sql
=> ALTER ROLE bob PROFILE prof;
```
```sql
ALTER ROLE
```
Проверим, какой профиль связан с ролью:
```sql
=> SELECT r.rolname, p.pflname
FROM pg_authid r
  JOIN pg_profile p ON p.oid = r.rolprofile
WHERE r.rolname = 'bob';
```
```text
 rolname | pflname
---------+---------
 bob     | prof
(1 row)
```
Попробуем установить короткий пароль:
```sql
=> ALTER ROLE bob PASSWORD 'bob123';
```
```text
ERROR:  password must be at least 8 characters long
```
Попробуем сделать пароль длиннее:
```sql
=> ALTER ROLE bob PASSWORD 'bob12345';
```
```text
ERROR:  password must not contain user name
```
Усложним:
```sql
=> ALTER ROLE bob PASSWORD 'GGU2015ujlf';
```
```sql
ALTER ROLE
```
Модифицируем профиль prof, установив ограничение в три неудачные попытки начать сеанс до блокировки учетной записи.
```sql
=> ALTER PROFILE prof LIMIT FAILED_LOGIN_ATTEMPTS 3;
```
```sql
ALTER PROFILE
```
Боб пытается подключиться три раза с неправильными паролями:
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=bob password=12345678'
```
```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "bob"
```
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=bob password=qwerty'
```
```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "bob"
```

## Page 12: Page 12 {#source-page-012}

```sh
student$ psql 'host=localhost dbname=pgpro_profile user=bob password=q1w2e3r4'
```
```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "bob"
```
Теперь роль заблокирована:
```sql
=> SELECT CASE rolstatus
  WHEN 0 THEN 'роль активна'
  WHEN 1 THEN 'заблокирована вручную'
  WHEN 2 THEN 'заблокирована из-за бездействия'
  WHEN 4 THEN 'заблокирована по превышению числа попыток входа'
END status
FROM pg_roles
WHERE rolname = 'bob';
```
```text
                     status
-------------------------------------------------
 заблокирована по превышению числа попыток входа
(1 row)
```
Разблокируем роль, дадим Бобу шанс вспомнить пароль:
```sql
=> ALTER ROLE bob ACCOUNT UNLOCK;
```
```sql
ALTER ROLE
```
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=bob password=GGU2015ujlf' -c '\conninfo'
```
```text
You are connected to database "pgpro_profile" as user "bob" on host "localhost" (address
"127.0.0.1") at port "5432".
```
Теперь сократим срок действия пароля индивидуально для Боба, оставив профиль неизменным:
```sql
=> SELECT now();
```
```text
2026-07-27 23:43:30.462072+03
```
```sql
=> ALTER ROLE bob VALID UNTIL '2026-07-27 23:43:30.462072+03';
```
```sql
ALTER ROLE
```
Попытка подключения (пароль правильный):
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=bob password=GGU2015ujlf' -c '\conninfo'
```
```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "bob"
```
В журнале сообщений сервера видим причину отказа в соединении:
```sh
student$ sudo tail -n 20 /var/lib/pgpro/ent-16/log/postgresql-2026-07-27_234328.log | grep -B 2 expired
```
```sql
2026-07-27 23:43:30.484 MSK [827845] STATEMENT:  UPDATE pg_authid SET
rolpasssetat=2026-07-27 23:43:30.462072+03-interval '1 min' WHERE rolname = 'bob';
2026-07-27 23:43:30.643 MSK [828401] FATAL:  password authentication failed for user "bob"
2026-07-27 23:43:30.643 MSK [828401] DETAIL:  User "bob" has an expired password.
```
Следующим образом можно вернуть для роли профиль по умолчанию:
```sql
=> ALTER ROLE bob PROFILE default;
```
```sql
ALTER ROLE
```
Удалим профиль:
```sql
=> DROP PROFILE prof;
```
```sql
DROP PROFILE
```
Удалим роль:
```sql
=> DROP ROLE bob;
```
```sql
DROP ROLE
```

## Page 13: Итоги {#source-page-013}

**Расширение passwordcheck проверяет надежность паролей**
- Встроенный механизм профилей позволяет настраивать политики использования системы пользователями
- Профиль позволяет задавать уровень сложности пароля и ограничивать время его жизни
- Можно ограничивать количество неудачных попыток ввода пароля

## Page 14: Практика {#source-page-014}

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

### Комментарии преподавателя

1. Создайте профиль mgr1 с ограничением PASSWORD\_MIN\_UNIQUE\_CHARS = 8. Зарегистрируйте пользователя mgr1 с профилем mgr и проверьте возможность установки пароля не менее, чем с восемью отличающимися символами.

2. Используйте настройку LIMIT FAILED\_LOGIN\_ATTEMPTS по аналогии с демонстрацией.

## Page 15: 1. Профиль пользователя {#source-page-015}

Создадим базу данных pgpro\_profile:
```sh
student$ /opt/pgpro/ent-16/bin/createdb pgpro_profile
```
```sh
student$ psql -d pgpro_profile
```
Создадим профиль с ограничением на минимальное количество отличающихся символов в пароле:
```sql
=> CREATE PROFILE mgr LIMIT PASSWORD_MIN_UNIQUE_CHARS 8;
```
```sql
CREATE PROFILE
```
Зарегистрируем пользователя с этим профилем:
```sql
=> CREATE ROLE mgr1 LOGIN PROFILE mgr;
```
```sql
CREATE ROLE
```
Правило для парольной аутентификации нового пользователя при подключении к БД pgpro\_profile:
```text
/var/lib/pgpro/ent-16/pg_hba.conf.d/pgpro_profile.conf
```
```text
# TYPE  DATABASE       USER   ADDRESS  METHOD
host    pgpro_profile  mgr1   all      scram-sha-256
```
```sql
=> SELECT pg_reload_conf();
```
```text
 pg_reload_conf
----------------
 t
(1 row)
```
Проверим профиль роли:
```sql
=> SELECT r.rolname, p.pflname, p.pflpasswordminuniqchars
FROM pg_roles r
  JOIN pg_profile p ON r.rolprofile = p.oid
WHERE r.rolname = 'mgr1';
```
```text
 rolname | pflname | pflpasswordminuniqchars
---------+---------+-------------------------
 mgr1    | mgr     |                       8
(1 row)
```
Пароль, разрешенный профилем:
```sql
=> ALTER ROLE mgr1 PASSWORD '12345678';
```
```sql
ALTER ROLE
```
Такой пароль был успешно назначен роли.
Пароль с меньшим количеством отличающихся символов:
```sql
=> ALTER ROLE mgr1 PASSWORD '12345677';
```
```text
ERROR:  password must contain at least 8 unique characters
```
### 2. Ограничение неудачных попыток ввода пароля
Разрешим лишь две попытки.
```sql
=> ALTER PROFILE mgr LIMIT FAILED_LOGIN_ATTEMPTS 2;
```
```sql
ALTER PROFILE
```
Пару раз введем неверный пароль.
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=mgr1 password=manager'
```
```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "mgr1"
```
```sh
student$ psql 'host=localhost dbname=pgpro_profile user=mgr1 password=manager'
```

## Page 16: Page 16 {#source-page-016}

```text
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL:
password authentication failed for user "mgr1"
```
Блокировка должна быть уже установлена:
```sql
=> SELECT CASE rolstatus
  WHEN 0 THEN 'роль активна'
  WHEN 1 THEN 'заблокирована вручную'
  WHEN 2 THEN 'заблокирована из-за бездействия'
  WHEN 4 THEN 'заблокирована по превышению числа попыток входа'
END status
FROM pg_roles
WHERE rolname = 'mgr1';
```
```text
                     status
-------------------------------------------------
 заблокирована по превышению числа попыток входа
(1 row)
```
Удалим роль и профиль:
```sql
=> DROP ROLE mgr1;
```
```sql
DROP ROLE
```
```sql
=> DROP PROFILE mgr;
```
```sql
DROP PROFILE
```
Удалим дополнительный файл конфигурации:
```sh
student$ sudo rm /var/lib/pgpro/ent-16/pg_hba.conf.d/pgpro_profile.conf
```
