diff --git a/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md b/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md index cd7baa9aff..1f86c7b652 100644 --- a/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -38,7 +38,7 @@ A **ClusterIP** service is the **default** Kubernetes **service**. It gives you However, this can be accessed using the Kubernetes Proxy: -``` +```bash kubectl proxy --port=8080 ``` @@ -58,7 +58,7 @@ kind: Service metadata: name: my-internal-service spec: - selector: + selector: app: my-app type: ClusterIP ports: @@ -70,9 +70,25 @@ spec: _This method requires you to run `kubectl` as an **authenticated user**._ +List all ClusterIPs: + +{% code overflow="wrap" %} +```bash +kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP +``` +{% endcode %} + ### NodePort -When **NodePort** is utilized, a designated port is made available on all Nodes (representing the Virtual Machines). **Traffic** directed to this specific port is then systematically **routed to the service**. Typically, this method is not recommended due to its drawbacks. +When **NodePort** is utilised, a designated port is made available on all Nodes (representing the Virtual Machines). **Traffic** directed to this specific port is then systematically **routed to the service**. Typically, this method is not recommended due to its drawbacks. + +List all NodePorts: + +{% code overflow="wrap" %} +```bash +kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort +``` +{% endcode %} An example of NodePort specification: @@ -95,34 +111,28 @@ spec: If you **don't specify** the **nodePort** in the yaml (it's the port that will be opened) a port in the **range 30000–32767 will be used**. -### LoadBalancer +### LoadBalancer -Exposes the Service externally **using a cloud provider's load balancer**. On GKE, this will spin up a [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) that will give you a single IP address that will forward all traffic to your service. - -You have to pay for a LoadBalancer per exposed service, which can get expensive. - -### ExternalName +Exposes the Service externally **using a cloud provider's load balancer**. On GKE, this will spin up a [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) that will give you a single IP address that will forward all traffic to your service. In AWS it will launch a Load Balancer. -**[From the docs:](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)** -Services of type ExternalName **map a Service to a DNS name**, not to a typical selector such as `my-service` or `cassandra`. You specify these Services with the `spec.externalName` parameter. +You have to pay for a LoadBalancer per exposed service, which can be expensive. -This Service definition, for example, maps the `my-service` Service in the `prod` namespace to `my.database.example.com`: +List all LoadBalancers: -```yaml -apiVersion: v1 -kind: Service -metadata: - name: my-service - namespace: prod -spec: - type: ExternalName - externalName: my.database.example.com +{% code overflow="wrap" %} +```bash +kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer ``` - -When looking up the host `my-service.prod.svc.cluster.local`, the cluster DNS Service returns a `CNAME` record with the value `my.database.example.com`. Accessing `my-service` works in the same way as other Services but with the crucial difference that **redirection happens at the DNS level** rather than via proxying or forwarding. +{% endcode %} ### External IPs +{% hint style="success" %} +External IPs are exposed by services of type Load Balancers and they are generally used when an external Cloud Provider Load Balancer is being used. + +For finding them, check for load balancers with values in the `EXTERNAL-IP` field. +{% endhint %} + Traffic that ingresses into the cluster with the **external IP** (as **destination IP**), on the Service port, will be **routed to one of the Service endpoints**. `externalIPs` are not managed by Kubernetes and are the responsibility of the cluster administrator. In the Service spec, `externalIPs` can be specified along with any of the `ServiceTypes`. In the example below, "`my-service`" can be accessed by clients on "`80.11.12.10:80`" (`externalIP:port`) @@ -144,9 +154,36 @@ spec: - 80.11.12.10 ``` +### ExternalName + +[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services of type ExternalName **map a Service to a DNS name**, not to a typical selector such as `my-service` or `cassandra`. You specify these Services with the `spec.externalName` parameter. + +This Service definition, for example, maps the `my-service` Service in the `prod` namespace to `my.database.example.com`: + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: my-service + namespace: prod +spec: + type: ExternalName + externalName: my.database.example.com +``` + +When looking up the host `my-service.prod.svc.cluster.local`, the cluster DNS Service returns a `CNAME` record with the value `my.database.example.com`. Accessing `my-service` works in the same way as other Services but with the crucial difference that **redirection happens at the DNS level** rather than via proxying or forwarding. + +List all ExternalNames: + +{% code overflow="wrap" %} +```bash +kubectl get services --all-namespaces | grep ExternalName +``` +{% endcode %} + ### Ingress -Unlike all the above examples, **Ingress is NOT a type of service**. Instead, it sits i**n front of multiple services and act as a “smart router”** or entrypoint into your cluster. +Unlike all the above examples, **Ingress is NOT a type of service**. Instead, it sits **in front of multiple services and act as a “smart router”** or entrypoint into your cluster. You can do a lot of different things with an Ingress, and there are **many types of Ingress controllers that have different capabilities**. @@ -179,6 +216,20 @@ spec: servicePort: 8080 ``` +List all the ingresses: + +{% code overflow="wrap" %} +```bash +kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' +``` +{% endcode %} + +Although in this case it's better to get the info of each one by one to read it better: + +```bash +kubectl get ingresses --all-namespaces -o=yaml +``` + ### References * [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0)