*ACL

アクセス制御リストの略である Redis ACL は、実行可能なコマンドとアクセスできるキーに関して特定の接続を制限できるようにする機能です。これが機能する方法は、接続後、クライアントはユーザ名と有効なパスワードを提供して認証する必要があるということです: 認証の段階が成功した場合、接続は特定のユーザとそのユーザの制限に関連付けられます。Redis は、新しい接続が "デフォルト" のユーザですでに認証されるように構成できます (これがデフォルト構成です)。したがって、defaultユーザを構成すると、副作用として、特定の機能のサブセットのみを明示的に認証されていない接続に提供することができます。

デフォルトの構成では、Redis 6 (ACL を持つ最初のバージョン) は古いバージョンの Redis と全く同じように機能します。つまり、全ての新しい接続は全ての可能なコマンドを呼び出し、全てのキーにアクセスできるため、ACL 機能は古いクライアントとアプリケーションと下位互換性があります。また、requirepass 構成ディレクティブを使ってパスワードを構成する古い方法は、引き続き期待通り機能しますが、現在はデフォルトユーザのパスワードを設定するだけです。

Redis の AUTH コマンドは Redis 6 で拡張されたため、2つの引数の形式で使えるようになりました:

AUTH <username> <password>

古い形式に従って使われる場合、つまり:

AUTH <password>

認証に使われるユーザ名は "default" であるため、パスワードを指定するだけで、defaultユーザに対して認証する必要があります。これにより、過去との完全な後方互換性が提供されます。

*ACL が役立つ時

ACL を使う前に、この保護層を実装することで達成したい目標を自問することをお勧めします。通常、ACL によって提供される2つの主な目標があります。

  1. コマンドとキーへのアクセスを制限してセキュリティを向上させ、信頼できないクライアントにはアクセス権が無く、信頼できるクラインとには必要な作業を実行するためのデータベースへの最小限のアクセスレベルしか持たないようにします。例えば、あるクライアントは読み取り専用コマンドだけを実行できるかもしれません。
  2. ソフトウェアエラーや手動のミスのために、Redis にアクセスするプロセスや人間がデータや構成を損傷できないように、運用上の安全性を向上させたいと考えています。例えば、Redis から遅延ジョブをフェッチするワーカーが、FLUSHALL コマンドを呼び出すことができるようにする理由はありません。

ACL のもう1つの一般的な使用法は、マネージド Redis インスタンスに関連しています。Redis は、他の社内顧客の Redis インフラストラクチャを処理する社内チームによってマネージドサービスとして提供されるか、クラウドプロバイダによる software-as-a-service のセットアップで、しばしば提供されます。このようなセットアップの両方で、構成コマンドが顧客から除外されていることを確認する必要があります。これを行う方法は、過去にはコマンドの名前変更で、長い間 ACL 無しで生き残ることが可能なトリックでしたが、理想的ではありません。

*ACL コマンドを使った ACL の設定

ACL は、指定されたユーザが実行できることとできないことを記述する DSL (domain specific language) を使って定義されます。このようなルールは、ユーザが実際に何ができるかを理解するためにルールの順序が重要な場合があるため、常に最初から最後まで、左から右へ実装されます。

デフォルトでは、default と呼ばれる1つのユーザが定義されています。ACL LIST コマンドを使って、現在アクティブな ACL をチェックし、新しく開始されたデフォルト構成の Redis インスタンスの設定を検証します:

> ACL LIST
1) "user default on nopass ~* +@all"

上記のコマンドは、ユーザに設定されている現在の ACL を description に戻すことにより、Redis 構成ファイルで使われているものと同じ形式でユーザのリストを報告します。

各行の最初の2つの単語は、"user" とそれに続くユーザ名です。次の単語は、様々なことを説明する ACL ルールです。ルールがどのように機能するかを詳しく示しますが、今のところ、defaultユーザはアクティブ (on)、パスワード不要 (nopass)、全ての可能なキー (~*)、可能な全てのコマンド (+@all) を呼び出すことができます。

また、defaultユーザの特殊なケースでは、nopass ルールがあるということは、明示的な AUTH 呼び出しを必要とせずに、新しい接続がでデフォルトのユーザで自動的に認証されることを意味します。

*ACL ルール

以下は有効な ACL ルールのリストです。あるルールは、フラグをアクティブ化または削除するため、またはユーザ ACL に指定した変更を実行するために使われる単一の単語です。別のルールは、コマンド名あるいはカテゴリ名、またはキーパーターンなどと連結された char プリフィックスです。

ユーザを有効、禁止にします:

  • on: ユーザを有効にします: 個のユーザとして認証できます。
  • off: ユーザを無効にします: このユーザで認証することができなくなります。ただし、すでに認証されている接続は引き続き動作します。デフォルトのユーザに off のフラグが立てられている場合、新しい接続は認証されずに開始され、デフォルトのユーザ構成に関係なく何らかの方法で認証するためにユーザは AUTH オプションを指定して AUTH または HELLO を送信する必要があります。

コマンドの許可と禁止

  • +<command>: ユーザが呼び出すことができるコマンドのリストにコマンドを追加します。
  • -<command>: ユーザが呼び出すことのできるコマンドのリストからコマンドを削除します。
  • +@<category>: ユーザによって呼ばれるカテゴリの全てのコマンドを追加します。有効なカテゴリは @admin、@set、@sortedset ... などです。ACL CAT コマンドを呼び出すと完全なリストが表示されます。特別なカテゴリ @all は、現在サーバに存在するコマンドと、モジュールを介して将来ロードされるコマンドの両方を含む全てのコマンドを意味します。
  • -@<category>: +@<category> と似ていますが、クライアントが呼び出すことができるコマンドのリストからこのコマンドを削除します。
  • +<command>|subcommand: それ以外の場合は無効になっているコマンドの特定のサブコマンドを許可します。この形式は、-DEBUG|SEGFAULT のように負の形式では許可されておらず、"+" で始まる加算のみが許可されていることに注意してください。この ACL は、コマンドが既に全体としてアクティブになっている場合に、エラーを引き起こします。
  • allcommands: +@all のエイリアス。これは、モジュールシステムを介して将来ロードされる全てのコマンドを実行する機能を意味することに注意してください。
  • nocommands: -@all のエイリアス。

特定のキーを許可および禁止します:

  • ~<pattern>: コマンドの一部として言及できるキーのパターンを追加します。例えば、~* は全てのキーを許可します。パターンは、KEYS のような glob 形式のパターンです。複数のパターンを指定することができます。
  • allkeys: ~* のエイリアス。
  • resetkeys: 許可されたキーパターンのリストをフラッシュします。例えば、ACL ~foo:* ~bar:* resetkeys ~objects:* は、クライアントがパターンobjects:* に一致するキーのみアクセスできることになります。

ユーザの有効なパスワードを構成します:

  • ><password>: このパスワードを、ユーザの有効なパスワードのリストに追加します。例えば、>mypass は "mypass" を有効なパスワードに追加します。このディレクティブは nopass フラグ (後述) をクリアします。全てのユーザは、任意の数のパスワードを持つことができます。
  • <<password>: このパスワードを有効なパスワードから削除します。削除しようとしているパスワードが実際には設定されていない場合、エラーが発生します。
  • #<hash>: この SHA-256 ハッシュ値をユーザの有効なパスワードのリストに追加します。このハッシュ値は ACL ユーザ用に入力されたパスワードのハッシュと比較されます。これにより、ユーザはクリアテキストのパスワードを保存するのではなく、ハッシュを acl.conf ファイルに保存できます。パスワードハッシュは 64 文字で、小文字の16進文字のみを含む必要があるため、SHA-256 ハッシュ値だけだが受け入れられます。
  • !<hash>: このハッシュ値を有効なパスワードのリストから削除します。ハッシュ値で指定されたパスワードが分からないが、ユーザからパスワードを削除したい場合に便利です。
  • nopass: ユーザに設定された全てのパスワードが削除され、ユーザはパスワードを必要としないというフラグが立てられます: これは全てのパスワードがこのユーザに対して機能することを意味します。このディレクティブがdefaultユーザに使われる場合、全ての新しい接続は明示的な AUTH コマンドを必要とせずにデフォルトのユーザですぐに認証されます。resetpass ディレクティブはこの状態をクリアすることに注意してください。
  • resetpass: 許可されたパスワードのリストをフラッシュします。さらに、nopass 状態を削除します。resetpass の後、ユーザにはパスワードが関連付けられておらず、パスワードを追加せずに (あるいは後で nopass として設定せずに)、認証する方法はありません。

注意: nopass のフラグが付けられておらず、有効なパスワードのリストが無い使い方は、そのようなユーザとしてログインする方法が無いため、事実上使えません。

ユーザをリセットします:

  • reset は以下のアクションを実行します: resetpass、resetkeys、off、-@all。ユーザは作成直後と同じ状態に戻ります。

*ACL SETUSER コマンドを使ってユーザ ACL の作成と編集

ユーザは、主に2つの方法で作成および変更できます:

  1. ACL コマンドと ACL SETUSER サブコマンドの使用
  2. ユーザを定義できるサーバ構成を変更してサーバを再起動するか、外部 ACL ファイルを使っている場合は、ACL LOAD を発行するだけです。

このセクションでは、ACL コマンドを使ってユーザを定義する方法を学びます。このような知識を使うと、構成ファイルを介して同じことを行うのは簡単です。構成でユーザを定義することは独自のセクションに値するものであり、後で個別に説明します。

始めに、最も単純な ACL SETUSER コマンド呼び出しを試してみましょう:

> ACL SETUSER alice
OK

SETUSER コマンドはユーザ名とユーザに適用する ACL ルールのリストを取ります。ただし、上記の例では、ルールを全く指定しませんでした。ユーザが存在しない場合は、作成するユーザのデフォルトの属性を使って単にユーザを作成します。ユーザが既に存在する場合、上記のコマンドは何もしません。

デフォルトのユーザステータスを確認してみましょう:

> ACL LIST
1) "user alice off -@all"
2) "user default on nopass ~* +@all"

作成したばかりのユーザ "alice" は以下の通りです:

  • オフ状態、つまり、無効になっています。AUTH は機能しません。
  • どのコマンドにもアクセスできません。ユーザはデフォルトでコマンドにアクセスできないように作成されるため、上記の出力の -@all は省略できますが、ACL LIST は暗黙的では無く明示的にしようとします。
  • 最後にユーザがアクセスできるキーパターンはありません。
  • また、ユーザはパスワードが設定されていません。

そのようなユーザは完全に役に立ちません。ユーザがアクティブで、パスワードがあり、文字列 "cached:" で始まるキー名に GET コマンドのみでアクセスできるようにユーザを定義してみましょう。

> ACL SETUSER alice on >p1pp0 ~cached:* +get
OK

これで、ユーザは何かを行うことができますが、他の事を行うことを拒否します:

> AUTH alice p1pp0
OK
> GET foo
(error) NOPERM this user has no permissions to access one of the keys used as arguments
> GET cached:1234
(nil)
> SET cached:1234 zap
(error) NOPERM this user has no permissions to run the 'set' command or its subcommand

物事が期待通りに動作します。ユーザ alice (ユーザ名は大文字と小文字が区別されることを思い出してください) の構成を検査するために、コンピュータが読み取るのにより適するように設計された ACL LIST の代替手段を使えますが、ACL LIST はより人間に偏っています。

> ACL GETUSER alice
1) "flags"
2) 1) "on"
3) "passwords"
4) 1) "2d9c75..."
5) "commands"
6) "-@all +get"
7) "keys"
8) 1) "cached:*"

ACL GETUSER は、より解析可能な用語でユーザを説明するフィールド値配列を返します。出力にはフラグのセット、キーパターンのリスト、パスワードなどが含まれます。RESP3 を使うと、出力はおそらく読みやすくなりますので、マップ応答として返されます:

> ACL GETUSER alice
1# "flags" => 1~ "on"
2# "passwords" => 1) "2d9c75..."
3# "commands" => "-@all +get"
4# "keys" => 1) "cached:*"

注意: コミュニティが新しいプロトコルに切り替えるには時間が掛かるため、今後も Redis のデフォルトプロトコルであるバージョン 2 を使い続けます。

別の ACL SETUSER コマンドを使って (alice は ACL コマンドを使えないので、別のユーザから)、複数のパターンをユーザに追加できます:

> ACL SETUSER alice ~objects:* ~items:* ~public:*
OK
> ACL LIST
1) "user alice on >2d9c75... ~cached:* ~objects:* ~items:* ~public:* -@all +get"
2) "user default on nopass ~* +@all"

メモリ内のユーザ表現は、期待したものになります。

*ACL SETUSER を複数回呼び出すとどうなりますか

ACL SETUSER が複数回呼び出された時に何が起こるかを理解することは非常に重要です。全ての SETUSER 呼び出しはユーザをリセットするのではなく、ACLルールを既存のユーザに適用するだけということを知ることは重要です。ユーザは未知の場合のみリセットされます: その場合、新しいユーザはゼロ ACL で作成されます。つまり、ユーザは何もできず、パスワードを持たないなどです: 安全のためにはこれが最良のデフォルトです。

ただし、後の呼び出しではユーザが段階的に変更されるため、例えば以下のシーケンスになります:

> ACL SETUSER myuser +set
OK
> ACL SETUSER myuser +get
OK

myuser は GETSET の両方を呼び出すことができるようになります:

> ACL LIST
1) "user default on nopass ~* +@all"
2) "user myuser off -@all +set +get"

*コマンドカテゴリで遊ぶ

全てのコマンドを次々に指定してユーザの ACL を設定するのは非常に面倒なので、代わりに以下のようにします:

> ACL SETUSER antirez on +@all -@dangerous >42a979... ~*

+@all と -@dangerous とすることで、全てのコマンドを含め、後で Redis コマンドテーブル内で危険とタグ付けされた全てのコマンドを削除しました。コマンドカテゴリは +@all を除いてモジュールコマンドを含まないことに注意してください。+@all とすると、モジュールシステムを介してロードされる将来のコマンドも含め、全てのコマンドをユーザが実行できます。ただし、ACL rule +@read またはその他を使う場合、モジュールコマンドは常に除外されます。健全さのために Redis の内部コマンドを信頼する必要があるため、これは非常に重要です。モジュールが危険なものを公開する可能性があり、ACL が単なる付加的なものである場合、+@all -... の形式である場合は、意図していないものを決して含めないようにする必要があります。

However to remember that categories are defined, and what commands each category exactly includes, is impossible and would be super boring, so the Redis ACL command exports the CAT subcommand that can be used in two forms:

ACL CAT -- 利用可能な全てのカテゴリを一覧表示します
ACL CAT <category-name> -- カテゴリ内の全てのコマンドを一覧表示します

例:

 > ACL CAT
 1) "keyspace"
 2) "read"
 3) "write"
 4) "set"
 5) "sortedset"
 6) "list"
 7) "hash"
 8) "string"
 9) "bitmap"
10) "hyperloglog"
11) "geo"
12) "stream"
13) "pubsub"
14) "admin"
15) "fast"
16) "slow"
17) "blocking"
18) "dangerous"
19) "connection"
20) "transaction"
21) "scripting"

ご覧のとおり今のところ 21 の異なるカテゴリがあります。次に、geo カテゴリの一部であるコマンドを確認しましょう:

> ACL CAT geo
1) "geohash"
2) "georadius_ro"
3) "georadiusbymember"
4) "geopos"
5) "geoadd"
6) "georadiusbymember_ro"
7) "geodist"
8) "georadius"

コマンドは複数のカテゴリの一部である場合があるため、例えば +@geo -@read のような ACL ルールは、特定の geo コマンドは読み取り専用コマンドであるため、除外されることに注意してください。

*サブコマンドの追加

コマンド全体を除外または含める機能では十分ではないことがあります。多くの Redis コマンドは引数として渡されるサブコマンドに基づいて複数の事を実行します。例えば、CLIENT コマンドは危険な操作と危険ではない操作をするために使えます。Many deployments may not be happy to provide the ability to execute CLIENT KILL to non admin-level users, but may still want them to be able to run CLIENT SETNAME.

注意: 新しい RESP3 HELLO コマンドはおそらくすぐに SETNAME オプションを提供しますが、これはとにかく良い例です。

このような場合、以下の方法でユーザの ACL を変更できます:

ACL SETUSER myuser -client +client|setname +client|getname

CLIENT コマンドの削除を開始し、後で2つの許可されたサブコマンドを追加しました。逆を行うことはできないことに注意してください。サブコマンドは追加のみが可能であり、除外することはできません。詳細新しいサブコマンドが追加される可能性があるためです: 一部のユーザに有効な全てのサブコマンドを指定する方がはるかに安全です。さらに、まだ無効になっていないコマンドに関するサブコマンドを追加すると、これは ACL ルールのバグにすぎない可能性があるため、エラーが生成されます。

> ACL SETUSER default +debug|segfault
(error) ERR Error in ACL SETUSER modifier '+debug|segfault': Adding a
subcommand of a command already fully added is not allowed. Remove the
command to start. Example: -DEBUG +DEBUG|DIGEST

サブコマンドのマッチングによってパフォーマンスが低下する可能性があることに注意してください。ただし、このような低下は、総合的なベンチマークを使っても測定が難しく、追加の CPU のコストはそのようなコマンドが呼ばれた時にのみ支払われ、他のコマンドが呼ばれた時には支払われません。

*+@all VS -@all

前のセクションでは、単一のコマンドの追加/削除に基づいてコマンド ACL を定義する方法を説明しました。

*パスワードが内部で保存される方法

Redis は、SHA256 ではハッシュ化されたパスワードを内部に保存します。パスワードを設定し、ACL LIST または GETUSER の出力を確認すると、疑似ランダムに見える16進文字列が表示されます。Here is an example, because in the previous examples, for the sake of brevity, the long hex string was trimmed:

> ACL GETUSER default
1) "flags"
2) 1) "on"
   2) "allkeys"
   3) "allcommands"
3) "passwords"
4) 1) "2d9c75273d72b32df726fb545c8a4edc719f0a95a6fd993950b10c474ad9c927"
5) "commands"
6) "+@all"
7) "keys"
8) 1) "*"

また、古いコマンド CONFIG GET requirepass は、Redis 6 以降、クリアテキストのパスワードではなく、ハッシュ化されたパスワードを返します。

SHA256 を使うと、パスワードをクリアテキストに保存することを回避しながら、非常に高速な AUTH コマンドを使えます。これは Redis の非常に重要な機能であり、クライアントが Redis に期待するものと一貫性があります。

ただし、ACL passwords は実際にはパスワードではありません: この場合パスワードは人間が使う認証トークンではないため、サーバとクライアントの間での共有秘密鍵になります。例えば:

* 長さの制限はありません。パスワードは一部のクライアントソフトウェアに記憶されるだけです。このコンテキストでパスワードを呼び出す必要がある人間は存在しません。
* ACL パスワードは他の物を保護するものではありません: 例えば、一部のメールアカウントのパスワードになることはありません。
* 特定のサーバの Redis コマンドにアクセスできるか、システム自体が破損しているために、ハッシュ化されたパスワード自体にアクセスできる場合、そのようなパスワードが保護しているものに既にアクセスできます: Redis インスタンスの安定性と、Redis が含んでいるデータ。

このため、パスワードのクラッキングを困難にするために、時間とスペースを使うアルゴリズムを使うためにパスワード認証を遅くすることは、非常に不適切な選択です。代わりに、とても強力なパスワードを生成することをお勧めします。これにより、ハッシュを持っていても、辞書攻撃やブルートフォース攻撃を使ってパスワードをクラックするすることはできません。このため、システム暗号化疑似ランダムジェネレータを使ってパスワードを生成する特別な ACL コマンドがあります。

> ACL GENPASS
"dd721260bfe1b3d9601e7fbab36de6d04e2e67b0ef1c53de59d45950db0dd3cc"

このコマンドは、64バイトの英数字文字列に変換された 32 バイト (256ビット) の疑似乱数文字列を出力します。これは、攻撃を回避するのに十分な長さであり、管理、カットアンドペースト、保存などを容易にするのに十分な長さです。これは、Redis パスワードを生成するために使う必要があるものです。

*外部 ACL ファイルの使用

ユーザを Redis 構成内に保存するには、2つの方法があります。

1. ユーザは、`redis.conf` ファイル内で直接指定できます。
2. 外部 ACL ファイルを指定することができます。

2つの方法は相互に互換性が無く、Redis はどちらか一方を使うように要求します。redis.conf 内でユーザを指定することは、単純なユースケースに適した非常に単純な方法です。定義するユーザが複数いる場合、複雑な環境では、ACL ファイルを使うことを強くお勧めします。

redis.conf 内と外部 ACL ファイル内で使われる形式は全く同じであるため、一方から他方に切り替えるのは簡単で、以下のようになります:

user <username> ... acl rules ...

例えば:

user worker +@list +@connection ~jobs:* on >ffa9203c493aa99

外部 ACL ファイルを使いたい場合、以下のように aclfile という構成ディレクティブを指定する必要があります:

aclfile /etc/redis/users.acl

redis.conf ファイル内で数人のユーザを直接指定する場合は、CONFIG REWRITE を使ってファイルを書き替えることで新しいユーザ構成をファイル内に保存できます。

ただし、外部 ACL ファイルはより強力です。以下の事ができます:

* ACL ファイルを手動で変更し、Redis に新しい構成をリロードさせたい場合は、[ACL LOAD](/commands/acl-load) を使います。このコマンドは、*全てのユーザが正しく指定されている場合のみ*ファイルをロードできることに注意してください。そうでない場合はユーザにエラーが報告され、古い構成が引き続き有効です。
* 現在の ACL 構成を ACL ファイルに保存するには、[ACL SAVE](/commands/acl-save) を使います。

CONFIG REWRITEACL SAVE もトリガーしないことに注意してください: ACL ファイルを使う場合、構成と ACL は別個に処理されます。

*Sentinel とレプリカの ACL ルール

Redis レプリカと Redis Sentinel インスタンスに Redis インスタンスへのフルアクセスを提供したくない場合は、全てが正しく機能するために許可する必要がある一連のコマンドを下記に示します。

Sentinel のために、ユーザがマスタとレプリカインスタンスの両方で以下のコマンドにアクセスできるようにします:

  • AUTH, CLIENT, SUBSCRIBE, SCRIPT, PUBLISH, PING, INFO, MULTI, SLAVEOF, CONFIG, CLIENT, EXEC。

Sentinel はデータベース内のキーにアクセスする必要が無いため、ACL ルールは以下のようになります (注意: AUTH は常に許可されているため、AUTH は必要ありません):

ACL setuser sentinel-user >somepassword +client +subscribe +publish +ping +info +multi +slaveof +config +client +exec on

Redis レプリカは、マスタインスタンスで以下のコマンドをホワイトリストに追加する必要があります:

  • PSYNC, REPLCONF, PING

キーにアクセスする必要が無いため、これは以下のルールに変換されます:

ACL setuser replica-user >somepassword +psync +replconf +ping on

マスタがコマンドのセットを実行できるようにレプリカを設定する必要はないことに注意してください: マスタは、レプリカの観点から常に root ユーザとして認証されます。

*このドキュメントの TODO

  • カテゴリを追加/削除する場合、モジュールコマンドが無視されるように指定してください。
  • いくつかのベンチマークを使って、キーマッチングのコストを文章化します。
  • +@all にモジュールコマンドと将来の全てのコマンドがどのように含まれるかも文章化します。
  • requirepass および単一引数 AUTH の下位互換性を文章化します。
TOP
inserted by FC2 system