Skip to content

LDAPとの統合 ​

Lightweight Directory Access Protocol(LDAP)は、ディレクトリ情報にアクセスおよび管理するためのプロトコルです。EMQXはパスワード認証のためにLDAPサーバーとの統合をサポートしています。この統合により、ユーザーはLDAPの認証情報を使用してEMQXで認証を行うことが可能になります。

前提条件

EMQX認証の基本概念の知識

パスワード認証方式 ​

EMQXのLDAP統合には、以下の2つの異なる認証方式があります。

  • LDAPバインド認証

    EMQXはLDAPバインドを直接利用してユーザー名とパスワードを認証します。クライアントが接続すると、EMQXは提供されたユーザー名とパスワードを受け取り、設定されたbase_dnとfilterを用いて識別名(DN)を構築します。その後、これらの認証情報を使ってLDAPサーバーに対してバインド(ログイン)を試みます。バインド操作が成功すれば認証が承認され、失敗すれば接続は拒否されます。

    この方式は既存のLDAPユーザーエントリのみに依存し、EMQXがパスワードハッシュなどの機密データを取得・処理する必要がありません。設定が簡単でLDAPスキーマの変更も不要です。

    この方式は以下のような場合に適しています。

    • LDAPサーバーにユーザーアカウントが既に存在している。
    • LDAPスキーマを変更または拡張できない。
    • 最小限の設定でLDAPサーバー側で直接認証を処理したい。
  • ローカルパスワード比較

    EMQXはusernameとpasswordの設定で指定されたバインドアカウントを使ってLDAPサーバーに接続します。次にクライアントのLDAPエントリを検索し、特定の属性から保存されているパスワード(通常はハッシュ形式)を取得します。クライアントから提供されたパスワードはEMQX内で取得したハッシュとローカルに比較されます。

    この方式は認証プロセスに対してより柔軟かつ詳細な制御を提供します。より複雑な検証ロジックやセキュリティ戦略をサポートし、追加のユーザー属性も処理可能です。例えば、EMQXはユーザーのisSuperUserフラグをパスワード照会時に取得できるため、認証時にユーザーのスーパーユーザー権限を判別し、権限レベルに応じた異なるアクセスや操作を提供できます。

    この方式は以下のような場合に適しています。

    • カスタム認証属性(例:isSuperuser、ACLルール)を保存または処理する必要がある。
    • LDAPサーバーのスキーマやデータを設定する権限がある。
    • 単純なLDAPバインド以上の高度なセキュリティや検証ロジックが必要。

LDAPデータスキーマとクエリ ​

TIP

このセクションは「ローカルパスワード比較」認証方式に適用されます。「LDAPバインド認証」方式を使用する場合は、このセクションをスキップできます。

このセクションでは、LDAPスキーマの設定、LDAP認証情報の作成、およびパスワード認証用の認証情報の保存方法について説明します。

LDAPスキーマは、LDAPディレクトリ内で認証データを整理・保存するための構造とルールを定義します。LDAP認証機能はほぼすべてのLDAPスキーマをサポートしています。以下はOpenLDAPの例です。

sql
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.1.4 NAME 'isSuperuser'
	EQUALITY booleanMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
	SINGLE-VALUE
	USAGE userApplications )

objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4 NAME 'mqttUser'
	SUP top
	STRUCTURAL
	MAY ( isSuperuser )
    MUST ( uid $ userPassword ) )

上記のスキーマ例は、ユーザーがスーパーユーザーかどうかを示すisSuperuser属性を定義しています。また、ユーザーを表すオブジェクトクラスmqttUserを定義し、このクラスにはuserPassword属性が必須となっています。

LDAP認証情報を作成するには、必要な属性名、ベースオブジェクトの識別名(dn)、およびLDAPクエリのフィルターを定義する必要があります。

以下は、OpenLDAPのスキーマに基づくLDAPデータ交換フォーマット(LDIF)で指定されたサンプルLDAP認証情報です。

sql
## create organization: emqx.io
dn:dc=emqx,dc=io
objectclass: top
objectclass: dcobject
objectclass: organization
dc:emqx
o:emqx,Inc.

## create organization unit: testdevice.emqx.io
dn:ou=testdevice,dc=emqx,dc=io
objectClass: top
objectclass:organizationalUnit
ou:testdevice

## create user=mqttuser0001,
#         password=mqttuser0001,
#         passhash={SHA}mlb3fat40MKBTXUVZwCKmL73R/0=
#         base64passhash=e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9
dn:uid=mqttuser0001,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
uid: mqttuser0001
userPassword:: e1NIQX1tbGIzZmF0NDBNS0JUWFVWWndDS21MNzNSLzA9

## create user=mqttuser0002
#         password=mqttuser0002,
#         passhash={SSHA}n9XdtoG4Q/TQ3TQF4Y+khJbMBH4qXj4M
#         base64passhash=e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=
dn:uid=mqttuser0002,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
uid: mqttuser0002
userPassword:: e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=

## create a superuser mqttuser0003
#         password=mqttuser0003,
#         passhash={MD5}ybsPGoaK3nDyiQvveiCOIw==
#         base64passhash=e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0=
dn:uid=mqttuser0003,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
uid: mqttuser0003
isSuperuser: TRUE
userPassword:: e01ENX15YnNQR29hSzNuRHlpUXZ2ZWlDT0l3PT0=

LDAPサーバー起動時にスキーマとLDIFファイルが読み込まれるように、LDAP設定ファイルslapd.confを編集します。以下はslapd.confの例です。

TIP

LDAP認証情報の保存方法やアクセス方法は、ビジネスニーズに応じて決定してください。

sh
include         /usr/local/etc/openldap/schema/core.schema
include         /usr/local/etc/openldap/schema/cosine.schema
include         /usr/local/etc/openldap/schema/inetorgperson.schema
include         /usr/local/etc/openldap/schema/emqx.schema

TLSCACertificateFile  /usr/local/etc/openldap/cacert.pem
TLSCertificateFile    /usr/local/etc/openldap/cert.pem
TLSCertificateKeyFile /usr/local/etc/openldap/key.pem

database mdb
suffix "dc=emqx,dc=io"
rootdn "cn=root,dc=emqx,dc=io"
rootpw {SSHA}eoF7NhNrejVYYyGHqnt+MdKNBh4r1w3W

directory       /usr/local/etc/openldap/data

ダッシュボードでLDAP認証を設定する ​

EMQXダッシュボードでLDAPをパスワード認証に使用する設定が可能です。

  1. EMQXダッシュボードの左ナビゲーションメニューからアクセス制御 -> 認証をクリックします。

  2. 認証ページの右上にある作成をクリックします。

  3. メカニズムでパスワードベースを選択し、バックエンドでLDAPを選択すると、以下のように設定タブに移動します。

    authn-ldap
  4. 以下の指示に従って設定してください。

    • LDAPサーバーに接続するための情報を入力します。

      • サーバー:EMQXが接続するサーバーのアドレスを指定します(host:port形式)。

      • ユーザー名:EMQXがLDAPサーバーにバインドするために使用するアカウント名(バインドDN)を指定します。例:cn=root,dc=emqx,dc=io。このアカウントはユーザーエントリの読み取り権限を持ち、通常LDAP設定ファイル(例:slapd.conf)で定義されたrootdnと同じです。

      • パスワード:上記ユーザー名に対応するプレーンテキストのパスワードで、バインド操作を完了するために使用します。この値はLDAP設定のrootpwの実際のパスワードと一致する必要があります。

    • 認証設定:認証に関する設定を入力します。

      • パスワード認証方式:認証方式を選択します。LDAPバインド認証(デフォルト)またはローカルパスワード比較から選択可能です。

      • バインドパスワード:EMQXがLDAPサーバーに対して自身を認証するために使用するパスワードを指定します。これは${password}というプレースホルダーで参照され、実行時に設定オプションのパスワードで定義された実際のパスワードに解決されます。

      • ベースDN:LDAP検索操作の開始点(ベースDN)を指定します。EMQXはこのDNから設定されたフィルターに一致するユーザーエントリを検索します。${username}などのプレースホルダーを使ってクライアント識別子を動的に構築可能です。詳細はRFC 4511 Search Requestを参照してください。

        TIP

        DNは識別名(Distinguished Name)を指します。これは各オブジェクトエントリの一意の識別子であり、情報ツリー内のエントリの位置も示します。

      • パスワードハッシュ属性:認証方式にローカルパスワード比較を選択した場合に適用される、ユーザーのパスワードを表す属性名を指定します。この属性の値はRFC 3112に準拠し、サポートされるアルゴリズムはmd5、sha、sha256、sha384、sha512、sshaです。

      • スーパーユーザー属性:認証方式にローカルパスワード比較を選択した場合に適用される、ユーザーがスーパーユーザーかどうかを示す属性名を指定します。この属性の値はブール値で、存在しない場合はfalseとみなされます。

      • クライアントID上書き属性:MQTTクライアント接続のクライアントIDを上書きするLDAP属性名を指定します。これにより認証データに基づいて一意のクライアントIDを割り当てられ、マルチテナントなどのセッション競合を防止できます。

      • 前提条件:Variform式で、LDAP認証機能をクライアント接続に適用するかどうかを制御します。式はクライアントの属性(username、clientid、listenerなど)に対して評価され、結果が文字列の"true"の場合のみ認証機能が呼び出されます。詳細は認証機能の前提条件を参照してください。

    • TLSを有効化:TLSを有効にする場合はトグルスイッチをオンにします。TLS有効化の詳細はネットワークとTLSを参照してください。

    • フィルター:LDAPクエリの条件を定義します。フィルターはエントリが一致するための条件を設定し、構文はRFC 4515に準拠し、プレースホルダーもサポートします。

    • 詳細設定:同時接続数や接続タイムアウトまでの待機時間を設定します。

      • コネクションプールサイズ(任意):EMQXノードからLDAPへの同時接続数を整数で指定します。デフォルトは8です。
      • クエリタイムアウト(任意):EMQXがクエリのタイムアウトとみなすまでの待機時間を秒単位で指定します。デフォルトは5秒です。
  5. 設定が完了したら、作成をクリックします。

設定ファイルでLDAP認証を構成する ​

EMQXの設定ファイルでLDAP認証機能を設定できます。

LDAP認証はmechanism = password_basedかつbackend = ldapで識別されます。

以下はローカルパスワード比較方式のサンプル設定です。

bash
{
  backend = "ldap"
  mechanism = "password_based"
  method {
    type = hash
    password_attribute = "userPassword"
    is_superuser_attribute = "isSuperuser"
  }
  server = "127.0.0.1:389"
  query_timeout = "5s"
  username = "root"
  password = "root password"
  pool_size = 8
  base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
  filter = "(objectClass=mqttUser)"
}

以下はLDAPバインド認証方式のサンプル設定です。

bash
{
  backend = "ldap"
  mechanism = "password_based"
  method {
    type = bind
    bind_password = "${password}"
  }
  server = "127.0.0.1:389"
  query_timeout = "5s"
  username = "root"
  password = "root password"
  pool_size = 8
  base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
  filter = "(objectClass=mqttUser)"
}

LDAPからACLルールを取得する ​

クライアントの認証に加えて、EMQXは認証時に使用した同じLDAPエントリからユーザーごとのACL(アクセス制御リスト)ルールを取得できます。これにより認証と認可をLDAPで一元管理できます。

認証プロセス中、EMQXは設定されたbase_dnとfilterを使ってユーザーのLDAPエントリを検索します。ACL関連の属性が見つかれば、それらを取得してクライアントのセッションにキャッシュします。これらのルールはパブリッシュ/サブスクライブの権限チェックに使用され、繰り返しLDAPクエリを行う必要がありません。

サポートされるACL属性 ​

LDAPからACLルールを取得する機能を有効にするには、LDAPスキーマに以下のいずれかの属性を定義する必要があります。

  • mqttPublishTopic:クライアントがパブリッシュ可能なトピックのホワイトリスト。
  • mqttSubscriptionTopic:クライアントがサブスクライブ可能なトピックのホワイトリスト。
  • mqttPubSubTopic:クライアントがパブリッシュおよびサブスクライブ可能なトピック。
  • mqttAclRule:JSON形式で定義された詳細なACLルール。アクション(パブリッシュやサブスクライブ)、許可(許可または拒否)、トピックフィルターなどを細かく制御可能。
  • mqttAclTtl:クライアントセッション内でACLルールが有効な期間(TTL)を指定する任意の属性。

上記の属性名はあくまで例です。LDAP認証機能の設定で適切なフィールドを使いカスタマイズ可能です。

これらの属性の動作や意味はLDAPオーソライザーで定義されたものと同じですが、mqttAclTtlはLDAP認証機能固有の属性です。この属性により、取得したACLルールをクライアントセッション内でどのくらいの期間キャッシュするかを制御できます。値は秒数の数値文字列(例:60)か、1s、15m、1h、1dなどの時間単位付きの期間を指定できます。

指定したTTLが経過すると、EMQXはキャッシュされたルールを使用せず、デフォルトの認可設定にフォールバックします。ただし、後続の認証やセッションで新しいルールが取得されれば更新されます。

ACLルール用LDAPスキーマ例 ​

以下の例はACLルール用の属性を定義したスキーマです。

attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.1.4 NAME 'isSuperuser'
	EQUALITY booleanMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
	SINGLE-VALUE
	USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.1 NAME ( 'mqttPublishTopic' 'mpt' )
	EQUALITY caseExactMatch
	SUBSTR caseExactSubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.2 NAME ( 'mqttSubscriptionTopic' 'mst' )
	EQUALITY caseExactMatch
	SUBSTR caseExactSubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.3 NAME ( 'mqttPubSubTopic' 'mpst' )
	EQUALITY caseExactMatch
	SUBSTR caseExactSubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.4 NAME ( 'mqttAclRule' 'mar' )
	EQUALITY caseExactMatch
	SUBSTR caseExactSubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	USAGE userApplications )
attributetype ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4.5 NAME ( 'mqttAclTtl' 'mat' )
	EQUALITY caseExactMatch
	SUBSTR caseExactSubstringsMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
	USAGE userApplications )
objectclass ( 1.3.6.1.4.1.11.2.53.2.2.3.1.2.3.4 NAME 'mqttUser'
	SUP top
	STRUCTURAL
	MAY ( isSuperuser $ mqttPublishTopic $ mqttSubscriptionTopic $ mqttPubSubTopic $ mqttAclRule $ mqttAclTtl )
  MUST ( uid $ userPassword ))

ACL属性を含むLDIFエントリの例 ​

以下は、OpenLDAPのスキーマに基づくACL属性を含むLDAP認証データの例です。

sql
dn:dc=emqx,dc=io
objectclass: top
objectclass: dcobject
objectclass: organization
dc:emqx
o:emqx,Inc.

# create testdevice.emqx.io
dn:ou=testdevice,dc=emqx,dc=io
objectClass: top
objectclass:organizationalUnit
ou:testdevice

## create user=mqttuser0002
#         password=mqttuser0002,
#         passhash={SSHA}n9XdtoG4Q/TQ3TQF4Y+khJbMBH4qXj4M
#         base64passhash=e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=
dn:uid=mqttuser0002,ou=testdevice,dc=emqx,dc=io
objectClass: top
objectClass: mqttUser
objectClass: mqttDevice
objectClass: mqttSecurity
uid: mqttuser0002
isEnabled: TRUE
mqttAccountName: user2
mqttPublishTopic: mqttuser0002/pub/1
mqttPublishTopic: mqttuser0002/pub/+
mqttPublishTopic: mqttuser0002/pub/#
mqttSubscriptionTopic: mqttuser0002/sub/1
mqttSubscriptionTopic: mqttuser0002/sub/+
mqttSubscriptionTopic: mqttuser0002/sub/#
mqttPubSubTopic: mqttuser0002/pubsub/1
mqttPubSubTopic: mqttuser0002/pubsub/+
mqttPubSubTopic: mqttuser0002/pubsub/#
mqttAclRule: [{"permission": "allow", "action": "pub", "topic": "mqttuser0002/complexrule1/1"}]
mqttAclRule: {"permission": "allow", "action": "pub", "topic": "mqttuser0002/complexrule2/#"}
mqttAclTtl: 1s
userPassword:: e1NTSEF9bjlYZHRvRzRRL1RRM1RRRjRZK2toSmJNQkg0cVhqNE0=

LDAP認証機能設定例 ​

ACLルールの取得とキャッシュを有効にするには、LDAP認証機能の設定で属性名を明示的に指定する必要があります。

bash
{
  backend = "ldap"
  mechanism = "password_based"
  method {
    type = hash
    password_attribute = "userPassword"
    is_superuser_attribute = "isSuperuser"
  }
  server = "127.0.0.1:389"
  query_timeout = "5s"
  username = "root"
  password = "root password"
  pool_size = 8
  base_dn = "uid=${username},ou=testdevice,dc=emqx,dc=io"
  filter = "(objectClass=mqttUser)"
  publish_attribute = "mqttPublishTopic"
  subscribe_attribute = "mqttSubscriptionTopic"
  all_attribute = "mqttPubSubTopic"
  acl_attribute = "mqttAclRule"
  acl_ttl_attribute = "mqttAclTtl"
}