Перейти к основному содержимому

Практикум

Создание сертификата центра сертификации

  1. Создайте каталоги для хранения сертификатов и временно назначьте им владельца student:

    $ sudo mkdir -p /etc/pangolin/ssl/{CA,PG}

    $ sudo chown -R student:student /etc/pangolin

    $ ls -Rl /etc/pangolin
    /etc/pangolin:
    итого 4
    drwxr-xr-x 4 student student 4096 сен 25 20:58 ssl

    /etc/pangolin/ssl:
    итого 8
    drwxr-xr-x 2 student student 4096 сен 25 20:58 CA
    drwxr-xr-x 2 student student 4096 сен 25 20:58 PG

    /etc/pangolin/ssl/CA:
    итого 0

    /etc/pangolin/ssl/PG:
    итого 0
  2. Для удобства экспортируйте переменную окружения с префиксом DN, который будет использоваться в командах openssl:

     $ export DN_PREFIX='/C=RU/ST=Moscow_reg./L=Moscow/O=PangolinEDU'
  3. В каталоге /etc/pangolin/ssl/CA создайте приватный ключ центра сертификации:

     $ cd /etc/pangolin/ssl/CA

    $ openssl genrsa -out CA.key 4096

    $ ls -l
    итого 4
    -rw------- 1 student student 3243 сен 25 21:27 CA.key
  4. Создайте самоподписанный сертификат центра сертификации:

     $ openssl req -x509 -new -extensions v3_ca -days 3650 -key CA.key -out CA.crt - subj "${DN_PREFIX}/CN=PangolinEDU_CA"

    $ ls -ltr
    итого 8
    -rw------- 1 student student 3243 сен 25 21:27 CA.key -rw-r--r-- 1 student student 2021 сен 25 21:35 CA.crt
  5. Проверьте содержимое сертификата центра сертификации:

    $ openssl x509 -noout -in CA.crt -text -certopt no_sigdump,no_pubkey Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number:
    79:38:86:f4:d4:46:1c:3a:32:67:0c:b8:ac:1b:a8:1a:65:40:f0:7a
    Signature Algorithm: sha256WithRSAEncryption
    Issuer: C = RU, ST = Moscow_reg., L = Moscow, O = PangolinEDU, CN =
    PangolinEDU_CA
    Validity
    Not Before: Sep 25 18:35:01 2024 GMT
    Not After : Sep 23 18:35:01 2034 GMT
    Subject: C = RU, ST = Moscow_reg., L = Moscow, 0 = PangolinEDU, CN = PangolinEDU_CA
    X509v3 extensions:
    X509v3 Subject Key Identifier:
    A3:10:41:AE:DA:43:63:9C:C3:7E:F3:B6:41:4B:5A:BD:E9:56:3E:40
    X509v3 Authority Key Identifier:

    keyid:A3:10:41:AE:DA:43:63:9C:C3:7E:F3:B6:41:4B:5A:BD:E9:56:3E:40

    X509v3 Basic Constraints: critical
    CA:TRUE

Создание сертификата сервера

  1. Перейдите в каталог для хранения сертификата сервера:

    $ cd /etc/pangolin/ssl/PG
  2. Создайте файл настройки сертификата сервера:

    $ cat << EOF >> pg.conf
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    PangolinEDU_CA
    Subject: C = RU, ST = Moscow_reg., L = Moscow, O = PangolinEDU, CN =
    X509v3 Basic Constraints: critical
    CA:TRUE
    subjectAltName = @alt_names
    [ ssl_client ]
    extendedKeyUsage = clientAuth, serverAuth
    basicConstraints = CA:FALSE
    subjectKeyIdentifier=hash
    authorityKeyIdentifier=keyid,issuer
    subjectAltName = @alt_names
    [ v3_ca ]
    basicConstraints = CA:TRUE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    authorityKeyIdentifier=keyid:always,issuer
    [alt_names]
    EOF
  3. Выполните две команды, добавляющие в файл конфигурации сертификата сервера еще две настройки будущего сертификата:

    $ echo DNS.1 = $(hostname -f) >> pg.conf
    $ echo IP.1 = $(hostname --all-ip-addresses) >> pg.conf
  4. Проверьте результирующее содержимое файл конфигурации сертификата сервера:

    $ cat pg.conf
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    [ ssl_client ]
    extendedKeyUsage = clientAuth, serverAuth
    basicConstraints = CA:FALSE
    subjectKeyIdentifier=hash
    authorityKeyIdentifier=keyid,issuer
    subjectAltName = @alt_names
    [ v3_ca ]
    basicConstraints = CA:TRUE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    authorityKeyIdentifier=keyid:always,issuer
    [alt_names]
    DNS.1 = p620.class.edu
    IP.1 = <ipvalue>
  5. Создайте запрос на сертификацию:

    $ openssl req -new -nodes -text -out ./pg.csr -keyout ./pg.key -subj "${DN_PREFIX}/CN=$(hostname -f)" -config ./pg.conf
    Generating a RSA private key
    ......+++++
    ...................................................+++++
    writing new private key to './pg.key'
    -----
    $ ls -ltrh
    итого 12K
    -rw-r--r-- 1 student student 623 сен 26 09:42 pg.conf
    -rw------- 1 student student 1,7K сен 26 09:52 pg.key
    -rw-r--r-- 1 student student 3,8K сен 26 09:52 pg.csr
  6. Проверьте содержимое запроса на сертификацию:

    $ openssl req -text -noout -in pg.csr -reqopt no_sigdump,no_pubkey
    Certificate Request:
    Data:
    Version: 1 (0x0)
    Subject: C = RU, ST = Moscow_reg., L = Moscow, O = PangolinEDU, CN =
    p620.class.edu
    Attributes:
    Requested Extensions:
    X509v3 Basic Constraints:
    CA:FALSE
    X509v3 Key Usage:
    Digital Signature, Non Repudiation, Key Encipherment
    X509v3 Subject Alternative Name:
    DNS:p620.class.edu, IP Address:<ipvalue>
  7. Подпишите запрос на сертификацию и выпустите сертификат:

    $ openssl x509 -req -in ./pg.csr -text -days 3650 -CA ../CA/CA.crt -CAkey ../CA/CA.key -CAcreateserial -out ./pg.crt -extensions ssl_client -extfile ./pg.conf
    Signature ok
    subject=C = RU, ST = Moscow_reg., L = Moscow, O = PangolinEDU, CN =
    p620.class.edu
    Getting CA Private Key

    $ ls -ltr
    итого 16
    -rw-r--r-- 1 student student 623 сен 26 09:42 pg.conf
    -rw------- 1 student student 1704 сен 26 09:52 pg.key
    -rw-r--r-- 1 student student 3868 сен 26 09:52 pg.csr
    -rw-r--r-- 1 student student 3601 сен 26 10:02 pg.crt
  8. Проверьте присутствие в сертификате расширенных атрибутов:

     $ openssl x509 -noout -in pg.crt -ext subjectAltName,extendedKeyUsage X509v3 Extended Key Usage:
    TLS Web Client Authentication, TLS Web Server Authentication
    X509v3 Subject Alternative Name:
    DNS:p620.class.edu, IP Address:<ipvalue>

Настройка сервера

  1. Установите владельца postgres и группу postgres на все файлы в каталоге /etc/pangolin/ssl/. Разрешите только владельцу доступ в каталог с ключом и сертификатом сервера:

    $ cd
    $ sudo chown -R postgres:postgres /etc/pangolin/ssl
    $ sudo chmod go= /etc/pangolin/ssl/PG/
    $ ls -ld /etc/pangolin/ssl/PG/
    drwx------ 2 postgres postgres 4096 сен 26 10:02 /etc/pangolin/ssl/PG/
  2. Создайте каталог для хранения подключаемой конфигурации сервера с настройками SSL и подключите его к основному файлу конфигурации:

    $ sudo -u postgres mkdir /etc/pangolin/ssl/conf
    $ echo "include_dir '/etc/pangolin/ssl/conf'" | sudo -Eu postgres tee -a $PGDATA/postgresql.conf
    include_dir '/etc/pangolin/ssl/conf'
    $ sudo -Eu postgres tail -1 $PGDATA/postgresql.conf include_dir '/etc/pangolin/ssl/conf'
  3. В каталоге с подключаемой конфигурацией создайте файл настроек сервера для работы с SSL:

    $ sudo -Eu postgres tee /etc/pangolin/ssl/conf/pgssl.conf << EOF
    ssl = on
    ssl_ca_file = '/etc/pangolin/ssl/CA/CA.crt'
    ssl_cert_file = '/etc/pangolin/ssl/PG/pg.crt'
    ssl_key_file = '/etc/pangolin/ssl/PG/pg.key'
    EOF
    ssl = on
    ssl_ca_file = '/etc/pangolin/ssl/CA/CA.crt'
    ssl_cert_file = '/etc/pangolin/ssl/PG/pg.crt'
    ssl_key_file = '/etc/pangolin/ssl/PG/pg.key'
  4. Рестартуйте сервер, проверьте, есть ли ошибки в конфигурации SSL, а также подключилась ли конфигурация:

     $ sudo systemctl restart postgresql
    $ psql -U postgres -c "select name, setting, applied, sourcefile from pg_file_settings where name ~ 'ssl';"
    name | setting | applied | sourcefile
    ---------------+-----------------------------+---------+-----------------------------------
    ssl | on | t | /etc/pangolin/ssl/conf/pgssl.conf
    ssl_ca_file | /etc/pangolin/ssl/CA/CA.crt | t | /etc/pangolin/ssl/conf/pgssl.conf
    ssl_cert_file | /etc/pangolin/ssl/PG/pg.crt | t | /etc/pangolin/ssl/conf/pgssl.conf
    ssl_key_file | /etc/pangolin/ssl/PG/pg.key | t | /etc/pangolin/ssl/conf/pgssl.conf
    (4 строки)

    $ psql -U postgres -c \
    "select name, setting from pg_settings where setting ~ 'etc.*ssl';"
    name | setting
    --------------+-----------------------------
    ssl_ca_file | /etc/pangolin/ssl/CA/CA.crt
    ssl_cert_file | /etc/pangolin/ssl/PG/pg.crt
    ssl_key_file | /etc/pangolin/ssl/PG/pg.key
    (3 строки)

Настройка разрешений в pg_hba.conf

  1. Сохраните оригинальную версию файла pg_hba.conf:

    $ sudo -Eu postgres cp -v $PGDATA/pg_hba.conf{,.orig} '/pgdata/06/data/pg_hba.conf' -> '/pgdata/06/data/pg_hba.conf.orig'
  2. Установите пользователю student пароль student:

    $ psql -U postgres -c "alter user student password 'student'" ALTER ROLE
  3. Замените в pg_hba.conf в записях для локальных подключений через UNIX сокет тип аутентификации с trust на peer. Все остальные записи с trust должны использовать аутентификацию по паролю:

    $ sudo -Eu postgres sed -i -e 's/\(^local.*\)trust/\1peer/' -e '/^host/,$s/trust/scram-sha-256/' $PGDATA/pg_hba.conf

    Эти действия автоматизированы потоковым редактором sed, но могут быть выполнены в обычном текстовом редакторе. В этом примере опция -i заставляет редактор sed выполнять редактирование непосредственно в файле, а не в потоке. Первая команда редактировани, указанная после опции -e, заменяет строку trust строкой peer в тех строках, которые начинаются с local. Вторая команда после -e заменяет в строках от первой, начинающейся с host до последней все вхождения trust строкой scram-sha-256.

  4. Проверьте результат редактирования pg_hba.conf:

    $ sudo -Eu postgres sed -n '/^local/,$p' $PGDATA/pg_hba.conf
    local all all peer
    # IPv4 local connections:
    host all all 127.0.0.1/32 scram-sha-256
    # IPv6 local connections:
    host all all ::1/128 scram-sha-256

    # Allow replication connections from localhost, by a user with the
    # replication privilege.
    local replication all peer
    host replication all 127.0.0.1/32 scram-sha-256
    host replication all ::1/28 scram-sha-256
  5. Проверьте правильность pg_hba.conf средствами SQL:

    $ sudo -u postgres psql -c \
    "select type, database, user_name, auth_method, error from pg_hba_file_rules"
    type | database | user_name | auth_method | error
    -------+---------------+-----------+---------------+-------
    local | {all} | {all} | pper |
    host | {all} | {all} | scram-sha-256 |
    host | {all} | {all} | scram-sha-256 |
    local | {replication} | {all} | peer |
    host | {replication} | {all} | scram-sha-256 |
    host | {replication} | {all} | scram-sha-256 |
    (6 rows)
  6. В основном конфигурационном файле разрешите только два метода аутентификации для пользователей, не являющихся администраторами безопасности. Далее рестартуйте сервер и проверьте возможность локального подключения:

    $ sudo -Eu postgres sed -i.bak "s/^enabled_extra_auth_methods.*$/enabled_extra_auth_methods = 'scram-sha-256, peer'/" $PGDATA/postgresql.conf

    $ sudo systemctl restart postgresql

    $ psql
    psql (15.5)
    Type "help" for help.

    student@student=> \conninfo
    You are connected to database "student" as user "student" via socket in "/tmp" at port "5432".

Проверка работы SSL

  1. Получите статистику использования SSL обслуживающих процессов:

    student@student=> select * from pg_stat_ssl;
    pid | ssl | version | cipher | bits | client_dn | client_serial | issuer_dn
    -------+-----+---------+--------+------+-----------+---------------+-----------
    88281 | f | | | | | |
    (1 row)

    student@student=> select pg_backend_pid();
    pg_backend_pid
    ----------------
    88281
    (1 row)

    Из вывода команд видно, что SSL не используется.

  2. Сбросьте подключение и откройте новое через закольцовывающий сетевой интерфейс (loopback, ему соответствует сетевое имя localhost). При этом потребуется ввести пароль, так как будет использован метод аутентификации scram-sha-256. Проверьте состояние SSL:

    student@student=> \c - - localhost
    Password for user student:
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
    You are now connected to database "student" as user "student" on host "localhost" (address "::1") at port "5432".

    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ] -+-----------------------
    pid | 88359
    ssl | t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn |
    client_serial |
    issuer_dn |
  3. Снова сбросьте подключение и подключитесь к localhost, запретив SSL:

    student@student=> \c "host=localhost sslmode=disable"
    Password for user student:
    You are now connected to database "student" as user "student".

    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ]-+------
    pid | 88423
    ssl | f
    version |
    cipher |
    bits |
    client_dn |
    client_serial |
    issuer_dn |
  4. Включите SSL без сброса соединения:

    student@student=> \c -reuse-previous=on sslmode=require
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
    You are now connected to database "student" as user "student".

    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ]-+-----------------------
    pid | 88441
    ssl | t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn
    client_serial |
    issuer_dn |
  5. Завершите сеанс и попробуйте подключиться с настройками sslmode, требующими подтверждения выпуска сертификата сервера доверенным центром сертификации:

    student@student=> \q
    $ psql "host=localhost password=student sslmode=verify-ca"
    psql: ошибка: подключиться к серверу "localhost" (::1), порту 5432 не удалось: файл корневых сертификатов "/home/student/.postgresql/root.crt" не существует Укажите полный путь к файлу или отключите проверку сертификата сервера, изменив sslmode.

    $ psql "host=localhost password=student sslmode=verify-full"
    psql: ошибка: подключиться к серверу "localhost" (::1), порту 5432 не удалось: файл корневых сертификатов "/home/student/.postgresql/root.crt" не существует Укажите полный путь к файлу или отключите проверку сертификата сервера, изменив sslmode.

    Все возможные значения параметра sslmode приведены в документации: https://www.postgresql.org/docs/16/libpq-connect.html#LIBPQ-PARAMKEYWORDS.

  6. Создайте символическую ссылку на файл сертификата центра сертификации:

    $ mkdir .postgresql
    $ ln -s /etc/pangolin/ssl/CA/CA.crt .postgresql/root.crt
    $ ls -l .postgresql/
    итого 0
    lrwxrwxrwx 1 student student 27 сен 27 13:26 root.crt -> /etc/pangolin/ssl/CA/CA.crt
  7. Снова проверьте возможность подключения в режиме verify-ca:

    $ psql "host=localhost password=student sslmode=verify-ca"
    psql (15.5)
    SSL-соединение (протокол: TLSv1.3, шифр: TLS_AES_256_GCM_SHA384, сжатие: выкл.)
    Введите "help", чтобы получить справку.

    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ]-+-----------------------
    pid | 90015
    ssl |t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn |
    client_serial |
    issuer_dn |
  8. Проверьте возможность подключения в режиме verify-full:

    student@student=> \c -reuse-previous=on sslmode=verify-full
    подключиться к серверу "localhost" (::1), порту 5432 не удалось: server certificate for "p620.class.edu" (and 1 other name) does not match host name "localhost"
    Сохранено предыдущее подключение

    Необходимо указать то имя хоста, которое соответствует указанным в атрибутах SAN или CN, в случае его отсутствия:

    student@student=> \c "host=p620.class.edu sslmode=verify-full"
    подключиться к серверу "p620.class.edu" (fe80::a00:27ff:fe48:5b30), порту 5432 не удалось: FATAL: no pg_hba.conf entry for host "fe80::a00:27ff:fe48:5b30%enp0s3", user "student", database "student", SSL encryption
    Сохранено предыдущее подключение
    student@student=> \q

    Так как в pg_hba.conf отсутствует соответствующее разрешение, соединение не удалось.

  9. Добавьте в pg_hba.conf разрешение подключаться по адресу интерфейса, соответствующего FQDN (Fully Qualified Domain Name полное доменное имя хоста), внесенному в атрибуты SAN (Subject Alternative Name - альтернативное доменное имя хоста) и CN сертификата (Common Name - обычное имя хоста).

    Данные действия рекомендуется выполнить в сеансе postgres.

    [student@p620 ~]$ sudo -i -u postgres

    В переменную окружения LNUM запоминаем самый первый номер строки с типом подключения, отличным от host, определенный запросом к представлению pg_hba_file_rules (отображает содержимое pg_hba.conf, поле line_number - номер строки):

    [postgres@p620 ~]$ export LNUM=$(psql -At -c "select min(line_number) from pg_hba_file_rules where type != 'host'")

    [postgres@p620 ~]$ echo $LNUM
    89

    Добавляем после строки с номером, запомненным в LNUM, правило: host student student <IP адрес хоста> scram-sha-256:

    [postgres@p620 ~]$ echo "${LNUM}a\host student student \ $(hostname -I | tr -dc [0-9.])/32 scram-sha-256" \
    | xargs -i sed -i {} $PGDATA/pg_hba.conf

    Проверяем, что получилось в файле pg_hba.conf, получив с помощью sed его содержимое от строки, содержащей в начале слово local, до конца файла:

    [postgres@p620 ~]$ sed -n '/^local/,$p' $PGDATA/pg_hba.conf
    local all all peer
    host student student <ipvalue> /32 scram-sha-256
    # IPv4 local connections:
    host all all 127.0.0.1/32 scram-sha-256
    # IPv6 local connections:
    host all all ::1/128 scram-sha-256
    # Allow replication connections from localhost, by a user with the
    # replication privilege.
    local replication all peer
    host replication all 127.0.0.1/32 scram-sha-256
    host replication all ::1/128 scram-sha-256

    Если вывод приведенной выше команды отличается от вашего, то просто скопируйте в обычном текстовом редакторе в файл pg_hba.conf строки, выведенные sed:

    [postgres@p620 ~]$ psql -c 'select pg_reload_conf()' pg_reload_conf
    ----------------
    t
    (1 строка)
    [postgres@p620 ~]$ exit выход
  10. Подключитесь в режиме sslmode=verify-full, указав IPv4 адрес сервера:

    $ psql -x "host=$(hostname -I) password=student sslmode=verify-full" \ -c 'select * from pg_stat_ssl'
    -[ RECORD 1 ]-+-----------------------
    pid | 93891
    ssl | t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn |
    client_serial |
    issuer_dn |

    При генерации сертификата сервера был указан атрибут IP.1 = <ipvalue>, что и позволяет подключиться, указав IPv4 адрес.

  11. Попробуйте сделать то же, указав вместо IPv4 адреса FQDN сервера:

    $ psql -x "host=$(hostname) password=student sslmode=verify-full" \ -c 'select * from pg_stat_ssl'
    psql: ошибка: подключиться к серверу "p620.class.edu"
    (fe80::a00:27ff:fe48:5b30), порту 5432 не удалось: FATAL: no pg_hba.conf entry
    for host "fe80::a00:27ff:fe48:5b30%enp0s3", user "student", database "student",
    SSL encryption

    Причина в том, что не работает разрешение имен для IPv4 адреса сервера:

    $ ping -c3 `hostname`
    PING p620.class.edu(p620.class.edu (fe80::a00:27ff:fe48:5b30%enp0s3)) 56 data bytes
    64 bytes from p620.class.edu (fe80::a00:27ff:fe48:5b30%enp0s3): icmp_seq=1 ttl=64 time=0.029 ms
    64 bytes from p620.class.edu (fe80::a00:27ff:fe48:5b30%enp0s3): icmp_seq=2 ttl=64 time=0.041 ms
    64 bytes from p620.class.edu (fe80::a00:27ff:fe48:5b30%enp0s3): icmp_seq=3 ttl=64 time=0.041 ms

    Исправьте ситуацию, добавив в файл /etc/hosts статическое соответствие доменного имени сервера IPv4 адресу его основного интерфейса:

    $ echo "$(hostname -I) $(hostname) $(hostname -s)" | sudo tee -a /etc/hosts

    $ cat /etc/hosts
    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    <ipvalue> p620.class.edu p620

    $ ping -c3 `hostname`
    PING p620.class.edu (<ipvalue>) 56(84) bytes of data.
    64 bytes from p620.class.edu (<ipvalue>): icmp_seq=1 ttl=64 time=0.026 ms
    64 bytes from p620.class.edu (<ipvalue>): icmp_seq=2 ttl=64 time=0.026 ms
    64 bytes from p620.class.edu (<ipvalue>): icmp_seq=3 ttl=64 time=0.024 ms

    --- p620.class.edu ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2059ms
    rtt min/avg/max/mdev = 0.024/0.025/0.026/0.000 ms

    Теперь разрешение имен для IPv4 адреса сервера работает, попробуем подключиться:

    $ psql -x "host=$(hostname) password=student sslmode=verify-full" \ -c 'select * from pg_stat_ssl'
    -[ RECORD 1 ]-+-----------------------
    pid | 94100
    ssl | t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn |
    client_serial |
    issuer_dn |

Проверка работы SSL

  1. Создайте запрос на подпись клиентского сертификата:

    $ cd .postgresql/
    $ pwd /home/student/.postgresql
    $ openssl req -new -nodes -text -out ./postgresql.csr -keyout ./postgresql.key - subj "/CN=student"
    Generating a RSA private key
    ........+++++ ................................................................................ .....+++++
    writing new private key to './postgresql.key'
    -----
  2. Подпишите запрос на сертификацию и получите сертификат:

    $ sudo openssl x509 -req -in ./postgresql.csr -text -days 3650 -CA ./root.crt - CAkey /etc/pangolin/ssl/CA/CA.key -CAcreateserial -out ./postgresql.crt
    Signature ok
    subject=CN = student
    Getting CA Private Key

    $ sudo chown student:student postgresql.crt

    $ ls -ltr
    итого 16
    lrwxrwxrwx 1 student student 27 сен 27 13:26 root.crt -> /etc/pangolin/ssl/CA/CA.crt
    -rw------- 1 student student 1704 сен 29 19:36 postgresql.key
    -rw-r--r-- 1 student student 3316 сен 29 19:36 postgresql.csr
    -rw-r--r-- 1 root root 41 сен 29 19:37 root.srl
    -rw-r--r-- 1 student student 3226 сен 29 19:37 postgresql.crt
  3. Проверьте возможность подключения:

    $ psql -x "host=$(hostname) password=student sslmode=prefer"
    psql (15.5)
    SSL-соединение (протокол: TLSv1.3, шифр: TLS_AES_256_GCM_SHA384, сжатие: выкл.) Введите "help", чтобы получить справку.
    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ]-+-------------------------------------------------------------- pid | 115125
    ssl | t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn | /CN=student
    client_serial | 389951548294704679529084448680543693286257451745
    issuer_dn | /C=RU/ST=Moscow_reg./L=Moscow/O=PangolinEDU/CN=PangolinEDU_CA

Расширение sslinfo

  1. Подключите к базе данных student расширение sslinfo:

    $ sudo -Eu postgres psql -d student -c 'create extension sslinfo' 2> /dev/null
  2. Подключитесь к БД student в сеансе student и проверьте, подключено ли расширение:

    $ psql
    psql (15.5)
    Введите "help", чтобы получить справку.

    student@student=> \dx
    Список установленных расширений
    Имя | Версия | Схема | Описание
    ---------+--------+------------+------------------------------------
    plpgsql | 1.1 | pg_catalog | PL/pgSQL procedural language
    sslinfo | 1.2 | public | information about SSL certificates
    (2 строки)
  3. Получите список функций в расширении:

    student@student=> \dx+ sslinfo Объекты в расширении "sslinfo"
    Описание объекта
    ------------------------------------
    function ssl_cipher()
    function ssl_client_cert_present()
    function ssl_client_dn()
    function ssl_client_dn_field(text)
    function ssl_client_serial()
    function ssl_extension_info()
    function ssl_issuer_dn()
    function ssl_issuer_field(text)
    function ssl_is_used()
    function ssl_version()
    (10 строк)
  4. Средствами расширения проверьте, включен ли SSL. Затем инициируйте сессию с SSL и проверьте снова:

    student@student=> select ssl_is_used(); ssl_is_used
    -------------
    f
    (1 строка)

    student@student=> \c "host=p620.class.edu password=student"
    SSL-соединение (протокол: TLSv1.3, шифр: TLS_AES_256_GCM_SHA384, сжатие: выкл.) Сейчас вы подключены к базе данных "student" как пользователь "student" (сервер "p620.class.edu": адрес "<ipvalue>", порт "5432").
    student@student=> select ssl_is_used(); ssl_is_used
    -------------
    t
    (1 строка)
  5. Получите сертификаты клиента и издателя:

    student@student=> select ssl_client_dn(); ssl_client_dn
    ---------------
    /CN=student
    (1 строка)
    student@student=> select ssl_issuer_dn(); ssl_issuer_dn
    ---------------------------------------------------------------
    /C=RU/ST=Moscow_reg./L=Moscow/O=PangolinEDU/CN=PangolinEDU_CA
    (1 строка)

Аутентификация по сертификату

  1. Измените метод аутентификации для подключения пользователя student к БД student на cert, также замените тип подключения на hostssl:

    $ sudo -Eu postgres sed -i.bak 's/^host\(.*student.*32\).*$/hostssl\1 cert/' $PGDATA/pg_hba.conf
    $ sudo -Eu postgres tail -12 $PGDATA/pg_hba.conf
    # "local" is for Unix domain socket connections only
    local all all peer
    hostssl student student <ipvalue> cert
    # IPv4 local connections:
    host all all 127.0.0.1/32 scram-sha-256
    # IPv6 local connections:
    host all all ::1/128 scram-sha-256
    # Allow replication connections from localhost, by a user with the # replication privilege.
    local replication all peer
    host replication all 127.0.0.1/32 scram-sha-256
    host replication all ::1/128 scram-sha-256
  2. Перечитайте и проверьте конфигурацию:

    $ sudo -Eu postgres psql -c 'select pg_reload_conf()'
    $ sudo -Eu postgres psql -c 'select * from pg_hba_file_rules'
    line_number | type | database | user_name | address | netmask | auth_method |
    -------------+---------+--------------+--------------+-----------+-----------------------------------------+-----------------+
    89 | local | {all} | {all} | | | peer
    90 | hotssl | {student} | {student} | <ipvalue> | 255.255.255.255 | cert
    92 | host | {all} | {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256
    94 | host | {all} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256
    97 | local | {replication}| {all} | | | peer
    98 | host | {replication}| {all} | 127.0.0.1 | 255.255.255.255 | scram-sha-256
    99 | host | {replication}| {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | scram-sha-256
    (7 rows)
  3. Разрешите аутентификацию cert:

    $ sudo -Eu postgres sed -i.bak "s/^enabled_extra_auth_methods.*$/enabled_extra_auth_methods = 'scram-sha-256, peer, cert'/" $PGDATA/postgresql.conf
    $ sudo systemctl restart postgresql
  4. Проверьте возможность входа в сеанс. Пароль более указывать не потребуется, так как при генерации пользовательского сертификата он не был защищен паролем:

    $ psql -h $(hostname)
    psql (15.5)
    SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
    student@student=> select * from pg_stat_ssl \gx
    -[ RECORD 1 ]-+-------------------------------------------------------------- pid | 116416
    ssl |t
    version | TLSv1.3
    cipher | TLS_AES_256_GCM_SHA384
    bits | 256
    client_dn | /CN=student
    client_serial | 389951548294704679529084448680543693286257451745
    issuer_dn | /C=RU/ST=Moscow_reg./L=Moscow/O=PangolinEDU/CN=PangolinEDU_CA
    student@student=> \q