4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

pythonでLDAPにデータの追加取得をする

Posted at

はじめに

認証やツリー構造のデータの管理などでLDAPが使用されます。RDBと比べるとLDAPは使用される機会が少なく使用方法も異なるのでpythonでLDAPを操作する方法をまとめます。さらにLDAP認証のサンプルは色々なところで紹介されていますが、もっと簡単にするためシンプルな例を紹介します。

環境準備

LDAPサーバ

LDAPサーバは、UbuntuやCentosにldapをインストールしてもできますがdockerイメージがあったため、そちらを使用します。

dockerイメージのpull

dockerイメージは単純にpullするだけです。


docker pull osixia/openldap

dockerイメージの起動

イメージの起動時にldapのパスワードとトップのドメイン、各ポートのマウントをしておきます。dockerネットワークを利用している場合は、ポートのマウントはせずにネットワークとIPアドレスの設定をします。


 docker run -p 389:389 -p 636:636 --env LDAP_DOMAIN="sample-ldap" --env LDAP_ADMIN_PASSWORD="LdapPass" --name LDAPSERVER --detach osixia/openldap

結果


> docker ps
CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS              PORTS               NAMES
4f6e1b4eaf29        osixia/openldap     "/container/tool/run"   2 hours ago         Up 2 hours          0.0.0.0:389->389/tcp, 0.0.0.0:636->636/tcp   LDAPSERVER

Ldapライブラリのインストール

クライアントはpythonで使用するのでLDAPクライアントのライブラリldap3をpipでインストールします。


pip install ldap3

LDAPの操作

LDAPのサーバとクライアントの用意ができたため、これから操作のソースを作成していきます。

LDAPへのログイン

LDAPへの操作にはログインが必要なため、まずはログインをします。LDAPサーバのIPアドレスやポート番号、タイムアウト等必要な設定を追加したServerクラスを設定します。そのServerクラスを使用してConnectionクラスを生成します。この時にはLDAPサーバへ接続されず、bind()で始めて接続されます。dcとpasswordはdocker run時に指定した値になり、cnはデフォルトはadminになります。

main.py

conn = Connection(server, 'cn=admin,dc=sample-ldap',  password='LdapPass')
result = conn.bind()
print(result)

結果

> python main.py' 
True

bindの結果がTrueとなっているため、LDAPサーバへ接続ができたことが分かります。

ドメイン

接続ができたため次はLDAPの追加と取得をしていきます。
LDAPはトップからdc、ou、cnの順にツリー構造で構成されているため、まずはdcから追加と取得していきます。

ドメインの追加

サンプルコードは上のソースの続きになります。作成したコネクションのadd関数の第一引数に追加したいdcとトップのdcをつなげた文字列を指定して、第二引数に'domain'を指定します。この時に第一引数の文字列のカンマの後にスペースを入れるとエラーするので注意してください。

main.py

# ドメインの追加
dc_result = conn.add('dc=sample-component,dc=sample-ldap', 'domain')
print(dc_result)

結果

True

実行結果はバインドと同じでaddの結果としてTrueが返ってきたため、追加できたことがわかります。

ドメインの取得

サンプルコードは上のソースの続きになります。上で追加したdcを取得します。conn.search()の第一引数に調べたいLDAPのパスを指定します。第二引数はdomainを指定します。その結果、conn.entries にsample-componentの情報が取得できます。

main.py

# ドメインの取得
conn.search('dc=sample-component,dc=sample-ldap', '(objectclass=domain)')
print(conn.entries)

結果

True
[DN: dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T22:35:26.491599
]

今回は、第二引数にdomainを指定してドメインを検索しているので対象の1個のentriesが取得できます。後ほどソースを載せますが第二引数に他の値を入れると複数取得できます。

オーガニゼーション

LDAPのdcが追加できたので次はouの追加と取得していきます。

オーガニゼーションの追加

サンプルコードは上のソースの続きになります。作成したコネクションのadd関数の第一引数に追加したいouとdcをつなげた文字列を指定して、第二引数に'organizationalUnit'を指定します。

main.py

# ドメインの追加
ou_result = conn.add('ou=sample-unit,dc=sample-component,dc=sample-ldap', 'organizationalUnit')
print(ou_result)

結果

True

実行結果はバインドと同じでaddの結果としてTrueが返ってきたため、追加できたことがわかります。

オーガニゼーションの取得

サンプルコードは上のソースの続きになります。上で追加したouを取得します。conn.search()の第一引数に検索したいパスを指定します。第二引数はorganizationalUnitを指定します。その結果、conn.entries にsample-unitの情報が取得できます。

main.py

# オーガニゼーションの取得
conn.search('ou=sample-unit,dc=sample-component,dc=sample-ldap', '(objectclass=organizationalUnit)')
print(conn.entries)

# dc指定のオーガニゼーションの取得
conn.search('dc=sample-component,dc=sample-ldap', '(objectclass=organizationalUnit)')
print(conn.entries)


結果


[DN: ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:27:36.594396]
[DN: ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:27:36.604398
, DN: ou=sample-unit2,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:27:36.604398
]

第一引数にオーガニゼーションを検索している場合は対象の1個のentriesが取得できます。ドメインを検索している場合は、ドメインが含んでいるouの数だけ複数取得できます。

コモンネーム

LDAPのouが追加できたので次はcnの追加と取得していきます。

コモンネームの追加

サンプルコードは上のソースの続きになります。作成したコネクションのadd関数の第一引数に追加したいcnとouとdcをつなげた文字列を指定して、第二引数に'inetOrgPerson'を指定して、第三引数に付加情報を指定します。

main.py

# ドメインの追加
cn_result = conn.add('cn=sample-name,ou=sample-unit,dc=sample-component,dc=sample-ldap', 'inetOrgPerson', {'sn':'sample'})
print(cn_result)

結果

True

実行結果はバインドと同じでaddの結果としてTrueが返ってきたため、追加できたことがわかります。

コモンネームの取得

サンプルコードは上のソースの続きになります。上で追加したcnを取得します。conn.search()の第一引数に検索したいパスを指定します。第二引数はinetOrgPersonを指定します。その結果、conn.entries にsample-nameの情報が取得できます。

main.py

# コモンネームの取得
conn.search('cn=sample-name,ou=sample-unit,dc=sample-component,dc=sample-ldap', '(objectclass=inetOrgPerson)')
print(conn.entries)

# ou指定のコモンネームの取得
conn.search('ou=sample-unit,dc=sample-component,dc=sample-ldap', '(objectclass=inetOrgPerson)')
print(conn.entries)

# dc指定のコモンネームの取得
conn.search('dc=sample-component,dc=sample-ldap', '(objectclass=inetOrgPerson)')
print(conn.entries)

結果


[DN: cn=sample-name,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:36:41.125246
]
[DN: cn=sample-name,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:36:41.156378
, DN: cn=sample-name2,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:36:41.157365
, DN: cn=sample-name3,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:36:41.157365
, DN: cn=sample-name1,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:36:41.157365
]
[DN: cn=sample-name,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:51:20.773638
, DN: cn=sample-name2,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:51:20.773638
, DN: cn=sample-name3,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:51:20.774650
, DN: cn=sample-name1,ou=sample-unit,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:51:20.774650
, DN: cn=sample-name,ou=sample-unit1,dc=sample-component,dc=sample-ldap - STATUS: Read - READ TIME: 2020-03-25T23:51:20.774650
]

第二引数にinetOrgPersonを指定してコモンネームを検索している場合は対象の1個のentriesが取得できます。オーガニゼーションやドメインを検索している場合はそれぞれが含んでいるcnの数だけ複数取得できます。

おわりに

LDAPに関しては、LDAP認証として使用しただけなので今回のようにLDAPのドメインから追加したりそれぞれのディレクトリから検索方法を変えて検索することはしていませんでした。使用するのに癖はありますが、思った以上にシンプルな方法で値を取得できるのでツリー構造のデータならこちらの方がRDBより使いやすくなるかもしれません。次は他の操作も見ていきます。

4
4
0

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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?