Support OpenID for Kubernetes VIM Authentication

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

Problem description

There are several ways for authentication in Kubernetes VIM. Currently, Tacker already supports using Service Account Token as bearer token for authentication. This specification proposes Tacker to support OpenID Connect Token [1] as bearer token for authentication. The OpenID Connect is defined by OpenID Connect Core 1.0 [2].

Proposed Change

The following diagram shows the image of authentication with 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. Login to OpenID Provider(IdP), create client, add user and groups, and so on.

  2. Configure the Kubernetes API server to enable the OpenID Connect(OIDC) plugin.

  3. Register VIM using command or API.

    • This step is only required for V1 LCM operations. In V2 LCM operations, authentication parameters can be passed by VimConnectionInfo in each LCM requests, thus this step is no longer required.

  4. Call the create vim method of class NFVOPlugin.

  5. Store the client_id, client_secret, username, password, token_url, ssl_ca_cert to TackerDB.

  6. Execute CNF LCM operation(e.g. instantiate).

  7. Get client_id, client_secret, username, password, token_url, ssl_ca_cert from TackerDB.

  8. Call InfraDriver’s Kubernetes client method to create resources.

  9. Get a id_token from the IdP using client_id, client_secret, user_name, password, token_url, ssl_ca_cert.

  10. Call Kubernetes APIs with the id_token.

Note

The IdP has investigated with Keycloak [3]. Whether there is a difference using another IdP requires additional investigation.

The following changes are required to support OIDC authentication:

  • Changes in VIM APIs

  • Changes in Kubernetes Infra Driver

1) Changes in VIM APIs

As mentioned above, Tacker’s support for OIDC authentication requires the following parameters:

  • client_id

  • client_secret

  • username

  • password

  • token_url

  • ssl_ca_cert

Note

  • The client_id is a identifier of Tacker(OIDC client) at the IdP.

  • The username is a identifier of a user at the IdP.

  • The username will be included in id_token(A JSON Web Token).

  • The username in id_token will be verified what permissions it has to Kubernetes when calling Kubernetes APIs.

The request parameters of Register VIM API [4] should be set as below:

  • The username, password and ssl_ca_cert are set in the auth_cred.

  • The client_id and client_secret should be added as new fields in the auth_cred.

  • When using Service Account Token for authentication, the auth_url is set to the endpoint of Kubernetes. When using OpenID Connect Token for authentication, the auth_url is still set to the endpoint of Kubernetes, and a new field oidc_token_url should be added in the auth_cred for setting the endpoint of IdP.

As a result, the following functions need to be modified.

  • VIM command group(register/set/list/show)

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

VIM configuration

Sample file of VIM Configuration for Kubernetes:

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"

Note

The parameter auth_cred.ssl_ca_cert contains 2 certificates. One for VIM and one for IdP.

Parameters for V1/V2 LCM API

As mentioned above, VIM registration is required only for V1 LCM API. The below shows the sample of request parameter using V1 instantiate 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"
    }
  ]
}

In V2 LCM API, authentication information can be included in VimConnectionInfo in each LCM request parameters, thus the sample of request parameter of V2 Instantiate VNF will be as follows:

{
  "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) Changes in Kubernetes Infra Driver

The flow of calling the Kubernetes APIs is shown as below (take instantiate as an example):

../../_images/0155.png
  1. The Client sends a request to Tacker-server to instantiate a vnf.

  2. Tacker-server gets the vimAuth from TackerDB, and calls the instantiate rpc-api of Tacker-conductor.

  3. Tacker-conductor calls the instantiate_vnf method of VnfLcmDriver.

  4. VnfLcmDriver calls the instantiate_vnf of InfraDriver(Kubernetes).

  5. InfraDriver(Kubernetes) sends request to IdP to get an id_token.

  6. InfraDriver(Kubernetes) sends requests with the id_token to Kubernetes to create resources.

Note

Each LCM operation(instantiate, terminate, etc) will get a individual token from IdP, and the token will be used in all API calls to the Kubernetes VIM in one LCM processing.

Get token from IdP

Get token from IdP requires the following parameters:

  • token_url

  • client_id

  • client_secret

  • username

  • password

  • ssl_ca_cert

  • grant_type(the value is fixed to “password”)

  • scope(the value is fixed to “openid”)

A sample of getting a token through curl:

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

Alternatives

None

Data model impact

As mentioned above, OIDC authentication requires the client_id, client_secret, username, password, token_url, ssl_ca_cert.

The following fields will not change:

  • The username is located at VimAuth.auth_cred.username

  • The password is located at VimAuth.password

  • The ssl_ca_cert is located at VimAuth.ssl_ca_cert

The following fields need to be extended in the VimAuth.auth_cred:

  • The client_id will be located at the VimAuth.auth_cred.client_id

  • The client_secret will be located at the VimAuth.auth_cred.client_secret

  • The oidc_token_url will be located at the VimAuth.auth_cred.oidc_token_url

Since VimAuth.auth_cred is a json, the table doesn’t actually need any changes.

Note

For security, client_secret may also need to be encrypted with fernet as well as password.

REST API impact

The parameter auth_cred in the VIM APIs will add the follow fields:

  • client_id

  • client_secret

  • oidc_token_url

The following APIs need to be changed:

  • Register VIM: POST /v1.0/vims (auth_cred in both Request and Response parameters)

  • List VIMs: GET /v1.0/vims (auth_cred in Response parameters)

  • Show VIM: GET /v1.0/vims/{vim_id} (auth_cred in Response parameters)

  • Update VIM: PUT /v1.0/vims/{vim_id} (auth_cred in both Request and Response parameters)

Security impact

None

Notifications impact

None

Other end user impact

None

Performance impact

None

Other deployer impact

None

Developer impact

None

Implementation

Assignee(s)

Primary assignee:

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

Other contributors:

Qibin Yao <yaoqibin@fujitsu.com>

Ayumu Ueha<ueha.ayumu@fujitsu.com>

Yoshiyuki Katada <katada.yoshiyuk@fujitsu.com>

Yusuke Niimi<niimi.yusuke@fujitsu.com>

Work Items

  • Implement to support:

    • Extend client_id and client_secret in auth_cred of VIM command group.

    • Extend client_id and client_secret in auth_cred of VIM APIs.

    • Add logic for calling Kubernetes with id_token.

    • Modify the vim config generator tool(gen_vim_config.sh) to add client_id and client_secret.

    • Add new unit and functional tests.

Dependencies

None

Testing

Unit and functional tests will be added to cover cases required in the spec.

Documentation Impact

  1. API guide will add client_id and client_secret in the auth_cred of VIM APIs.

  2. User guide will add a manual on how to use the IdP to authenticate users in Kubernetes.

References