AnsibleでOpenLDAP環境構築 -⑥ldapユーザにssh鍵認証設定

投稿者: | 2018年1月23日

AnsibleでOpenLDAP環境構築 -⑤ldapユーザをssh鍵認証でログインするための設定まで終わったら、いよいよ大詰めldapユーザにssh鍵認証設定。

LDAP構築 まとめの例にならい、
パスフレーズ(ssh鍵認証用パスワード)⇒ sshmanager
ssh秘密鍵/公開鍵生成 ⇒ ssh-keygenコマンドを実行

とした。


■ssh鍵認証設定用playbook

以下の内容でplaybookを作成してみた。

[root@ansible_sv ~]# vi/etc/ansible/yml/6_setPubkey.yml
           1- hosts: ldap_sv
           2  remote_user: root
           3
           4  vars:
           5    gid: "ldapmanager"
           6    uid: "user01"
           7    gidnum: "1001"
           8    uidnum: "1001"
           9    keypass: "sshmanager"
          10
          11  tasks:
          12  - name: execute su
          13    shell: >
          14      su {{ uid }}
          15
          16  - name: create .ssh directory
          17    file:
          18      path=/home/{{ uid }}/.ssh
          19      state=directory
          20      owner={{ uid }}
          21      group={{ gid }}
          22      mode=0700
          23
          24  - name: create sshPublickey
          25    shell: >
          26      ssh-keygen -t ed25519 -f /home/{{ uid }}/.ssh/id_ed25519 -N "{{ keypass }}"
          27
          28  - name: chmod id_ed25519*
          29    file:
          30      path=/home/{{ uid }}/.ssh/{{ item }}
          31      state=file
          32      owner={{ uid }}
          33      group={{ gid }}
          34      mode=0600
          35    with_items:
          36      - 'id_ed25519'
          37      - 'id_ed25519.pub'
          38
          39  - name: rename authorized_keys
          40    shell: >
          41      mv /home/{{ uid }}/.ssh/id_ed25519.pub /home/{{ uid }}/.ssh/authorized_keys
          42
          43  - name: userdel
          44    ldap_entry:
          45      dn: uid={{ uid }},cn={{ gid }},ou=Group,dc=abc,dc=def,dc=com
          46      state: absent
          47      server_uri: ldap://localhost/
          48      bind_dn: cn=Manager,dc=abc,dc=def,dc=com
          49      bind_pw: manager
          50
          51  - name: stdout slappasswd
          52    shell: slappasswd -s ldapuser01
          53    register: user01pass
          54
          55  - name: stdout sshPublickey
          56    shell: cat /home/{{ uid }}/.ssh/authorized_keys
          57    register: pubkey
          58
          59  - name: re-exec useradd
          60    ldap_entry:
          61      dn: uid={{ uid }},cn={{ gid }},ou=Group,dc=abc,dc=def,dc=com
          62      state: present
          63      server_uri: ldap://localhost/
          64      bind_dn: cn=Manager,dc=abc,dc=def,dc=com
          65      bind_pw: "manager"
          66      objectClass:
          67        - top
          68        - posixAccount
          69        - account
          70        - ldapPublickey
          71      attributes:
          72        gecos: ldapsystem manager
          73        cn: "{{ gid }}"
          74        uid: "{{ uid }}"
          75        uidNumber: "{{ uidnum }}"
          76        gidNumber: "{{ gidnum }}"
          77        homeDirectory: /home/{{ uid }}
          78        loginShell: /bin/bash
          79        userPassword: "{{ user01pass.stdout }}"
          80        sshPublicKey: "{{ pubkey.stdout }}"

以下、各モジュールの説明。

hosts:(1行目)
処理を実行する対象ホストを指定。「ldap_sv」は/etc/ansible/hostsに記述したホスト名となる。

remote_user:(2行目)
hosts:で指定したホストで処理を実行する際に、どのユーザで処理を実行するかを指定。上記の例では先頭の階層に記述しているため、それ以降の全階層において適用される。

vars:(4行目)
変数を宣言するモジュール。変数の宣言は1行だけでなく複数可。またこの場合一番上位のhostsモジュールと同じ階層に位置されているので、それ以下のすべての階層に有効となる。言うまでもないかもしれないが、ここで変数を使う理由として、ldapユーザが後々追加になった場合に、playbookを使いまわすのにいちいちファイルの内容全部をチェックして修正箇所を網羅するのは非効率なので、ldapユーザ追加時に、主に変更が発生しそうな箇所はあらかじめ変数にして、追加が発生した場合にその変数1箇所だけを修正するようにしたかった。

tasks:(10行目)
処理の内容を、tasks:以降に記述する。tasks:を記述しないとエラーになるので注意。

name:(12、16、24、28、39、43、51、55、59行目)
ansible-playbookコマンドを実行した際に、実行結果に出力させる文字列を指定する。

shell:(13、25、40、52、56、行目)
linuxコマンドを直接指定できる。類似モジュールで「command:」もあるが、shellは複数行記述できる。

file:(17、29行目)
ファイルやディレクトリの作成、アクセス権限の指定ができるモジュール。複数のモジュール引数が存在するので、以下の表に示す。

モジュール引数 条件 説明
path= ディレクトリやファイル、シンボリックリンクの位置をフルパスで指定する。
state= file pathで指定した既存のファイルを示す。もしファイルがない場合はcopyモジュールやtemplateモジュールが発動する。
link pathで指定したシンボリックリンクを示す。
directory pathで指定した既存のディレクトリを示す。ディレクトリがない場合はサブディレクトリとして作成され、アクセス権限は上位ディレクトリから継承される。
hard ハードリンクを指定する。
touch pathで指定したファイルを空の状態で作成する。linuxコマンドのtouchコマンドに相当する。
absent pathで指定したファイルやディレクトリ、シンボリックリックを削除する。
owner= ファイルのオーナーを指定する。lsコマンド等で表示されるオーナーの部分に当たる。
group= ファイルのグループを指定する。lsコマンド等で表示されるグループの部分に当たる。
mode= ファイルのアクセス権限を指定する。chmodコマンドに相当する。

with_items:(35行目)
「item」と記述したところに入る文字列を指定する。文字列は複数指定することができる。
実はここでも行頭に「-」が記述されているが、yml形式においては、ひとつのモジュールに対して複数の処理を当てはめる場合にこのような記述になるらしい。
上記例でも「task:」の中に複数の「- name:」があるのと同じ考えといったところだろうか。

ldap_entry:(44、60行目)
ldap関連モジュール。ldap_attrやldap_sert,ldap_searchがある。詳細はansible公式ページのldap関連もしくはGitHubを参照。

モジュール引数 条件 説明
dn: 登録するベースDN(本稿ではdc=abc,dc=def,dc=com)を指定する。
state: present ベースDN/組織/グループ/ユーザを設定するときに指定する。
absent ベースDN/組織/グループ/ユーザを削除するときに指定する。
server_uri: OpenLDAPサーバのURLを「ldap://<OpenLDAPサーバのIPアドレス>」という記述で指定する。
bind_dn: 設定/削除する際にバインド(認証)する管理者DN(本稿では「cn=Manager,dc=abc,dc=def,dc=com」)を指定する。
bind_pw: 設定/削除する際にバインド(認証)する管理者パスワード(本稿では「manager」)を指定する。
objectClass: ベースDN/組織/グループ/ユーザに対し、設定/削除するオブジェクトクラスを指定する。オブジェクトクラスの記述の前に「‐」をつけて、複数指定することも可能。その際にオブジェクトクラスや属性の継承関係やスキーマの有無などは事前に確認すべし。
attributes: ベースDN/組織/グループ/ユーザに対し、設定/削除する属性を指定する。属性は「dc:」「o:」のように、実際にスキーマに登録されているものを指定する。

ldap系モジュールを使用するにあたって
事前に開発パッケージをインストールしておく必要がある。詳細はAnsibleでOpenLDAP環境構築 -③組織(ou)/グループ(cn)の設定を参照。

register:(53、57行目)
直前で実行したモジュールの標準出力結果を、指定した変数に代入してくれる。※ここで注意することは、registerで得た文字列は「<registerモジュールで指定した変数名>.stdout」と記述しているように、.stdoutをつけて使用すること。

 

■補足

上記playbookの内容を少し説明すると。。。

・14行目
suコマンドを実行するように仕掛けているが、ansibleではsuコマンドを推奨していないらしく、warningが出てしまう。エラーではないので気にはしないが、ldapユーザが初回ログインした時に、oddjobサービスによってちゃんとホームディレクトリが作成されるか、念のため動作確認の意味を含めている。

・29~37行
「path=/home/{{ uid }}/.ssh/{{ item }}」と記述している。itemという変数を使って、with_itemsでid_ed25519とid_ed25519.pubの2つのファイルに対してアクセス権限を変更している。

・44~49行目
「state: absent」と記述し、一旦ldapユーザを削除している。60行以降でsshPublicKeyモジュールを付け加えてユーザ再登録を行うため。

 

■ansible-playbookコマンドでplaybookを実行

いよいよansibleの実行。コマンドは
# ansible-playbook <playbook名(フルパス)>

[root@ansible_sv ~]# ansible-playbook /etc/ansible/yml/6_setPubkey.yml
SSH password:

PLAY [ldap_sv] ***************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************
ok: [192.168.3.6]

TASK [execute su] ************************************************************************************************************************************
 [WARNING]: Consider using 'become', 'become_method', and 'become_user' rather than running su

changed: [192.168.3.6]

TASK [create .ssh directory] *************************************************************************************************************************
changed: [192.168.3.6]

TASK [create sshPublickey] ***************************************************************************************************************************
changed: [192.168.3.6]

TASK [chmod id_ed25519*] *****************************************************************************************************************************
changed: [192.168.3.6] => (item=id_ed25519)
changed: [192.168.3.6] => (item=id_ed25519.pub)

TASK [rename authorized_keys] ************************************************************************************************************************
changed: [192.168.3.6]

TASK [userdel] ***************************************************************************************************************************************
changed: [192.168.3.6]

TASK [stdout slappasswd] *****************************************************************************************************************************
changed: [192.168.3.6]

TASK [stdout sshPublickey] ***************************************************************************************************************************
changed: [192.168.3.6]

TASK [re-exec useradd] *******************************************************************************************************************************
changed: [192.168.3.6]

PLAY RECAP *******************************************************************************************************************************************
192.168.3.6                : ok=10   changed=9    unreachable=0    failed=0

[root@ansible_sv ~]#

suコマンドをたたいているところは、案の定ピンク文字。([WARNING]: Consider using ‘become’, ‘become_method’, and ‘become_user’ rather than running su)ホームディレクトリの作成は必要な作業なので、やむなし。
無事成功\(^o^)/

実行結果の説明はAnsibleでOpenLDAP環境構築 -①OpenLDAPサーバ関連のパッケージインストールを参照。

 

■OpenLDAPサーバで事後確認

念のためansible-playbookコマンドで実行したplaybookの内容がOpenLDAPサーバにちゃんと反映されたか確認。
ここで事後確認するポイントは、playbookに沿って以下。
・/etc/<ldapユーザ名>/.ssh及び、その配下のid_ed25519、authorized_keysのアクセス権限が期待値どおりであること。
(/etc/<ldapユーザ名>/.ssh⇒0700、id_ed25519/authorized_keys⇒0600)
・ldapユーザがsshPublicKey属性つきで登録されていること。(ldapsearchコマンドで確認)

[root@ldapmanager ~]# ls -l /home
合計 0
drwx------. 3 user01 ldapmanager 74  1月 25 13:53 user01
[root@ldapmanager ~]# ls -l /home/user01/.ssh
合計 8
-rw-------. 1 user01 ldapmanager  98  1月 25 13:53 authorized_keys
-rw-------. 1 user01 ldapmanager 464  1月 25 13:53 id_ed25519
[root@ldapmanager ~]#

アクセス権限は大丈夫のようだ。

[root@ldapmanager ~]# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'dc=abc,dc=def,dc=com' 'uid=*'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: uid=user01,cn=ldapmanager,ou=Group,dc=abc,dc=def,dc=com
cn: ldapmanager
objectClass: top
objectClass: posixAccount
objectClass: account
objectClass: ldapPublicKey
loginShell: /bin/bash
userPassword:: e1NTSEF9MWNXYXloRmlkV0F4aGdTY3ZudUw3eElQNE5LMERPOWk=
uidNumber: 1001
gidNumber: 1001
gecos: ldapsystem manager
homeDirectory: /home/user01
sshPublicKey: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9SdWAQw736AdPnGnvHfGEPRZSe
 UflZVEqbFyqgM0AM root@ldapmanager
uid: user01

[root@ldapmanager ~]#

sshPublicKey属性ありました\(^o^)/

playbook成功!!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA