読む時間の目安: 5 分
アクセス承認プラグイン
本節では Docker Engine において一般的に利用されているプラグインについて説明します。 Docker Engine によって管理されるプラグインに関する情報については Docker Engine プラグインシステム を参照してください。
Docker において即座に利用できる承認モデルは、使うか使わないかだけの単純なものです。 Docker デーモンへのアクセス権限を持ったユーザーは、どのような Docker クライアントコマンドでも実行できます。 Docker Engine API 呼び出しによりデーモンにアクセスできる権限に関しても同じことが言えます。 これ以上のアクセス制御を必要とするなら、承認プラグインを生成して Docker デーモンの設定に加えることになります。 承認プラグインを利用すれば Docker 管理者は、Docker デーモンへのアクセスを管理するための詳細なアクセスポリシーを設定することができます。
承認プラグインは、適切な開発スキルを持っていれば誰でも作り出すことができます。 開発スキルの基本として必要になるのは、Docker の知識、REST への理解、的確なプログラミングノウハウです。 本節では承認プラグイン開発者に向けて、プラグインのアーキテクチャー、状況、手法などの有用な情報を示します。
基本的な仕組み
Docker が提供する プラグインインフラストラクチャー は Docker を拡張するものであり、汎用 API を利用したサードパーティー製のコンポーネントをロードして、やりとりを行ないます。 アクセス承認サブシステムは、このようなメカニズムのもとで構築されました。
このサブシステムを利用すれば、Docker デーモンを再ビルドすることなく、承認プラグインを追加することができます。 つまりインストール済みの Docker デーモンに対してプラグイン追加ができるわけです。 ただし新たなプラグインを追加したら Docker デーモンの再起動が必要です。
承認プラグインは、その時点での承認コンテキスト(authentication context)とコマンドコンテキスト(command context)の双方に基づいて、Docker デーモンへの要求を承認または拒否します。 承認コンテキストには、ユーザー情報の詳細や承認手法があります。 またコマンドコンテキストには関連するリクエストデータすべてがあります。
承認プラグインは Docker プラグイン API に示すルールに従わなければなりません。 また各プラグインは プラグインの検出 に示すディレクトリ配下に置く必要があります。
メモ: AuthZ
とAuthN
という略表記は、それぞれ承認(authorization)と認証(authentication)を表わします。
デフォルトのユーザー承認メカニズム
Docker デーモン において TLS が有効である場合、デフォルトのユーザー承認処理においては、ユーザー情報を証明書のサブジェクト名(subject name)から引き出します。
つまりUser
の項目にはクライアント証明書のサブジェクトコモン名(subject common name)が設定されており、AuthenticationMethod
の項目にはTLS
が設定されています。
基本的なアーキテクチャー
利用するプラグインは Docker デーモンを起動するにあたって、あらかじめ登録しておく必要があります。 プラグインは複数インストールして、それらを結びつけることが可能です。 この結びつき(chain)には順序があります。 デーモンに対するリクエストは、それぞれその結びつきの順に受け渡されます。 この場合、すべてのプラグインがリソースに対するアクセス権限を有している場合に限って、アクセスが許可されます。
HTTP リクエストが CLI または Engine API を通じて Docker デーモンに要求されると、承認サブシステムがそのリクエストをインストールされた承認プラグインに受け渡します。 このリクエストには(呼び出しを行った)ユーザー情報とコマンドコンテキストが含まれています。 プラグインはこのリクエストを許可するか拒否するかを決定しなければなりません。
以下に示すシーケンス図は、承認の許可と拒否の処理フローを示しています。
プラグインに送信された各リクエストには、認証されたユーザー情報、HTTP ヘッダー、リクエストまたはレスポンスの本体が含まれています。
プラグインに受け渡されるのは、ユーザー名と使用される認証方法だけです。
ここで重要なのは、ユーザーの資格情報やトークンは受け渡されないということです。
そしてリクエストやレスポンス本体のほとんどは、承認プラグインには受け渡されません。
リクエストやレスポンス本体が受け渡されるのは、唯一Content-Type
がtext/*
かapplication/json
であるときだけです。
HTTP 接続を乗っ取る可能性のあるコマンド(HTTP Upgrade
)、たとえばexec
などの場合には、承認プラグインは、最初の HTTP リクエストに対してのみ呼び出されます。
プラグインがそのコマンドを一度受け入れたら、その後の処理フローにおいて承認処理は適用されません。
特にストリーミングデータは承認プラグインに受け渡されません。
チャンク形式の HTTP レスポンスを返すlogs
やevents
のようなコマンドでは HTTP リクエストだけが承認プラグインに送信されます。
承認処理フロー内でのリクエストやレスポンスの処理中には、Docker デーモンに対してさらにクエリーの実行が必要になる場合があります。 そのような処理フローを実施するため、プラグインは通常ユーザーが行うのと同様にデーモン API を呼び出します。 そういった追加のクエリーを可能とするためにプラグインの機能として、管理者が適切な承認やセキュリティポリシーを設定できるような手段を提供しておくことが必要になります。
Docker クライアントの処理フロー
承認プラグインを有効化し設定可能とするために、プラグイン開発者が Docker クライアントとのやりとりにおいて対応すべきことを、本節において説明します。
Docker デーモンの設定
承認プラグインの有効化は、専用のコマンドラインフラグを使って--authorization-plugin=PLUGIN_ID
のように指定します。
このフラグにはPLUGIN_ID
という値を与えます。
この値はプラグインのソケット、または仕様ファイルへのパスのいずれかです。
承認プラグインはデーモンを再起動しなくてもロードされます。
詳しくは dockerd
のドキュメント を参照してください。
$ dockerd --authorization-plugin=plugin1 --authorization-plugin=plugin2,...
Docker の承認サブシステムでは複数の--authorization-plugin
パラメーターを指定することができます。
コマンドの呼び出し(承認許可時)
$ docker pull centos
...
f1b10cd84249: Pull complete
...
コマンドの呼び出し(承認拒否時)
$ docker pull centos
...
docker: Error response from daemon: authorization denied by plugin PLUGIN_NAME: volumes are not allowed.
プラグインからのエラー
$ docker pull centos
...
docker: Error response from daemon: plugin PLUGIN_NAME failed with error: AuthZPlugin.AuthZReq: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
API スキーマと実装
Docker の標準的なプラグインにおける登録メソッドに加えて、各プラグインには以下に示す 2 つのメソッドを実装していなければなりません。
-
/AuthZPlugin.AuthZReq
この承認リクエストメソッドは、クライアントからのリクエストをデーモンが処理する前に呼び出されます。 -
/AuthZPlugin.AuthZRes
この承認レスポンスメソッドは、クライアントに対して Docker デーモンがレスポンスを返信するまえに呼び出されます。
/AuthZPlugin.AuthZReq
リクエスト
{
"User": "The user identification",
"UserAuthNMethod": "The authentication method used",
"RequestMethod": "The HTTP method",
"RequestURI": "The HTTP request URI",
"RequestBody": "Byte array containing the raw HTTP request body",
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string "
}
レスポンス
{
"Allow": "Determined whether the user is allowed or not",
"Msg": "The authorization message",
"Err": "The error message if things go wrong"
}
/AuthZPlugin.AuthZRes
リクエスト
{
"User": "The user identification",
"UserAuthNMethod": "The authentication method used",
"RequestMethod": "The HTTP method",
"RequestURI": "The HTTP request URI",
"RequestBody": "Byte array containing the raw HTTP request body",
"RequestHeader": "Byte array containing the raw HTTP request header as a map[string][]string",
"ResponseBody": "Byte array containing the raw HTTP response body",
"ResponseHeader": "Byte array containing the raw HTTP response header as a map[string][]string",
"ResponseStatusCode":"Response status code"
}
レスポンス
{
"Allow": "Determined whether the user is allowed or not",
"Msg": "The authorization message",
"Err": "The error message if things go wrong"
}
リクエスト承認
各プラグインはリクエスト承認メッセージにおいて、2 種類のフォーマットをサポートしなければなりません。 1 つはデーモンからプラグインに向けてのものであり、もう 1 つはその後に発生するプラグインからデーモンに向けてのものです。 以下の一覧表は、各メッセージにおける内容を示します。
デーモン -> プラグイン
項目 | 日本語訳 | 型 | 内容説明 |
---|---|---|---|
User | ユーザー | string | ユーザー ID。 |
Authentication method | 承認メソッド | string | 利用する承認メソッド。 |
Request method | リクエストメソッド | enum | HTTP メソッド (GET/DELETE/POST) |
Request URI | リクエスト URI | string | HTTP リクエスト URI。API バージョンを含む。(たとえば v.1.17/containers/json) |
Request headers | リクエストヘッダー | map[string]string | キーバリューペアによるリクエストヘッダー(承認ヘッダーは除く)。 |
Request body | リクエスト本体 | []byte | 生のリクエスト本体 |
プラグイン -> デーモン
項目 | 日本語訳 | 型 | 内容説明 |
---|---|---|---|
Allow | 許可 | bool | リクエストが許可あるいは拒否されたことを表わすブール値。 |
Msg | メッセージ | string | 承認メッセージ。(アクセス拒否時にクライアントに返される。) |
Err | エラー | string | エラーメッセージ。(プラグインエラーの際にクライアントに返される。文字列値はログに出力されるため資格情報は含めてはならない。) |
レスポンス承認
各プラグインはリクエスト承認メッセージにおいて、2 種類のフォーマットをサポートしなければなりません。 1 つはデーモンからプラグインに向けてのものであり、もう 1 つはその後に発生するプラグインからデーモンに向けてのものです。 以下の一覧表は、各メッセージにおける内容を示します。
デーモン -> プラグイン
項目 | 日本語訳 | 型 | Description |
---|---|---|---|
User | ユーザー | string | ユーザー ID。 |
Authentication method | 承認メソッド | string | 利用する承認メソッド。 |
Request method | リクエストメソッド | string | HTTP メソッド (GET/DELETE/POST) |
Request URI | リクエスト URI | string | HTTP リクエスト URI。API バージョンを含む。(たとえば v.1.17/containers/json) |
Request headers | リクエストヘッダー | map[string]string | キーバリューペアによるリクエストヘッダー(承認ヘッダーは除く)。 |
Request body | リクエスト本体 | []byte | 生のリクエスト本体。 |
Response status code | レスポンスステータスコード | int | Docker デーモンからのステータスコード。 |
Response headers | レスポンスヘッダー | map[string]string | キーバリューペアによるレスポンスヘッダー。 |
Response body | レスポンス本体 | []byte | Docker デーモンからの生のレスポンス本体。 |
プラグイン -> デーモン
項目 | 日本語訳 | 型 | 内容説明 |
---|---|---|---|
Allow | 許可 | bool | レスポンスが許可あるいは拒否されたことを表わすブール値。 |
Msg | メッセージ | string | 承認メッセージ。(アクセス拒否時にクライアントに返される。) |
Err | エラー | string | エラーメッセージ。(プラグインエラーの際にクライアントに返される。文字列値はログに出力されるため資格情報は含めてはならない。) |