github.com/cilium/cilium@v1.16.2/Documentation/security/tls-visibility.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  .. _gs_tls_inspection:
     8  
     9  ************************************************
    10  Inspecting TLS Encrypted Connections with Cilium
    11  ************************************************
    12  
    13  This document serves as an introduction for how network security teams can use Cilium to transparently inspect
    14  TLS-encrypted connections.  This TLS-aware inspection allows Cilium API-aware visibility and policy to function
    15  even for connections where client to server
    16  communication is protected by TLS, such as when a client accesses the API service via HTTPS.  This capability is similar to
    17  what is possible to traditional hardware firewalls, but is implemented entirely in software on the Kubernetes worker node,
    18  and is policy driven, allowing inspection to target only selected network connectivity.
    19  
    20  This type of visibility is
    21  extremely valuable to be able to monitor how external API services are being used,
    22  for example, understanding which S3 buckets are being accessed by an given application.
    23  
    24  .. include:: gsg_requirements.rst
    25  
    26  
    27  Edit the ClusterRole for Cilium to give it access to Kubernetes secrets
    28  
    29  
    30  .. code-block:: shell-session
    31  
    32      $ kubectl edit clusterrole cilium -n kube-system
    33  
    34  Add the following section at the end of the file:
    35  
    36  
    37  .. code-block:: yaml
    38  
    39    - apiGroups:
    40      - ""
    41      resources:
    42      - secrets
    43      verbs:
    44      - get
    45  
    46  
    47  Deploy the Demo Application
    48  ===========================
    49  
    50  To demonstrate TLS-interception we will use the same ``mediabot`` application that we used for the DNS-aware policy example.
    51  This application will access the Star Wars API service using HTTPS, which would normally mean that network-layer mechanisms
    52  like Cilium would not be able to see the HTTP-layer details of the communication, since all application data is encrypted
    53  using TLS before that data is sent on the network.
    54  
    55  In this guide we will learn about:
    56  
    57  - Creating an internal Certificate Authority (CA) and associated certificates signed by that CA to enable TLS interception.
    58  - Using Cilium network policy to select the traffic to intercept using DNS-based policy rules.
    59  - Inspecting the details of the HTTP request using cilium monitor (accessing this visibility data via Hubble, and applying
    60    Cilium network policies to filter/modify the HTTP request is also possible, but is beyond the scope of this simple Getting Started Guide)
    61  
    62  
    63  First off, we will create a single pod ``mediabot`` application:
    64  
    65  .. parsed-literal::
    66  
    67     $ kubectl create -f \ |SCM_WEB|\/examples/kubernetes-dns/dns-sw-app.yaml
    68     $ kubectl wait pod/mediabot --for=condition=Ready
    69     $ kubectl get pods
    70     NAME                             READY   STATUS    RESTARTS   AGE
    71     pod/mediabot                     1/1     Running   0          14s
    72  
    73  
    74  A Brief Overview of the TLS Certificate Model
    75  =============================================
    76  
    77  TLS is a protocol that "wraps" other protocols like HTTP and ensures that communication between client and
    78  server has confidentiality (no one can read the data except the intended recipient), integrity (recipient
    79  can confirm that the data has not been modified in transit), and authentication (sender can confirm that
    80  it is talking with the intended destination, not an impostor).  We will provide a highly simplified overview
    81  of TLS in this document, but for full details, please see
    82  `<https://en.wikipedia.org/wiki/Transport_Layer_Security>`_ .
    83  
    84  From an authentication perspective, the TLS model relies on a "Certificate Authority" (CA) which is an
    85  entity that is trusted to create proof that a given network service (e.g., www.cilium.io)
    86  is who they say they are.   The goal is to prevents a malicious party in the network between the client
    87  and the server from intercepting the traffic and pretending to be the destination server.
    88  
    89  In the case of "friendly interception" for network security monitoring, Cilium uses a model similar to
    90  traditional firewalls with TLS inspection capabilities:  the network security team creates their own "internal
    91  certificate authority"
    92  that can be used to create alternative certificates for external destinations.  This model requires each
    93  client workload to also trust this new certificate, otherwise the client's TLS library will reject
    94  the connection as invalid.  In this model, the network firewall uses the certificate signed by the internal
    95  CA to act like the destination service and terminate the TLS connection.  This allows the firewall to
    96  inspect and even modify the application layer data, and then initiate another TLS connect to the actual
    97  destination service.
    98  
    99  The CA model within TLS is based on cryptographic keys and certificates.  Realizing the above model
   100  requires four primary steps:
   101  
   102  1) Create an internal certificate authority by generating a CA private key and CA certificate.
   103  
   104  2) For any destination where TLS inspection is desired (e.g., artii.herokuapp.com in the example below),
   105     generate a private key and certificate signing request with a common name that matches the destination DNS
   106     name.
   107  
   108  3) Use the CA private key to create a signed certificate.
   109  
   110  4) Ensure that all clients where TLS inspection is have the CA certificate installed so that they will
   111     trust all certificates signed by that CA.
   112  
   113  5) Given that Cilium will be terminating the initial TLS connection from the
   114     client and creating a new TLS connection to the destination, Cilium must be told the set of CAs that it
   115     should trust when validating the new TLS connection to the destination service.
   116  
   117  .. note::
   118  
   119      In a non-demo environment it is EXTREMELY important that you keep the above private keys safe, as anyone
   120      with access to this private key will be able to inspect TLS-encrypted traffic (certificates on the other
   121      hand are public information, and are not at all sensitive).  In the guide below, the
   122      CA private key does not need to be provided to Cilium at all (it is used only to create certificates, which
   123      can be done offline) and private keys for individual destination services are stored as Kubernetes secrets.
   124      These secrets should be stored in a namespace where they can be accessed by Cilium, but not general purpose
   125      workloads.
   126  
   127  Generating and Installing TLS Keys and Certificates
   128  ===================================================
   129  
   130  Now that we have explained the high-level certificate model used by TLS, we will walk through the
   131  concrete steps to generate the appropriate keys and certificates using the ``openssl`` utility.
   132  
   133  The following image describes the different files containing cryptographic data that are generated
   134  or copied, and what components in the system need access to those files:
   135  
   136  .. image:: images/cilium_tls_visibility_gsg.png
   137  
   138  You can use openssl on your local system if it is already installed, but if not a simple
   139  shortcut is to use ``kubectl exec`` to execute ``/bin/bash`` within any of the cilium pods, and
   140  then run the resulting ``openssl`` commands.  Use ``kubectl cp`` to copy the resulting files out
   141  of the cilium pod when it is time to use them to create Kubernetes secrets of copy them to the
   142  ``mediabot`` pod.
   143  
   144  Create an Internal Certificate Authority (CA)
   145  ---------------------------------------------
   146  
   147  Generate CA private key named 'myCA.key':
   148  
   149  .. code-block:: shell-session
   150  
   151      $ openssl genrsa -des3 -out myCA.key 2048
   152  
   153  Enter any password, just remember it for some of the later steps.
   154  
   155  Generate CA certificate from the private key:
   156  
   157  .. code-block:: shell-session
   158  
   159      $ openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.crt
   160  
   161  The values you enter for each prompt do not need to be any specific value, and do not need to be
   162  accurate.
   163  
   164  Create Private Key and Certificate Signing Request for a Given DNS Name
   165  -----------------------------------------------------------------------
   166  
   167  Generate an internal private key and certificate signing with a common name that matches the DNS name
   168  of the destination service to be intercepted for inspection (in this example, use ``artii.herokuapp.com``).
   169  
   170  First create the private key:
   171  
   172  .. code-block:: shell-session
   173  
   174      $ openssl genrsa -out internal-artii.key 2048
   175  
   176  Next, create a certificate signing request, specifying the DNS name of the destination service
   177  for the common name field when prompted.  All other prompts can be filled with any value.
   178  
   179  .. code-block:: shell-session
   180  
   181      $ openssl req -new -key internal-artii.key -out internal-artii.csr
   182  
   183  The only field that must be a specific value is ensuring that ``Common Name`` is the exact DNS
   184  destination ``artii.herokuapp.com`` that will be provided to the client.
   185  
   186  
   187  This example workflow will work for any DNS
   188  name as long as the toFQDNs rule in the policy YAML (below) is also updated to match the DNS name in the certificate.
   189  
   190  
   191  Use CA to Generate a Signed Certificate for the DNS Name
   192  --------------------------------------------------------
   193  
   194  Use the internal CA private key to create a signed certificate for artii.herokuapp.com named ``internal-artii.crt``.
   195  
   196  .. code-block:: shell-session
   197  
   198      $ openssl x509 -req -days 360 -in internal-artii.csr -CA myCA.crt -CAkey myCA.key -CAcreateserial -out internal-artii.crt -sha256
   199  
   200  Next we create a Kubernetes secret that includes both the private key and signed certificates for the destination service:
   201  
   202  .. code-block:: shell-session
   203  
   204      $ kubectl create secret tls artii-tls-data -n kube-system --cert=internal-artii.crt --key=internal-artii.key
   205  
   206  Add the Internal CA as a Trusted CA Inside the Client Pod
   207  ---------------------------------------------------------
   208  
   209  Once the CA certificate is inside the client pod, we still must make sure that the CA file is picked up by the TLS library used by your
   210  application.  Most Linux applications automatically use a set of trusted CA certificates that are bundled along with the Linux distro.
   211  In this guide, we are using an Ubuntu container as the client, and so will update it with Ubuntu specific instructions.  Other Linux distros
   212  will have different mechanisms.  Also, individual applications may leverage their own certificate stores rather than use the OS certificate
   213  store.  Java applications and the aws-cli are two common examples.  Please refer to the application or application runtime documentation
   214  for more details.
   215  
   216  For Ubuntu, we first copy the additional CA certificate to the client pod filesystem
   217  
   218  .. code-block:: shell-session
   219  
   220      $ kubectl cp myCA.crt default/mediabot:/usr/local/share/ca-certificates/myCA.crt
   221  
   222  Then run the Ubuntu-specific utility that adds this certificate to the global set of trusted certificate authorities in /etc/ssl/certs/ca-certificates.crt .
   223  
   224  
   225  .. code-block:: shell-session
   226  
   227      $ kubectl exec mediabot -- update-ca-certificates
   228  
   229  This command will issue a WARNING, but this can be ignored.
   230  
   231  Provide Cilium with List of Trusted CAs
   232  ---------------------------------------
   233  
   234  Next, we will provide Cilium with the set of CAs that it should trust when originating the secondary TLS connections.
   235  This list should correspond to the standard set of global CAs that your organization trusts.  A logical option for this is the standard CAs
   236  that are trusted by your operating system, since this is the set of CAs that were being used prior to introducing TLS inspection.
   237  
   238  To keep things simple, in this example we will simply copy this list out of the Ubuntu filesystem of the mediabot pod, though it is
   239  important to understand that this list of trusted CAs is not specific to a particular TLS client or server, and so this step need only
   240  be performed once regardless of how many TLS clients or servers are involved in TLS inspection.
   241  
   242  .. code-block:: shell-session
   243  
   244      $ kubectl cp default/mediabot:/etc/ssl/certs/ca-certificates.crt ca-certificates.crt
   245  
   246  We then will create a Kubernetes secret using this certificate bundle so that Cilium can read the
   247  certificate bundle and use it to validate outgoing TLS connections.
   248  
   249  
   250  .. code-block:: shell-session
   251  
   252      $ kubectl create secret generic tls-orig-data -n kube-system --from-file=ca.crt=./ca-certificates.crt
   253  
   254  
   255  Apply DNS and TLS-aware Egress Policy
   256  =====================================
   257  
   258  Up to this point, we have created keys and certificates to enable TLS inspection, but we
   259  have not told Cilium which traffic we want to intercept and inspect.   This is done using
   260  the same Cilium Network Policy constructs that are used for other Cilium Network Policies.
   261  
   262  The following Cilium network policy indicates that Cilium should perform HTTP-aware inspect
   263  of communication between the ``mediabot`` pod to ``artii.herokuapp.com``.
   264  
   265  .. literalinclude:: ../../examples/kubernetes-tls-inspection/l7-visibility-tls.yaml
   266  
   267  Let's take a closer look at the policy:
   268  
   269  * The ``endpointSelector`` means that this policy will only apply to pods with labels ``class: mediabot, org:empire`` to have the egress access.
   270  * The first egress section uses ``toFQDNs: matchName`` specification to allow TCP port 443 egress to ``artii.herokuapp.com``.
   271  * The ``http`` section below the toFQDNs rule
   272    indicates that such connections should be parsed as HTTP, with a policy of ``{}`` which will allow all requests.
   273  * The ``terminatingTLS`` and ``originatingTLS`` sections indicate that TLS interception should be used to terminate the initial TLS connection
   274    from mediabot and initiate a new out-bound TLS connection to ``artii.herokuapp.com``.
   275  * The second egress section allows ``mediabot`` pods to access ``kube-dns`` service. Note that
   276    ``rules: dns`` instructs Cilium to inspect and allow DNS lookups matching specified patterns.
   277    In this case, inspect and allow all DNS queries.
   278  
   279  Note that with this policy the ``mediabot`` doesn't have access to any internal cluster service other than ``kube-dns``
   280  and will have no access to any other external destinations either. Refer to :ref:`Network Policy`
   281  to learn more about policies for controlling access to internal cluster services.
   282  
   283  Let's apply the policy:
   284  
   285  .. parsed-literal::
   286  
   287    $ kubectl create -f \ |SCM_WEB|\/examples/kubernetes-tls-inspection/l7-visibility-tls.yaml
   288  
   289  
   290  Demonstrating TLS Inspection
   291  ============================
   292  
   293  Recall that the policy we pushed will allow all HTTPS requests from ``mediabot`` to ``artii.herokuapp.com``, but will parse all data at
   294  the HTTP-layer, meaning that cilium monitor will report each HTTP request and response.
   295  
   296  To see this, open a new window and run the following command to identity the name of the
   297  cilium pod (e.g, cilium-97s78) that is running on the same Kubernetes worker node as the ``mediabot`` pod.
   298  
   299  Then start running cilium-dbg monitor in "L7 mode" to monitor for HTTP requests being reported by Cilium:
   300  
   301  .. code-block:: shell-session
   302  
   303      $ kubectl exec -it -n kube-system cilium-d5x8v -- cilium-dbg monitor -t l7
   304  
   305  Next in the original window, from the ``mediabot`` pod we can access ``artii.herokuapp.com`` via HTTPS:
   306  
   307  .. code-block:: shell-session
   308  
   309      $ kubectl exec -it mediabot -- curl -sL 'https://artii.herokuapp.com/fonts_list'
   310      ...
   311      ...
   312  
   313      $ kubectl exec -it mediabot -- curl -sL 'https://artii.herokuapp.com/make?text=cilium&font=univers'
   314      ...
   315      ...
   316  
   317  Looking back at the cilium-dbg monitor window, you will see each individual HTTP request and response.  For example::
   318  
   319      -> Request http from 2585 ([k8s:class=mediabot k8s:org=empire k8s:io.kubernetes.pod.namespace=default k8s:io.cilium.k8s.policy.serviceaccount=default k8s:io.cilium.k8s.policy.cluster=default]) to 0 ([reserved:world]), identity 24948->2, verdict Forwarded GET https://artii.herokuapp.com/fonts_list => 0
   320      -> Response http to 2585 ([k8s:io.kubernetes.pod.namespace=default k8s:io.cilium.k8s.policy.serviceaccount=default k8s:io.cilium.k8s.policy.cluster=default k8s:class=mediabot k8s:org=empire]) from 0 ([reserved:world]), identity 24948->2, verdict Forwarded GET https://artii.herokuapp.com/fonts_list => 200
   321  
   322  Refer to :ref:`l4_policy` and :ref:`l7_policy` to learn more about Cilium L4 and L7 network policies.
   323  
   324  Clean-up
   325  ========
   326  
   327  .. parsed-literal::
   328  
   329     $ kubectl delete -f \ |SCM_WEB|\/examples/kubernetes-dns/dns-sw-app.yaml
   330     $ kubectl delete cnp l7-visibility-tls
   331     $ kubectl delete secret -n kube-system tls-orig-data
   332     $ kubectl delete secret -n kube-system artii-tls-data