访问授权插件

本文档描述了 Docker Engine 中可用的 Docker Engine 插件。要查看 Docker Engine 管理的插件信息,请参阅Docker Engine 插件系统

Docker 开箱即用的授权模型是全有或全无的。任何有权访问 Docker 守护进程的用户都可以运行任何 Docker 客户端命令。对于使用 Docker Engine API 联系守护进程的调用者也是如此。如果需要更精细的访问控制,可以创建授权插件并将其添加到 Docker 守护进程配置中。通过使用授权插件,Docker 管理员可以配置精细的访问策略,以管理对 Docker 守护进程的访问。

任何具有适当技能的人都可以开发授权插件。这些技能最基本的是了解 Docker、理解 REST 和扎实的编程知识。本文档描述了授权插件开发人员可用的架构、状态和方法信息。

基本原则

Docker 的插件基础设施通过使用通用 API 加载、删除和与第三方组件通信来扩展 Docker。访问授权子系统就是利用此机制构建的。

使用此子系统,您无需重新构建 Docker 守护进程即可添加授权插件。您可以将插件添加到已安装的 Docker 守护进程中。您确实需要重新启动 Docker 守护进程才能添加新插件。

授权插件根据当前身份验证上下文和命令上下文批准或拒绝向 Docker 守护进程发出的请求。身份验证上下文包含所有用户详细信息和身份验证方法。命令上下文包含所有相关的请求数据。

授权插件必须遵循Docker 插件 API 中描述的规则。每个插件都必须位于插件发现部分描述的目录中。

注意

缩写 AuthZAuthN 分别表示授权和身份验证。

默认用户授权机制

如果Docker 守护进程中启用了 TLS,默认用户授权流会从证书主题名称中提取用户详细信息。也就是说,User 字段设置为客户端证书主题通用名称,AuthenticationMethod 字段设置为 TLS

基本架构

您负责在 Docker 守护进程启动时注册您的插件。您可以安装多个插件并将它们链接在一起。此链可以是有序的。对守护进程的每个请求都按顺序通过链。只有当所有插件都授予对资源的访问权限时,才授予访问权限。

当通过 CLI 或 Engine API 向 Docker 守护进程发出 HTTP 请求时,身份验证子系统会将请求传递给已安装的身份验证插件。请求包含用户(调用者)和命令上下文。插件负责决定是否允许或拒绝请求。

下面的序列图描述了允许和拒绝授权流

Authorization Allow flow
Authorization Deny flow

发送到插件的每个请求都包含已认证用户、HTTP 标头以及请求/响应正文。仅用户名称和使用的身份验证方法会传递给插件。最重要的是,不会传递任何用户凭据或令牌。最后,并非所有请求/响应正文都会发送到授权插件。仅当 Content-Typetext/*application/json 时,才会发送这些请求/响应正文。

对于可能劫持 HTTP 连接(HTTP Upgrade)的命令,例如 exec,授权插件仅在初始 HTTP 请求时调用。一旦插件批准了该命令,授权就不再应用于流的其余部分。具体来说,流数据不会传递给授权插件。对于返回分块 HTTP 响应的命令,例如 logsevents,只有 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 的标准插件注册方法外,每个插件都应实现以下两种方法

  • /AuthZPlugin.AuthZReq 此授权请求方法在 Docker 守护进程处理客户端请求之前调用。

  • /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"
}

请求授权

每个插件必须支持两种请求授权消息格式,一种是从守护进程到插件,然后是从插件到守护进程。下表详细说明了每条消息中预期包含的内容。

守护进程 -> 插件

名称类型描述
用户字符串用户身份
身份验证方法字符串使用的身份验证方法
请求方法枚举HTTP 方法(GET/DELETE/POST)
请求 URI字符串HTTP 请求 URI,包括 API 版本(例如,v.1.17/containers/json)
请求头map[string]string作为键值对的请求头(不含授权头)
请求正文[]byte原始请求正文

插件 -> 守护进程

名称类型描述
允许布尔值指示请求是否允许或拒绝的布尔值
消息字符串授权消息(如果访问被拒绝,将返回给客户端)
错误字符串错误消息(如果插件遇到错误,将返回给客户端。提供的字符串值可能会出现在日志中,因此不应包含机密信息)

响应授权

插件必须支持两种授权消息格式,一种是从守护进程到插件,然后是从插件到守护进程。下表详细说明了每条消息中预期包含的内容。

守护进程 -> 插件

名称类型描述
用户字符串用户身份
身份验证方法字符串使用的身份验证方法
请求方法字符串HTTP 方法(GET/DELETE/POST)
请求 URI字符串HTTP 请求 URI,包括 API 版本(例如,v.1.17/containers/json)
请求头map[string]string作为键值对的请求头(不含授权头)
请求正文[]byte原始请求正文
响应状态码整数Docker 守护进程的状态码
响应头map[string]string作为键值对的响应头
响应正文[]byte原始 Docker 守护进程响应正文

插件 -> 守护进程

名称类型描述
允许布尔值指示响应是否允许或拒绝的布尔值
消息字符串授权消息(如果访问被拒绝,将返回给客户端)
错误字符串错误消息(如果插件遇到错误,将返回给客户端。提供的字符串值可能会出现在日志中,因此不应包含机密信息)
© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.