# kubelogin/system_test

This is an automated test for verifying behavior of the plugin with a real Kubernetes cluster and OIDC provider.

## Purpose

This test checks the following points:

1. User can set up Kubernetes OIDC authentication using the [setup guide](../docs/setup.md).
1. User can log in to an OIDC provider on a browser.
1. User can access the cluster using a token returned from the plugin.

It depends on the following components:

- Kubernetes cluster (Kind)
- OIDC provider (Dex)
- Browser (Chrome)
- kubectl command

## How it works

Let's take a look at the diagram.

![diagram](../docs/system-test-diagram.svg)

It prepares the following resources:

1. Generate a pair of CA certificate and TLS server certificate for Dex.
1. Run Dex on a container.
1. Create a Kubernetes cluster using Kind.
1. Mutate `/etc/hosts` of the machine so that the browser access Dex.
1. Mutate `/etc/hosts` of the kind container so that kube-apiserver access Dex.

It performs the test by the following steps:

1. Run kubectl.
1. kubectl automatically runs kubelogin.
1. kubelogin automatically runs [chromelogin](login/chromelogin).
1. chromelogin opens the browser, navigates to `http://localhost:8000` and enter the username and password.
1. kubelogin gets an authorization code from the browser.
1. kubelogin gets a token.
1. kubectl accesses an API with the token.
1. kube-apiserver verifies the token by Dex.
1. Check if kubectl exited with code 0.

## Run locally

You need to set up the following components:

- Docker
- Kind
- Chrome or Chromium

Add the following line to `/etc/hosts` so that the browser can access the Dex.

```
127.0.0.1 dex-server
```

Generate CA certificate and add `cert/ca.crt` into your trust store.
For macOS, you can add it by Keychain.

```shell script
make -C cert
```

Run the test.

```shell script
make
```

Clean up.

```shell script
make terminate
make clean
```

## Technical consideration

### Network and DNS

Consider the following issues:

- kube-apiserver runs on the host network of the kind container.
- kube-apiserver cannot resolve a service name by kube-dns.
- kube-apiserver cannot access a cluster IP.
- kube-apiserver can access another container via the Docker network.
- Chrome requires exactly match of domain name between Dex URL and a server certificate.

Consequently,

- kube-apiserver accesses Dex by resolving `/etc/hosts` and via the Docker network.
- kubelogin and Chrome accesses Dex by resolving `/etc/hosts` and via the Docker network.

### TLS server certificate

Consider the following issues:

- kube-apiserver requires `--oidc-issuer` is HTTPS URL.
- kube-apiserver requires a CA certificate at startup, if `--oidc-ca-file` is given.
- kube-apiserver mounts `/usr/local/share/ca-certificates` from the kind container.
- It is possible to mount a file from the CI machine.
- It is not possible to issue a certificate using Let's Encrypt in runtime.
- Chrome requires a valid certificate in `~/.pki/nssdb`.

As a result,

- kube-apiserver uses the CA certificate of `/usr/local/share/ca-certificates/dex-ca.crt`. See the `extraMounts` section of [`cluster.yaml`](cluster/cluster.yaml).
- kubelogin uses the CA certificate in `output/ca.crt`.
- Chrome uses the CA certificate in `~/.pki/nssdb`.

### Test environment

- Set the issuer URL to kube-apiserver. See [`cluster.yaml`](cluster/cluster.yaml).
- Set `BROWSER` environment variable to run [`chromelogin`](login/chromelogin) by `xdg-open`.
