Redisの認証機能(AUTH)でセキュリティを強化する方法

はい、承知いたしました。Redisの認証機能(AUTH)およびACLs(Access Control Lists)を用いたセキュリティ強化に関する詳細な記事を作成します。約5000語を目指して、各側面を深く掘り下げて記述します。


Redis認証機能(AUTH)とACLsによるセキュリティ強化の徹底解説

はじめに:なぜRedisのセキュリティが重要なのか

インメモリデータ構造ストアとして絶大な人気を誇るRedisは、キャッシュ、メッセージブローカー、セッションストア、データベースなど、多様な用途で利用されています。その高速性と柔軟性から、現代の多くのアプリケーションの中核を担っています。

しかし、Redisが扱うデータは、セッション情報、ユーザープロファイル、キャッシュされた機密データなど、非常に重要なものであることが少なくありません。不適切に保護されたRedisインスタンスは、これらの機密データが漏洩したり、悪意のある第三者によってデータが改変・削除されたりするリスクに晒されます。最悪の場合、Redisインスタンスが乗っ取られ、システム全体に被害が及ぶ可能性もあります。

インターネット上には、パスワード設定されていない、あるいはデフォルトパスワードのまま公開されているRedisインスタンスを探索するツールが存在します。このような無防備なインスタンスは、サイバー攻撃の格好の標的となります。実際に、設定ミスによりデータが公開され、身代金を要求されるといったインシデントも報告されています。

Redisのセキュリティ対策は、単に推奨される設定というだけでなく、本番環境でRedisを利用する上での必須事項です。その中でも、クライアントからの接続を許可する前に正当なユーザーであることを確認する「認証」は、セキュリティ対策の第一線に位置づけられます。

本記事では、Redisの認証機能であるAUTHコマンドを用いた基本的なパスワード認証から、Redis 6.0で導入されたより高度なACLs(Access Control Lists)によるユーザーベースのアクセス制御まで、Redisの認証メカニズムを徹底的に解説します。さらに、認証機能だけでは不十分な理由や、ネットワークセキュリティ、TLS/SSL、永続化ファイルの保護など、他のセキュリティ対策と認証を組み合わせる方法についても詳細に説明し、多層防御の観点からRedisをセキュアに運用するための知識を提供します。

Redisセキュリティの基本原則(認証以外の側面)

認証機能の詳細に入る前に、Redisのセキュリティ対策全体像の中で、認証がどのような位置づけにあるのかを理解するために、認証以外の基本的なセキュリティ対策についても触れておきます。これらは認証と並行して、あるいは認証の前提として考慮すべき重要な側面です。

  1. ネットワークセキュリティ: Redisインスタンスがインターネットに直接公開されるべきではありません。
    • bind ディレクティブ: Redisの設定ファイル(redis.conf)にあるbindディレクティブを使用して、RedisがリッスンするIPアドレスを制限します。アプリケーションサーバーや同じVPC内のプライベートIPアドレスにバインドすることで、外部からの直接接続を防ぎます。
      conf
      bind 127.0.0.1 # ローカルホストのみ
      bind 192.168.1.100 # 特定のローカルIPアドレス
      bind 127.0.0.1 192.168.1.100 # 複数のIPアドレス
      # bind ::1 fe80::1 # IPv6

      bind 0.0.0.0 は、すべてのインターフェースからの接続を許可するため、ファイアウォールなどでアクセス元を厳格に制限しない限り絶対に使用すべきではありません
    • ファイアウォール: サーバーレベル、あるいはクラウドプロバイダーのセキュリティグループ機能などを用いて、Redisが使用するポート(デフォルトは6379)へのアクセスを、信頼できる特定のIPアドレスやネットワークレンジからのみに制限します。これは最も基本的なネットワークセキュリティ対策です。
    • VPC/サブネット: Redisインスタンスを公開ネットワークから隔離されたプライベートネットワーク(VPCなど)内にデプロイします。アプリケーションサーバーも同じネットワーク内に配置し、外部からのアクセスはロードバランサーやAPIゲートウェイ経由でのみ許可するように設計します。
  2. 最小権限の原則: Redisを実行するOSユーザーは、必要最小限の権限を持つ専用のユーザーとするべきです。rootユーザーでの実行は避けてください。
  3. 永続化ファイルの保護: RedisはRDBファイルやAOFファイルにデータを永続化することがあります。これらのファイルには機密データが含まれる可能性があるため、OSレベルのファイルシステム権限設定により、Redisを実行しているユーザー以外は読み書きできないように保護する必要があります。ファイルが不用意にコピーされたり、第三者によってアクセスされたりするリスクを軽減します。
  4. ロギングと監視: Redisのログ設定を適切に行い、セキュリティ関連のイベント(認証失敗など)を記録します。これらのログを中央集権的なログ管理システムに集約し、異常がないか監視することで、潜在的なセキュリティインシデントを早期に検出できます。

これらの対策は、本記事の主題である「認証」と組み合わせて実施することで、より強固なセキュリティ層を構築します。ネットワークセキュリティは、そもそも不審な接続をRedisインスタンスに到達させないための「外堀」であり、認証は到達した接続に対して「誰がアクセス権を持つか」を確認する「門番」の役割を果たします。

Redisの基本的な認証機能(requirepass

Redisに最初に導入された認証機能は、設定ファイル(redis.conf)でパスワードを設定し、クライアントが接続後にAUTHコマンドでそのパスワードを送信することで認証を行うというシンプルなメカニズムです。これはrequirepassディレクティブによって有効化されます。

requirepassの設定

redis.confファイルを開き、requirepassディレクティブを探します。デフォルトではコメントアウトされているか、設定されていません。これを有効化し、強力なパスワードを設定します。

“`conf

デフォルトでは認証は無効です

requirepass foobared

認証を有効化し、強力なパスワードを設定します

requirepass YourSuperSecurePassword123!@#
“`

注意点: requirepassに設定するパスワードは、redis.confファイル内に平文で保存されます。これは、そのファイル自体が適切に保護されていない場合、パスワードが容易に漏洩するリスクがあることを意味します。このため、redis.confファイルへのアクセス権限は厳格に管理する必要があります。

設定変更後、Redisサーバーを再起動または設定ファイルをリロードして、設定を反映させます。

AUTHコマンドによる認証

requirepassが設定されたRedisインスタンスにクライアントが接続すると、認証が成功するまでほとんどのコマンドの実行が拒否されます。認証されていない状態でコマンドを実行しようとすると、通常は以下のようなエラーが返されます。

(error) NOAUTH Authentication required.

クライアントは、接続後にAUTH <password>コマンドを送信して認証を行います。

redis-cliでの例:

bash
$ redis-cli
127.0.0.1:6379> PING
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH YourSuperSecurePassword123!@#
OK
127.0.0.1:6379> PING
PONG

認証が成功すると、クライアントはその接続セッション中は自由にコマンドを実行できるようになります(もちろん、後述するACLsによってさらに制限されていない限り)。

アプリケーションからの利用:

多くのRedisクライアントライブラリは、接続時にパスワードを指定するオプションを提供しています。例えば、Pythonのredis-pyでは以下のように指定します。

“`python
import redis

r = redis.StrictRedis(host=’localhost’, port=6379, password=’YourSuperSecurePassword123!@#’)

try:
r.ping()
print(“Authenticated successfully!”)
# コマンド実行
r.set(‘mykey’, ‘myvalue’)
print(r.get(‘mykey’))
except redis.exceptions.AuthenticationError:
print(“Authentication failed!”)
except Exception as e:
print(f”An error occurred: {e}”)
“`

他の言語のライブラリでも同様の方法でパスワードを指定できます。重要なのは、アプリケーションコードの中にパスワードを直接ハードコーディングせず、環境変数、設定ファイル、あるいは専用のシークレット管理システム(HashiCorp Vault, AWS Secrets Manager, Kubernetes Secretsなど)から安全に取得して利用することです。

requirepassの利点と限界

利点:

  • 設定が非常にシンプル: パスワードを1つ設定するだけなので、実装が容易です。
  • 古いRedisバージョンでも利用可能: ACLsが導入される前のバージョンでも利用できる標準的な認証方法です。

限界:

  • 単一パスワード: すべてのクライアントが同じパスワードを使用する必要があります。これは、パスワードが漏洩した場合の影響範囲が広く、特定のユーザーやアプリケーションだけアクセス権を取り消すといった粒度の細かい制御ができません。
  • 権限管理ができない: requirepassは、認証が成功すればすべてのコマンドへのアクセスを許可します。読み取り専用ユーザー、管理者ユーザー、特定のキーパターンにのみアクセスできるユーザーなど、異なる権限を持つユーザーを作成することはできません。
  • パスワードの平文保存: redis.confファイルにパスワードが平文で保存されるのはセキュリティ上のリスクとなります。
  • パスワード漏洩時の対応が困難: すべてのクライアントのパスワードを一斉に変更する必要があり、システム全体への影響が大きくなります。

これらの限界があるため、特に複数のアプリケーションやユーザーが同じRedisインスタンスにアクセスする場合、あるいはきめ細かい権限制御が必要な場合には、requirepassによる認証だけでは不十分です。Redis 6.0以降で利用可能なACLsは、これらの課題を解決するために導入されました。

Redis ACLs(Access Control Lists)による高度な認証と認可

Redis 6.0で導入されたACLs(Access Control Lists)は、ユーザーベースの認証と、より柔軟なアクセス制御(認可)を提供します。requirepassの限界を克服し、セキュリティを大幅に強化できる機能です。

ACLsの基本概念

ACLsでは、「ユーザー」という概念が導入されます。各ユーザーには、パスワードまたはパスワードのハッシュ、そしてそのユーザーが実行できるコマンドやアクセスできるキーパターンなどを定義する「ルール」のセットが関連付けられます。

接続してきたクライアントは、ユーザー名とパスワード(またはハッシュ)を提示して認証を行います。認証が成功すると、そのクライアントは認証に使用したユーザーに関連付けられたルールに基づいて、どのコマンドを実行できるか、どのキーにアクセスできるかが決定されます。

ACLsの設定方法

ACLsは、主に以下の2つの方法で設定できます。

  1. redis.conf ファイルでの設定: Redisサーバー起動時に読み込まれる静的な設定方法です。設定変更にはRedisの再起動またはリロードが必要です。
  2. ACL コマンドでの設定: Redisが実行中に動的にユーザーを作成、変更、削除する方法です。コマンドによる変更はデフォルトでは永続化されないため、ACL SAVEコマンドでACL設定ファイルを明示的に保存する必要があります。

多くの場合、本番環境ではredis.confで基本的なユーザーを定義し、必要に応じて動的にACLコマンドを使用するというハイブリッドな運用が考えられます。ただし、redis.confでの管理はGitなどのバージョン管理システムとの連携が容易であり、設定の再現性が高いため推奨されることが多いです。

ACLsを有効にするには、redis.confでACLファイルを設定するか、直接ユーザーを定義します。

“`conf

ACL機能を有効化し、ACL定義を記載したファイルを指定します

aclfile /path/to/users.acl

もしくは、redis.conf内で直接ユーザーを定義します

user

例: デフォルトユーザーを無効化し、新しいユーザーを定義

requirepass は ACL 有効時は通常不要ですが、後方互換性や特定のシナリオで

使用されることがあります。ACL のみを使用する場合はコメントアウト推奨。

requirepass YourSuperSecurePassword123!@

default ユーザーの設定 (ACL 有効化時は default ユーザーが作成される)

default ユーザーは、ACL コマンドで認証されなかった接続に対するデフォルトの権限を定義します。

デフォルトでは認証なしで全権限となりますが、安全のため無効化または制限すべきです。

user default off

管理者ユーザーの定義

ユーザー名: admin

パスワード: 強力なパスワードのSHA-256ハッシュ (ACL SETUSER … > で生成)

権限: 全てのコマンド実行を許可 (@all カテゴリ)

user admin on >hashedpassword +@all

アプリケーション用ユーザーの定義 (読み書き可能だが、特定のキーパターンのみ)

ユーザー名: app_user

パスワード: 強力なパスワードのSHA-256ハッシュ

権限: “app_data:”で始まるキーに対する全てのコマンド実行を許可 (~app_data:* キーパターン)

さらに、一部の非データアクセス系コマンド (+PING, +INFO, +CLIENT) を許可

ただし、管理者コマンド (@admin) は禁止 (-@admin)

user app_user on >hashedpassword ~app_data:* +PING +INFO +CLIENT -@admin

読み取り専用キャッシュ用ユーザーの定義

ユーザー名: cache_reader

パスワード: 強力なパスワードのSHA-256ハッシュ

権限: “cache:”で始まるキーに対する読み取りコマンドのみ許可 (~cache:* キーパターン, @read カテゴリ)

user cache_reader on >hashedpassword ~cache:* +@read

ログ記録のみを行うユーザー (APPEND など特定のコマンドのみ許可)

ユーザー名: log_writer

パスワード: 強力なパスワードのSHA-256ハッシュ

権限: “logs:”で始まるキーに対するAPPENDコマンドのみ許可 (~logs:* キーパターン, +APPEND コマンド)

user log_writer on >hashedpassword ~logs:* +APPEND
“`

redis.conf でACLsを設定する場合、aclfile ディレクティブを使用すると、ACLsに関する設定を別のファイルに分離できます。これは、redis.confが肥大化するのを防ぎ、ACLsの設定だけをバージョン管理したい場合に便利です。

“`conf

redis.conf

… 他の設定 …

aclfile /etc/redis/users.acl

… 他の設定 …

“`

そして、/etc/redis/users.acl の中身は、redis.confuser ディレクティブの内容と同じ形式で記述します。

ACL設定を反映させるには、Redisサーバーを再起動または設定ファイルのリロードが必要です (redis-cli CONFIG REWRITEaclfile を使用している場合はACLファイルを更新 しない ことに注意してください。ACLコマンドによる変更は ACL SAVE で aclfile に保存されます)。

ACL コマンドによる管理

Redisが起動中に、ACL コマンドファミリーを使用してユーザーの管理や設定の確認を行えます。管理者ユーザーとして認証されたクライアントからこれらのコマンドを実行します。

  • ACL LIST: 定義されている全てのユーザーとそのルールを一覧表示します。
    redis
    admin> ACL LIST
    user admin on >hashedpassword ~* +@all
    user app_user on >hashedpassword ~app_data:* +PING +INFO +CLIENT -@admin
    user cache_reader on >hashedpassword ~cache:* +@read
    user log_writer on >hashedpassword ~logs:* +APPEND
    user default off allcommands allkeys
  • ACL USERS: 定義されているユーザー名のみを一覧表示します。
    redis
    admin> ACL USERS
    1) "admin"
    2) "app_user"
    3) "cache_reader"
    4) "log_writer"
    5) "default"
  • ACL CAT [category]: コマンドカテゴリとその関連コマンドを表示します。引数なしの場合は全てのカテゴリ、カテゴリ名を指定するとそのカテゴリに含まれるコマンドを表示します。
    “`redis
    admin> ACL CAT
    1) “admin”
    2) “connection”
    3) “deprecated”
    … (その他のカテゴリ)

    admin> ACL CAT read
    1) “bitcount”
    2) “get”
    3) “hgetall”
    … (読み取り関連コマンド)
    * **`ACL GETUSER <username>`:** 特定のユーザーの詳細な設定(状態、パスワードハッシュ、ルールなど)を表示します。redis
    admin> ACL GETUSER app_user
    1) “flags”
    2) 1) “on”
    2) “allkeys” # ~app_data: は ACL LIST では表示されるが GETUSER では allkeys に含まれることが多い
    3) “nopass” # >hashedpassword が設定されている場合は表示されない
    3) “passwords”
    4) 1) “” # ハッシュ化されたパスワードが表示される
    5) “commands”
    6) “+APPEND +CLIENT +INFO +PING +@read -@admin” # ACL LIST とは少し表示形式が異なる場合がある
    7) “keys”
    8) 1) “app_data:

    * **`ACL SETUSER <username> <rules ...>`:** ユーザーを作成または既存のユーザーの設定を変更します。redis

    新しいユーザーを作成

    admin> ACL SETUSER new_user on >securehash +@read ~public:*
    OK

    既存ユーザーの設定を変更 (パスワードのみ変更など)

    admin> ACL SETUSER app_user >newsecurehash
    OK
    * **`ACL DELUSER <username> [<username> ...]`:** 指定したユーザーを削除します。redis
    admin> ACL DELUSER new_user
    OK
    * **`ACL SAVE`:** ACLコマンドで行った設定変更を `aclfile` ディレクティブで指定されたファイルに永続化します。**このコマンドを実行しないと、Redis再起動時に設定が失われます。**redis
    admin> ACL SAVE
    OK
    * **`ACL LOAD`:** `aclfile` で指定されたファイルからACL設定を再読み込みします。動的に変更した設定をファイルの内容で上書きしたい場合などに使用します。redis
    admin> ACL LOAD
    OK
    * **`ACL DRYRUN <username> <command> [<arg> ...]`:** 特定のユーザーとして、指定されたコマンドを実行した場合に権限があるかどうかをシミュレーションします。デバッグに非常に役立ちます。redis
    admin> ACL DRYRUN cache_reader GET cache:item:123
    (integer) 1 # 権限がある
    admin> ACL DRYRUN cache_reader SET cache:item:123 new_value
    (integer) 0 # 権限がない
    admin> ACL DRYRUN cache_reader KEYS *
    (integer) 0 # 権限がない (~cache:* のみに制限されているため)
    “`

ACL ルールの詳細

ACLルールは非常に柔軟で、複数のルールを組み合わせてユーザーの権限を定義します。主なルールタイプは以下の通りです。

  • 認証:
    • :password: 平文のパスワードを指定します。非推奨です。
    • >hashedpassword: SHA-256でハッシュ化されたパスワードを指定します。ACLコマンドのACL SETUSER ... >で生成できます。例: >e04d1e43187999553b31d2f43c891997c7b8b7618108701d50d02c54c599d18c
    • !<hashedpassword>: SHA-256ハッシュですが、このユーザーはパスワード認証ではログインできません(特定のシナリオで使用されます)。
    • #<hash algorithm>:<hash>: 将来的に他のハッシュアルゴリズムがサポートされる可能性があります。
    • nopass: パスワード認証なしでログインできます。defaultユーザーを認証なしで許可する場合などに使用されますが、セキュリティ上のリスクが高いため、特定のネットワークからのみアクセスを許可する場合などに限定すべきです。
  • ユーザーの状態:
    • on: ユーザーを有効化します。
    • off: ユーザーを無効化します。このユーザー名では認証できません。
  • コマンド権限:
    • +<command>: 指定したコマンドの実行を許可します(例: +GET, +SET)。
    • -<command>: 指定したコマンドの実行を禁止します(例: -FLUSHALL, -KEYS)。
    • +@<category>: 指定したカテゴリに含まれる全てのコマンドの実行を許可します(例: +@read, +@write, +@admin)。
    • -@<category>: 指定したカテゴリに含まれる全てのコマンドの実行を禁止します。
    • +ALLCOMMANDS または +@all: 全てのコマンドの実行を許可します。
    • -ALLCOMMANDS または -@all: 全てのコマンドの実行を禁止します。
    • allcommands: +@all と同じです。
    • nocommands: -@all と同じです。
    • ルールは特定の順序で評価されるわけではなく、最終的に許可されているか禁止されているかで判断されます。一般的に、より具体的なルール(例: +SET)は、より一般的なルール(例: -@write)よりも優先される傾向がありますが、意図しない権限が付与されないように、許可したいコマンド/カテゴリを明示的に指定し、不要なコマンド/カテゴリを禁止する(特に -@admin-@dangerous)のが安全です。
  • キーへのアクセス権限:
    • ~<keypattern>: 指定したキーパターンにマッチするキーへのアクセスを許可します。複数のパターンを指定できます。ACLsが有効な場合、デフォルトではどのキーにもアクセスできません。アクセスしたいキーパターンを明示的に指定する必要があります。
      • ~*: 全てのキーへのアクセスを許可します。
      • ~users:{user_id}:*: 特定のユーザーに関連するキーパターン。
      • ~{tenant}:data:*: テナントごとにキーを分離している場合のパターン。
      • ~temp:?: temp:の後に1文字が続くキー(例: temp:a, temp:b)。
      • ~[0-9]*: 数字で始まるキー。
    • allkeys: ~* と同じです。
    • nokeyaccess: どのキーにもアクセスできません。

パスワードのハッシュ化:

ACL SETUSER <username> > コマンドを使用すると、安全なハッシュ化されたパスワードを生成できます。RedisはSHA-256を使用します。

“`redis
admin> ACL SETUSER myappuser > mysecretpassword123
OK # このコマンドはユーザーを作成/更新し、パスワードをハッシュ化して設定します

その後、このユーザーの情報を確認し、ハッシュを取得できます

admin> ACL GETUSER myappuser

4) 1) “d63d46f18f83f97d0e491247d558b4a9d9c4110e61d218a0d4f2430638593529” # これがハッシュ化されたパスワードです

``redis.conf`でユーザーを定義する際は、このハッシュ値を使用します。

conf
user myappuser on >d63d46f18f83f97d0e491247d558b4a9d9c4110e61d218a0d4f2430638593529 +@read +@write ~app:* -@admin

default ユーザーについて:

ACLsが有効化されると、defaultという名前の特殊なユーザーが自動的に作成されます。このユーザーは、ACL AUTHコマンドを使用せずに認証を試みたクライアント(つまり、AUTHコマンドでパスワードのみを提供した場合や、クライアントライブラリでユーザー名を指定せずにパスワードのみを指定した場合など)や、ACLsによって定義された他のどのユーザー名/パスワードの組み合わせでも認証に失敗した接続に対して適用されるデフォルトの権限を定義します。

デフォルトのdefaultユーザーは、通常、パスワードなしで全権限を持つ状態になっています。これは非常に危険なので、ACLsを有効にする際には、まずdefaultユーザーの権限をoffにするか、最小限の権限に制限することを強く推奨します。

“`conf

redis.conf または ACL SETUSER コマンドで設定

user default off # 認証なしの接続を全て拒否

または、認証なしの接続に限定的な読み取り権限のみを与える (非推奨)

user default on nopass +@read ~public_data:*

“`

ACLsの設計原則とベストプラクティス

ACLsのパワーを最大限に活用し、セキュアなRedis環境を構築するためには、以下の原則とベストプラクティスを考慮する必要があります。

  1. 最小権限の原則 (Principle of Least Privilege): 各ユーザーに対して、その役割を果たすために必要最小限の権限のみを与えます。不要なコマンド権限やキーアクセス権限は与えないようにします。例えば、キャッシュの読み取りしか行わないアプリケーションには+@readと適切な~keypatternのみを与え、+@write+@adminは与えません。
  2. ユーザーの分割: アプリケーションごと、サービスごと、あるいは機能ごとにユーザーを分割します。これにより、特定のユーザーの認証情報が漏洩した場合でも、被害範囲を限定できます。例えば、Webサイトのセッション管理用にはsession_user、ワーカープロセス用にはworker_userのようにユーザーを分けます。
  3. 強力なパスワードとハッシュ化: 各ユーザーには推測困難な強力なパスワードを設定し、必ずハッシュ化して保存・設定します。パスワードの定期的なローテーションも検討します。
  4. キー名の体系化: ACLsのキーパターン指定を活用するため、キー名の命名規則を体系的に定めます。例えば、{application_name}:{feature}:{id} のような形式でキー名を付けることで、~application_name:*~application_name:feature:* といったキーパターンで容易にアクセス制御できます。
  5. default ユーザーの無効化または制限: 前述の通り、default ユーザーは認証されていない接続に適用されるため、セキュリティ上のリスクを避けるために無効化 (off) するのが最も安全です。特定の信頼できるネットワークからの接続に対してのみ認証なしアクセスを許可する場合でも、最小限の権限に制限すべきです。
  6. 設定のバージョン管理: redis.confaclfile でACL設定を行う場合、これらの設定ファイルをGitなどのバージョン管理システムで管理し、変更履歴を追跡できるようにします。
  7. 定期的なレビューと監査: 定義されているユーザー、その権限、およびパスワードの強度を定期的にレビューし、現在のシステム構成やセキュリティポリシーと整合性が取れているか確認します。
  8. ACL DRYRUN を活用したテスト: 設定したACLルールが意図通りに機能するか、ACL DRYRUN コマンドを使用してシミュレーションテストを行います。これにより、設定ミスによるアクセス拒否や、逆に意図しないアクセス許可を防ぐことができます。
  9. ACL SAVE の徹底: ACLコマンドで設定を変更した場合は、必ず ACL SAVE コマンドを実行して設定を永続化することを忘れないでください。

ACL AUTH コマンド

ACLsを有効にしている場合、クライアントはAUTH <username> <password>コマンドを使用して認証を行います。

redis-cliでの例:

bash
$ redis-cli
127.0.0.1:6379> PING
(error) NOAUTH Authentication required.
127.0.0.1:6379> AUTH app_user mysecretpassword123 # ユーザー名とパスワードを指定
OK
127.0.0.1:6379> GET app_data:config
"..."
127.0.0.1:6379> FLUSHALL # 権限がないコマンドを試す
(error) NOPERM user has no permissions to run command
127.0.0.1:6379> GET cache:item:123 # 権限がないキーパターンへのアクセスを試す
(error) NOPERM user has no permissions to access keys matching pattern cache:item:123

ACLsでは、認証が成功しても、実行しようとしているコマンドやアクセスしようとしているキーパターンに対してユーザーが適切な権限を持っていない場合は、NOPERMエラーが返されます。

アプリケーションからの利用も同様に、クライアントライブラリでユーザー名とパスワードの両方を指定して接続します。

“`python
import redis

r = redis.StrictRedis(host=’localhost’, port=6379, username=’app_user’, password=’mysecretpassword123′)

try:
r.ping()
print(“Authenticated successfully!”)
# コマンド実行
print(r.get(‘app_data:config’))
r.set(‘app_data:counter’, 1)
print(r.get(‘app_data:counter’))

# 権限がない操作を試す (エラー発生を想定)
# r.flushall()
# r.get('some_other_key')

except redis.exceptions.AuthenticationError:
print(“Authentication failed!”)
except redis.exceptions.ResponseError as e:
# ACLsによる権限エラーは ResponseError として捕捉されることが多い
print(f”Permission denied: {e}”)
except Exception as e:
print(f”An error occurred: {e}”)
“`

ACLsを使用することで、アプリケーションごとに異なるユーザーを作成し、それぞれのユーザーに必要な最小限の権限のみを与えることが可能になり、セキュリティレベルが大幅に向上します。

認証と他のセキュリティ対策の組み合わせ

Redisの認証機能(requirepassやACLs)は非常に重要ですが、これだけでセキュリティが万全になるわけではありません。前述のネットワークセキュリティを含め、他のセキュリティ対策と組み合わせて多層防御を構築することが不可欠です。

認証 + ネットワークセキュリティ (Firewall, bind)

これは最も基本的な組み合わせです。ファイアウォールやbind設定によって、信頼できるホストからのみRedisポートへの接続を許可し、さらに接続してきたクライアントに対して認証を要求します。

  • 利点: 不正なアクセス試行の多くをネットワークレベルでブロックできるため、認証レイヤーへの負荷を軽減し、公開される攻撃対象領域を減らせます。
  • 考慮事項: 信頼できるネットワーク内のクライアントが侵害された場合、そのクライアントになりすましてRedisにアクセスされるリスクは残ります。

認証 + TLS/SSL 暗号化

デフォルトでは、Redisクライアントとサーバー間の通信は暗号化されていません。これは、中間者攻撃(Man-in-the-Middle attack)によって、認証情報(パスワードやユーザー名)ややり取りされるデータが盗聴・改ざんされるリスクがあることを意味します。

特に、ネットワーク境界を越えてRedisにアクセスする場合(例えば、異なるサブネット間やインターネット経由でVPN接続する場合など)は、TLS/SSLによる通信暗号化が強く推奨されます。

Redisは、バージョン6.0からネイティブでTLS/SSLをサポートしています。redis.confで以下の設定を行います。

“`conf

TLS ポートを有効化 (通常のポートとは別に設定することも、置き換えることも可能)

tls-port 6379 # または別のポート番号

サーバー証明書ファイルと秘密鍵ファイルを指定

tls-cert-file /path/to/redis.crt
tls-key-file /path/to/redis.key

クライアント認証 (Mutual TLS) を有効にする場合は、CA 証明書を指定

tls-ca-cert-file /path/to/ca.crt

tls-auth-clients yes # クライアントは有効な証明書を提示する必要がある

通常の非TLSポートを無効にする場合はコメントアウト

port 0

“`

TLS/SSLを有効にすると、クライアントはTLS接続でRedisに接続する必要があります。認証(AUTH/ACL)は、TLSハンドシェイクが完了したに行われます。これにより、認証情報を含む全ての通信内容が暗号化され、盗聴のリスクが排除されます。

Mutual TLS (tls-auth-clients yes) を有効にすると、Redisサーバーはクライアントに対しても証明書を提示することを要求し、その証明書が信頼できるCAによって署名されていることを検証します。これにより、証明書ベースの認証レイヤーが追加されます。ただし、これはRedisのユーザー/パスワード認証を置き換えるものではなく、クライアントの身元確認として機能します。一般的には、ACLsによるユーザー認証と組み合わせて使用し、誰がどの権限でアクセスするかはACLsで制御します。

認証 + OSレベルの権限 + 永続化ファイルの保護

認証やネットワーク対策はオンラインの状態でのアクセス制御に焦点を当てていますが、Redisサーバーが停止している場合や、RDB/AOFファイルがシステム上に存在する場合のセキュリティも考慮する必要があります。

  • Redisプロセスを必要最小限の権限を持つ専用のOSユーザーで実行します。
  • RDBファイルおよびAOFファイルが保存されるディレクトリとファイルに対して、Redisを実行しているOSユーザーのみが読み書きできるようなファイルシステム権限(chmod, chown)を設定します。これにより、たとえOSにログインしたとしても、権限のないユーザーがこれらの機密データを含むファイルを読み取ったり、改ざんしたりするのを防ぎます。

認証 + ログ監視

認証失敗のログを監視することは、ブルートフォース攻撃や認証情報の推測試行を検出するために非常に重要です。

redis.conflogfileディレクティブを設定し、ログファイルを指定します。Redisは認証の成功/失敗や、ACLsによる権限エラーなどをログに記録します。

conf
logfile "/var/log/redis/redis-server.log"
loglevel verbose # 認証関連のイベントは verbose 以上で記録されることが多い

これらのログを、Syslog、Logstash/Elasticsearch、Splunk、CloudWatch Logsなどの集中型ログ管理システムに転送し、リアルタイムで監視およびアラートを設定します。特定のIPアドレスからの認証失敗が短時間に大量に発生した場合や、存在しないユーザー名での認証試行が頻繁に発生した場合などにアラートを出すことで、攻撃の兆候を早期に発見できます。

認証情報の安全な管理

Redisの認証機能を有効にする上で、最も重要かつ困難な課題の一つが、認証情報(パスワード、ユーザー名)の安全な管理です。

  • ハードコーディングの禁止: アプリケーションのソースコード、設定ファイル(Gitなどで管理される可能性のあるもの)、スクリプトなどに認証情報をハードコーディングすることは絶対に避けてください。これは認証情報の漏洩リスクを劇的に高めます。
  • 環境変数の利用: アプリケーション起動時に環境変数として認証情報を渡す方法は、ハードコーディングよりは安全ですが、サーバーにログインできるユーザーからは容易に読み取られてしまいます。
  • 設定ファイルの利用(限定的): アプリケーション専用の設定ファイルに認証情報を記載し、そのファイルへのアクセス権限を厳格に制限する方法もあります。ただし、このファイルもシステム上に配置されるためリスクはゼロではありません。
  • シークレット管理システムの利用: 最も推奨される方法は、HashiCorp Vault、AWS Secrets Manager、Azure Key Vault、Google Secret Manager、Kubernetes Secretsなどの専用シークレット管理システムを利用することです。これらのシステムは認証情報を暗号化して安全に保管し、認証・認可されたアプリケーションやユーザーのみが必要な認証情報を取得できる仕組みを提供します。アプリケーションは起動時にシークレット管理システムにアクセスして認証情報を取得し、それを使用してRedisに接続します。これにより、認証情報がファイルシステム上やコード内に平文で存在することを避けることができます。

特に、コンテナ化された環境やクラウド環境では、シークレット管理システムとの連携が容易であり、推奨されるベストプラクティスです。

レプリケーション、Sentinel、Cluster環境での認証

Redisの認証機能は、レプリケーション、Sentinel、Clusterといった構成でも正しく機能するように設定する必要があります。

レプリケーション (Master-Replica)

マスターにrequirepassまたはACLsが設定されている場合、レプリカがマスターに接続して同期を行う際にも認証が必要です。

  • requirepass: レプリカのredis.confmasterauthディレクティブを設定し、マスターのパスワードを指定します。
    conf
    # replica の redis.conf
    masterauth YourSuperSecurePassword123!@#
  • ACLs: レプリカのredis.confmasterusermasterauthディレクティブを設定し、マスターへの接続に使用するACLユーザーのユーザー名とパスワード(ハッシュ化されていないもの)を指定します。
    conf
    # replica の redis.conf
    masteruser replica_user
    masterauth repl_password # パスワードのハッシュではなく、元のパスワードを指定

    マスター側では、レプリケーション専用のACLユーザーを作成し、レプリケーションに必要な権限(例えば、+@replication カテゴリや特定のコマンド)と、レプリカのIPアドレスからの接続を許可するルールを設定することが望ましいです。

Sentinel

SentinelはRedisインスタンスの状態を監視し、フェイルオーバーを調整するシステムです。監視対象のRedisインスタンスに認証が設定されている場合、Sentinelも認証情報を使用してRedisに接続する必要があります。

  • requirepass: Sentinelの設定ファイル(sentinel.conf)で、監視対象のマスター名に対してsentinel auth-pass <master-name> <password>を設定します。
    conf
    # sentinel.conf
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel auth-pass mymaster YourSuperSecurePassword123!@#
  • ACLs: SentinelはRedis 6.2以降でACLsをサポートしています。sentinel.confsentinel auth-user <master-name> <username> <password>を設定します。
    conf
    # sentinel.conf
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel auth-user mymaster sentinel_user sentinel_password

    Redisインスタンス側では、Sentinel専用のACLユーザーを作成し、監視に必要なコマンド(例: +PING, +INFO, +CLIENT, +CLUSTER(Clusterの場合), +REPLCONF(レプリケーション状態確認))およびフェイルオーバーに必要なコマンド(例: +SLAVEOF / +REPLICAOF, +CLIENT KILL, +CONFIG)の権限を与えます。

Cluster

Redis Cluster環境でも、各ノード間での認証が必要です。ACLsを使用する場合、Clusterノード間の通信はdefaultユーザーの権限に依存します。ノード間通信には特定のコマンドが必要なため、defaultユーザーにそれらのコマンド実行権限がないとClusterが正常に動作しません。

または、Clusterノード間の通信用に専用のパスワードを設定することも可能です。

“`conf

redis.conf (Clusterノード用)

cluster-announce-ip # 外部からアクセス可能なIPを設定する場合

cluster-announce-port # 外部からアクセス可能なポートを設定する場合

cluster-announce-bus-port # 外部からアクセス可能なクラスタバスポートを設定する場合

cluster-require-pass ClusterBusPassword # ノード間通信用のパスワード
cluster-config-file nodes.conf # ノード情報ファイル

クライアント認証用の ACL または requirepass は別途設定

user admin on >hashedpassword +@all
user app_user on >hashedpassword ~app:* +@read +@write -@admin
“`

クライアントがClusterに接続する際は、通常のAUTHまたはACL AUTHを使用します。Clusterノード間の通信は、cluster-require-passで設定されたパスワードを使用します。Redis 6.0以降でACLsを使用している場合、defaultユーザーに+@clusterカテゴリなどの権限を与えることで、ノード間通信を許可するのが一般的な方法です。

よくある認証/ACLに関するトラブルシューティング

認証やACLsを設定する際に発生しがちな問題と、その解決策をいくつか挙げます。

  1. NOAUTH Authentication required. エラー:
    • 原因: RedisサーバーにrequirepassまたはACLsが設定されているにも関わらず、クライアントが認証コマンド(AUTHまたはACL AUTH)を送信していないか、パスワードが間違っている。または、ACLsでdefaultユーザーがoffになっており、認証なしで接続しようとしている。
    • 解決策: クライアント(redis-cliやアプリケーション)が正しいパスワード(ACLsの場合はユーザー名とパスワード)を指定して認証を実行しているか確認します。redis-cliで手動でAUTHコマンドを実行してテストできます。
  2. NOPERM user has no permissions to run command または NOPERM user has no permissions to access keys matching pattern ... エラー:
    • 原因: クライアントは認証には成功したが、認証に使用したユーザーに、実行しようとしているコマンドやアクセスしようとしているキーパターンに対する権限がACLsで許可されていない。
    • 解決策: ACL GETUSER <username>コマンドを実行して、そのユーザーに定義されているルールを確認します。実行したいコマンドやキーパターンに対する+<command>, +@<category>, ~<keypattern> ルールが正しく設定されているか確認します。必要に応じてACL SETUSERでルールを変更し、ACL SAVEで保存します。ACL DRYRUNコマンドで権限をシミュレーションするとデバッグが容易です。
  3. ACL設定がRedis再起動後に失われる:
    • 原因: ACLコマンド(ACL SETUSER, ACL DELUSERなど)で設定を変更したが、ACL SAVEコマンドを実行しなかった。
    • 解決策: 設定変更後、必ずACL SAVEコマンドを実行して、aclfileで指定されたファイル(または指定されていない場合のデフォルトファイル)に設定を永続化します。
  4. redis.confで設定したACLユーザーが反映されない:
    • 原因: redis.confの変更を反映するためにRedisサーバーを再起動または設定ファイルのリロードをしていない。または、aclfileディレクティブとredis.conf内でのuser定義が混在しており、意図しない設定が適用されている。
    • 解決策: Redisサーバーを正しく再起動または設定ファイルのリロードを行います。aclfileを使用している場合は、ACL設定はaclfileにのみ記述し、redis.conf内ではaclfileディレクティブのみを設定するようにします。ACL LOADコマンドでaclfileの内容を明示的に読み込むこともできます。
  5. レプリカ/Sentinel/Clusterがマスターに接続できない:
    • 原因: マスターに設定された認証情報(requirepassまたはACLsユーザー/パスワード)が、レプリカのmasterauth/masteruser、Sentinelのsentinel auth-pass/sentinel auth-user、またはClusterのcluster-require-passと一致していない。
    • 解決策: 各設定ファイルで指定されている認証情報がマスター側の設定と正確に一致しているか確認します。ACLsを使用している場合は、レプリケーションやSentinel監視に必要な権限がマスター側のACLsで許可されているか確認します。

まとめ:多層防御による強固なRedisセキュリティ

Redisのセキュリティ強化において、認証機能(AUTHとACLs)は最も重要な要素の一つです。しかし、それ単独で完全なセキュリティを保証するものではありません。本記事で詳細に説明したように、以下の要素を組み合わせて多層防御を構築することが不可欠です。

  1. ネットワークセキュリティ: bind設定、ファイアウォール、VPCなどを用いて、信頼できるネットワークからのアクセスのみを許可し、攻撃対象領域を最小限に抑えます。
  2. 認証と認可 (AUTH / ACLs):
    • 最低限、requirepassによるパスワード認証を有効化します(非推奨、ACLsへの移行を強く推奨)。
    • 可能であれば、Redis 6.0以降のACLsを使用して、ユーザーベースの認証と最小権限の原則に基づいたきめ細かいアクセス制御(コマンド、キーパターン単位での認可)を実装します。
    • defaultユーザーは無効化または厳格に制限します。
    • ユーザーごとに強力で推測困難なパスワードを使用し、ハッシュ化して保存します。
  3. 通信の暗号化 (TLS/SSL): Redis 6.0以降のネイティブTLSサポートを利用し、クライアントとサーバー間の通信内容が盗聴・改ざんされるのを防ぎます。特にネットワーク境界を越える通信には必須です。
  4. OSレベルのセキュリティ: Redisプロセスを専用の非rootユーザーで実行し、永続化ファイル(RDB/AOF)へのアクセス権限を適切に設定します。
  5. 認証情報の安全な管理: アプリケーションコードや設定ファイルに認証情報をハードコーディングせず、環境変数やシークレット管理システムを利用して安全に管理します。
  6. ロギングと監視: Redisのログ設定を適切に行い、セキュリティ関連のイベントを監視することで、不正アクセスや攻撃の兆候を早期に検出します。

これらの対策を組み合わせることで、Redisインスタンスを様々な脅威から保護し、保存されている機密データの安全性を確保することができます。特に、現代の複雑なアプリケーション環境では、ACLsによるユーザーベースのきめ細かい権限制御が不可欠です。

Redisのセキュリティは、一度設定すれば終わりではなく、システムの変更、アプリケーションの追加、ユーザーの増減などに応じて定期的に見直し、必要に応じてACLsなどの設定を更新していく継続的なプロセスです。常に最新のセキュリティ情報に注意を払い、セキュアな運用を心がけましょう。


コメントする

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

上部へスクロール