# Ingressgateway

> Using Istio's Service Mesh Features

---

Site [llms.txt](/llms.txt)

---

To route HTTP(S) traffic into the cluster, we utilize the Ingress Gateway provided by Istio.

It can be configured using Istio's resources, like `Gateway`s and `VirtualService`s, and can leverage the functionalities of the [service mesh](/docs/kubernetes/network/servicemesh/).

The best source for detailed information about the specific features and the custom resources is [Istio's own documentation](https://istio.io/latest/docs/).

Also a good place to start is our [workshop example](https://zivgitlab.uni-muenster.de/wwu-it/kube/examples/-/tree/main/workshop) describing all components to route HTTPS Traffic to a service.

However, in the following, let's address some common questions related to the Ingressgateway in the University of Münster Kubernetes cluster.

## TLS Certificates

Istio resolves the secrets referenced by a `Gateway` in the namespace of the Ingressgateway, not in the namespace of the `Gateway` itself. Since you cannot create secrets in that namespace, we run a service that watches all gateways and copies every referenced secret from your namespace into the Ingressgateway's namespace, named `<namespace>--<secret-name>`. That copied name is the one your gateway has to reference, which is why the [security policies](/docs/kubernetes/security_policies/) require the prefix.

You do not have to trigger anything: the copy follows its source, so a renewal by the [certificate management](/docs/kubernetes/services/certificatemanagement/) is propagated automatically, and as soon as no gateway references a certificate any more, its copy is removed.

A server can reference secrets in three ways, each requiring a specific kind of secret:

| Field                      | Role                                            | Required secret                           |
| -------------------------- | ----------------------------------------------- | ----------------------------------------- |
| `tls.credentialName`       | server certificate                              | `kubernetes.io/tls`                       |
| `tls.credentialNames`      | server certificates (RSA + ECDSA on one server) | `kubernetes.io/tls`                       |
| `tls.caCertCredentialName` | client CA for mutual TLS                        | `Opaque`, with a `ca.crt` or `cacert` key |

This would for example serve the certificate stored in the secret `example-certificate` in the namespace `example`:

```yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: example
  namespace: example
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - example/example.uni-muenster.de
      port:
        name: https
        number: 443
        protocol: HTTPS
      tls:
        credentialName: example--example-certificate
        minProtocolVersion: TLSV1_3
        mode: SIMPLE
```

### Client Certificates

If you want your clients to authenticate with a certificate of their own, set the server to `mode: MUTUAL` and point `caCertCredentialName` at the CA you want to validate those client certificates against.

Note that this is not the same as the mTLS **inside** the [service mesh](/docs/kubernetes/network/servicemesh/), which is configured with a `PeerAuthentication` and secures the traffic between pods. The setting described here authenticates external clients at the Ingressgateway.

The CA is an `Opaque` secret in your namespace holding the CA certificate under the key `ca.crt` (`cacert` works as well):

```sh
kubectl --context kube-staging-ms1 -n example create secret generic client-cacert --from-file=ca.crt=ca.crt
```

Its name must end in `-cacert`, because Istio only recognises a secret as CA material with that suffix. Together with the namespace prefix, the server then references it as `example--client-cacert`:

```yaml
tls:
  mode: MUTUAL
  credentialName: example--example-certificate
  caCertCredentialName: example--client-cacert
```

### Debugging

A single faulty reference must not stop the certificates of all other namespaces from being propagated, so it is skipped instead. To keep the problem visible, a warning event is recorded on the `Gateway` in your own namespace.

You can see these either in your namespace's events (e.g. `kubectl --context kube-staging-ms1 -n my-namespace get events`) or directly on the resource (e.g. `kubectl --context kube-staging-ms1 -n my-namespace describe gateway my-gateway`).

| Reason                        | Cause                                                             |
| ----------------------------- | ----------------------------------------------------------------- |
| `SourceSecretNotFound`        | the referenced secret does not exist in your namespace            |
| `InvalidSourceSecret`         | wrong secret type, or a CA secret without a `ca.crt`/`cacert` key |
| `InvalidCaCertCredentialName` | `caCertCredentialName` does not end in `-cacert`                  |

Since the naming rules are already enforced when the `Gateway` is created, these events usually point at a secret that is missing, not yet created by the certificate management, or of the wrong type.

## Internal Services

The Istio Ingressgateways are reachable from outside of the University Network. If you still want to restrict your service to the university network, you can achieve this using an AuthorizationPolicy, as demonstrated in the following example:

```yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: example
  namespace: example
spec:
  rules:
    - from:
        - source:
            principals:
              - cluster.local/ns/istio-ingressgateway/sa/istio-ingressgateway-service-account
            remoteIpBlocks:
              - 10.0.0.0/8
              - 128.176.0.0/16
              - 2001:4cf0::/29
      to:
        - operation:
            ports:
              - "8080"
  selector:
    matchLabels:
      app.kubernetes.io/name: example
```

## Custom Error Pages

To enhance customer experience, we've replaced some Istio error pages with more user-friendly versions.
In the current setup, these error pages are set globally and cannot be customized by administrators.

### 503 - Service Unavailable

When our Istio Ingress Gateway can't find your service, a custom error page will inform the customer that the service is unavailable and advise them to contact the service administrator.

### 403 - Forbidden

By default, Istio responds with a `RBAC: Access Denied` message and a 403 HTTP status code if access is denied due to AuthorizationPolicies.

To display the custom error page instead, ensure that the label `custom-error.k8s.uni-muenster.de/enabled: "true"` is present on the pods and that all pods have an Istio Sidecar (which should already be in place due to the `AuthorizationPolicies`).
