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