支持 Kubernetes VIM 身份验证的 OpenID

https://blueprints.launchpad.net/tacker/+spec/support-openid-k8s-vim

问题描述

Kubernetes VIM 中存在多种身份验证方式。目前,Tacker 已经支持使用服务帐户令牌作为 bearer token 进行身份验证。本规范建议 Tacker 支持 OpenID Connect Token [1] 作为 bearer token 进行身份验证。OpenID Connect 由 OpenID Connect Core 1.0 [2] 定义。

提议的变更

下图显示了使用 OpenID Connect 进行身份验证的图像

            +----------------+   1.setup OpenID Provider(IdP)
            |                +----------------------------------------------------------------+
            |      User      |   2.setup Kubernetes                                           |
            |                +----------------------------------------+                       |
            +-----+------+---+                                        |                       |
    6.CNF LCM     |      | 3.register vim                             |                       |
(e.g. instantiate)|      |                                            |                       |
                  |      |                                            |                       |
        +-----------------------------------------------------+   +---v---------+    +--------v--------+
        |         |      |                                    |   |     VIM     |    |                 |
        | +-------v------v---+  4.create vim   +------------+ |   | (Kubernetes |    | OpenID Provider |
        | |                  +----------------->            | |   | API Server) |    | (Keycloak etc.) |
        | |  Tacker-server   |                 | NFVOPlugin | |   |             |    |                 |
        | |                  +-----+           |            | |   +---^---------+    +--------^--------+
        | +-------+----------+     |           +------+-----+ |       |                       |
        |         | 8.create       |          5.save  |       |       |                       |
        |         | resource       |          VimAuth |       |       |                       |
        | +------------------+     |7.get      +------v-----+ |       |                       |
        | | +-----v--------+ |     |VimAuth    |            | |       |10.call Kubernetes API |
        | | |              | |     +----------->  TackerDB  | |       |                       |
        | | | InfraDriver  | |                 |            | |       |                       |
        | | | (Kubernetes) | |                 +------------+ |       |                       |
        | | |              +------------------------------------------+           9.get token |
        | | |              +------------------------------------------------------------------+
        | | +--------------+ |                                |
        | | Tacker-conductor |                                |
        | +------------------+                        Tacker  |
        +-----------------------------------------------------+
  1. 登录到 OpenID 提供程序(IdP),创建客户端,添加用户和组,等等。

  2. 配置 Kubernetes API 服务器以启用 OpenID Connect(OIDC) 插件。

  3. 使用命令或 API 注册 VIM。

    • 此步骤仅适用于 V1 LCM 操作。在 V2 LCM 操作中,身份验证参数可以由每个 LCM 请求中的 VimConnectionInfo 传递,因此不再需要此步骤。

  4. 调用 NFVOPlugin 类的 create vim 方法。

  5. 将 client_id、client_secret、username、password、token_url、ssl_ca_cert 存储到 TackerDB。

  6. 执行 CNF LCM 操作(例如实例化)。

  7. 从 TackerDB 获取 client_id、client_secret、username、password、token_url、ssl_ca_cert。

  8. 调用 InfraDriver 的 Kubernetes 客户端方法以创建资源。

  9. 使用 client_id、client_secret、user_name、password、token_url、ssl_ca_cert 从 IdP 获取 id_token。

  10. 使用 id_token 调用 Kubernetes APIs。

注意

IdP 已经与 Keycloak [3] 进行了调查。使用其他 IdP 是否存在差异需要进一步调查。

支持 OIDC 身份验证需要以下更改

  • VIM APIs 中的更改

  • Kubernetes Infra Driver 中的更改

1) VIM APIs 中的更改

如上所述,Tacker 对 OIDC 身份验证的支持需要以下参数

  • client_id

  • client_secret

  • username

  • password

  • token_url

  • ssl_ca_cert

注意

  • client_id 是 IdP 中 Tacker (OIDC 客户端) 的标识符。

  • username 是 IdP 中用户的标识符。

  • username 将包含在 id_token (JSON Web Token) 中。

  • 调用 Kubernetes APIs 时,id_token 中的 username 将被验证它对 Kubernetes 具有哪些权限。

Register VIM API [4] 的请求参数应设置为如下

  • username、password 和 ssl_ca_cert 设置在 auth_cred 中。

  • client_id 和 client_secret 应作为 auth_cred 中的新字段添加。

  • 在使用服务帐户令牌进行身份验证时,auth_url 设置为 Kubernetes 的端点。在使用 OpenID Connect Token 进行身份验证时,auth_url 仍然设置为 Kubernetes 的端点,并且应在 auth_cred 中添加一个新字段 oidc_token_url 用于设置 IdP 的端点。

因此,需要修改以下函数。

  • VIM 命令组(register/set/list/show)

  • VIM API 组(register/update/list/show)

VIM 配置

Kubernetes 的 VIM 配置示例文件

vim_config.yaml

auth_url: 'https://192.168.2.82:6443'
oidc_token_url: 'https://192.168.2.81:8443/auth/realms/kubernetes/protocol/openid-connect/token'
project_name: "default"
username: 'end-user'
password: 'end-user'
client_id: 'tacker'
client_secret: 'E3xaNpB8reiUuEyrD8y6wQ1obPJAtbbU'
ssl_ca_cert: |
    -----BEGIN CERTIFICATE-----
    MIICwjCCAaqgAwIBAgIBADANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdrdWJl
    LWNhMB4XDTIwMDgyNjA5MzIzMVoXDTMwMDgyNDA5MzIzMVowEjEQMA4GA1UEAxMH
    a3ViZS1jYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxkeE16lPAd
    pfJj5GJMvZJFcX/CD6EB/LUoKwGmqVoOUQPd3b/NGy+qm+3bO9EU73epUPsVaWk2
    Lr+Z1ua7u+iib/OMsfsSXMZ5OEPgd8ilrTGhXOH8jDkif9w1NtooJxYSRcHEwxVo
    +aXdIJhqKdw16NVP/elS9KODFdRZDfQ6vU5oHSg3gO49kgv7CaxFdkF7QEHbchsJ
    0S1nWMPAlUhA5b8IAx0+ecPlMYUGyGQIQgjgtHgeawJebH3PWy32UqfPhkLPzxsy
    TSxk6akiXJTg6mYelscuxPLSe9UqNvHRIUoad3VnkF3+0CJ1z0qvfWIrzX3w92/p
    YsDBZiP6vi8CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMB
    Af8wDQYJKoZIhvcNAQELBQADggEBAIbv2ulEcQi019jKz4REy7ZyH8+ExIUBBuIz
    InAkfxNNxV83GkdyA9amk+LDoF/IFLMltAMM4b033ZKO5RPrHoDKO+xCA0yegYqU
    BViaUiEXIvi/CcDpT9uh2aNO8wX5T/B0WCLfWFyiK+rr9qcosFYxWSdU0kFeg+Ln
    YAaeFY65ZWpCCyljGpr2Vv11MAq1Tws8rEs3rg601SdKhBmkgcTAcCzHWBXR1P8K
    rfzd6h01HhIomWzM9xrP2/2KlYRvExDLpp9qwOdMSanrszPDuMs52okXgfWnEqlB
    2ZrqgOcTmyFzFh9h2dj1DJWvCvExybRmzWK1e8JMzTb40MEApyY=
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    MIIDgTCCAmkCFBkaTpj6Fm1yuBJrOI7OF1ZxEKbOMA0GCSqGSIb3DQEBCwUAMH0x
    CzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3Ux
    DTALBgNVBAoMBGpmdHQxDDAKBgNVBAsMA2RldjEUMBIGA1UEAwwLdGFja2VyLmhv
    c3QxGDAWBgkqhkiG9w0BCQEWCXRlc3RAamZ0dDAeFw0yMjAzMDgwMjQ2MDZaFw0y
    MzAzMDgwMjQ2MDZaMH0xCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8w
    DQYDVQQHDAZTdXpob3UxDTALBgNVBAoMBGpmdHQxDDAKBgNVBAsMA2RldjEUMBIG
    A1UEAwwLdGFja2VyLmhvc3QxGDAWBgkqhkiG9w0BCQEWCXRlc3RAamZ0dDCCASIw
    DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIUIDZLvKs7NKBZo+172uH9dftL
    pNM4dGgfc4jvmFjZswDex9Vqrlt7pcdrorlv2w3PWyODEzmx98EsDxVtrBNPP5lQ
    aGk6zVtC7J7trIODqD/xhS8G2H4weX1znx0NVi50pqDxVxqeXO11rwtglJ7Wwkp6
    R9dkMbr3ZHWWKEZauBWX4NX16XErniSemW8Co/Oa3coX7CtrSzRCDJJcD8MdMFBE
    m02obSh88N+YJPRLBBIGl2JfZdD0IZldUe9RozhGA80gcJeLiVoNeVIpznc/LGTr
    xHWOb2Wh0yP6gl3KX4JjJ0NubZPaskUHILFN34F5a3fVQE3t7dQk8jq7JlMCAwEA
    ATANBgkqhkiG9w0BAQsFAAOCAQEAH0B2qgwKjWje0UfdQOb1go8EKsktHOvIDK5+
    dXz2wNFJpKCekvSGK4/2KEp1McTTDj0w8nlWcGZgaOcvjuq8ufWrggjdADa2xJHr
    4pfxNMQrQXCFZ5ikCoLDx9QKDyN81b12GWpr1yPYIanSghbhx4AW7BkVQwtELun8
    d6nHGTixkqxljbEB9qM/wOrQMlm/9oJvyU4Po7weav8adPVyx8zFh9UCH2qXKUlo
    3e5D8BKkBpo4DtoXGPaYBuNt/lI7emhfikcZ2ZbeytIGdC4InoooYMKJkfjMxyim
    DSqhxuyffTmmMmEx1GK9PYLy7uPJkfn/mn9K9VL71p4QnJQt7g==
    -----END CERTIFICATE-----
type: "kubernetes"

注意

参数 auth_cred.ssl_ca_cert 包含 2 个证书。一个用于 VIM,一个用于 IdP。

V1/V2 LCM API 的参数

如上所述,VIM 注册仅适用于 V1 LCM API。以下显示了使用 V1 实例化 API 的请求参数示例。

{
  "flavourId": "simple",
  "additionalParams": {
    "lcm-kubernetes-def-files": [
      "Files/kubernetes/stateful_set.yaml"
    ]
  },
  "vimConnectionInfo": [
    {
      "id": "8a3adb69-0784-43c7-833e-aab0b6ab4470",
      "vimId": "8d8373fe-6977-49ff-83ac-7756572ed186"
      "vimType": "kubernetes"
    }
  ]
}

在 V2 LCM API 中,身份验证信息可以包含在每个 LCM 请求参数中的 VimConnectionInfo 中,因此 V2 实例化 VNF 的请求参数示例如下

{
  "flavourId": "simple",
  "additionalParams": {
    "lcm-kubernetes-def-files": [
      "Files/kubernetes/stateful_set.yaml"
    ]
  },
  "vimConnectionInfo": {
    "vim1": {
      "vimType": "kubernetes",
      "accessInfo": {
        "oidc_token_url": "https://keycloak.example.com:8443/realms/sample-realm/protocol/openid-connect/token",
        "username": "user",
        "password": "password",
        "client_id": "sample-client-id",
        "client_secret": "sample-secret"
      },
      "interfaceInfo": {
        "endpoint": "https://k8s.example.com:6443",
        "ssl_ca_cert": "sample-ssl-ca-cert"
      }
    }
  }
}

1) Kubernetes Infra Driver 中的更改

调用 Kubernetes APIs 的流程如下所示(以 instantiate 为例)

../../_images/0155.png
  1. 客户端向 Tacker-server 发送请求以实例化 vnf。

  2. Tacker-server 从 TackerDB 获取 vimAuth,并调用 Tacker-conductor 的 instantiate rpc-api。

  3. Tacker-conductor 调用 VnfLcmDriver 的 instantiate_vnf 方法。

  4. VnfLcmDriver 调用 InfraDriver(Kubernetes) 的 instantiate_vnf。

  5. InfraDriver(Kubernetes) 向 IdP 发送请求以获取 id_token。

  6. InfraDriver(Kubernetes) 使用 id_token 向 Kubernetes 发送请求以创建资源。

注意

每个 LCM 操作(instantiate、terminate 等)将从 IdP 获取一个单独的 token,并且该 token 将在一次 LCM 处理中用于所有对 Kubernetes VIM 的 API 调用。

从 IdP 获取 token

从 IdP 获取 token 需要以下参数

  • token_url

  • client_id

  • client_secret

  • username

  • password

  • ssl_ca_cert

  • grant_type(值为固定为“password”)

  • scope(值为固定为“openid”)

通过 curl 获取 token 的示例

curl --cacert cacert.crt -d "grant_type=password" -d "scope=openid" \
-d "client_id=kubernetes" -d "client_secret=E3xaNpB8reiUuEyrD8y6wQ1obPJAtbbU" \
-d "username=tacker" -d "password=tacker" \
https://keycloakserver:8443/realms/kubenetes/protocol/openid-connect/token

备选方案

数据模型影响

如上所述,OIDC 身份验证需要 client_id、client_secret、username、password、token_url、ssl_ca_cert。

以下字段不会更改

  • username 位于 VimAuth.auth_cred.username

  • password 位于 VimAuth.password

  • ssl_ca_cert 位于 VimAuth.ssl_ca_cert

需要在 VimAuth.auth_cred 中扩展以下字段

  • client_id 将位于 VimAuth.auth_cred.client_id

  • client_secret 将位于 VimAuth.auth_cred.client_secret

  • oidc_token_url 将位于 VimAuth.auth_cred.oidc_token_url

由于 VimAuth.auth_cred 是一个 json,因此表实际上不需要任何更改。

注意

为了安全起见,client_secret 也可能需要使用 fernet 与 password 一起加密。

REST API 影响

VIM APIs 中的 auth_cred 将添加以下字段

  • client_id

  • client_secret

  • oidc_token_url

需要更改以下 APIs

  • Register VIM: POST /v1.0/vims (auth_cred 在 Request 和 Response 参数中)

  • List VIMs: GET /v1.0/vims (auth_cred 在 Response 参数中)

  • Show VIM: GET /v1.0/vims/{vim_id} (auth_cred 在 Response 参数中)

  • Update VIM: PUT /v1.0/vims/{vim_id} (auth_cred 在 Request 和 Response 参数中)

安全影响

通知影响

其他最终用户影响

性能影响

其他部署者影响

开发人员影响

实现

负责人

主要负责人

Masaki Ueno<masaki.ueno.up@hco.ntt.co.jp>

其他贡献者

Qibin Yao <yaoqibin@fujitsu.com>

Ayumu Ueha<ueha.ayumu@fujitsu.com>

Yoshiyuki Katada <katada.yoshiyuk@fujitsu.com>

Yusuke Niimi<niimi.yusuke@fujitsu.com>

工作项

  • 实现支持

    • 扩展 VIM 命令组中的 client_id 和 client_secret 在 auth_cred 中。

    • 扩展 VIM APIs 中的 client_id 和 client_secret 在 auth_cred 中。

    • 添加使用 id_token 调用 Kubernetes 的逻辑。

    • 修改 vim 配置生成工具 (gen_vim_config.sh) 以添加 client_id 和 client_secret。

    • 添加新的单元和功能测试。

依赖项

测试

将添加单元和功能测试,以涵盖规范所需的用例。

文档影响

  1. API 指南将在 VIM APIs 的 auth_cred 中添加 client_id 和 client_secret。

  2. 用户指南将添加有关如何使用 IdP 验证 Kubernetes 中用户的手册。

参考资料