Настройка 2 серверов LDAP с секъюрной репликой между ними

Модераторы: flash, mordor

Ответить
Аватара пользователя
flashdeath
Администратор
Сообщения: 25
Зарегистрирован: 08 ноя 2007, 14:22

Настройка 2 серверов LDAP с секъюрной репликой между ними

Сообщение flashdeath »

По работе пришла задача настроить безопасный LDAP.
Что значит безопасный?
1. Это должно быть 2 Инстанса объединенные репликой (релицироваться должен основной корень LDAP и его конфигурация).
2. Пароли не должны фигурировать в конфигах.
3. требуется модификация схемы по просьбе разработки.

В качестве OS используем RedHat подобный дистрибутив RedOS8

Заливку OS оставлю без внимания, оговорившись только что используем минимальную инсталляцию.
Нам потребуется CA (certificete autority) для генерации сертов сервера и клиента репликации.
Ставим нужные пакеты

Код: Выделить всё

yum install openssl openldap-servers openldap-clients cyrus-sasl -y
Если у вас уже есть CA то данный раздел можно пропустить

Переходим к созданию CA
На одной из нод нашего LDAP (но можно и на любом стороннем сервере) создаем каталог CA

Код: Выделить всё

mkdir /CA
там создаем нужные подкаталоги

Код: Выделить всё

mkdir -p /CA/{certs,crl,newcerts,private,csr}
Создаем файл serial и ставим в него базовый номер серта

Код: Выделить всё

echo 1000 > /CA/serial
Создаем файл crlnumber и ставим в него базовый номер crl

Код: Выделить всё

echo 0100 > /CA/crlnumber 
Создаем индексный файл

Код: Выделить всё

touch /CA/index.txt
Создаем openssl.cnf файл - это конфигурация нашего CA

Код: Выделить всё

HOME                    = .
openssl_conf = openssl_init
config_diagnostics = 1
oid_section = new_oids

[ new_oids ]
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

[openssl_init]
providers = provider_sect
ssl_conf = ssl_module

[provider_sect]
default = default_sect
[default_sect]
activate = 1

[ ssl_module ]
system_default = crypto_policy

[ crypto_policy ]
.include = /etc/crypto-policies/back-ends/opensslcnf.config

[ ca ]
default_ca      = CA_default            # The default ca section

[ CA_default ]
#CA
dir             = /CA           		# Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file. several certs with same subject.
unique_subject  = no
new_certs_dir   = $dir/newcerts         # default place for new certs.
certificate     = $dir/ca.crt   		# The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/ca.key   # The private key
x509_extensions = usr_cert              # The extensions to add to the cert
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options

#CRL
default_days    = 3650                  # how long to certify for
default_crl_days= 365                   # how long before next CRL
default_md      = sha512                # use SHA-256 by default
preserve        = no                    # keep passed DN ordering
policy          = policy_match

[ policy_match ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
domainComponent         = optional
UID                     = optional
emailAddress            = optional

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
domainComponent         = optional
UID                     = optional
emailAddress            = optional

[ req ]
default_bits            = 4096
default_md              = sha512
default_keyfile         = privkey.key
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only


[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
#countryName_default            = RU
countryName_min                 = 0
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
#stateOrProvinceName_default    = Russia

localityName                    = Locality Name (eg, city)
#localityName_default           = Moscow

0.organizationName              = Organization Name (eg, company)
#0.organizationName_default     = Test Local

# we can do this but it is not needed normally :-)
#1.organizationName             = Second Organization Name (eg, company)
#1.organizationName_default     = World Wide Web Pty Ltd

organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default = IT

commonName                      = Common Name (eg, your name or your server\'s hostname)
commonName_max                  = 128

domainName                      = Domain Name (eg local)
uid                             = UID

emailAddress                    = Email Address
emailAddress_max                = 128

[ req_attributes ]
challengePassword               = A challenge password
challengePassword_min           = 0
challengePassword_max           = 20
unstructuredName                = An optional company name

[ usr_cert ]
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

[ srv_cert ]                                             # Server certificate extensions
basicConstraints = CA:FALSE                                 # Not a CA certificate
nsCertType = server                                         # Server certificate type
keyUsage = critical, digitalSignature, keyEncipherment      # Key usage for a server cert
extendedKeyUsage = serverAuth
authorityKeyIdentifier = keyid,issuer

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true

[ crl_ext ]
authorityKeyIdentifier=keyid:always

[ proxy_cert_ext ]
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo

[ tsa ]
default_tsa = tsa_config1       # the default TSA section

[ tsa_config1 ]
dir             = /CA           		# TSA root directory
serial          = $dir/tsaserial        # The current serial number (mandatory)
crypto_device   = builtin               # OpenSSL engine to use for signing
signer_cert     = $dir/tsacert.crt      # The TSA signing certificate (optional)
certs           = $dir/ca.crt   		# Certificate chain to include in reply (optional)
signer_key      = $dir/private/tsa.key  # The TSA private key (optional)
signer_digest  = sha512                 # Signing digest to use. (Optional)
default_policy  = tsa_policy1           # Policy if request did not specify it (optional)
other_policies  = tsa_policy2, tsa_policy3      # acceptable policies (optional)
digests     = sha1, sha256, sha384, sha512  # Acceptable message digests (mandatory)
accuracy        = secs:1, millisecs:500, microsecs:100  # (optional)
clock_precision_digits  = 0     # number of digits after dot. (optional)
ordering                = yes   # Is ordering defined for timestamps? (optional, default: no)
tsa_name                = yes   # Must the TSA name be included in the reply? (optional, default: no)
ess_cert_id_chain       = no    # Must the ESS cert id chain be included? (optional, default: no)
ess_cert_id_alg         = sha1  # algorithm to compute certificate identifier (optional, default: sha1)

[insta] # CMP using Insta Demo CA
server = pki.certificate.fi:8700
path = pkix/

recipient = "/C=RU/O=Test Local/CN=Insta Test CA" # or set srvcert or issuer
ignore_keyusage = 1 # potentially needed quirk
unprotected_errors = 1 # potentially needed quirk
extracertsout = insta.extracerts.pem
ref = 3078 # user identification
secret = pass:insta # can be used for both client and server side
cmd = ir # default operation, can be overridden on cmd line with, e.g., kur
subject = "/CN=openssl-cmp-test"
newkey = insta.priv.pem
out_trusted = apps/insta.ca.crt # does not include keyUsage digitalSignature
certout = insta.cert.pem

[pbm] # Password-based protection for Insta CA
ref = $insta::ref # 3078
secret = $insta::secret # pass:insta

[signature] # Signature-based protection for Insta CA
trusted = $insta::out_trusted # apps/insta.ca.crt

secret = # disable PBM
key = $insta::newkey # insta.priv.pem
cert = $insta::certout # insta.cert.pem

[ir]
cmd = ir

[cr]
cmd = cr

[kur]
cmd = kur
oldcert = $insta::certout # insta.cert.pem

[rr]
cmd = rr
oldcert = $insta::certout # insta.cert.pem
Создаем ключ CA и даем к нему доступ только на чтение

Код: Выделить всё

openssl genrsa -out /CA/private/ca.key 4096
chmod 400 /CA/private/ca.key
Проверяем ключ

Код: Выделить всё

openssl rsa -noout -text -in /CA/private/ca.key
Создаем конревой сертификат CA

Код: Выделить всё

openssl req -config openssl_root.cnf -key /CA/private/ca.key -new -x509 -days 356000 -sha512 -extensions v3_ca -out /CA/certs/ca.crt -subj "/C=RU/ST=Russia/L=Moscow/O=TEST LOCAL/OU=IT/CN=CA_TEST_LOCAL"
Меняем на него права и проверяем что все правильно

Код: Выделить всё

chmod 444 /CA/certs/ca.crt
openssl x509 -noout -text -in /CA/certs/ca.crt
Создаем wildcard сертификат для наших серверов в домене toadmins.local (это реальные имена серверов, при этом они должны корекно резолвиться в DNS)
сначала создаем новый ключ и хадаем доступ на него только чтение.

Код: Выделить всё

openssl genrsa -out /CA/private/winldcard-server.key 4096
chmod 400 /CA/private/winldcard-server.key
Затем создаем запрос сертификата.

Код: Выделить всё

openssl req -config /CA/openssl.cnf -key /CA/private/winldcard-server.key -new -sha512 -out /CA/csr/winldcard-server.csr -subj "/C=RU/ST=Russia/L=Moscow/O=TEST LOCAL/OU=IT/CN=*.toadmins.local"
Проверяем запрос

Код: Выделить всё

openssl req -in /CA/csr/winldcard-server.csr -text -verify -noout
Подписываем сертификат

Код: Выделить всё

openssl ca -config /CA/openssl.cnf -extensions srv_cert -days 3650 -notext -md sha512 -in /CA/csr/winldcard-server.csr -out /CA/certs/winldcard-server.crt
Дальше 2 раза нажимаем "y"
на вопросы системы
1.

Код: Выделить всё

Sign the certificate? [y/n]:y
и
2.

Код: Выделить всё

1 out of 1 certificate requests certified, commit? [y/n]
Проверяем сертификат

Код: Выделить всё

openssl x509 -text -noout -in /CA/certs/winldcard-server.crt
Создаем сертификат пользователя
Cначала создаем ключ

Код: Выделить всё

openssl genpkey -algorithm RSA -out /CA/private/repadmin.key
Создаем запрос серттификата

Код: Выделить всё

openssl req -config /CA/openssl.cnf -key /CA/private/repadmin.key -new -sha512 -out /CA/csr/repadmin4.csr -subj "/DC=local/DC=test/UID=repadmin"
И подписывам сертификат

Код: Выделить всё

openssl ca -config /CA/openssl.cnf -extensions usr_cert -days 3650 -notext -md sha512 -in /CA/csr/repadmin.csr  -out /CA/certs/repadmin.crt
С сертификатами вообщем все, кроме одного дополнения ниже

На будущее если надо отозвать серт и перегенировать crl, то команды следующие

Код: Выделить всё

openssl ca -config /CA/openssl.cnf -revoke /CA/certs/winldcard-server.crt
этой командой отзываем серверный сертификат
при этом в индексном файле напротив сертификата появится буква R

Код: Выделить всё

R       341219130532Z   241221130728Z   1000...
Чтобы остальные системы знали что сертификат отозван надо создать (или обновить существующий) crl.crt
Делается это командой

Код: Выделить всё

openssl ca -config /CA/openssl.cnf -gencrl -out /CA/crl/crl.crt
содержимое crl можно посмотреть командой

Код: Выделить всё

openssl crl -text -noout -in crl/crl.crt
и там будут серийники отозванных сертификатов

Преходим к настройке LDAP
нам из нашего CA нужны 5 файлов

Код: Выделить всё

1. ca.crt
2. winldcard-server.crt
3. winldcard-server.key
4. repadmin.crt
5. repadmin.key
Эти файлы надо скопировать в каталог /etc/openldap/certs на каждый LDAP сервер
Меняем права на каталоги LDAP

Код: Выделить всё

chown -R ldap: /etc/openldap/ /var/lib/ldap
запускаем LDAP на обоих серверах

Код: Выделить всё

systemctl enable --now slapd
У меня установлен openldap сервер версии 2.6.4
Его основное отличие от более ранних версий (2.2 - 2.4 ...)- это то, что теперь файл slapd.conf не работает, всю конфигурацию надо делать через ldapadd/ldapmodify
при этом создаются файлы и папки в каталоге

Код: Выделить всё

/etc/openldap/slap.d
Начнем мы c изменения в файла /etc/openldap/ldap.conf
На первой ноде пропишем

Код: Выделить всё

BASE dc=test,dc=local # корень нашего будущего дерева LDAP
URI ldap://ldap01.toadmins.local # LDAP URL для запросов ldapadd/modify
TLS_CACERT      /etc/openldap/certs/ca.crt # CA сертификат для использования TLS
На второй ноде соответсятвено

Код: Выделить всё

BASE dc=test,dc=local # корень нашего будущего дерева LDAP
URI ldap://ldap02.toadmins.local # LDAP URL для запросов ldapadd/modify
TLS_CACERT      /etc/openldap/certs/ca.crt # CA сертификат для использования TLS
Теперь генерируем пароль нашего администратавного рутового пользователя, для этого выполним команду

Код: Выделить всё

slappasswd -s 12345678
где слово 12345678 это и есть наш пароль
в ответ получаем что-то вроде

Код: Выделить всё

{SSHA}B5Dd......NoAKfT6XIj97jvj
Далее команды будут выполняться на обоих серверах
до того момента как настироим репликацию

Собираем файл

Код: Выделить всё

1-init.ldif

Код: Выделить всё

#Задаем наш суффикс поиска и dn рутового пользователя
dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=test,dc=local
-
replace: olcRootDN
olcRootDN: cn=admin,dc=test,dc=local
-
replace: olcRootPW
olcRootPW: {SSHA}3o+TaZSo13aOYz2xBymJtOeBRC6Jd9QJ

#Включаем TLS
dn: cn=config
changetype: modify
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/winldcard-server.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/winldcard-server.key
-
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca.crt
-
replace: olcTLSVerifyClient
olcTLSVerifyClient: allow
и Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 1-init.ldif
Загружаем схемы

Код: Выделить всё

ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
Задаем корень в файле 2-add-base.ldif

Код: Выделить всё

dn: dc=test,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: TEST AUTH DOMAIN
dc: test
и применяем

Код: Выделить всё

ldapadd -x -D "cn=admin,dc=test,dc=local" -w "12345678" -f 2-add-base.ldif
Включаем поддержку дополнительных модулей, они нам понадобятся для включения репликации
файл

Код: Выделить всё

3-add_module_entry.ldif

Код: Выделить всё

# create new
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
Применяем

Код: Выделить всё

ldapadd -Y EXTERNAL -H ldapi:/// -f 3-add_module_entry.ldif
Включаем модули репликации
файл

Код: Выделить всё

 4-enable_modules.ldif

Код: Выделить всё

dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: syncprov.la
olcModuleLoad: accesslog.la
Применяем

Код: Выделить всё

ldapadd -Y EXTERNAL -H ldapi:/// -f 4-enable_modules.ldif
Для репликации нам надо создать отдельную базу которая будет использоваться для синхронизации и каталог под нее
создадим каталог и дадим на него права пользователю ldap

Код: Выделить всё

mkdir -p /var/lib/ldap/accesslog
chown -R ldap: /var/lib/ldap/accesslog
Нужно сгенерирорвать пароль пользователя repadmin
он нам нужен будет для базы данных репликации.
генерируем его так же через slappasswd
файл

Код: Выделить всё

 5-accesslog.ldif

Код: Выделить всё

dn: olcDatabase={3}mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {3}mdb
olcDbDirectory: /var/lib/ldap/accesslog
olcSuffix: cn=accesslog
olcRootDN: cn=repadmin,cn=accesslog
olcRootPW: {SSHA}hy+e7Hmt0zckdDZajSd0q26Vv7Z/3xlb
olcDbIndex: default eq
olcDbIndex: entryCSN,entryUUID eq
Применяем

Код: Выделить всё

ldapadd -Y EXTERNAL -H ldapi:/// -f 5-accesslog.ldif
Создаем пользователя repadmin в LDAP
пароль генерим с помощью slappasswd
Файл

Код: Выделить всё

5.5-createrepadmin.ldif

Код: Выделить всё

dn: uid=repadmin,dc=test,dc=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: repadmin
cn: repadmin
sn: systemuser
userPassword: {SSHA}3o+TaZSo13aOYz2xBymJtOeBRC6Jd9QJ
Применяем

Код: Выделить всё

ldapadd -x -D "cn=admin,dc=test,dc=local" -w "12345678" -f 5.5-createrepadmin.ldif
Задаем права доступа к дереву LDAP
файл

Код: Выделить всё

6-acl.ldif

Код: Выделить всё

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to attrs=userPassword
  by self write
  by anonymous auth
  by dn="cn=admin,dc=test,dc=local" manage
  by dn="uid=repadmin,dc=test,dc=local" manage
  by * none
olcAccess: {1}to dn.base=""
   by anonymous auth
   by dn="cn=admin,dc=test,dc=local" manage
   by dn="uid=repadmin,dc=test,dc=local" manage
   by * none
olcAccess: {2}to *
  by self write
  by anonymous auth
  by dn="cn=admin,dc=test,dc=local" manage
  by dn="uid=repadmin,dc=test,dc=local" manage
  by * none

dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to *
  by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
  by dn.base="cn=admin,dc=test,dc=local" read
  by dn.base="uid=repadmin,dc=test,dc=local" read
  by * none

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to *
  by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external, cn=auth" manage
  by dn="cn=admin,dc=test,dc=local" manage
  by dn="uid=repadmin,dc=test,dc=local" manage
  by * none  
Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 6-acl.ldif
Проверяем

Код: Выделить всё

ldapsearch -H ldap://`hostname` -D "uid=repadmin,dc=test,dc=local" -w 12345678
Должны увидеть дерево LDAP

Настраиваем базовую репликацию (не секьюрную)
файлы разные для 2 серверов
для первой ноды файл

Код: Выделить всё

7-replication-server1.ldif

Код: Выделить всё

# Define a unique server ID for server1
dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 1

# Add the syncprov overlay for the {2}mdb database
dn: olcOverlay=syncprov,olcDatabase={2}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

# Configure syncrepl for replication and enable mirrormode
dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=002
  provider=ldap://ldap02.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: olcMirrorMode
olcMirrorMode: TRUE

dn: olcOverlay=syncprov,olcDatabase={3}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

# Configure syncrepl for config
dn: olcOverlay=syncprov,olcDatabase={0}config,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=004
  provider=ldap://ldap02.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: olcMirrorMode
olcMirrorMode: TRUE

для второй ноды файл 
7-replication-server2.ldif

# Define a unique server ID for server1
dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 2

# Add the syncprov overlay for the {2}mdb database
dn: olcOverlay=syncprov,olcDatabase={2}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

# Configure syncrepl for replication and enable mirrormode
dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=001
  provider=ldap://ldap01.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: olcMirrorMode
olcMirrorMode: TRUE

#dn: olcOverlay=syncprov,olcDatabase={3}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

# Configure syncrepl for config
dn: olcOverlay=syncprov,olcDatabase={0}config,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=003
  provider=ldap://ldap01.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: oclMirrorMode
olcMirrorMode: TRUE
Применяем соответсятвено
на первой ноде

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 7-replication-server1.ldif
на второй ноде

Код: Выделить всё

# Define a unique server ID for server1
dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 2

dn: olcOverlay=syncprov,olcDatabase={3}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

dn: olcOverlay=syncprov,olcDatabase={2}mdb,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

dn: olcOverlay=syncprov,olcDatabase={0}config,cn=config
changetype: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov

# Configure syncrepl for replication and enable mirrormode
dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=001
  provider=ldap://ldap01.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: olcMirrorMode
olcMirrorMode: TRUE

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=003
  provider=ldap://ldap01.toadmins.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 5 300 3"
  interval=00:00:05:00
-
replace: olcMirrorMode
olcMirrorMode: TRUE

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 7-replication-server2.ldif
Прописали оверлеи и настраиваем сами реплики (как видно из логов их по 2 одна для корня test.local вторая для конфигурации и cn=config)
файл

Код: Выделить всё

7.1-replication-fix.ldif

Код: Выделить всё

dn: cn=config
changetype: modify
replace: olcServerID
olcServerID: 1 ldap://ldap01.toadmins.local
olcServerID: 2 ldap://ldap02.toadmins.local

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=001
  provider=ldap://ldap01.test.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
olcSyncRepl: rid=002
  provider=ldap://ldap02.test.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
-
replace: olcMirrorMode
olcMirrorMode: TRUE
-
replace: olcDbIndex
olcDbIndex: gidNumber eq
olcDbIndex: memberUid eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: uniqueMember eq
olcDbIndex: entryUUID eq

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=003
  provider=ldap://ldap01.test.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
olcSyncRepl: rid=004
  provider=ldap://ldap02.test.local
  bindmethod=simple
  binddn="uid=repadmin,dc=test,dc=local"
  credentials=12345678
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
-
replace: olcMirrorMode
olcMirrorMode: TRUE
После этого репликация должна заработать в небезопасном режиме по 2 причинам.
1. пароли в кофигах
2. для реплики используется незащищеный LDAP

проверяем
1 создаем OU
файл

Код: Выделить всё

 createOU.ldif

Код: Выделить всё

#create OU
dn: ou=Users,dc=test,dc=local
objectClass: top
objectClass: organizationalUnit
ou: Users
2. Создаем пользователей
файл

Код: Выделить всё

 createuser.ldif

Код: Выделить всё

dn: uid=testuser1,ou=Users,dc=test,dc=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: testuser1
cn: Test User 1
sn: User1
userPassword: {SSHA}RsIRD3ug1CrIQksX5fGwSZmoUyxKg1oj

dn: uid=testuser2,ou=Users,dc=test,dc=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: testuser2
cn: Test User 2
sn: User2
userPassword: {SSHA}RsIRD3ug1CrIQksX5fGwSZmoUyxKg1oj
Записи должны появиться на обоих серверах, и при этом неважно, на каком из 2 серверов вы это проделывали
если не получилось смотрите логи.

удалить записи можно так

Код: Выделить всё

ldapdelete -H ldaps://ldap02.toadmins.local -D "cn=admin,dc=test,dc=local" -w 12345678 uid=testuser2,ou=Users,dc=test,dc=local
Переходим к защите нашей реплики, включаем tls

для этого создаем отдельный файл в хомяке (своей домашней директории)
файл

Код: Выделить всё

~/.ldaprc
для первой ноды

Код: Выделить всё

BASE            dc=test,dc=local
URI             ldaps://ldap01.toadmins.local
TLS_CACERT      /etc/openldap/certs/ca.crt
TLS_CERT        /etc/openldap/certs/repadmin.crt
TLS_KEY         /etc/openldap/certs/repadmin.key
SASL_MECH       EXTERNAL
для второй ноды

Код: Выделить всё

BASE            dc=test,dc=local
URI             ldaps://ldap02.toadmins.local
TLS_CACERT      /etc/openldap/certs/ca.crt
TLS_CERT        /etc/openldap/certs/repadmin.crt
TLS_KEY         /etc/openldap/certs/repadmin.key
SASL_MECH       EXTERNAL
И правим

Код: Выделить всё

/etc/openldap/ldap.conf
для первой ноды

Код: Выделить всё

BASE            dc=test,dc=local
URI             ldaps://ldap01.toadmins.local
TLS_CACERT      /etc/openldap/certs/ca.crt
SASL_MECH       EXTERNAL
TLS_CERT        /etc/openldap/certs/repadmin.crt
TLS_KEY         /etc/openldap/certs/repadmin.key
TLS_CACERTDIR   /etc/openldap/certs
TLS_REQCERT     demand
SASL_NOCANON    on
для второй ноды

Код: Выделить всё

BASE            dc=test,dc=local
URI             ldaps://ldap02.toadmins.local
TLS_CACERT      /etc/openldap/certs/ca.crt
SASL_MECH       EXTERNAL
TLS_CERT        /etc/openldap/certs/repadmin.crt
TLS_KEY         /etc/openldap/certs/repadmin.key
TLS_CACERTDIR   /etc/openldap/certs
TLS_REQCERT     demand
SASL_NOCANON    on
Прверяем, для этого на обеих нодах запускаем ldapsearch

Код: Выделить всё

ldapsearch -Z
Должны получить что-то вроде этого

Код: Выделить всё

# test.local
dn: dc=test,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: TEST AUTH DOMAIN
dc: test

# repadmin, test.local
dn: uid=repadmin,dc=test,dc=local
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: repadmin
cn: repadmin
sn: systemuser
userPassword:: e1NTSEF9M28rVGFaU28xM2FPWXoyeEJ5bUp0T2VCUkM2SmQ5UUo=

# Users, test.local
dn: ou=Users,dc=test,dc=local
objectClass: top
objectClass: organizationalUnit
ou: Users
Теперь настраиваем авторизацию по сертификату
файл

Код: Выделить всё

7.2-replication-tls.ldif

Код: Выделить всё

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=001
  provider=ldaps://ldap01.toadmins.local
  bindmethod=sasl
  saslmech=EXTERNAL
  tls_cacertdir=/etc/openldap/certs
  tls_cert=/etc/openldap/certs/repadmin.crt
  tls_key=/etc/openldap/certs/repadmin.key
  tls_cacert=/etc/openldap/certs/ca.crt
  tls_reqcert=demand
  tls_crlcheck=none
  starttls=no
  authzid="uid=repadmin,dc=test,dc=local"
  authcid="uid=repadmin,dc=test,dc=local"
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
olcSyncRepl: rid=002
  provider=ldaps://ldap02.toadmins.local
  bindmethod=sasl
  saslmech=EXTERNAL
  tls_cacertdir=/etc/openldap/certs
  tls_cert=/etc/openldap/certs/repadmin.crt
  tls_key=/etc/openldap/certs/repadmin.key
  tls_cacert=/etc/openldap/certs/ca.crt
  tls_reqcert=demand
  tls_crlcheck=none
  starttls=no
  authzid="uid=repadmin,dc=test,dc=local"
  authcid="uid=repadmin,dc=test,dc=local"
  searchbase="dc=test,dc=local"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
-
replace: olcMirrorMode
olcMirrorMode: TRUE
-
replace: olcDbIndex
olcDbIndex: gidNumber eq
olcDbIndex: memberUid eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: uniqueMember eq
olcDbIndex: entryUUID eq

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcSyncRepl
olcSyncRepl: rid=003
  provider=ldaps://ldap01.toadmins.local
  bindmethod=sasl
  saslmech=EXTERNAL
  tls_cacertdir=/etc/openldap/certs
  tls_cert=/etc/openldap/certs/repadmin.crt
  tls_key=/etc/openldap/certs/repadmin.key
  tls_cacert=/etc/openldap/certs/ca.crt
  tls_reqcert=demand
  tls_crlcheck=none
  starttls=no
  authzid="uid=repadmin,dc=test,dc=local"
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
olcSyncRepl: rid=004
  provider=ldaps://ldap02.toadmins.local
  bindmethod=sasl
  saslmech=EXTERNAL
  tls_cacertdir=/etc/openldap/certs
  tls_cert=/etc/openldap/certs/repadmin.crt
  tls_key=/etc/openldap/certs/repadmin.key
  tls_cacert=/etc/openldap/certs/ca.crt
  tls_reqcert=demand
  tls_crlcheck=none
  starttls=no
  authzid="uid=repadmin,dc=test,dc=local"
  searchbase="cn=config"
  scope=sub
  schemachecking=on
  type=refreshAndPersist
  retry="30 10 60 +"
  timeout=0
-
replace: olcMirrorMode
olcMirrorMode: TRUE
Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 7.2-replication-tls.ldif
Проверяем репликацию
На первом хосте заводим пользователя USER01, на втором USER02
При запросе LDAPSEARCH на любом сервере должны быть видны оба.

Осталось поправить лимиты запросов
файл

Код: Выделить всё

8-set-limits

Код: Выделить всё

dn: olcDatabase={2}mdb,cn=config
changetype: modify
replace: olcLimits
olcLimits: dn.exact="dc=test,dc=local" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited
-
replace: olcSizeLimit
olcSizeLimit: 10000
Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 8-set-limits
Приступаем к 3 задаче
есть 3 конфига
1.

Код: Выделить всё

10-custom-schema.ldif
- добавляет новые атребуты в core

Код: Выделить всё

#ADD NEW ATTRIBUTES
dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.1 NAME 'googleToken' DESC 'A token used for
 Google authentication' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115
 .121.1.15{1024} SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.2 NAME 'PBKDF2Hash' DESC 'PBKDF2 hash for s
 ecure password storage' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.1
 15.121.1.40{256} SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.3 NAME 'passwordHash' DESC 'Legacy password
 hash' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{200}
 SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.4 NAME 'salt' DESC 'salt' EQUALITY octetStri
 ngMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{100} SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.5 NAME 'googleAuthKeyConfirmed' DESC 'google
 AuthKeyConfirmed boolean' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.
 121.1.7 SINGLE-VALUE )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.6 NAME 'googleAuthGroupEnabled' DESC 'google
 AuthGroupEnabled' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
 SINGLE-VALUE )
 
dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.2.3.4.5.6.7 NAME 'emailVerified' DESC 'emailVerified'
 EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) 

Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 10-custom-schema.ldif
2.

Код: Выделить всё

11-modify-schema.ldif
- модифицирует объекткласс person

Код: Выделить всё

dn: cn={0}core,cn=schema,cn=config
changetype: modify
replace: olcObjectClasses
olcObjectClasses: ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )
 MAY ( userPassword $ googleToken $ mail $ telephoneNumber $ description $ PBKDF2Hash $
 passwordHash $ salt $ googleAuthKeyConfirmed $ googleAuthGroupEnabled $
 emailVerified) )
Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 11-modify-schema.ldif
3.

Код: Выделить всё

12-schema-fix.ldif
- восстанавливает схему

Код: Выделить всё

#ADD ATTRIBUTES
dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'
  DESC 'RFC2247: domain component object'
  SUP top AUXILIARY MUST dc )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.2 NAME 'country'
  DESC 'RFC2256: a country'
  SUP top STRUCTURAL
  MUST c
  MAY ( searchGuide $ description ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.4 NAME 'organization'
  DESC 'RFC2256: an organization'
  SUP top STRUCTURAL
  MUST o
  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
  x121Address $ registeredAddress $ destinationIndicator $
  preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
  telephoneNumber $ internationalISDNNumber $
  facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
  postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.5 NAME 'organizationalUnit'
  DESC 'RFC2256: an organizational unit'
  SUP top STRUCTURAL
  MUST ou
  MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
  x121Address $ registeredAddress $ destinationIndicator $
  preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
  telephoneNumber $ internationalISDNNumber $
  facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
  postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.11 NAME 'applicationProcess'
  DESC 'RFC2256: an application process'
  SUP top STRUCTURAL
  MUST cn
  MAY ( seeAlso $ ou $ l $ description ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.12 NAME 'applicationEntity'
  DESC 'RFC2256: an application entity'
  SUP top STRUCTURAL
  MUST ( presentationAddress $ cn )
  MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
  description ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.13 NAME 'dSA'
  DESC 'RFC2256: a directory system agent (a server)'
  SUP applicationEntity STRUCTURAL
  MAY knowledgeInformation )
  
dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.7 NAME 'organizationalPerson'
  DESC 'RFC2256: an organizational person'
  SUP person STRUCTURAL
  MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
  preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
  telephoneNumber $ internationalISDNNumber $
  facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
  postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )

dn: cn={0}core,cn=schema,cn=config
changetype: modify
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.8 NAME 'organizationalRole'
  DESC 'RFC2256: an organizational role'
  SUP top STRUCTURAL
  MUST cn
  MAY ( x121Address $ registeredAddress $ destinationIndicator $
  preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
  telephoneNumber $ internationalISDNNumber $ facsimileTelephoneNumber $
  seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
  postOfficeBox $ postalCode $ postalAddress $
  physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
Применяем

Код: Выделить всё

ldapmodify -Y EXTERNAL -H ldapi:/// -f 12-schema-fix.ldif
в конце выполняем проверку конфигурации командой

Код: Выделить всё

slaptest
Должен быть вывод

Код: Выделить всё

config file testing succeeded
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Ответить