远程 API 认证

Incus 守护程序的远程通信通过 HTTPS 上的 JSON 进行。

要访问远程 API,客户端必须向 Incus 服务器进行身份验证。支持以下身份验证方法

TLS 客户端证书

当使用 TLS 客户端证书进行身份验证时,客户端和服务器在首次启动时都会生成一个密钥对。服务器将使用该密钥对进行所有 HTTPS 连接到 Incus 套接字。客户端将使用其证书作为所有客户端-服务器通信的客户端证书。

若要重新生成证书,只需删除旧证书即可。在下次连接时,将生成一个新证书。

通信协议

支持的协议必须为 TLS 1.3 或更高版本。

可以通过在客户端和服务器上设置 INCUS_INSECURE_TLS 环境变量来强制 Incus 接受 TLS 1.2。但是,这不是受支持的设置,并且仅应在被迫使用过时的公司代理时使用。

所有通信必须使用完美前向保密,并且密码必须限于强椭圆曲线密码(例如 ECDHE-RSA 或 ECDHE-ECDSA)。

任何生成的密钥都应至少为 4096 位 RSA,最好为 384 位 ECDSA。使用签名时,只应信任 SHA-2 签名。

由于我们控制着客户端和服务器,因此没有理由支持任何向损坏的协议或密码的向后兼容性。

受信任的 TLS 客户端

您可以使用 incus config trust list 获取 Incus 服务器信任的 TLS 证书列表。

可以通过以下两种方式添加受信任的客户端

使用服务器进行身份验证的工作流程类似于 SSH,其中与未知服务器的初始连接会触发提示

  1. 当用户使用 incus remote add 添加服务器时,会通过 HTTPS 联系服务器,下载其证书并将指纹显示给用户。

  2. 系统会要求用户确认这确实是服务器的指纹,他们可以通过连接到服务器或询问有权访问服务器的人员运行 info 命令并比较指纹来手动检查。

  3. 服务器尝试对客户端进行身份验证

    • 如果客户端证书在服务器的信任存储中,则授予连接。

    • 如果客户端证书不在服务器的信任存储中,则服务器会提示用户输入令牌。如果提供的令牌匹配,则将客户端证书添加到服务器的信任存储中,并授予连接。否则,连接将被拒绝。

可以通过 TLS 授权 限制 TLS 客户端对 Incus 的访问。若要撤消对客户端的信任,请使用 incus config trust remove <fingerprint> 从服务器中删除其证书。

使用 JSON Web Token (JWT) 执行 TLS 身份验证

作为直接使用客户端 TLS 证书进行身份验证的替代方法,Incus 还支持用户派生一个 bearer 令牌并通过 HTTP Authorization 标头使用它。

为此,用户必须生成一个签名的 JWT,其 Subject 字段设置为其客户端证书的完整指纹,它必须具有有效的 NotBeforeNotAfter 字段,并由客户端证书的私钥签名。

向服务器添加受信任的证书

添加受信任客户端的首选方法是将他们的证书直接添加到服务器上的信任存储。为此,请将客户端证书复制到服务器,并使用 incus config trust add-certificate <file> 注册它。

使用令牌添加客户端证书

您还可以使用令牌添加新客户端。令牌在可配置的时间 (core.remote_token_expiry) 或使用后过期。

若要使用此方法,请通过调用 incus config trust add 为每个客户端生成一个令牌,这将提示输入客户端名称。然后,客户端可以通过在提示时提供生成的令牌将他们的证书添加到服务器的信任存储中。

注意

如果您的 Incus 服务器位于 NAT 后面,则在将其作为客户端的远程服务器添加时,必须指定其外部公网地址

incus remote add <name> <IP_address>

在服务器上生成令牌时,Incus 会包含一个 IP 地址列表,客户端可以使用这些地址访问服务器。但是,如果服务器位于 NAT 后面,这些地址可能是客户端无法连接的本地地址。在这种情况下,您必须手动指定外部地址。

或者,客户端可以在添加远程时直接提供令牌:incus remote add <name> <token>

使用 PKI 系统

PKI 设置中,系统管理员管理一个中央 PKI,它为所有 Incus 客户端颁发客户端证书,为所有 Incus 守护进程颁发服务器证书。

要启用 PKI 模式,请完成以下步骤

  1. CA 证书添加到所有机器

    • client.ca 文件放在客户端的配置目录中 (~/.config/incus)。

    • server.ca 文件放在服务器的配置目录中 (/var/lib/incus)。

  2. 将 CA 颁发的证书放在客户端和服务器上,替换自动生成的证书。

  3. 重新启动服务器。

在这种模式下,任何与 Incus 守护进程的连接都将使用预先设定的 CA 证书进行。

如果服务器证书未由 CA 签名,连接将简单地通过正常的身份验证机制。如果服务器证书有效且由 CA 签名,则连接将继续,无需提示用户提供证书。

请注意,生成的证书不会自动受信任。您仍然必须通过 受信任的 TLS 客户端 中描述的方法之一将它们添加到服务器。

加密本地密钥

incus 客户端还支持加密的客户端密钥。可以使用以下方法生成的密钥可以用密码加密:

ssh-keygen -p -o -f .config/incus/client.key

注意

除非您启用 keepalive 模式,否则每次调用 Incus 都会导致提示,这可能会有点烦人。

$ incus list remote-host:
Password for client.key:
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

注意

虽然 incus 命令行支持加密的密钥,但诸如 Ansible 的连接插件 之类的工具不支持。

OpenID Connect 身份验证

Incus 支持使用 OpenID Connect 通过 OIDC 身份提供者对用户进行身份验证。

注意

支持通过 OpenID Connect 进行身份验证,但目前没有用户角色处理机制。任何通过配置的 OIDC 身份提供者进行身份验证的用户都可以完全访问 Incus。

要将 Incus 配置为使用 OIDC 身份验证,请设置 oidc.* 服务器配置选项。您的 OIDC 提供者必须配置为启用 设备授权授权 类型。

要添加一个指向使用 OIDC 身份验证配置的 Incus 服务器的远程,请运行 incus remote add <remote_name> <remote_address>。然后系统会提示您通过 Web 浏览器进行身份验证,您必须在其中确认 Incus 使用的设备代码。然后,Incus 客户端将检索并存储访问令牌和刷新令牌,并将这些令牌提供给 Incus 以进行所有交互。

重要

任何通过配置的 OIDC 身份提供者进行身份验证的用户都可以完全访问 Incus。要限制用户访问权限,您还必须配置 授权。目前,唯一与 OIDC 兼容的授权方法是 Open Fine-Grained Authorization (OpenFGA)

TLS 服务器证书

Incus 支持使用 ACME 服务(例如 Let’s Encrypt)颁发服务器证书。

要启用此功能,请设置以下服务器配置

  • acme.domain: 应为其颁发证书的域名。

  • acme.email: 用于 ACME 服务帐户的电子邮件地址。

  • acme.agree_tos: 必须设置为 true,以同意 ACME 服务的服务条款。

  • acme.ca_url: ACME 服务的目录 URL。默认情况下,Incus 使用“Let’s Encrypt”。

要使此功能正常工作,Incus 必须可以从端口 80 访问。这可以通过使用反向代理(例如 HAProxy)来实现。

这是一个使用 incus.example.net 作为域名的最小 HAProxy 配置。颁发证书后,Incus 将可以从 https://incus.example.net/ 访问。

# Global configuration
global
  log /dev/log local0
  chroot /var/lib/haproxy
  stats socket /run/haproxy/admin.sock mode 660 level admin
  stats timeout 30s
  user haproxy
  group haproxy
  daemon
  ssl-default-bind-options ssl-min-ver TLSv1.2
  tune.ssl.default-dh-param 2048
  maxconn 100000

# Default settings
defaults
  mode tcp
  timeout connect 5s
  timeout client 30s
  timeout client-fin 30s
  timeout server 120s
  timeout tunnel 6h
  timeout http-request 5s
  maxconn 80000

# Default backend - Return HTTP 301 (TLS upgrade)
backend http-301
  mode http
  redirect scheme https code 301

# Default backend - Return HTTP 403
backend http-403
  mode http
  http-request deny deny_status 403

# HTTP dispatcher
frontend http-dispatcher
  bind :80
  mode http

  # Backend selection
  tcp-request inspect-delay 5s

  # Dispatch
  default_backend http-403
  use_backend http-301 if { hdr(host) -i incus.example.net }

# SNI dispatcher
frontend sni-dispatcher
  bind :443
  mode tcp

  # Backend selection
  tcp-request inspect-delay 5s

  # require TLS
  tcp-request content reject unless { req.ssl_hello_type 1 }

  # Dispatch
  default_backend http-403
  use_backend incus-nodes if { req.ssl_sni -i incus.example.net }

# Incus nodes
backend incus-nodes
  mode tcp

  option tcp-check

  # Multiple servers should be listed when running a cluster
  server incus-node01 1.2.3.4:8443 check
  server incus-node02 1.2.3.5:8443 check
  server incus-node03 1.2.3.6:8443 check

故障场景

在以下情况下,身份验证预计会失败。

服务器证书已更改

服务器证书可能会在以下情况下更改

  • 服务器已完全重新安装,因此获得了新证书。

  • 连接正在被拦截 (MITM)。

在这种情况下,客户端将拒绝连接到服务器,因为证书指纹与该远程的配置中的指纹不匹配。

然后,用户必须联系服务器管理员,以检查证书是否确实已更改。如果确实如此,可以将证书替换为新的证书,或者完全删除并重新添加远程。

服务器信任关系被撤销

如果另一个受信任的客户端或本地服务器管理员在服务器上删除了客户端的信任条目,则服务器信任关系将被撤销。

在这种情况下,服务器仍然使用相同的证书,但所有 API 调用都会返回 403 代码,并显示错误,表明客户端不受信任。