Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions chromium-cdp-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Chromium CDP with Token Authentication

This example uses Chromium, a headless browser exposing a [CDP (Chrome DevTools Protocol)](https://chromedevtools.github.io/devtools-protocol/) websocket interface, with token-based authentication and persistent storage.

## Features

- **Token authentication**: All CDP requests (HTTP and WebSocket) require a valid token
- **Admin API**: Create, list, and revoke tokens via REST endpoints
- **Bootstrap token**: Set an initial admin token via environment variable
- **Persistent storage**: Token database is stored on a volume that survives restarts

## Running

1. Install the `kraft` CLI tool and a container runtime engine, for example [Docker](https://docs.docker.com/get-docker/).

1. Clone the examples repository and `cd` into the `examples/chromium-cdp-auth/` directory:

```console
git clone https://github.com/unikraft-cloud/examples
cd examples/chromium-cdp-auth/
```

1. Make sure to log into Unikraft Cloud by setting your token and a metro close to you.
This guide uses `fra` (Frankfurt, DE):

```console
export UKC_TOKEN=token
export UKC_METRO=fra
```

1. Set a bootstrap admin token that will be used for initial setup:

```console
export BOOTSTRAP_ADMIN_TOKEN=my-secret-admin-token
```

1. Deploy the app:

```console
./deploy.sh
```

The deploy script builds an erofs root filesystem, creates a persistent volume for the token database, and deploys the instance.

## Authentication

All CDP endpoints require a valid token, passed either as:
- **Query parameter**: `?token=<TOKEN>`
- **Authorization header**: `Authorization: Bearer <TOKEN>`

The bootstrap admin token (set via `BOOTSTRAP_ADMIN_TOKEN` env var) can be used for initial setup. Use it to create additional tokens.

### Token Management API (admin only)

**Create a token:**
```console
curl -X POST https://<instance-url>/api/tokens \
-H "Authorization: Bearer $BOOTSTRAP_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "my-client", "expiresInDays": 7}'
```

**List tokens:**
```console
curl https://<instance-url>/api/tokens \
-H "Authorization: Bearer $BOOTSTRAP_ADMIN_TOKEN"
```

**Revoke a token:**
```console
curl -X DELETE https://<instance-url>/api/tokens/<token> \
-H "Authorization: Bearer $BOOTSTRAP_ADMIN_TOKEN"
```

### Public Endpoints

- `GET /health` — health check (no auth required)

## Testing

To query the service you need to use a CDP client.
You can use the Python-based implementation in the `test/` directory:

```console
cd test/
python -m venv .venv
source .venv/bin/activate
pip install poetry
poetry install
```

Take a screenshot, passing the token as the last argument:

```console
python cdp-screenshot.py https://<instance-url> https://google.com screenshot.png <TOKEN>
```

Or set the token via environment variable:

```console
export CDP_TOKEN=<TOKEN>
python cdp-screenshot.py https://<instance-url> https://google.com screenshot.png
```

## Instance Management

List instances:
```console
kraft cloud instance list
```

Remove an instance:
```console
kraft cloud instance remove <instance-name>
```

## Learn more

- [CDP Documentation](https://chromedevtools.github.io/devtools-protocol/)
- [Unikraft Cloud's Documentation](https://unikraft.cloud/docs/)
- [Building `Dockerfile` Images with `Buildkit`](https://unikraft.org/guides/building-dockerfile-images-with-buildkit)

Use the `--help` option for detailed information on using Unikraft Cloud:

```console
kraft cloud --help
```

Or visit the [CLI Reference](https://unikraft.org/docs/cli/reference).
4 changes: 4 additions & 0 deletions chromium-cdp-auth/chromium-cdp/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/node_modules/
/.unikraft/
/.rootfs/
/*.png
5 changes: 5 additions & 0 deletions chromium-cdp-auth/chromium-cdp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/node_modules/
/.unikraft/
/.rootfs/
/*.png
/initrd
243 changes: 243 additions & 0 deletions chromium-cdp-auth/chromium-cdp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
FROM debian:bookworm AS build

ARG NODE_VERSION=22.8.0

RUN set -xe; \
apt-get -yqq update; \
apt-get -yqq install \
libcups2 \
libnss3 \
libatk1.0-0 \
libnspr4 \
libpango1.0-0 \
libasound2 \
libatspi2.0-0 \
libxdamage1 \
libatk-bridge2.0-0 \
libxkbcommon0 \
libdrm2 \
libxcomposite1 \
libxfixes3 \
libxrandr2 \
libgbm1 \
libnss3; \
apt-get -yqq install \
ca-certificates \
curl \
build-essential \
libssl-dev \
python3 \
git \
;

RUN set -xe; \
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION%%.*}.x | bash -; \
apt-get -yqq install nodejs \
;

WORKDIR /app
COPY package* .

RUN set -xe; \
npm install \
;

# Strip some binaries
RUN cd /root/.cache/ms-playwright/chromium-*/chrome-linux; \
strip chrome \
chrome_crashpad_handler \
chrome_sandbox \
chrome-wrapper \
libEGL.so \
libGLESv2.so \
libvk_swiftshader.so \
libvulkan.so.1 \
xdg-mime \
xdg-settings \
; \
cd /root/.cache/ms-playwright/chromium_headless_shell-*/chrome-linux; \
strip chrome \
headless_shell \
libEGL.so \
libGLESv2.so \
libvk_swiftshader.so \
libvulkan.so.1 \
; \
strip /usr/bin/node \
;

RUN mkdir /home/tmp

FROM scratch

# Create required directories.
COPY --from=build /home/tmp /tmp

# Chrome binary
COPY --from=build /root/.cache/ms-playwright /root/.cache/ms-playwright

# Chrome libraries
COPY --from=build /lib/x86_64-linux-gnu/libdl.so.2 \
/lib/x86_64-linux-gnu/libpthread.so.0 \
/lib/x86_64-linux-gnu/libgobject-2.0.so.0 \
/lib/x86_64-linux-gnu/libglib-2.0.so.0 \
/lib/x86_64-linux-gnu/libnss3.so \
/lib/x86_64-linux-gnu/libnssutil3.so \
/lib/x86_64-linux-gnu/libsmime3.so \
/lib/x86_64-linux-gnu/libnspr4.so \
/lib/x86_64-linux-gnu/libatk-1.0.so.0 \
/lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 \
/lib/x86_64-linux-gnu/libcups.so.2 \
/lib/x86_64-linux-gnu/libgio-2.0.so.0 \
/lib/x86_64-linux-gnu/libdrm.so.2 \
/lib/x86_64-linux-gnu/libdbus-1.so.3 \
/lib/x86_64-linux-gnu/libexpat.so.1 \
/lib/x86_64-linux-gnu/libxcb.so.1 \
/lib/x86_64-linux-gnu/libxkbcommon.so.0 \
/lib/x86_64-linux-gnu/libatspi.so.0 \
/lib/x86_64-linux-gnu/libm.so.6 \
/lib/x86_64-linux-gnu/libX11.so.6 \
/lib/x86_64-linux-gnu/libXcomposite.so.1 \
/lib/x86_64-linux-gnu/libXdamage.so.1 \
/lib/x86_64-linux-gnu/libXext.so.6 \
/lib/x86_64-linux-gnu/libXfixes.so.3 \
/lib/x86_64-linux-gnu/libXrandr.so.2 \
/lib/x86_64-linux-gnu/libgbm.so.1 \
/lib/x86_64-linux-gnu/libpango-1.0.so.0 \
/lib/x86_64-linux-gnu/libcairo.so.2 \
/lib/x86_64-linux-gnu/libasound.so.2 \
/lib/x86_64-linux-gnu/libgcc_s.so.1 \
/lib/x86_64-linux-gnu/libc.so.6 \
/lib/x86_64-linux-gnu/libffi.so.8 \
/lib/x86_64-linux-gnu/libpcre2-8.so.0 \
/lib/x86_64-linux-gnu/libplc4.so \
/lib/x86_64-linux-gnu/libplds4.so \
/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 \
/lib/x86_64-linux-gnu/libavahi-common.so.3 \
/lib/x86_64-linux-gnu/libavahi-client.so.3 \
/lib/x86_64-linux-gnu/libgnutls.so.30 \
/lib/x86_64-linux-gnu/libz.so.1 \
/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 \
/lib/x86_64-linux-gnu/libmount.so.1 \
/lib/x86_64-linux-gnu/libselinux.so.1 \
/lib/x86_64-linux-gnu/libsystemd.so.0 \
/lib/x86_64-linux-gnu/libXau.so.6 \
/lib/x86_64-linux-gnu/libXdmcp.so.6 \
/lib/x86_64-linux-gnu/libXi.so.6 \
/lib/x86_64-linux-gnu/libXrender.so.1 \
/lib/x86_64-linux-gnu/libwayland-server.so.0 \
/lib/x86_64-linux-gnu/libfribidi.so.0 \
/lib/x86_64-linux-gnu/libthai.so.0 \
/lib/x86_64-linux-gnu/libharfbuzz.so.0 \
/lib/x86_64-linux-gnu/libpixman-1.so.0 \
/lib/x86_64-linux-gnu/libfontconfig.so.1 \
/lib/x86_64-linux-gnu/libfreetype.so.6 \
/lib/x86_64-linux-gnu/libpng16.so.16 \
/lib/x86_64-linux-gnu/libxcb-shm.so.0 \
/lib/x86_64-linux-gnu/libxcb-render.so.0 \
/lib/x86_64-linux-gnu/libkrb5.so.3 \
/lib/x86_64-linux-gnu/libk5crypto.so.3 \
/lib/x86_64-linux-gnu/libcom_err.so.2 \
/lib/x86_64-linux-gnu/libkrb5support.so.0 \
/lib/x86_64-linux-gnu/libp11-kit.so.0 \
/lib/x86_64-linux-gnu/libidn2.so.0 \
/lib/x86_64-linux-gnu/libunistring.so.2 \
/lib/x86_64-linux-gnu/libtasn1.so.6 \
/lib/x86_64-linux-gnu/libnettle.so.8 \
/lib/x86_64-linux-gnu/libhogweed.so.6 \
/lib/x86_64-linux-gnu/libgmp.so.10 \
/lib/x86_64-linux-gnu/libblkid.so.1 \
/lib/x86_64-linux-gnu/libcap.so.2 \
/lib/x86_64-linux-gnu/libgcrypt.so.20 \
/lib/x86_64-linux-gnu/liblzma.so.5 \
/lib/x86_64-linux-gnu/libzstd.so.1 \
/lib/x86_64-linux-gnu/liblz4.so.1 \
/lib/x86_64-linux-gnu/libbsd.so.0 \
/lib/x86_64-linux-gnu/libdatrie.so.1 \
/lib/x86_64-linux-gnu/libgraphite2.so.3 \
/lib/x86_64-linux-gnu/libbrotlidec.so.1 \
/lib/x86_64-linux-gnu/libkeyutils.so.1 \
/lib/x86_64-linux-gnu/libresolv.so.2 \
/lib/x86_64-linux-gnu/libgpg-error.so.0 \
/lib/x86_64-linux-gnu/libmd.so.0 \
/lib/x86_64-linux-gnu/libbrotlicommon.so.1 \
/lib/x86_64-linux-gnu/libXcomposite.so.1 \
/lib/x86_64-linux-gnu/libXfixes.so.3 \
/lib/x86_64-linux-gnu/libXrandr.so.2 \
/lib/x86_64-linux-gnu/libgbm.so.1 \
/lib/x86_64-linux-gnu/

# Other Chrome-related libraries
COPY --from=build /usr/lib/x86_64-linux-gnu/libsoftokn3.so \
/usr/lib/x86_64-linux-gnu/libsqlite3.so.0 \
/usr/lib/x86_64-linux-gnu/libudev.so.1 \
/usr/lib/x86_64-linux-gnu/libfreebl3.so \
/usr/lib/x86_64-linux-gnu/libfreeblpriv3.so \
/usr/lib/x86_64-linux-gnu/libudev.so.1.7.5 \
/usr/lib/x86_64-linux-gnu/libnssckbi.so \
/usr/lib/x86_64-linux-gnu/

# Node binary
COPY --from=build /usr/bin/node /usr/bin/node

# System libraries
COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 \
/lib/x86_64-linux-gnu/libz.so.1 \
/lib/x86_64-linux-gnu/libbrotlidec.so.1 \
/lib/x86_64-linux-gnu/libbrotlienc.so.1 \
/lib/x86_64-linux-gnu/libnghttp2.so.14 \
/lib/x86_64-linux-gnu/libcrypto.so.3 \
/lib/x86_64-linux-gnu/libssl.so.3 \
/lib/x86_64-linux-gnu/libicui18n.so.72 \
/lib/x86_64-linux-gnu/libicuuc.so.72 \
/lib/x86_64-linux-gnu/libstdc++.so.6 \
/lib/x86_64-linux-gnu/libm.so.6 \
/lib/x86_64-linux-gnu/libgcc_s.so.1 \
/lib/x86_64-linux-gnu/libpthread.so.0 \
/lib/x86_64-linux-gnu/libdl.so.2 \
/lib/x86_64-linux-gnu/libbrotlicommon.so.1 \
/lib/x86_64-linux-gnu/libicudata.so.72 \
/lib/x86_64-linux-gnu/librt.so.1 \
/lib/x86_64-linux-gnu/libtinfo.so.6 \
/lib/x86_64-linux-gnu/libproc2.so.0 \
/lib/x86_64-linux-gnu/

COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=build /etc/ld.so.cache /etc/ld.so.cache

# Dbus and system files
COPY --from=build /usr/lib/dbus-1.0 /usr/lib/dbus-1.0
COPY --from=build /usr/lib/systemd /usr/lib/systemd
COPY --from=build /usr/lib/tmpfiles.d /usr/lib/tmpfiles.d
COPY --from=build /usr/lib/sysusers.d /usr/lib/sysusers.d
COPY --from=build /usr/lib/sysctl.d /usr/lib/sysctl.d

# Data files
COPY --from=build /usr/share/fonts /usr/share/fonts

COPY --from=build /run /run

# Distro definition
COPY --from=build /etc/os-release /etc/os-release
COPY --from=build /usr/lib/os-release /usr/lib/os-release

# Configuration files
COPY --from=build /etc /etc

# Required by wrapper script
COPY --from=build /bin/sh /bin/sh

# Required by Playwright / Chrome
COPY --from=build /usr/bin/ps /usr/bin/ps

# Node application, including Playwright.
COPY --from=build /app /app

# Actual server implementation
COPY ./proxy.js /app/proxy.js

# Default data directory (will be overridden by volume mount)
COPY --from=build /home/tmp /app/data

# Wrapper script set environment
COPY ./wrapper.sh /usr/bin/wrapper.sh
13 changes: 13 additions & 0 deletions chromium-cdp-auth/chromium-cdp/Kraftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
spec: v0.6

runtime: base-compat:latest

labels:
cloud.unikraft.v1.instances/scale_to_zero.policy: "idle"
cloud.unikraft.v1.instances/scale_to_zero.stateful: "true"
cloud.unikraft.v1.instances/scale_to_zero.cooldown_time_ms: 1000

#rootfs: ./Dockerfile
rootfs: ./initrd

cmd: ["/usr/bin/wrapper.sh", "/usr/bin/node", "/app/proxy.js"]
Loading
Loading