LoginSignup
26
24

More than 5 years have passed since last update.

LDAPでsudoを一元管理する

Last updated at Posted at 2014-11-04

=====================

環境

  • CentOS 6.5
  • OpenLDAP

Overview

まともに管理すると煩雑になりがちなsudoをLDAPで一元的に管理したい。

Installation

with Ansible

インストール手順は全てplaybook化してあります。

$ git clone git@github.com:shufo/ansible-sudo-ldap.git
$ cd ansible-sudo-ldap
$ vagrant up

でVagrant仮想マシン上に以下の手動でのインストール手順を再現したOpenLDAP+sudoなテスト環境が出来ます。(要Ansible, Vagrant)

立ち上がったら

$ vagrant ssh
[vagrant@vagrant ~]$ sudo su
[root@vagrant ~]$ su - test
[test@vagrant ~]$ sudo cat /var/log/secure 
"Enter [test]'s Password:" password

で動作確認出来ます。

リモートに構築する場合はansible_hostsファイルを編集し

default ansible_ssh_host=127.0.0.1 ansible_ssh_port=22

playbookを直接実行してください。

ansible-playbook site.yml -i ansible_hosts

クライアント側のみ構築する場合はtasks/main.ymlのLDAPサーバ側用のタスクをコメントアウトしてください。

---
# - include: server.yml
- include: client.yml

手動

LDAPサーバ設定

  • OpenLDAP、依存パッケージのインストール
  yum install openldap openldap-servers openldap-clients pam_ldap 
  • LDAPディレクトリ初期化
mkdir /var/lib/ldap
chown ldap:ldap /var/lib/ldap
rm -fR /etc/openldap/slapd.d/*
  • 設定ファイルコピー
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
cp /usr/share/openldap-servers/slapd.conf.obsolete /etc/openldap/slapd.conf
  • LDAPサーバのrootパスワード生成
/usr/sbin/slappasswd -s password
/etc/openldap/slapd.conf
# スキーマファイル設定
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/duaconf.schema
include /etc/openldap/schema/dyngroup.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/java.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/ppolicy.schema
include /etc/openldap/schema/collective.schema

# 接続プロトコル
allow bind_v2

# 管理ファイル
pidfile     /var/run/openldap/slapd.pid
argsfile    /var/run/openldap/slapd.args

# TLS設定
#TLSCACertificatePath  /etc/openldap/ssl/cacert.pem
#TLSCertificateFile    /etc/openldap/ssl/server.crt
#TLSCertificateKeyFile /etc/openldap/ssl/server.key

# userPasswordに関するアクセス権
access to attrs=userPassword
    by self write
    by dn="cn=Directory Manager,dc=example,dc=com" write
    by anonymous auth
    by * none

# その他の属性に対するアクセス権
access to *
    by self write
    by dn="cn=Directory Manager,dc=example,dc=com" write
    by * read

# monitorデータベースに対するアクセス権
database monitor
access to *
    by dn.exact="cn=Directory Manager,dc=example,dc=com" read
    by * none

# データベース設定
database    bdb
suffix      "dc=example,dc=com"
checkpoint  1024 15
rootdn      "dc=example,dc=com"
rootpw      {SSHA}jadajsdna〜中略〜hogehoge
directory   /var/lib/ldap

# indexの設定
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

  • LDAPサーバにsudo用のschemaを読みこませる

schema.OpenLDAPをスキーマに追加。

  cp /usr/share/doc/sudo-1.8.6p3/schema.OpenLDAP /etc/openldap/schema/sudo.schema

/etc/openldap/slapd.confに

/etc/openldap/slapd.conf
  include /etc/openldap/schema/sudo.schema

を追加。

  • openldapを起動
  service slapd start
  • エントリを作成する

ベースになるエントリを作成します。

add_ou.ldif
  dn: dc=example,dc=com
  objectClass: dcObject
  objectClass: organization
  dc: example
  o: example

  dn: ou=people,dc=example,dc=com
  objectClass: organizationalUnit
  ou: people

  dn: ou=groups,dc=example,dc=com
  objectClass: organizationalUnit
  ou: groups
  ldapadd -D "cn=Directory Manager,dc=example,dc=com" -w password -f add_ou.ldif
  • ユーザを作成する

サンプルとしてtestユーザを作成する。

add_user.ldif
  dn: uid=test,ou=people,dc=example,dc=com
objectClass: account
objectClass: posixAccount
uid: test
cn: test
userPassword: {SSHA}hogehoge〜中略〜
loginShell: /bin/bash
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/test

posixAccountクラスの必須属性はloginShelluidNumbergidNumberhomeDirectoryなのでこの4つは最低限含める必要があります。

  ldapadd -D "cn=Directory Manager,dc=example,dc=com" -w password -f add_user.ldif
  • グループを作成する

サンプルとしてmembersグループを作成する。

add_group.ldif
  dn: cn=members,ou=groups,dc=example,dc=com
  objectClass: top
  cn: members
  objectClass: posixGroup
  gidNumber: 1000
  ldapadd -D "cn=Directory Manager,dc=example,dc=com" -w password -f add_group.ldif
  • sudoers用ouを作成する
  vim sudoersOU.ldif
sudoersOU.ldif
  dn: ou=SUDOers,dc=example,dc=com
  description: SUDOers
  objectClass: organizationalUnit
  objectClass: top
  ou: SUDOers
  ldapadd -x -D "cn=Directory Manager,dc=example,dc=com" -w password -f sudoersOU.ldif
  • /etc/sudoersを編集する
  [root@agenttest user.0]# cat /etc/sudoers | grep -v "^#" | grep -v "^\s*$"
Cmnd_Alias FILE_READ = /bin/cat, /bin/more, /usr/bin/tail
Cmnd_Alias SERVICE = /sbin/service
Cmnd_Alias NETWORK_LOOKUP = /bin/ping, /bin/netstat, /usr/bin/nslookup
Cmnd_Alias DELEGATING = /bin/chown, /bin/chmod, /bin/chgrp
Defaults   !visiblepw
Defaults    always_set_home
Defaults    env_reset
Defaults    env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Defaults    env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    !root_sudo
Defaults    !lecture
Defaults    log_host
Defaults    log_year
Defaults    logfile=/var/log/sudo.log
Defaults    ignore_dot
Defaults    ignore_local_sudoers
Defaults    timestamp_timeout=0
Defaults    passprompt="Enter [%u]'s Password:"
Defaults    badpass_message="The password is not corresponding. Try again."
Defaults    insults
Defaults    secure_path=/sbin:/bin:/usr/sbin:/usr/bin
root    ALL=(ALL)   ALL
%members       ALL=(ALL) FILE_READ
%wheel ALL=NOPASSWD: ALL

解説: Cmnd_Aliasで定義したコマンドの集まりを各グループに対して割り当てている。
%members ALL=(ALL) FILE_READmembersグループにFILE_READで定義した/bin/cat, /bin/more, /usr/bin/tailコマンドの実行を許可している。membersグループのユーザに対してALL(全て)のホストからALL(任意)のユーザ権限でFILE_READで定義したコマンドが実行可能という意味。lessではなくmoreを許可しているのはless:!/bin/bashとless内でコマンドを実行することでrootのシェルを取得出来るから。
!root_sudoでrootでのsudoを禁止、!lectureで最初にでる説明を非表示、ignore_local_sudoersでLDAP参照のみにしてローカルの/etc/sudoersを無視するようにしている。

  • sudoers2ldifでldifファイルに変換する
  export SUDOERS_BASE=ou=SUDOers,dc=example,dc=com
  cat /etc/sudoers | perl /usr/share/doc/sudo-1.8.6p3/sudoers2ldif > sudoers.ldif
sudoers.ldif
  dn: cn=defaults,ou=SUDOers,dc=example,dc=com
  objectClass: top
  objectClass: sudoRole
  cn: defaults
  description: Default sudoOption's go here
  sudoOption: !visiblepw
    sudoOption: always_set_home
  sudoOption: env_reset
  sudoOption: env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC 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: !root_sudo
  sudoOption: !lecture
  sudoOption: log_host
  sudoOption: log_year
  sudoOption: logfile=/var/log/sudo.log
  sudoOption: ignore_dot
  sudoOption: ignore_local_sudoers
  sudoOption: timestamp_timeout=0
  sudoOption: passprompt="Enter [%u]'s Password:"
  sudoOption: badpass_message="The password is not corresponding. Try again."
  sudoOption: secure_path=/sbin:/bin:/usr/sbin:/usr/bin

  〜中略〜
  • LDIFをインポートする

sudoers2ldifで変換したLDIFをインポートする

  ldapadd -x -D "cn=Directory Manager,dc=example,dc=com" -w password -f sudoers.ldif

LDAPクライアント側設定

  • 依存パッケージのインストール
  yum install openldap-clients nss-pam-ldapd pam_ldap openssh-ldap authconfig
  • 認証周りをauthconfigで設定
  # LDAPによるユーザ情報参照を有効にする
  authconfig --enableldap --update
  # LDAPによる認証を有効にする
  authconfig --enableldapauth --update
  # ユーザのホームディレクトリの自動作成を有効にする
  authconfig --enablemkhomedir --update
  # shadowパスワードの使用を有効にする
  authconfig --enableshadow --update  
  # local認証を有効にする
  authconfig --enablelocauthorize --update
  # LDAPサーバのURIを指定
  authconfig --ldapserver=ldap://127.0.0.1:389 --update
  # LDAPサーバのベースDNを指定
  authconfig --ldapbasedn=dc=example,dc=com --update 

以上のコマンドを実行した結果のPAMの設定は以下です。

/etc/pam.d/system-auth
  #%PAM-1.0
  # This file is auto-generated.
  # User changes will be destroyed the next time authconfig is run.
  auth        required      pam_env.so
  auth        sufficient    pam_unix.so nullok try_first_pass
  auth        requisite     pam_succeed_if.so uid >= 500 quiet
  auth        sufficient    pam_ldap.so use_first_pass
  auth        required      pam_deny.so

  account     required      pam_unix.so broken_shadow
  account     sufficient    pam_localuser.so
  account     sufficient    pam_succeed_if.so uid < 500 quiet
  account     [default=bad success=ok user_unknown=ignore] pam_ldap.so
  account     required      pam_permit.so

  password    requisite     pam_cracklib.so try_first_pass retry=3 type=
  password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
  password    sufficient    pam_ldap.so use_authtok
  password    required      pam_deny.so

  session     optional      pam_keyinit.so revoke
  session     required      pam_limits.so
  session     optional      pam_mkhomedir.so skel=/etc/skel umask=077
  session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
  session     required      pam_unix.so
  session     optional      pam_ldap.so

pam_mkhomedirモジュールを有効にしているのでユーザのホームディレクトリが存在しない場合自動的に作られます。自動削除はされないので必要なくなったら削除しましょう。

/etc/pam.d/password-auth
  #%PAM-1.0
  # This file is auto-generated.
  # User changes will be destroyed the next time authconfig is run.
  auth        required      pam_env.so
  auth        sufficient    pam_unix.so nullok try_first_pass
  auth        requisite     pam_succeed_if.so uid >= 500 quiet
  auth        sufficient    pam_ldap.so use_first_pass
  auth        required      pam_deny.so

  account     required      pam_unix.so broken_shadow
  account     sufficient    pam_localuser.so
  account     sufficient    pam_succeed_if.so uid < 500 quiet
  account     [default=bad success=ok user_unknown=ignore] pam_ldap.so
  account     required      pam_permit.so

  password    requisite     pam_cracklib.so try_first_pass retry=3 type=
  password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
  password    sufficient    pam_ldap.so use_authtok
  password    required      pam_deny.so

  session     optional      pam_keyinit.so revoke
  session     required      pam_limits.so
  session     optional      pam_mkhomedir.so skel=/etc/skel umask=077
  session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
  session     required      pam_unix.so
  session     optional      pam_ldap.so
  • sudo-ldapの設定

sudo-ldap.confauthconfigでは設定出来ないので手動で設定します。

  [root@localhost]# sudo -V
  ldap.conf path: /etc/sudo-ldap.conf

  [root@localhost ]# cat /etc/sudo-ldap.conf  | grep -v "^#" | grep -v "^\s*$"
  binddn cn=Directory Manager
  bindpw password
  uri ldap://127.0.0.1:389
  sudoers_base ou=SUDOers,dc=example,dc=com
  sudoers_debug 1
  • sudoersの参照先をldapに切り替え
  [root@localhost]# cat /etc/nsswitch.conf | grep sudoers
  sudoers:  ldap files
  • 確認

他ユーザにsuして確認してみる。

  [root@localhost]# su - test
  [shufo@localhost ~]$ sudo cat /var/log/secure 
  sudo: ldap_set_option: debug -> 0
  sudo: ldap_set_option: ldap_version -> 3
  sudo: ldap_sasl_bind_s() ok
  sudo: Looking for cn=defaults: cn=defaults
  sudo: found:cn=defaults,ou=SUDOers,dc=example,dc=com
  sudo: ldap search '(|(sudoUser=test)(sudoUser=%test)(sudoUser=%#501)(sudoUser=ALL))'
  sudo: searching from base 'ou=SUDOers,dc=example,dc=com'
  sudo: adding search result
  sudo: result now has 0 entries
  sudo: ldap search '(sudoUser=+*)'
  sudo: searching from base 'ou=SUDOers,dc=example,dc=com'
  sudo: adding search result
  sudo: result now has 0 entries
  sudo: sorting remaining 0 entries
  sudo: searching LDAP for sudoers entries
  sudo: done with LDAP searches
  sudo: user_matches=1
  sudo: host_matches=0
  sudo: sudo_ldap_lookup(0)=0x40
  Enter [test]'s Password: [パスワード入力]
  test is not allowed to run sudo on localhost.  This incident will be reported.

LDAPサーバに問い合わせされているのがログから分かる。
実際に問い合わせているクエリはbaseDNのou=SUDOers,dc=example,dc=com(|(sudoUser=shufo)(sudoUser=%shufo)(sudoUser=%#501)(sudoUser=ALL))で検索している。

26
24
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
24