github.com/cilium/cilium@v1.16.2/Documentation/observability/hubble/configuration/tls.rst (about)

     1  .. only:: not (epub or latex or html)
     2  
     3      WARNING: You are looking at unreleased Cilium documentation.
     4      Please use the official rendered version released here:
     5      https://docs.cilium.io
     6  
     7  .. _hubble_enable_tls:
     8  
     9  *************************
    10  Configure TLS with Hubble
    11  *************************
    12  
    13  This page provides guidance to configure Hubble with TLS in a way that suits your
    14  environment. Instructions to enable Hubble are provided as part of each
    15  Cilium :ref:`getting_started` guide.
    16  
    17  Enable TLS on the Hubble API
    18  ============================
    19  
    20  When Hubble Relay is deployed, Hubble listens on a TCP port on the host network.
    21  This allows Hubble Relay to communicate with all Hubble instances in the
    22  cluster. Connections between Hubble instances and Hubble Relay are secured using
    23  mutual TLS (mTLS) by default.
    24  
    25  TLS certificates can be generated automatically or manually provided.
    26  
    27  The following options are available to configure TLS certificates automatically:
    28  
    29  * cilium's `certgen <https://github.com/cilium/certgen>`__ (using a Kubernetes ``CronJob``)
    30  * `cert-manager <https://cert-manager.io/>`__
    31  * `Helm <https://helm.sh/docs/chart_template_guide/function_list/#gensignedcert>`__
    32  
    33  Each of these method handles certificate rotation differently, but the end
    34  result is the secrets containing the key pair will be updated. As Hubble server
    35  and Hubble Relay support TLS certificates hot reloading, including CA
    36  certificates, this does not disrupt any existing connection. New connections
    37  are automatically established using the new certificates without having to
    38  restart Hubble server or Hubble Relay.
    39  
    40  .. tabs::
    41  
    42      .. group-tab:: CronJob (certgen)
    43  
    44          When using certgen, TLS certificates are generated at installation time
    45          and a Kubernetes ``CronJob`` is scheduled to renew them (regardless of
    46          their expiration date). The certgen method is easier to implement than
    47          cert-manager but less flexible.
    48  
    49          ::
    50  
    51              --set hubble.tls.auto.enabled=true               # enable automatic TLS certificate generation
    52              --set hubble.tls.auto.method=cronJob             # auto generate certificates using cronJob method
    53              --set hubble.tls.auto.certValidityDuration=1095  # certificates validity duration in days (default 3 years)
    54              --set hubble.tls.auto.schedule="0 0 1 */4 *"     # schedule for certificates re-generation (crontab syntax)
    55  
    56      .. group-tab:: cert-manager
    57  
    58          This method relies on `cert-manager <https://cert-manager.io/>`__ to generate
    59          the TLS certificates. cert-manager has becomes the de facto way to manage TLS on
    60          Kubernetes, and it has the following advantages compared to the other
    61          documented methods:
    62  
    63          * Support for multiple issuers (e.g. a custom CA,
    64            `Vault <https://www.vaultproject.io/>`__,
    65            `Let's Encrypt <https://letsencrypt.org/>`__,
    66            `Google's Certificate Authority Service <https://cloud.google.com/certificate-authority-service>`__,
    67            and more) allowing to choose the issuer fitting your organization's
    68            requirements.
    69          * Manages certificates via a
    70            `CRD <https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/>`__
    71            which is easier to inspect with Kubernetes tools than PEM files.
    72  
    73          **Installation steps**:
    74  
    75          #. First, install `cert-manager <https://cert-manager.io/docs/installation/>`__
    76             and setup an `issuer <https://cert-manager.io/docs/configuration/>`_.
    77             Please make sure that your issuer is able to create certificates under the
    78             ``cilium.io`` domain name.
    79          #. Install/upgrade Cilium including the following Helm flags:
    80  
    81          ::
    82  
    83              --set hubble.tls.auto.enabled=true                                 # enable automatic TLS certificate generation
    84              --set hubble.tls.auto.method=certmanager                           # auto generate certificates using cert-manager
    85              --set hubble.tls.auto.certValidityDuration=1095                    # certificates validity duration in days (default 3 years)
    86              --set hubble.tls.auto.certManagerIssuerRef.group="cert-manager.io" # Reference to cert-manager's issuer
    87              --set hubble.tls.auto.certManagerIssuerRef.kind="ClusterIssuer"
    88              --set hubble.tls.auto.certManagerIssuerRef.name="ca-issuer"
    89  
    90      .. group-tab:: Helm
    91  
    92          When using Helm, TLS certificates are (re-)generated every time Helm is used
    93          for install or upgrade.
    94  
    95          ::
    96  
    97              --set hubble.tls.auto.enabled=true               # enable automatic TLS certificate generation
    98              --set hubble.tls.auto.method=helm                # auto generate certificates using helm method
    99              --set hubble.tls.auto.certValidityDuration=1095  # certificates validity duration in days (default 3 years)
   100  
   101          The downside of the Helm method is that while certificates are automatically
   102          generated, they are not automatically renewed.  Consequently, running
   103          ``helm upgrade`` is required when certificates are about to expire (i.e. before
   104          the configured ``hubble.tls.auto.certValidityDuration``).
   105  
   106      .. group-tab:: User Provided Certificates
   107  
   108          In order to provide your own TLS certificates, ``hubble.tls.auto.enabled`` must be
   109          set to ``false``, secrets containing the certificates must be created in the
   110          ``kube-system`` namespace, and the secret names must be provided to Helm.
   111  
   112          Provided files must be **base64 encoded** PEM certificates.
   113  
   114          In addition, the **Common Name (CN)** and **Subject Alternative Name (SAN)**
   115          of the certificate for Hubble server MUST be set to
   116          ``*.{cluster-name}.hubble-grpc.cilium.io`` where ``{cluster-name}`` is the
   117          cluster name defined by ``cluster.name`` (defaults to ``default``).
   118  
   119          Once the certificates have been issued, the secrets must be created in the ``kube-system`` namespace.
   120  
   121          Each secret must contain the following keys:
   122  
   123          - ``tls.crt``: The certificate file.
   124          - ``tls.key``: The private key file.
   125          - ``ca.crt``: The CA certificate file.
   126  
   127          The following examples demonstrates how to create the secrets.
   128  
   129          Create the hubble server certificate secret:
   130  
   131          .. code-block:: shell-session
   132  
   133            $ kubectl -n kube-system create secret generic hubble-server-certs --from-file=hubble-server.crt --from-file=hubble-server.key --from-file=ca.crt
   134  
   135          If hubble-relay is enabled, the following secrets must be created:
   136  
   137          .. code-block:: shell-session
   138  
   139            $ kubectl -n kube-system create secret generic hubble-relay-server-certs --from-file=hubble-relay-server.crt --from-file=hubble-relay-server.key --from-file=ca.crt
   140            $ kubectl -n kube-system create secret generic hubble-relay-client-certs --from-file=hubble-relay-client.crt --from-file=hubble-relay-client.key --from-file=ca.crt
   141  
   142          If hubble-ui is enabled, the following secret must be created:
   143  
   144          .. code-block:: shell-session
   145  
   146            $ kubectl -n kube-system create secret generic hubble-ui-client-certs --from-file=hubble-ui-client.crt --from-file=hubble-ui-client.key --from-file=ca.crt
   147  
   148          Lastly, if the Hubble metrics API is enabled, the following secret must be created:
   149  
   150          .. code-block:: shell-session
   151  
   152            $ kubectl -n kube-system create secret generic hubble-metrics-certs --from-file=hubble-metrics.crt --from-file=hubble-metrics.key --from-file=ca.crt
   153  
   154          After the secrets have been created, the secret names must be provided to Helm and automatic certificate generation must be disabled:
   155  
   156          ::
   157  
   158              --set hubble.tls.auto.enabled=false                                       # Disable automatic TLS certificate generation
   159              --set hubble.tls.server.existingSecret="hubble-server-certs"
   160              --set hubble.relay.tls.server.enabled=true                                # Enable TLS on Hubble Relay (optional)
   161              --set hubble.relay.tls.server.existingSecret="hubble-relay-server-certs"
   162              --set hubble.relay.tls.client.existingSecret="hubble-relay-client-certs"
   163              --set hubble.ui.tls.client.existingSecret="hubble-ui-client-certs"
   164              --set hubble.metrics.tls.enabled=true                                     # Enable TLS on the Hubble metrics API (optional)
   165              --set hubble.metrics.tls.server.existingSecret="hubble-metrics-certs"
   166  
   167          - ``hubble.relay.tls.server.existingSecret`` and ``hubble.ui.tls.client.existingSecret``
   168            only need to be provided when ``hubble.relay.tls.server.enabled=true`` (default ``false``).
   169          - ``hubble.ui.tls.client.existingSecret`` only needs to be provided when ``hubble.ui.enabled`` (default ``false``).
   170          - ``hubble.metrics.tls.server.existingSecret`` only needs to be provided when ``hubble.metrics.tls.enabled`` (default ``false``).
   171            For more details on configuring the Hubble metrics API with TLS, see :ref:`hubble_configure_metrics_tls`.
   172  
   173  
   174  Troubleshooting
   175  ---------------
   176  
   177  If you encounter issues after enabling TLS, you can use the following instructions to help diagnose the problem.
   178  
   179  .. tabs::
   180  
   181      .. group-tab:: cert-manager
   182  
   183  
   184          While installing Cilium or cert-manager you may get the following error:
   185  
   186          ::
   187  
   188              Error: Internal error occurred: failed calling webhook "webhook.cert-manager.io": Post "https://cert-manager-webhook.cert-manager.svc:443/mutate?timeout=10s": dial tcp x.x.x.x:443: connect: connection refused
   189  
   190          This happens when cert-manager's webhook (which is used to verify the
   191          ``Certificate``'s CRD resources) is not available. There are several ways to
   192          resolve this issue. Pick one of the following options:
   193  
   194          .. tabs::
   195  
   196              .. tab:: Install CRDs first
   197  
   198                  Install cert-manager CRDs before Cilium and cert-manager (see `cert-manager's documentation about installing CRDs with kubectl <https://cert-manager.io/docs/installation/helm/#option-1-installing-crds-with-kubectl>`__):
   199  
   200                  .. code-block:: shell-session
   201  
   202                      $ kubectl create -f cert-manager.crds.yaml
   203  
   204                  Then install cert-manager, configure an issuer, and install Cilium.
   205  
   206              .. tab:: Upgrade Cilium
   207  
   208                  Upgrade Cilium from an installation with TLS disabled:
   209  
   210                  .. code-block:: shell-session
   211  
   212                      $ helm install cilium cilium/cilium \
   213                          --set hubble.tls.enabled=false \
   214                          ...
   215  
   216                  Then install cert-manager, configure an issuer, and upgrade Cilium enabling TLS:
   217  
   218                  .. code-block:: shell-session
   219  
   220                      $ helm install cilium cilium/cilium --set hubble.tls.enabled=true
   221  
   222              .. tab:: Disable webhook
   223  
   224                  Disable cert-manager validation (assuming Cilium is installed in the ``kube-system`` namespace):
   225  
   226                  .. code-block:: shell-session
   227  
   228                      $ kubectl label namespace kube-system cert-manager.io/disable-validation=true
   229  
   230                  Then install Cilium, cert-manager, and configure an issuer.
   231  
   232              .. tab:: Host network webhook
   233  
   234                  Configure cert-manager to expose its webhook within the host network namespace:
   235  
   236                  .. code-block:: shell-session
   237  
   238                      $ helm install cert-manager jetstack/cert-manager \
   239                              --set webhook.hostNetwork=true \
   240                              --set webhook.tolerations='["operator": "Exists"]'
   241  
   242                  Then configure an issuer and install Cilium.
   243  
   244      .. group-tab:: CronJob (certgen)
   245  
   246          If you are using ArgoCD, you may encounter issues on the initial
   247          installation because of how ArgoCD handles Helm hooks specified in the
   248          ``helm.sh/hook`` annotation.
   249  
   250          The ``hubble-generate-certs`` Job specifies a ``post-install`` Helm
   251          hook in order to generate the required Certificates at initial install time, since
   252          the CronJob will only run on the configured schedule which could be
   253          hours or days after the initial installation.
   254  
   255          Since ArgoCD will only run ``post-install`` hooks after all pods are
   256          ready and running, you may encounter a situation where the
   257          ``hubble-generate-certs`` Job is never run.
   258  
   259          It cannot be configured as a ``pre-install`` hook because it requires Cilium
   260          to be running first, and Hubble Relay cannot become ready until
   261          certificates are provisioned.
   262  
   263          To work around this, you can manually run the ``certgen`` CronJob:
   264  
   265          .. code-block:: shell-session
   266  
   267              $ kubectl -n kube-system create job hubble-generate-certs-initial --from cronjob/hubble-generate-certs
   268  
   269      .. group-tab:: Helm
   270  
   271          When using Helm certificates are not automatically renewed. If you
   272          encounter issues with expired certificates, you can manually renew them
   273          by running ``helm upgrade`` to renew the certificates.
   274  
   275      .. group-tab:: User Provided Certificates
   276  
   277          If you encounter issues with the certificates, you can check the
   278          certificates and keys by decoding them:
   279  
   280          .. code-block:: shell-session
   281  
   282              $ kubectl -n kube-system get secret hubble-server-certs -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
   283              $ kubectl -n kube-system get secret hubble-server-certs -o jsonpath='{.data.tls\.key}' | base64 -d | openssl rsa -text -noout
   284              $ kubectl -n kube-system get secret hubble-server-certs -o jsonpath='{.data.ca\.crt}' | base64 -d | openssl x509 -text -noout
   285  
   286          The same commands can be used for the other secrets as well.
   287  
   288          If hubble-relay is enabled but not responding or the pod is failing it's readiness probe,
   289          check the certificates and ensure the client certificate is issued by the CA (``ca.crt``) specified in the ``hubble-server-certs`` secret.
   290  
   291          Additionally you must ensure the **Common Name (CN)** and **Subject Alternative Name (SAN)**
   292          of the certificate for Hubble server MUST be set to
   293          ``*.{cluster-name}.hubble-grpc.cilium.io`` where ``{cluster-name}`` is
   294          the cluster name defined by ``cluster.name`` (defaults to ``default``).
   295  
   296  
   297  Validating the Installation
   298  ---------------------------
   299  
   300  The following section guides you through validating that TLS is enabled for Hubble
   301  and the connection between Hubble Relay and Hubble Server is using mTLS to secure the session.
   302  Additionally, the commands below can be used to troubleshoot issues with your TLS configuration if you encounter any issues.
   303  
   304  Before beginning verify TLS has been configured correctly by running the following command:
   305  
   306  .. code-block:: shell-session
   307  
   308     $ kubectl get configmap -n kube-system cilium-config -oyaml | grep hubble-disable-tls
   309       hubble-disable-tls: "false"
   310  
   311  You should see that the ``hubble-disable-tls`` configuration option is set to ``false``.
   312  
   313  Start by creating a Hubble CLI pod within the namespace that Hubble components are running in (for example: ``kube-system``):
   314  
   315  .. code-block:: shell-session
   316  
   317      $ kubectl apply -n kube-system -f https://raw.githubusercontent.com/cilium/cilium/main/examples/hubble/hubble-cli.yaml
   318  
   319  List Hubble Servers by running ``hubble watch peers`` within the newly created pod:
   320  
   321  .. code-block:: shell-session
   322  
   323      $ kubectl exec -it -n kube-system deployment/hubble-cli -- \
   324      hubble watch peers --server unix:///var/run/cilium/hubble.sock
   325  
   326      PEER_ADDED   172.18.0.2 kind-worker (TLS.ServerName: kind-worker.default.hubble-grpc.cilium.io)
   327      PEER_ADDED   172.18.0.3 kind-control-plane (TLS.ServerName: kind-control-plane.kind.hubble-grpc.cilium.io)
   328  
   329  Copy the IP and the server name of the first peer into the following environment variables for the next steps:
   330  
   331  .. note::
   332  
   333      If the ``TLS.ServerName`` is missing from your output then TLS is not enabled for the Hubble server and the following steps will not work.
   334      If this is the case, please refer to the previous sections to enable TLS.
   335  
   336  .. code-block:: shell-session
   337  
   338      $ IP=172.18.0.2
   339      $ SERVERNAME=kind-worker.default.hubble-grpc.cilium.io
   340  
   341  Connect to the first peer with the Hubble Relay client certificate to confirm
   342  that the Hubble server is accepting connections from clients who present the
   343  correct certificate:
   344  
   345  .. code-block:: shell-session
   346  
   347      $ kubectl exec -it -n kube-system deployment/hubble-cli -- \
   348      hubble observe --server ${IP?}:4244 \
   349          --tls-server-name ${SERVERNAME?} \
   350          --tls-ca-cert-files /var/lib/hubble-relay/tls/hubble-server-ca.crt \
   351          --tls-client-cert-file /var/lib/hubble-relay/tls/client.crt \
   352          --tls-client-key-file /var/lib/hubble-relay/tls/client.key
   353  
   354      Dec 13 08:49:58.888: 10.20.1.124:60588 (host) -> kube-system/coredns-565d847f94-pp8zs:8181 (ID:7518) to-endpoint FORWARDED (TCP Flags: SYN)
   355      Dec 13 08:49:58.888: 10.20.1.124:36308 (host) <- kube-system/coredns-565d847f94-pp8zs:8080 (ID:7518) to-stack FORWARDED (TCP Flags: SYN, ACK)
   356      Dec 13 08:49:58.888: 10.20.1.124:60588 (host) <- kube-system/coredns-565d847f94-pp8zs:8181 (ID:7518) to-stack FORWARDED (TCP Flags: SYN, ACK)
   357      ...
   358      ...
   359  
   360  Now try to query the Hubble server without providing any client certificate:
   361  
   362  .. code-block:: shell-session
   363  
   364      $ kubectl exec -it -n kube-system deployment/hubble-cli -- \
   365      hubble observe --server ${IP?}:4244 \
   366          --tls-server-name ${SERVERNAME?} \
   367          --tls-ca-cert-files /var/lib/hubble-relay/tls/hubble-server-ca.crt
   368  
   369      failed to connect to '172.18.0.2:4244': context deadline exceeded: connection error: desc = "transport: authentication handshake failed: mTLS client certificate requested, but not provided"
   370      command terminated with exit code 1
   371  
   372  You can also try to connect without TLS:
   373  
   374  .. code-block:: shell-session
   375  
   376      $ kubectl exec -it -n kube-system deployment/hubble-cli -- \
   377      hubble observe --server ${IP?}:4244
   378  
   379      failed to connect to '172.18.0.2:4244': context deadline exceeded: connection error: desc = "error reading server preface: EOF"
   380      command terminated with exit code 1
   381  
   382  To troubleshoot the connection, install OpenSSL in the Hubble CLI pod:
   383  
   384  .. code-block:: shell-session
   385  
   386      $ kubectl exec -it -n kube-system deployment/hubble-cli -- apk add --update openssl
   387  
   388  Then, use OpenSSL to connect to the Hubble server get more details about the TLS handshake:
   389  
   390  .. code-block:: shell-session
   391  
   392      $ kubectl exec -it -n kube-system deployment/hubble-cli -- \
   393      openssl s_client -showcerts -servername ${SERVERNAME} -connect ${IP?}:4244 \
   394      -CAfile /var/lib/hubble-relay/tls/hubble-server-ca.crt
   395  
   396      CONNECTED(00000004)
   397      depth=1 C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   398      verify return:1
   399      depth=0 CN = *.default.hubble-grpc.cilium.io
   400      verify return:1
   401      ---
   402      Certificate chain
   403       0 s:CN = *.default.hubble-grpc.cilium.io
   404         i:C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   405         a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA256
   406         v:NotBefore: Aug 15 17:39:00 2024 GMT; NotAfter: Aug 15 17:39:00 2027 GMT
   407      -----BEGIN CERTIFICATE-----
   408      MIICNzCCAd2gAwIBAgIUAlgykDuc1J+mzseHS0pREX6Uv3cwCgYIKoZIzj0EAwIw
   409      aDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNVBAcT
   410      AkNBMQ8wDQYDVQQKEwZDaWxpdW0xDzANBgNVBAsTBkNpbGl1bTESMBAGA1UEAxMJ
   411      Q2lsaXVtIENBMB4XDTI0MDgxNTE3MzkwMFoXDTI3MDgxNTE3MzkwMFowKjEoMCYG
   412      A1UEAwwfKi5kZWZhdWx0Lmh1YmJsZS1ncnBjLmNpbGl1bS5pbzBZMBMGByqGSM49
   413      AgEGCCqGSM49AwEHA0IABGjtY50MM21TolEy5RUrBa6WqHsw7PjNB3MhYLCsuJmO
   414      aQ1tIy6J2e7a9Cw2jmBlyj+dL8g0YLhRQX4n+leItSSjgaIwgZ8wDgYDVR0PAQH/
   415      BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0O
   416      BBYEFCDf5epVs8yyyZCdtBzc90HrQzpFMB8GA1UdIwQYMBaAFDKuJMmhNPJ71FvB
   417      AyHEMztI62NbMCoGA1UdEQQjMCGCHyouZGVmYXVsdC5odWJibGUtZ3JwYy5jaWxp
   418      dW0uaW8wCgYIKoZIzj0EAwIDSAAwRQIhAP0kyl0Eb7FBQw1uZE+LWnRyr5GDsB3+
   419      6rA/Rx042XZgAiBZML3lOW60tWMI1Pyn4cR4trFbzZpsUSwnQmOAb+paEw==
   420      -----END CERTIFICATE-----
   421      ---
   422      Server certificate
   423      subject=CN = *.default.hubble-grpc.cilium.io
   424      issuer=C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   425      ---
   426      Acceptable client certificate CA names
   427      C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   428      Requested Signature Algorithms: RSA-PSS+SHA256:ECDSA+SHA256:Ed25519:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA384:ECDSA+SHA512:RSA+SHA1:ECDSA+SHA1
   429      Shared Requested Signature Algorithms: RSA-PSS+SHA256:ECDSA+SHA256:Ed25519:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA384:ECDSA+SHA512
   430      Peer signing digest: SHA256
   431      Peer signature type: ECDSA
   432      Server Temp Key: X25519, 253 bits
   433      ---
   434      SSL handshake has read 1106 bytes and written 437 bytes
   435      Verification: OK
   436      ---
   437      New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
   438      Server public key is 256 bit
   439      This TLS version forbids renegotiation.
   440      No ALPN negotiated
   441      Early data was not sent
   442      Verify return code: 0 (ok)
   443      ---
   444      08EBFFFFFF7F0000:error:0A00045C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required:ssl/record/rec_layer_s3.c:1605:SSL alert number 116
   445      command terminated with exit code 1
   446  
   447  Breaking the output down:
   448  
   449  - ``Server Certificate``: This is the server certificate presented by the server.
   450  - ``Acceptable client certificate CA names``: These are the CA names that the server accepts for client certificates.
   451  - ``SSL handshake has read 1108 bytes and written 387 bytes``: Details on the handshake. Errors could be presented here if any occurred.
   452  - ``Verification: OK``: The server certificate is valid.
   453  - ``Verify return code: 0 (ok)``: The server certificate was verified successfully.
   454  - ``error:0A00045C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required``: The server requires a client certificate to be provided. Since a client certificate was not provided, the connection failed.
   455  
   456  If you provide the correct client certificate and key, the connection should be successful:
   457  
   458  .. code-block:: shell-session
   459  
   460      $ kubectl exec -i -n kube-system deployment/hubble-cli -- \
   461      openssl s_client -showcerts -servername ${SERVERNAME} -connect ${IP?}:4244 \
   462        -CAfile /var/lib/hubble-relay/tls/hubble-server-ca.crt \
   463        -cert /var/lib/hubble-relay/tls/client.crt \
   464        -key /var/lib/hubble-relay/tls/client.key
   465  
   466      CONNECTED(00000004)
   467      depth=1 C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   468      verify return:1
   469      depth=0 CN = *.default.hubble-grpc.cilium.io
   470      verify return:1
   471      ---
   472      Certificate chain
   473       0 s:CN = *.default.hubble-grpc.cilium.io
   474         i:C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   475         a:PKEY: id-ecPublicKey, 256 (bit); sigalg: ecdsa-with-SHA256
   476         v:NotBefore: Aug 15 17:39:00 2024 GMT; NotAfter: Aug 15 17:39:00 2027 GMT
   477      -----BEGIN CERTIFICATE-----
   478      MIICNzCCAd2gAwIBAgIUAlgykDuc1J+mzseHS0pREX6Uv3cwCgYIKoZIzj0EAwIw
   479      aDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNVBAcT
   480      AkNBMQ8wDQYDVQQKEwZDaWxpdW0xDzANBgNVBAsTBkNpbGl1bTESMBAGA1UEAxMJ
   481      Q2lsaXVtIENBMB4XDTI0MDgxNTE3MzkwMFoXDTI3MDgxNTE3MzkwMFowKjEoMCYG
   482      A1UEAwwfKi5kZWZhdWx0Lmh1YmJsZS1ncnBjLmNpbGl1bS5pbzBZMBMGByqGSM49
   483      AgEGCCqGSM49AwEHA0IABGjtY50MM21TolEy5RUrBa6WqHsw7PjNB3MhYLCsuJmO
   484      aQ1tIy6J2e7a9Cw2jmBlyj+dL8g0YLhRQX4n+leItSSjgaIwgZ8wDgYDVR0PAQH/
   485      BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0O
   486      BBYEFCDf5epVs8yyyZCdtBzc90HrQzpFMB8GA1UdIwQYMBaAFDKuJMmhNPJ71FvB
   487      AyHEMztI62NbMCoGA1UdEQQjMCGCHyouZGVmYXVsdC5odWJibGUtZ3JwYy5jaWxp
   488      dW0uaW8wCgYIKoZIzj0EAwIDSAAwRQIhAP0kyl0Eb7FBQw1uZE+LWnRyr5GDsB3+
   489      6rA/Rx042XZgAiBZML3lOW60tWMI1Pyn4cR4trFbzZpsUSwnQmOAb+paEw==
   490      -----END CERTIFICATE-----
   491      ---
   492      Server certificate
   493      subject=CN = *.default.hubble-grpc.cilium.io
   494      issuer=C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   495      ---
   496      Acceptable client certificate CA names
   497      C = US, ST = San Francisco, L = CA, O = Cilium, OU = Cilium, CN = Cilium CA
   498      Requested Signature Algorithms: RSA-PSS+SHA256:ECDSA+SHA256:Ed25519:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA384:ECDSA+SHA512:RSA+SHA1:ECDSA+SHA1
   499      Shared Requested Signature Algorithms: RSA-PSS+SHA256:ECDSA+SHA256:Ed25519:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA384:ECDSA+SHA512
   500      Peer signing digest: SHA256
   501      Peer signature type: ECDSA
   502      Server Temp Key: X25519, 253 bits
   503      ---
   504      SSL handshake has read 1106 bytes and written 1651 bytes
   505      Verification: OK
   506      ---
   507      New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
   508      Server public key is 256 bit
   509      This TLS version forbids renegotiation.
   510      No ALPN negotiated
   511      Early data was not sent
   512      Verify return code: 0 (ok)
   513      ---
   514      ---
   515      Post-Handshake New Session Ticket arrived:
   516      SSL-Session:
   517          Protocol  : TLSv1.3
   518          Cipher    : TLS_AES_128_GCM_SHA256
   519          Session-ID: 9ADFAFBDFFB876A9A8D4CC025470168D25485FF51929615199E9561F46FBF97B
   520          Session-ID-ctx:
   521          Resumption PSK: 58DD7621E7B353BD5C6FC3AAB5A907FF3D3251FAA184D28D2C69560E96806495
   522          PSK identity: None
   523          PSK identity hint: None
   524          SRP username: None
   525          TLS session ticket lifetime hint: 604800 (seconds)
   526          TLS session ticket:
   527          0000 - 55 93 99 70 30 37 6a 77-43 d7 0c 34 9f 24 51 40   U..p07jwC..4.$Q@
   528          ...
   529          ...
   530          0690 - 11 6d 26 ec 99 3a 6e a9-56 c9 ad a0 49 e2 f5 6a   .m&..:n.V...I..j
   531  
   532  Press ``ctrl-d`` to signal the TLS session and connection should be terminated.
   533  After the session has ended you will see output similar to the following:
   534  
   535  .. code-block:: shell-session
   536  
   537      @DONE
   538          06a0 - bf eb 8b 1d 8d 43 46 2a-07 02 e1 44 35 45 b1 a0   .....CF*...D5E..
   539          06b0 - 7d bb 27 2f 1a 35 b2 da-0d 00 15 fd 6c 1f 00 3b   }.'/.5......l..;
   540          06c0 - 9a 6e ff c9 5d ad 6b af-f7 20 39 99 5b ae 72 03   .n..].k.. 9.[.r.
   541          06d0 - c8 2d 93 7a e5 a7 e0 d5-70 95 8f b5 0b 56 9c      .-.z....p....V.
   542  
   543          Start Time: 1723744378
   544          Timeout   : 7200 (sec)
   545          Verify return code: 0 (ok)
   546          Extended master secret: no
   547          Max Early Data: 0
   548      ---
   549      read R BLOCK
   550  
   551  The output of this OpenSSL command is similar to the previous output, but without the error message.
   552  
   553  There is also an additional section, starting with ``Post-Handshake
   554  New Session Ticket arrived``, the presence of which indicates that the client
   555  certificate is valid and a TLS session was established. The summary of the TLS
   556  session printed after the connection has ended can also be used as an indicator
   557  of the established TLS session.
   558  
   559  .. _hubble_configure_metrics_tls:
   560  
   561  Hubble Metrics TLS and Authentication
   562  =====================================
   563  
   564  Starting with Cilium 1.16, Hubble supports configuring TLS on the Hubble
   565  metrics API in addition to the Hubble observer API.
   566  
   567  This can be done by specifying the following options to Helm at install or
   568  upgrade time, along with the TLS configuration options described in the
   569  previous section.
   570  
   571  .. note::
   572  
   573    This section assumes that you have already enabled :ref:`Hubble metrics<hubble_metrics>`.
   574  
   575  To enable TLS on the Hubble metrics API, add the following Helm flag to your
   576  list of options:
   577  
   578  ::
   579  
   580      --set hubble.metrics.tls.enabled=true # Enable TLS on the Hubble metrics API
   581  
   582  If you also want to enable authentication using mTLS on the Hubble metrics API,
   583  first create a ConfigMap with a CA certificate to use for verifying client
   584  certificates:
   585  
   586  ::
   587  
   588      kubectl -n kube-system create configmap hubble-metrics-ca --from-file=ca.crt
   589  
   590  Then, add the following flags to your Helm command to enable mTLS:
   591  
   592  ::
   593  
   594      --set hubble.metrics.tls.enabled=true                       # Enable TLS on the Hubble metrics API
   595      --set hubble.metrics.tls.server.mtls.enabled=true           # Enable mTLS authentication on the Hubble metrics API
   596      --set hubble.metrics.tls.server.mtls.name=hubble-metrics-ca # Use the CA certificate from the ConfigMap
   597  
   598  After the configuration is applied, clients will be required to authenticate
   599  using a certificate signed by the configured CA certificate to access the
   600  Hubble metrics API.
   601  
   602  .. note::
   603  
   604    When using TLS with the Hubble metrics API you will need to update your
   605    Prometheus scrape configuration to use HTTPS by setting a ``tls_config`` and
   606    provide the path to the CA certificate. When using mTLS you will also need to
   607    provide a client certificate and key signed by the CA certificate for
   608    Prometheus to authenticate to the Hubble metrics API.
   609  
   610  .. _hubble_api_tls:
   611  
   612  Access the Hubble API with TLS Enabled
   613  ======================================
   614  
   615  The examples are adapted from :ref:`hubble_cli`.
   616  
   617  Before you can access the Hubble API with TLS enabled, you need to obtain the
   618  CA certificate from the secret that was created when enabling TLS. The
   619  following examples demonstrate how to obtain the CA certificate and use it to
   620  access the Hubble API.
   621  
   622  Run the following command to obtain the CA certificate from the ``hubble-relay-server-certs`` secret:
   623  
   624  .. code-block:: shell-session
   625  
   626      $ kubectl -n kube-system get secret hubble-relay-server-certs -o jsonpath='{.data.ca\.crt}' | base64 -d > hubble-ca.crt
   627  
   628  After obtaining the CA certificate you can use the  ``--tls`` to enable TLS and
   629  ``--tls-ca-cert-files`` flag to specify the CA certificate. Additionally, when
   630  port-forwarding to Hubble Relay, you will need to specify the
   631  ``--tls-server-name`` flag:
   632  
   633  .. code-block:: shell-session
   634  
   635      $ hubble observe --tls --tls-ca-cert-files ./hubble-ca.crt --tls-server-name hubble.hubble-relay.cilium.io --pod deathstar --protocol http
   636      May  4 13:23:40.501: default/tiefighter:42690 -> default/deathstar-c74d84667-cx5kp:80 http-request FORWARDED (HTTP/1.1 POST http://deathstar.default.svc.cluster.local/v1/request-landing)
   637      May  4 13:23:40.502: default/tiefighter:42690 <- default/deathstar-c74d84667-cx5kp:80 http-response FORWARDED (HTTP/1.1 200 0ms (POST http://deathstar.default.svc.cluster.local/v1/request-landing))
   638      May  4 13:23:43.791: default/tiefighter:42742 -> default/deathstar-c74d84667-cx5kp:80 http-request DROPPED (HTTP/1.1 PUT http://deathstar.default.svc.cluster.local/v1/exhaust-port)
   639  
   640  To persist these options for the shell session, set the following environment variables:
   641  
   642  .. code-block:: shell-session
   643  
   644      $ export HUBBLE_TLS=true
   645      $ export HUBBLE_TLS_CA_CERT_FILES=./hubble-ca.crt
   646      $ export HUBBLE_TLS_SERVER_NAME=hubble.hubble-relay.cilium.io