AI Установка и Настройка FreeIPA с внешним Root CA

AI

Редактор
Регистрация
23 Август 2023
Сообщения
3 603
Лучшие ответы
0
Реакции
0
Баллы
243
Offline
#1
Цель


Настроить сервер FreeIPA (систему управления идентификацией) с использованием собственного (внешнего) корневого сертификата вместо самоподписанного.

Архитектура после изменений:

Root CA (apatsev.corp)
└── CA-сертификат для подсистемы FreeIPA/Dogtag (ipa.apatsev.corp) с вашим корпоративным сертификатом


Безопасность: Корневой ключ (rootCA.key) используется для подписи. Для максимальной безопасности выполните этот шаг на изолированной, защищённой машине, а не на будущем сервере FreeIPA.
ПОДГОТОВИТЕЛЬНЫЙ ЭТАП: Создание инфраструктуры PKI

Шаг 1: Создаём корневой сертификат (Root CA)


ВАЖНО: Этот шаг выполняется на защищённой управляющей машине, а не на сервере FreeIPA!
1.1 Создаём конфигурационный файл для Root CA:


cat > provision/files/rootCA.cnf << 'EOF'
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no

[ req_distinguished_name ]
C = RU
ST = Omsk Oblast
L = Omsk
O = MyCompany
OU = Apatsev
CN = apatsev.corp Root CA

[ v3_ca ]
basicConstraints = critical, CA:TRUE, pathlen:1
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
EOF

Что мы создали:


  • basicConstraints = CA:TRUE - указывает, что это CA-сертификат


  • keyUsage = keyCertSign - разрешает подписывать другие сертификаты


  • Остальные поля - ваши организационные данные
1.2 Генерируем приватный ключ:


openssl genrsa -out provision/files/rootCA.key 4096
1.3 Создаём самоподписанный корневой сертификат:


openssl req -x509 -new -key provision/files/rootCA.key \
-sha256 -days 3650 \
-out provision/files/rootCA.crt \
-config provision/files/rootCA.cnf -extensions v3_ca

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

openssl x509 -in provision/files/rootCA.crt -text -noout | grep -A 1 "Basic Constraints\|Key Usage"

Должны увидеть:

X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign

Шаг 2: Создаём конфигурацию для сертификата FreeIPA

2.1 Создаём файл ipa.cnf:


cat > provision/files/ipa.cnf << 'EOF'
[ req ]
prompt = no
distinguished_name = dn
req_extensions = req_ext

[ dn ]
CN = ipa.apatsev.corp
O = MyCompany

[ req_ext ]
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = @alt_names
subjectKeyIdentifier = hash

[ alt_names ]
DNS.1 = ipa.apatsev.corp
DNS.2 = ipa
EOF

Ключевые моменты:


  • CN = ipa.apatsev.corp - полное доменное имя сервера


  • CA:TRUE и keyCertSign - ОБЯЗАТЕЛЬНЫ для работы FreeIPA!


  • subjectAltName - альтернативные DNS-имена сервера
НАСТРОЙКА ANSIBLE

Шаг 4: Создаём inventory файл


Создайте файл inventory.yml:

cat > inventory.yml << 'EOF'
all:
children:
ipaserver:
hosts:
"freeipa-instance":
ansible_host: "158.160.100.220"
vars:
ansible_user: almalinux
ipaadmin_password: ADMPassword1
ipadm_password: ADMPassword1
ipaserver_no_host_dns: true
ipaserver_ip_addresses:
- '{{ ansible_default_ipv4.address|default(ansible_all_ipv4_addresses[0]) }}'
ipaserver_domain: apatsev.corp
ipaserver_realm: APATSEV.CORP
ipaserver_hostname: ipa.apatsev.corp
ipaserver_setup_dns: true
ipaserver_forwarders:
- 8.8.8.8
EOF
Шаг 5: Создаём скрипт для подписи сертификатов


Создайте файл external-ca.sh:

cat > provision/files/external-ca.sh << 'EOM'
#!/bin/bash
set -euo pipefail

script_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
provision_dir="$(cd "${script_root}/.." && pwd)"

master="${1:-}"
domain="${2:-}"

usage() {
cat <<EOF
Usage: $0 master-fqdn domain
EOF
}

if [ -z "$master" ]; then
echo "ERROR: master is not set"
usage
exit 1
fi

if [ -z "$domain" ]; then
echo "ERROR: domain is not set"
usage
exit 1
fi

if [[ "$master" != *".${domain}" ]]; then
echo "WARNING: master (${master}) does not look like it belongs to domain ${domain}"
fi

csr_file="${provision_dir}/${master}-ipa.csr"
if [ ! -f "$csr_file" ]; then
echo "ERROR: ${csr_file} not found"
exit 1
fi

root_ca_key="${script_root}/rootCA.key"
root_ca_crt="${script_root}/rootCA.crt"
ipa_conf="${script_root}/ipa.cnf"

for required in "$root_ca_key" "$root_ca_crt" "$ipa_conf"; do
if [ ! -f "$required" ]; then
echo "ERROR: required file ${required} is missing"
exit 1
fi
done

signed_cert="${provision_dir}/${master}-ipa.crt"
chain_file="${provision_dir}/${master}-chain.crt"

openssl x509 -req \
-in "$csr_file" \
-CA "$root_ca_crt" \
-CAkey "$root_ca_key" \
-out "$signed_cert" \
-days 1825 \
-sha256 \
-extfile "$ipa_conf" \
-extensions req_ext

cat "$signed_cert" "$root_ca_crt" > "$chain_file"

echo "Signed ${csr_file} with ${root_ca_crt} and produced ${signed_cert} and ${chain_file}"
EOM

Делаем скрипт исполняемым:

chmod +x provision/files/external-ca.sh
Шаг 6: Создаём основной playbook


Создайте файл playbook.yml:

cat > provision/playbook.yml << 'EOF'
---
- name: Playbook to configure IPA server step1
hosts: ipaserver
become: true
collections:
- freeipa.ansible_freeipa
vars:
ipaserver_external_ca: yes

roles:
- role: freeipa.ansible_freeipa.ipaserver
state: present

post_tasks:
- name: Copy CSR /root/ipa.csr from node to "{{ groups.ipaserver[0] + '-ipa.csr' }}"
ansible.builtin.fetch:
src: /root/ipa.csr
dest: "{{ groups.ipaserver[0] + '-ipa.csr' }}"
flat: yes

- name: Get /root/ipa.csr, sign with our Root CA and produce chain
hosts: localhost
gather_facts: false
tasks:
- name: Run external-ca.sh
ansible.builtin.command: >
/bin/bash
files/external-ca.sh
"{{ groups.ipaserver[0] }}"
"{{ ipaserver_domain | default(groups.ipaserver[0].split('.')[1:] | join('.')) }}"
args:
chdir: "{{ playbook_dir }}"

- name: Playbook to configure IPA server step2
hosts: ipaserver
become: true
collections:
- freeipa.ansible_freeipa
vars:
ipaserver_external_cert_files: "/root/chain.crt"

pre_tasks:
- name: Copy "{{ groups.ipaserver[0] + '-chain.crt' }}" to /root/chain.crt on node
ansible.builtin.copy:
src: "{{ groups.ipaserver[0] + '-chain.crt' }}"
dest: /root/chain.crt
force: yes
mode: preserve

roles:
- role: freeipa.ansible_freeipa.ipaserver
state: present
EOF
ЗАПУСК УСТАНОВКИ

Шаг 7: Подготовка управляющей машины


На машине, с которой будете запускать Ansible:

# Устанавливаем необходимые коллекции Ansible
ansible-galaxy collection install freeipa.ansible_freeipa

# Запускаем проверку подключения
ansible -i inventory.yml all -m ping
Шаг 8: Запуск установки


ansible-playbook -i inventory.yml provision/playbook.yml

Что происходит по этапам:


  1. Этап 1: FreeIPA устанавливается в режиме "внешний CA", генерируется CSR


  2. Этап 2: Наш скрипт подписывает CSR корневым сертификатом


  3. Этап 3: FreeIPA завершает установку с подписанным сертификатом
ПРОВЕРКА УСТАНОВКИ


После успешного выполнения playbook:

Проверка 1: Статус служб


$ sudo systemctl status ipa
● ipa.service - Identity, Policy, Audit
Loaded: loaded (/usr/lib/systemd/system/ipa.service; enabled; preset: disabled)
Active: active (exited) since Mon 2025-12-15 04:38:03 UTC; 19min ago
Process: 18000 ExecStart=/usr/sbin/ipactl start (code=exited, status=0/SUCCESS)
Main PID: 18000 (code=exited, status=0/SUCCESS)
CPU: 1.752s

Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting Directory Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting krb5kdc Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting kadmin Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting named Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting httpd Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting ipa-custodia Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting pki-tomcatd Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting ipa-otpd Service
Dec 15 04:38:03 ipa.apatsev.corp ipactl[18000]: Starting ipa-dnskeysyncd Service
Dec 15 04:38:03 ipa.apatsev.corp systemd[1]: Finished Identity, Policy, Audit.
Проверка 2: Веб-интерфейс


Откройте в браузере: https://ipa.apatsev.corp


ВНИМАНИЕ: Браузер будет ругаться на самоподписанный сертификат. Импортируйте rootCA.crt в хранилище доверенных корневых сертификатов вашего браузера.


Проверка 3: Командная строка


# Проверяем, что мы администраторы
$ kinit admin
$ ipa user-find
--------------
1 user matched
--------------
User login: admin
Last name: Administrator
Home directory: /home/admin
Login shell: /bin/bash
Principal name: admin@APATSEV.CORP
Principal alias: admin@APATSEV.CORP, root@APATSEV.CORP
UID: 1280400000
GID: 1280400000
Account disabled: False
----------------------------
Number of entries returned 1
----------------------------

Проверка 4: Сертификат


$ openssl x509 -in /etc/ipa/ca.crt -text -noout | grep -A 1 "Issuer\|CA:TRUE"
Issuer: C=RU, ST=Omsk Oblast, L=Omsk, O=MyCompany, OU=Apatsev, CN=apatsev.corp Root CA
Validity
--
CA:TRUE
X509v3 Key Usage: critical

ТИПИЧНЫЕ ПРОБЛЕМЫ И РЕШЕНИЯ

Проблема 1: "CA:TRUE not found in certificate"


Симптом: Установка падает на этапе 3 Решение: Убедитесь, что в ipa.cnf есть строки:

basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

Проблема 2: Нет доступа к веб-интерфейсу


Решение:


  1. Проверьте firewall:

sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service={http,https,ldap,ldaps,kerberos}
sudo firewall-cmd --reload
Проблема 3: Ошибки DNS


Решение: Добавьте в /etc/hosts на всех клиентах:

178.154.227.14 ipa.apatsev.corp ipa

БЕЗОПАСНОСТЬ

Что делать после установки:


  1. Защитите приватные ключи:

# На управляющей машине
chmod 600 provision/files/rootCA.key

  1. Бекап и восстановление:

# На сервере FreeIPA
$ ipa-backup --data
Preparing backup on ipa.apatsev.corp
Local roles match globally used roles, proceeding.
Stopping Directory Server
Backing up ipaca in APATSEV-CORP to LDIF
Backing up userRoot in APATSEV-CORP to LDIF
Backing up APATSEV-CORP
Starting Directory Server
Backed up to /var/lib/ipa/backup/ipa-data-2025-12-15-04-54-52
The ipa-backup command was successful

$ ipa-restore /var/lib/ipa/backup/ipa-data-2025-12-15-04-54-52
Directory Manager (existing master) password:

Preparing restore from /var/lib/ipa/backup/ipa-data-2025-12-15-04-54-52 on ipa.apatsev.corp
Performing DATA restore from DATA backup
Temporary setting umask to 022
Restoring data will overwrite existing live data. Continue to restore? [no]: yes
Each master will individually need to be re-initialized or
re-created from this one. The replication agreements on
masters running IPA 3.1 or earlier will need to be manually
re-enabled. See the man page for details.
Disabling all replication.
Stopping Directory Server
Restoring from userRoot in APATSEV-CORP
Restoring from ipaca in APATSEV-CORP
Starting Directory Server
Restoring umask to 18
The ipa-restore command was successful

  1. Настройте брандмауэр:

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
ЧЕК-ЛИСТ ПЕРЕД ЗАПУСКОМ


  • Hostname сервера: ipa.apatsev.corp


  • Все файлы в provision/files/:

    • rootCA.key


    • rootCA.crt


    • ipa.cnf


    • external-ca.sh (исполняемый)

  • В inventory.yml правильные IP и пароли


  • На управляющей машине установлен Ansible и коллекции


  • Есть SSH доступ к серверу


  • DNS записи или /etc/hosts настроены
 
Сверху Снизу