⚓ Как настроить SUDO через сервер OpenLDAP |

⚓ Как настроить SUDO через сервер OpenLDAP

Мануал

В этом руководстве мы покажем, как настроить SUDO через сервер OpenLDAP.

Помимо возможности предоставления прав sudo на локальной системе, sudo можно настроить и через LDAP.

Предоставление SUDO через OpenLDAP избавляет от необходимости наделять пользователей правами sudo через файл sudoers локальной системы.

Как настроить SUDO через сервер OpenLDAP

Для того чтобы настроить SUDO через сервер OpenLDAP, необходимо загрузить и включить схемы sudo OpenLDAP.

Аутентификация LDAP в Linux

Предполагая, что вы включили поддержку sudo в OpenLDAP, как описано в нашем руководстве выше, перейдем к настройке.

Создание организационной единицы (ou) OpenLDAP SUDOers

Прежде чем настраивать SUDO через OpenLDAP Server, необходимо создать SUDOers ou в структуре каталогов вашей организации.

vim sudoersou.ldif

Замените компоненты и описание домена соответствующим образом.

dn: ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectclass: organizationalunit
ou: SUDOers
description: itsecforu-demo LDAP SUDO Entry

Обновите базу данных OpenLDAP с помощью вышеуказанной записи об организационной единице SUDOers.\

ldapadd -Y EXTERNAL -H ldapi:/// -f sudoersou.ldif

Создание записи Defaults в OpenLDAP OU SUDOers

Согласно man-страницам sudoers.ldap, sudo сначала ищет запись cn=defaults в SUDOers OU.

Если она найдена, то многозначный атрибут sudoOption разбирается так же, как и глобальная строка Defaults в файле /etc/sudoers.

Преобразование файла sudoers в LDAP LDIF

Как же создать запись SUDOers по умолчанию со всеми необходимыми атрибутами sudo?

Чтобы упростить задачу, преобразуйте локальный файл sudoers, /etc/sudoers, в формат OpenLDAP и измените его по своему усмотрению.

  • В комплект поставки OpenLDAP обычно входит perl-скрипт sudoers2ldif, который используется для преобразования файла sudoers в LDIF-файл OpenLDAP.
  • Кроме того, в комплект поставки входит еще один инструмент под названием cvtsudoers, который может помочь вам решить ту же задачу, что и скрипт sudoers2ldif.

Найдем perl-скрипт sudoers

find / -iname sudoers2ldif

Если вы не можете найти его, то можете взять его из этого репозитория Github.

Проверьте сырую версию и загрузите ее следующим образом;

wget https://raw.githubusercontent.com/lbt/sudo/master/plugins/sudoers/sudoers2ldif

🖧 В чем разница между curl и Wget? | (itsecforu.ru)

Скрипт выглядит вот так:

less sudoers2ldif
!/usr/bin/env perl
Copyright (c) 2007, 2010-2011, 2013 Todd C. Miller <todd.miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use strict;
Converts a sudoers file to LDIF format in prepration for loading into
the LDAP server.
BUGS:
Does not yet handle multiple lines with : in them
Does not yet remove quotation marks from options
Does not yet escape + at the beginning of a dn
Does not yet handle line wraps correctly
Does not yet handle multiple roles with same name (needs tiebreaker)
CAVEATS:
Sudoers entries can have multiple RunAs entries that override former ones,
with LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole
my %RA;
my %UA;
my %HA;
my %CA;
my $base=$ENV{SUDOERS_BASE} or die "$0: Container SUDOERS_BASE undefined\n";
my @options=();
my $did_defaults=0;
my $order = 0;
parse sudoers one line at a time
while (<>){
remove comment
s/#.*//;
line continuation
_.=<> while s/\\\s*$//s;
cleanup newline
chomp;
ignore blank lines
next if /^\s*$/;
if (/^Defaults\s+/i) {
my $opt=$';
opt=~s/\s+$//; # remove trailing whitespace
push @options,$opt;
} elsif (/^(\S+)\s+([^=]+)=\s*(.*)/) {
Aliases or Definitions
my ($p1,$p2,$p3)=($1,$2,$3);
p2=~s/\s+$//; # remove trailing whitespace
p3=~s/\s+$//; # remove trailing whitespace
if ($p1 eq "User_Alias") {
UA{$p2}=$p3;
} elsif ($p1 eq "Runas_Alias") {
RA{$p2}=$p3;
} elsif ($p1 eq "Host_Alias") {
HA{$p2}=$p3;
} elsif ($p1 eq "Cmnd_Alias") {
CA{$p2}=$p3;
} else {
if (!$did_defaults++){
do this once
print "dn: cn=defaults,$base\n";
print "objectClass: top\n";
print "objectClass: sudoRole\n";
print "cn: defaults\n";
print "description: Default sudoOption's go here\n";
print "sudoOption: $_\n" foreach @options;
printf "sudoOrder: %d\n", ++$order;
print "\n";
}
Definition
my @users=split /\s*,\s*/,$p1;
my @hosts=split /\s*,\s*/,$p2;
my @cmds= split /\s*,\s*/,$p3;
@options=();
print "dn: cn=$users[0],$base\n";
print "objectClass: top\n";
print "objectClass: sudoRole\n";
print "cn: $users[0]\n";
will clobber options
print "sudoUser: $_\n"   foreach expand(\%UA,@users);
print "sudoHost: $_\n"   foreach expand(\%HA,@hosts);
foreach (@cmds) {
if (s/^\(([^\)]+)\)\s*//) {
my @runas = split(/:\s*/, $1);
if (defined($runas[0])) {
print "sudoRunAsUser: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[0]));
}
if (defined($runas[1])) {
print "sudoRunAsGroup: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[1]));
}
}
}
print "sudoCommand: $_\n" foreach expand(\%CA,@cmds);
print "sudoOption: $_\n" foreach @options;
printf "sudoOrder: %d\n", ++$order;
print "\n";
}
} else {
print "parse error: $_\n";
}
}
recursively expand hash elements
sub expand{
my $ref=shift;
my @a=();
preen the line a little
foreach (@_){
if NOPASSWD: directive found, mark entire entry as not requiring
s/NOPASSWD:\s*// && push @options,"!authenticate";
s/PASSWD:\s*// && push @options,"authenticate";
s/NOEXEC:\s*// && push @options,"noexec";
s/EXEC:\s*// && push @options,"!noexec";
s/SETENV:\s*// && push @options,"setenv";
s/NOSETENV:\s*// && push @options,"!setenv";
s/LOG_INPUT:\s*// && push @options,"log_input";
s/NOLOG_INPUT:\s*// && push @options,"!log_input";
s/LOG_OUTPUT:\s*// && push @options,"log_output";
s/NOLOG_OUTPUT:\s*// && push @options,"!log_output";
s/[[:upper:]]+://; # silently remove other tags
s/\s+$//; # right trim
}
do the expanding
push @a,$ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_ foreach @_;
@a;
}</todd.miller@courtesan.com>

Создайте переменную окружения bash, определяющую созданную выше запись организационной единицы SUDOers.

export SUDOERS_BASE="ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com"
echo $SUDOERS_BASE

Далее преобразуем файл /etc/sudoers в файл LDAP ldif для создания необходимой записи SUDOers ou defaults.

perl sudoers2ldif /etc/sudoers > sudoers_defaults.ldif

Также можно использовать команду cvtsudoers для преобразования файла sudoers в формат LDIF.

cvtsudoers /etc/sudoers -f ldif -o sudoers_defaults.ldif

Каково же содержимое файла sudoers_defaults.ldif?

cat sudoers_defaults.ldif
dn: cn=defaults,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: defaults
description: Default sudoOption's go here
sudoOption: !visiblepw
sudoOption: always_set_home
sudoOption: match_group_by_gid
sudoOption: always_query_group_plugin
sudoOption: env_reset
sudoOption: env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
sudoOption: env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
sudoOption: env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
sudoOption: env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
sudoOption: env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
sudoOption: secure_path = /sbin:/bin:/usr/sbin:/usr/bin
sudoOrder: 1
dn: cn=root,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: root
sudoUser: root
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOrder: 2
dn: cn=%wheel,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: %wheel
sudoUser: %wheel
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
sudoOrder: 3

Как видно, файл sudoers в формате LDAP ldif содержит OU SUDOers, многозначные атрибуты sudoOption, корневого пользователя cn и определенную группу wheel.

Атрибуты Sudo, использованные выше:

sudoOption: Аналогичен опции Defaults в файле /etc/sudoers.
Например, ниже приведены опции /etc/sudoers и способы их использования в LDAP SUDO:

  • NOPASSWD: !authenticate
  • PASSWD: authenticate
  • NOEXEC: noexec
  • EXEC: !noexec
  • SETENV: setenv
  • NOSETENV: !setenv
  • LOG_INPUT: log_input
  • NOLOG_INPUT: !log_input
  • LOG_OUTPUT: log_output
  • NOLOG_OUTPUT: !log_output
  • sudoUser: определяет имя пользователя, идентификатор пользователя (с префиксом ‘#’), имя или идентификатор группы Unix (с префиксом ‘%’ или ‘%#’ соответственно), netgroup пользователя (с префиксом ‘+’), имя или идентификатор группы не-Unix (с префиксом ‘%:’ или ‘%:#’ соответственно).
  • sudoHost: Имя хоста, IP-адрес, IP-сеть или нетгруппа хоста (с префиксом ‘+’) или значение ALL для соответствия любому хосту.
  • sudoRunAsUser: имя пользователя или uid (с префиксом ‘#’), от имени которого могут выполняться команды, или группа Unix (с префиксом ‘%’) или нетгруппа пользователей (с префиксом ‘+’), содержащая список пользователей, от имени которых могут выполняться команды. Значение ALL соответствует любому пользователю.
  • sudoCommand: Указывает полное имя Unix-команды с необязательными аргументами командной строки. Используйте ALL для соответствия любой команде.

Поэтому перед обновлением базы данных OpenLDAP с конфигурациями SUDOers можно модифицировать приведенный выше файл SUDOers LDAP ldif.

Например, удалите определенного пользователя root и группу wheel и добавьте пользователей, которым вы хотите назначить права SUDO через LDAP на удаленных клиентах.

Также удалите атрибуты sudoOrder.

cat > modified-sudoer2ldif.ldif << 'EOL'
dn: cn=defaults,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: defaults
description: itsecforu-demo SUDO via LDAP
sudoOption: !visiblepw
sudoOption: always_set_home
sudoOption: match_group_by_gid
sudoOption: always_query_group_plugin
sudoOption: env_reset
sudoOption: env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
sudoOption: env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
sudoOption: env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
sudoOption: env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
sudoOption: env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
sudoOption: env_keep+=SSH_AUTH_SOCK
sudoOption: secure_path = /sbin:/bin:/usr/sbin:/usr/bin
dn: cn=sudo,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: sudo
sudoUser: janedoe
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: ALL
EOL

Выше мы создали запись sudo в SUDOers ou и назначили пользователю janedoe права SUDO на выполнение всех команд от имени любого пользователя на любой системе, что аналогично строке ниже в файле /etc/sudoers.

janedoe ALL=(ALL:ALL) ALL

Обратите внимание, что пользователь должен существовать в базе данных OpenLDAP.

Обновление базы данных OpenLDAP

Далее загрузите конфигурацию SUDOers в базу данных OpenLDAP.

ldapadd -Y EXTERNAL -H ldapi:/// -f modified-sudoer2ldif.ldif

Если необходимо добавить другого пользователя в указанную выше роль;

cat > add-to-sudo-role.ldif << 'EOL'
dn: cn=sudo,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
changetype: modify
add: sudoUser
sudoUser: johndoe
EOL
ldapmodify -Y EXTERNAL -H ldapi:/// -f add-to-sudo-role.ldif

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

Имена ролей могут быть любыми описательными.

Например, чтобы разрешить пользователю mibeyam выполнять команду useradd только с помощью sudo, создайте ldif-файл, как показано ниже, и обновите базу данных OpenLDAP.

cat > sudo-specific-cmd.ldif << 'EOL'
dn: cn=cmdrole,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
objectClass: top
objectClass: sudoRole
cn: cmdrole
sudoUser: mibeyam
sudoHost: ALL
sudoRunAsUser: ALL
sudoCommand: /usr/sbin/useradd
'EOL'
ldapadd -Y EXTERNAL -H ldapi:/// -f sudo-specific-cmd.ldif

Настройка LDAP SUDO NOPASSWD

Иногда возникает необходимость разрешить некоторым пользователям выполнять команду SUDO без запроса пароля с помощью ldap-sudo-nopasswd.

Для этого можно использовать опцию NOPASSWD OpenLDAP SUDO, !authenticate с sudoOption атрибутом.

См. пример ниже

dn: cn=koromicha,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
cn: koromicha
objectclass: top
objectclass: sudoRole
sudocommand: ALL
sudohost: ALL
sudooption: !authenticate
sudorunasuser: ALL
sudouser: koromicha

Этот пользователь будет выполнять все команды SUDO без пароля.

Чтобы получить список SUDOers OU, просто выполните команду;

export SUDOERS_BASE=ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com
ldapsearch -b "$SUDOERS_BASE" -D cn=admin,dc=ldapmaster,dc=kifarunix-demo,dc=com -W -x sudoUser

Настройка клиента OpenLDAP для предоставления прав SUDO

Чтобы протестировать и подтвердить предоставление SUDO с помощью OpenLDAP, настройте клиент для аутентификации через OpenLDAP.

В данной демонстрации мы используем SSSD на системе Ubuntu 18.04 для обеспечения LDAP-аутентификации.

Поэтому сначала войдите в систему ( например Ubuntu) и настройте аутентификацию клиента следующим образом.

apt update

Установите SSSD и другие необходимые пакеты.

apt install sssd libpam-sss libnss-sss vim sssd-tools libsss-sudo

Создайте файл конфигурации SSSD со следующим содержимым.

vim /etc/sssd/sssd.conf

Замените значения ldap_default_bind_dn и ldap_default_authtok на свой Bind DN и пароль к нему.

Также замените значения Base DN, LDAP URI, SUDOers search base и ldap filter соответствующим образом.

[sssd]
services = nss, pam, sudo
config_file_version = 2
domains = default

[sudo]

[nss]

[pam]
offline_credentials_expiration = 60

[domain/default]
ldap_id_use_start_tls = True
cache_credentials = True
ldap_search_base = dc=ldapmaster,dc=itsecforu-demo,dc=com
id_provider = ldap
auth_provider = ldap
chpass_provider = ldap
access_provider = ldap
sudo_provider = ldap
ldap_uri = ldaps://ldapmaster.itsecforu-demo.com:636
ldap_default_bind_dn = cn=readonly,ou=system,dc=ldapmaster,dc=itsecforu-demo,dc=com
ldap_default_authtok = P@ssWord
ldap_tls_reqcert = demand
ldap_tls_cacert = /etc/ssl/certs/cacert.crt
ldap_tls_cacertdir = /etc/ssl/certs
ldap_search_timeout = 50
ldap_network_timeout = 60
ldap_sudo_search_base = ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
ldap_access_order = filter
ldap_access_filter = (objectClass=posixAccount)

Скопируйте сертификат удостоверяющего центра с сервера LDAP.

openssl s_client -connect ldapmaster.itsecforu-demo.com:636 -showcerts < /dev/null | openssl x509 -text

Сохраните его в указанном выше файле /etc/ssl/certs/ldapcert.crt.

При желании можно использовать другой файл.

vim /etc/ssl/certs/cacert.crt
-----BEGIN CERTIFICATE-----
MIID0TCCArmgAwIBAgIUQnXoL0eVw1STAXFBjKwNobOMtJ8wDQYJKoZIhvcNAQEL
BQAweDELMAkGA1UEBhMCS0UxEDAOBgNVBAgMB05haXJvYmkxEDAOBgNVBAcMB05h
....
...
FG4/H6F0CAD/ksl4w8aEP0JrdZsDxwmGv8GoM6fVI/3qcv2pD/+Fjif0GRcb7V6g
NsyGrEWBFOD+IrMDIm7KvTBEBJbc
-----END CERTIFICATE-----

Откройте файл /etc/ldap/ldap.conf и задайте расположение файла сертификата УЦ, скопированного с сервера OpenLDAP.

vim /etc/ldap/ldap.conf
...
TLS certificates (needed for GnuTLS)
TLS_CACERT     /etc/ssl/certs/ca-certificates.crt
TLS_CACERT       /etc/ssl/certs/cacert.crt

Определите базу поиска LDAP SUDOers.

echo "sudoers_base ou=SUDOers,dc=ldapmaster,dc=kifarunix-demo,dc=com" >> /etc/ldap/ldap.conf

Установите доступ на чтение/запись к файлу /etc/sssd/ для владельца (root).

chmod 600 -R /etc/sssd

Перезапустите службу SSSD

systemctl restart sssd

Включение автоматического создания домашнего каталога пользователя

Настройте подключаемый модуль аутентификации (PAM) на автоматическое создание домашнего каталога пользователя при первом входе в систему.

Этого можно добиться, отредактировав конфигурационный файл /etc/pam.d/common-session следующим образом;

vim /etc/pam.d/common-session

Добавьте приведенную ниже строку сразу после строки session optional pam_sss.so.

session required        pam_mkhomedir.so skel=/etc/skel/ umask=0022
...
# since the modules above will each just jump around
session required pam_permit.so
# and here are more per-package modules (the "Additional" block)
session required pam_unix.so 
session optional pam_sss.so 
session required        pam_mkhomedir.so skel=/etc/skel/ umask=0022
session optional pam_systemd.so 
# end of pam-auth-update config

Сохраните и выйдите из конфигурации.

Также убедитесь, что в файле /etc/nsswitch.conf есть следующая строка;

sudoers:        files sss

Назначение прав SUDO пользователя на конкретном хосте

Также можно назначить пользователю права sudo на определенном хосте.

Например, если у меня есть пользователь johndoe в моей базе данных OpenLDAP, и я хочу, чтобы этот пользователь выполнял команды с правами sudo только на хосте john.itsecforu-demo.com, то я создам в сервере OpenLDAP запись, как показано ниже.

dn: cn=john,ou=SUDOers,dc=ldapmaster,dc=itsecforu-demo,dc=com
cn: john
objectclass: top
objectclass: sudoRole
sudocommand: ALL
sudohost: john.itsecforu-demo.com
sudorunasuser: ALL
sudouser: johndoe

Если этот пользователь авторизуется на системе с именем хоста john.itsecforu-demo.com, то он может выполнить любую команду с правами sudo, в противном случае он не сможет иметь права sudo на любой другой системе.

см. также:

Пожалуйста, не спамьте и никого не оскорбляйте. Это поле для комментариев, а не спамбокс. Рекламные ссылки не индексируются!
Добавить комментарий