Skip to content

PostgreSQLとの統合 ​

EMQXはパスワード認証のためにPostgreSQLとの統合をサポートしています。

TIP

基本的なEMQX認証の概念についての知識

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

EMQXのPostgreSQL認証機能はほぼあらゆるストレージスキーマに対応しています。ビジネス要件に応じて、認証情報の保存方法やアクセス方法を自由に決めることができます。例えば、1つまたは複数のテーブルやビューを使用することが可能です。

ユーザーはクエリ文のテンプレートを提供し、以下のフィールドが含まれていることを保証する必要があります。

  • password_hash:必須。データベースに保存されているパスワード(プレーンテキストまたはハッシュ化済み)。
  • salt:任意。salt = "" またはこのフィールドを省略すると、ソルト値が追加されないことを示します。
  • is_superuser:任意。現在のクライアントがスーパーユーザーかどうかを示すフラグ。デフォルトは false。

認証情報を保存するためのテーブル構造の例:

sql
CREATE TABLE mqtt_user (
    id serial PRIMARY KEY,
    username text NOT NULL UNIQUE,
    password_hash  text NOT NULL,
    salt text NOT NULL,
    is_superuser boolean DEFAULT false,
    created timestamp with time zone DEFAULT NOW()
);

TIP

上記の例では、クエリに役立つ暗黙の UNIQUE インデックスフィールド(username)が作成されています。 システム内のユーザー数が多い場合は、クエリの応答時間を短縮しEMQXの負荷を軽減するために、事前にテーブルの最適化やインデックス付けを行ってください。

このテーブルでは、MQTTユーザーは username によって識別されます。

例えば、スーパーユーザー(is_superuser: true)でユーザー名が user123、パスワードが secret、ソルトが salt のドキュメントを追加したい場合、クエリ文は以下のようになります。

bash
INSERT INTO mqtt_user(username, password_hash, salt, is_superuser) VALUES ('user123', 'f84fa2149dbb62ed4e0cf1f550d2949b33a6513d3a7707e08502511c79ccb0ee', 'salt', true);
INSERT 0 1

対応する設定パラメータは以下の通りです。

  • password_hash_algorithm: sha256
  • salt_position: suffix

SQL:

sql
query = "SELECT password_hash, salt, is_superuser FROM mqtt_user WHERE username = ${username} LIMIT 1"

ダッシュボードでの設定 ​

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

  1. EMQXダッシュボードの左側ナビゲーションメニューから アクセス制御 -> 認証 をクリックします。
  2. 認証 ページの右上にある 作成 をクリックします。
  3. メカニズム に パスワードベース を選択し、バックエンド に PostgreSQL を選択すると、以下のように 設定 タブに移動します。
PostgreSQLによる認証
  1. 認証バックエンドの設定手順は以下の通りです。
    • PostgreSQLへの接続情報を入力します。

      • サーバー:EMQXが接続するサーバーアドレス(host:port)を指定します。
      • データベース:PostgreSQLのデータベース名。
      • ユーザー名:ユーザー名を指定します。
      • パスワード:ユーザーパスワードを指定します。
    • 認証に関する設定を行います。

      • パスワードハッシュ:プレーンテキストのパスワードに適用され、結果がデータベースに保存されるハッシュアルゴリズムを選択します。利用可能なオプションは plain、md5、sha、sha256、sha512、bcrypt、pbkdf2 です。選択したアルゴリズムに応じて追加設定があります。
        • md5、sha、sha256、sha512 の場合:
          • ソルト位置:ソルト(ランダムデータ)をパスワードにどのように混ぜるかを指定します。suffix、prefix、disable のいずれかを選択可能です。外部ストレージからEMQX組み込みデータベースへユーザー認証情報を移行する場合を除き、デフォルト値のままで問題ありません。
          • 結果のハッシュは16進数文字列として表現され、大文字・小文字を区別せずに保存された認証情報と比較されます。
        • plain の場合:
          • ソルト位置 は disable に設定してください。
        • bcrypt の場合:
          • ソルトラウンド数:ハッシュ関数を適用する回数を定義します。2のべき乗回数として表され、コストファクターとも呼ばれます。デフォルトは 10 で、範囲は 5 から 10 です。セキュリティ強化のためにはより高い値が推奨されます。注意:コストファクターを1増やすと認証にかかる時間が倍増します。
        • pbkdf2 の場合:
          • 疑似乱数関数:キー生成に使用するハッシュ関数を選択します(例:sha256)。
          • 反復回数:ハッシュ関数を実行する回数を設定します。デフォルトは 4096 です。
          • 生成キー長(任意):生成されるキーのバイト長を指定します。空欄の場合は選択した疑似乱数関数のデフォルト長になります。
          • 結果のハッシュは16進数文字列として表現され、大文字・小文字を区別せずに保存された認証情報と比較されます。
    • 前提条件:Variform式を使用して、このPostgreSQL認証機能をクライアント接続に適用するかどうかを制御します。この式はクライアントの属性(username、clientid、listenerなど)に対して評価され、結果が文字列 "true" の場合にのみ認証機能が呼び出されます。そうでなければスキップされます。前提条件の詳細は認証機能の前提条件を参照してください。

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

    • 詳細設定:接続プール、タイムアウト、プリペアドステートメントの挙動を設定します。

      • 接続プールサイズ(任意):EMQXノードからPostgreSQLサーバーへの同時接続数を指定します。デフォルトは 8。
      • クエリタイムアウト(任意):EMQXがクエリのタイムアウトとみなすまでの待機時間を指定します。ミリ秒、秒、分、時間単位が利用可能です。デフォルトは 5 秒。
      • 接続タイムアウト(任意):EMQXが接続試行のタイムアウトとみなすまでの待機時間を指定します。ミリ秒、秒、分、時間単位が利用可能です。デフォルトは 15 秒。
      • プリペアドステートメントを無効化(任意):データベースクエリでプリペアドステートメントの使用を無効にします。PostgreSQLのプロキシやミドルウェア(例:PGBouncerやSupabaseのトランザクションモード)がセッションレベルの機能(プリペアドステートメントなど)をサポートしていない場合に有効にしてください。デフォルトは無効。
    • SQL:データスキーマに従ってクエリ文を入力します。詳細はSQLデータスキーマとクエリ文を参照してください。

設定が完了したら、作成 をクリックしてください。

設定項目による設定 ​

EMQXの設定項目を使ってPostgreSQL認証機能を設定することも可能です。設定パラメータの完全な一覧はEMQX Enterprise設定マニュアルを参照してください。

PostgreSQL認証は mechanism = password_based および backend = postgresql で識別されます。

設定例:

bash
{
  mechanism = password_based
  backend = postgresql

  password_hash_algorithm {
    name = sha256
    salt_position = suffix
  }

  database = mqtt
  username = postgres
  password = public
  server = "127.0.0.1:5432"
  query = "SELECT password_hash, salt, is_superuser FROM users where username = ${username} LIMIT 1"
  query_timeout = "5s"
  connect_timeout = "15s"
  disable_prepared_statements = false
}