Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Locust as performance OQS tool #304

Merged
merged 11 commits into from
Oct 31, 2024
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@ We are explicitly soliciting contributors to maintain those integrations labelle

Currently available integrations at their respective support level:

| | **Build instructions** | **Pre-built Docker image or binary files** | Support? |
| ---------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------- |
| **curl** | [Github: oqs-demos/curl](curl) | [Dockerhub: openquantumsafe/curl](https://hub.docker.com/repository/docker/openquantumsafe/curl), [Dockerhub: openquantumsafe/curl-quic](https://hub.docker.com/repository/docker/openquantumsafe/curl-quic) | @baentsch, @pi-314159
| **Apache httpd** | [Github: oqs-demos/httpd](httpd) | [Dockerhub: openquantumsafe/httpd](https://hub.docker.com/repository/docker/openquantumsafe/httpd) | @baentsch
| **nginx** | [Github: oqs-demos/nginx](nginx) | [Dockerhub: openquantumsafe/nginx](https://hub.docker.com/repository/docker/openquantumsafe/nginx), [Dockerhub: openquantumsafe/nginx-quic](https://hub.docker.com/repository/docker/openquantumsafe/nginx-quic) | @baentsch, @bhess, @pi-314159
| **Chromium** | [Github: oqs-demos/chromium](chromium) (limited support) | - | @pi-314159 |
| **OpenSSH** | [Github: oqs-demos/openssh](openssh) | [Dockerhub: openquantumsafe/openssh](https://hub.docker.com/repository/docker/openquantumsafe/openssh) | unsupported
| **Wireshark** | [Github: oqs-demos/wireshark](wireshark) | [Dockerhub: openquantumsafe/wireshark](https://hub.docker.com/repository/docker/openquantumsafe/wireshark) | unsupported
| **Epiphany** | [Github: oqs-demos/epiphany](epiphany) | [Dockerhub: openquantumsafe/epiphany](https://hub.docker.com/repository/docker/openquantumsafe/epiphany) | unsupported
| **OpenVPN** | [Github: oqs-demos/openvpn](openvpn) | [Dockerhub: openquantumsafe/openvpn](https://hub.docker.com/repository/docker/openquantumsafe/openvpn) | unsupported
| **ngtcp2** | [Github: oqs-demos/ngtcp2](ngtcp2) | Dockerhub: [Server: openquantumsafe/ngtcp2-server](https://hub.docker.com/repository/docker/openquantumsafe/ngtcp2-server), [Client: openquantumsafe/ngtcp2-client](https://hub.docker.com/repository/docker/openquantumsafe/ngtcp2-client) | unsupported
| **OpenLiteSpeed** | [Github: oqs-demos/openlitespeed](openlitespeed) | [ Dockerhub: openquantumsafe/openlitespeed](https://hub.docker.com/repository/docker/openquantumsafe/openlitespeed) | unsupported
| **h2load** | [Github: oqs-demos/h2load](h2load) | [ Dockerhub: openquantumsafe/h2load](https://hub.docker.com/repository/docker/openquantumsafe/h2load) | unsupported
| **HAproxy** | [Github: oqs-demos/haproxy](haproxy) | [Dockerhub: openquantumsafe/haproxy](https://hub.docker.com/repository/docker/openquantumsafe/haproxy) | unsupported
| **Mosquitto** | [Github: oqs-demos/mosquitto](mosquitto) | [Dockerhub: openquantumsafe/mosquitto](https://hub.docker.com/repository/docker/openquantumsafe/mosquitto) | unsupported
| **Envoy** | [Github: oqs-demos/envoy](envoy) | [ Dockerhub: openquantumsafe/envoy](https://hub.docker.com/repository/docker/openquantumsafe/envoy) | unsupported
| **Unbound** | [Github: oqs-demos/unbound](unbound) | [ Dockerhub: openquantumsafe/unbound](https://hub.docker.com/repository/docker/openquantumsafe/unbound) | unsupported
| | **Build instructions** | **Pre-built Docker image or binary files** | Support? |
|-------------------|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- |
| **curl** | [Github: oqs-demos/curl](curl) | [Dockerhub: openquantumsafe/curl](https://hub.docker.com/repository/docker/openquantumsafe/curl), [Dockerhub: openquantumsafe/curl-quic](https://hub.docker.com/repository/docker/openquantumsafe/curl-quic) | @baentsch, @pi-314159
| **Apache httpd** | [Github: oqs-demos/httpd](httpd) | [Dockerhub: openquantumsafe/httpd](https://hub.docker.com/repository/docker/openquantumsafe/httpd) | @baentsch
| **nginx** | [Github: oqs-demos/nginx](nginx) | [Dockerhub: openquantumsafe/nginx](https://hub.docker.com/repository/docker/openquantumsafe/nginx), [Dockerhub: openquantumsafe/nginx-quic](https://hub.docker.com/repository/docker/openquantumsafe/nginx-quic) | @baentsch, @bhess, @pi-314159
| **Chromium** | [Github: oqs-demos/chromium](chromium) (limited support) | - | @pi-314159 |
| **Locust** | [Github: oqs-demos/locust](locust) | - | @davidgca|
| **OpenSSH** | [Github: oqs-demos/openssh](openssh) | [Dockerhub: openquantumsafe/openssh](https://hub.docker.com/repository/docker/openquantumsafe/openssh) | unsupported
| **Wireshark** | [Github: oqs-demos/wireshark](wireshark) | [Dockerhub: openquantumsafe/wireshark](https://hub.docker.com/repository/docker/openquantumsafe/wireshark) | unsupported
| **Epiphany** | [Github: oqs-demos/epiphany](epiphany) | [Dockerhub: openquantumsafe/epiphany](https://hub.docker.com/repository/docker/openquantumsafe/epiphany) | unsupported
| **OpenVPN** | [Github: oqs-demos/openvpn](openvpn) | [Dockerhub: openquantumsafe/openvpn](https://hub.docker.com/repository/docker/openquantumsafe/openvpn) | unsupported
| **ngtcp2** | [Github: oqs-demos/ngtcp2](ngtcp2) | Dockerhub: [Server: openquantumsafe/ngtcp2-server](https://hub.docker.com/repository/docker/openquantumsafe/ngtcp2-server), [Client: openquantumsafe/ngtcp2-client](https://hub.docker.com/repository/docker/openquantumsafe/ngtcp2-client) | unsupported
| **OpenLiteSpeed** | [Github: oqs-demos/openlitespeed](openlitespeed) | [ Dockerhub: openquantumsafe/openlitespeed](https://hub.docker.com/repository/docker/openquantumsafe/openlitespeed) | unsupported
| **h2load** | [Github: oqs-demos/h2load](h2load) | [ Dockerhub: openquantumsafe/h2load](https://hub.docker.com/repository/docker/openquantumsafe/h2load) | unsupported
| **HAproxy** | [Github: oqs-demos/haproxy](haproxy) | [Dockerhub: openquantumsafe/haproxy](https://hub.docker.com/repository/docker/openquantumsafe/haproxy) | unsupported
| **Mosquitto** | [Github: oqs-demos/mosquitto](mosquitto) | [Dockerhub: openquantumsafe/mosquitto](https://hub.docker.com/repository/docker/openquantumsafe/mosquitto) | unsupported
| **Envoy** | [Github: oqs-demos/envoy](envoy) | [ Dockerhub: openquantumsafe/envoy](https://hub.docker.com/repository/docker/openquantumsafe/envoy) | unsupported
| **Unbound** | [Github: oqs-demos/unbound](unbound) | [ Dockerhub: openquantumsafe/unbound](https://hub.docker.com/repository/docker/openquantumsafe/unbound) | unsupported
baentsch marked this conversation as resolved.
Show resolved Hide resolved


It should be possible to use the openssl (s_client), curl and GNOME Web/epiphany clients with all algorithm combinations available at the Open Quantum Safe TLS/X.509 interoperability test server at https://test.openquantumsafe.org (set up using `oqs-provider v0.6.1` and `liboqs v0.10.1`) but no guarantees are given for software not explicitly labelled with the name of a person offering support for it. Since [OQS-BoringSSL](https://github.com/open-quantum-safe/boringssl) no longer maintains the same set of algorithms, software that depends on OQS-BoringSSL (e.g., nginx-quic and curl-quic) may not fully (inter)operate with the test server.

Expand Down Expand Up @@ -62,6 +64,7 @@ All modifications to this repository are released under the same terms as [liboq
Dindyal Jeevesh Rishi (University of Mauritius / cyberstorm.mu)
Dan Rouhana (University of Washington)
JT (Henan Raytonne Trading Company)
David Gomez-Cambronero (Telefonica Innovacion digital)

## Acknowledgments

Expand Down
115 changes: 115 additions & 0 deletions locust/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# define the liboqs tag to be used
ARG LIBOQS_TAG=0.11.0

# define the oqsprovider tag to be used
ARG OQSPROVIDER_TAG=0.7.0

# define the openssl version to be baked in
ARG OPENSSL_BRANCH=openssl-3.3.2

# Default location where all binaries wind up:
ARG INSTALLDIR=/opt/oqssa

# Default Python version to be used
ARG PYTHON_VERSION=3.12.6

# liboqs build type variant; maximum portability of image:
ARG LIBOQS_BUILD_DEFINES="-DOQS_DIST_BUILD=ON"

# Default root CA signature algorithm; can be set to any listed at https://github.com/open-quantum-safe/oqs-provider#algorithms
ARG SIG_ALG="dilithium3"

# Default KEM algorithms; can be set to any listed at https://github.com/open-quantum-safe/oqs-provider#algorithms
ARG DEFAULT_GROUPS="x25519:x448:kyber512:p256_kyber512:kyber768:p384_kyber768:kyber1024:p521_kyber1024"

# Define the degree of parallelism when building the image; leave the number away only if you know what you are doing
ARG MAKE_DEFINES="-j 16"

# Define the Alpine version to be used
ARG ALPINE_VERSION=3.20.3

FROM alpine:${ALPINE_VERSION}
# Take in all global args
ARG LIBOQS_TAG
ARG OQSPROVIDER_TAG
ARG INSTALLDIR
ARG LIBOQS_BUILD_DEFINES
ARG SIG_ALG
ARG DEFAULT_GROUPS
ARG MAKE_DEFINES
ARG PYTHON_VERSION
ARG OPENSSL_BRANCH

LABEL version="1"

ENV DEBIAN_FRONTEND noninteractive
ENV LD_LIBRARY_PATH=${INSTALLDIR}/lib

RUN apk update && apk upgrade

# Get all software packages required for builing all components:
RUN apk add build-base linux-headers \
libtool automake autoconf cmake ninja \
make \
git wget vim nano zlib-dev py3-pip tcpdump python3-dev

# get all sources
WORKDIR /opt
RUN git clone --depth 1 --branch ${LIBOQS_TAG} https://github.com/open-quantum-safe/liboqs && \
git clone --depth 1 --branch ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git && \
git clone --depth 1 --branch ${OQSPROVIDER_TAG} https://github.com/open-quantum-safe/oqs-provider.git

# build OpenSSL3
WORKDIR /opt/openssl
RUN LDFLAGS="-Wl,-rpath -Wl,${INSTALLDIR}/lib64" ./config shared enable-zlib no-comp --prefix=${INSTALLDIR} && \
make ${MAKE_DEFINES} && make install_sw install_ssldirs install_dev && \
if [ -d ${INSTALLDIR}/lib64 ]; then ln -s ${INSTALLDIR}/lib64 ${INSTALLDIR}/lib; fi && \
if [ -d ${INSTALLDIR}/lib ]; then ln -s ${INSTALLDIR}/lib ${INSTALLDIR}/lib64; fi


# build liboqs
WORKDIR /opt/liboqs
RUN mkdir build && \
cd build && \
cmake -G"Ninja" .. ${LIBOQS_BUILD_DEFINES} -DCMAKE_INSTALL_PREFIX=${INSTALLDIR} && \
ninja install

# set path to use 'new' openssl. Dyn libs have been properly linked in to match
ENV PATH="${INSTALLDIR}/bin:${PATH}"
ENV LD_LIBRARY_PATH=${INSTALLDIR}/lib

# build & install provider (and activate by default)
WORKDIR /opt/oqs-provider
RUN ln -s ../openssl . && \
cmake -DOPENSSL_ROOT_DIR=${INSTALLDIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=${INSTALLDIR} -S . -B _build && \
cmake --build _build && \
cp _build/lib/oqsprovider.so ${INSTALLDIR}/lib64/ossl-modules && \
sed -i "s/default = default_sect/default = default_sect\noqsprovider = oqsprovider_sect/g" /opt/oqssa/ssl/openssl.cnf && \
sed -i "s/\[default_sect\]/\[default_sect\]\nactivate = 1\n\[oqsprovider_sect\]\nactivate = 1\n/g" /opt/oqssa/ssl/openssl.cnf && \
sed -i "s/providers = provider_sect/providers = provider_sect\nssl_conf = ssl_sect\n\n\[ssl_sect\]\nsystem_default = system_default_sect\n\n\[system_default_sect\]\nGroups = \$ENV\:\:DEFAULT_GROUPS\n/g" /opt/oqssa/ssl/openssl.cnf && \
sed -i "s/\# Use this in order to automatically load providers/\# Set default KEM groups if not set via environment variable\nKDEFAULT_GROUPS = $DEFAULT_GROUPS\n\n# Use this in order to automatically load providers/g" /opt/oqssa/ssl/openssl.cnf && \
sed -i "s/HOME\t\t\t= ./HOME\t\t= .\nDEFAULT_GROUPS\t= ${DEFAULT_GROUPS}/g" /opt/oqssa/ssl/openssl.cnf

# generate certificates for openssl s_server
ENV OPENSSL=${INSTALLDIR}/bin/openssl
ENV OPENSSL_CNF=${INSTALLDIR}/ssl/openssl.cnf

WORKDIR ${INSTALLDIR}/bin
# generate CA key and cert
RUN set -x; \
${OPENSSL} req -x509 -new -newkey ${SIG_ALG} -keyout CA.key -out CA.crt -nodes -subj "/CN=oqstest CA" -days 365 -config ${OPENSSL_CNF}

# Download current test.openquantumsafe.org test CA cert
WORKDIR ${INSTALLDIR}
RUN wget --no-check-certificate https://test.openquantumsafe.org/CA.crt && \
mv CA.crt oqs-testca.pem

# Install Locust
RUN mkdir /home/locust && cd /home/locust
ENV CFLAGS="-I/opt/python-${PYTHON_VERSION}-custom/include/${PYTHON_VERSION}"
ENV LDFLAGS="-L/opt/python-${PYTHON_VERSION}-custom/lib"
COPY requirements.txt /home/locust
RUN pip3 install --break-system-packages --upgrade pip
RUN pip3 install --break-system-packages -r /home/locust/requirements.txt
ADD / /mnt/locust

32 changes: 32 additions & 0 deletions locust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Purpose
This directory contains a Dockerfile that builds Locust using OpenSSL v3 using the [OQS provider](https://github.com/open-quantum-safe/oqs-provider) and Python3, which allows `Locust` to negotiate quantum-safe keys and use quantum-safe authentication in TLS 1.3.

For more information on `Locust`, see the [official Locust project](https://github.com/locustio/locust).

## Quick start

1) Be sure to have [docker installed](https://docs.docker.com/install).
2) Run `docker build -t oqs-locust:0.0.1 .` to create a post quantum-enabled Locust docker image.
3) In order to configure endpoints and their weight, modify the file [scenarios/locustfile.py](scenarios/locustfile.py), more information can be found in [USAGE.md](USAGE.md)
4) To verify all components perform quantum-safe operations, first start the container with docker compose

```
LOGGER_LEVEL=DEBUG HOST=https://YOUR_QS_HOST:4433 docker compose up --scale worker=8
```
4) Connect to the locust web interface at `http://localhost:8189` and start a load test.


## Notes on this Version:

In this version, we utilize the subprocess module to execute the oqs-openssl command within Locust. Ideally, the objective should be to leverage native Python libraries. However, as of now, there are no Python libraries that support quantum-safe (QS) group for TLS 1.3. Once such libraries become available, we should prioritize recompiling Python (for add the OQS-openssl version) and using the appropriate Python libraries for this functionality.

For further reference on the Locust API, please refer to the official documentation [here](https://docs.locust.io/en/stable/).

## Usage

Information how to use locust: [available in the separate file USAGE.md](USAGE.md).

## Disclaimer

[THIS IS NOT FIT FOR PRODUCTION USE]

56 changes: 56 additions & 0 deletions locust/USAGE.md
davidgca marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## Purpose
This directory contains a Dockerfile that builds the [OpenSSL v3](https://github.com/openssl/openssl) [OQS provider](https://github.com/open-quantum-safe/oqs-provider), and Python3 which allows locust to negotiate quantum-safe keys in TLS 1.3.

## Start
1) Run `docker build -t oqs-locust:0.0.1 .` to create a post quantum-enabled Locust docker image.
2) To verify all components perform quantum-safe operations, first start the container with docker compose, setting all environment variables as needed. For example:
```
LOGGER_LEVEL=DEBUG HOST=https://YOUR_QS_HOST:4433 GROUP=kyber1024 docker compose up --scale worker=8
```
3) Connect to the locust web interface at `http://localhost:8189` and start a load test.

By default, Locust supports all algorithms supported by the OQS openssl.

Some environments variables you need to know
- LOGGER_LEVEL: Set the log level for the locust master and worker. Default is ERROR.
- HOST: Set the host to test. Default is https://test:4433
- WORKERS: Set the number of workers. Default is 8. Ideally, the number of workers should be the same as the number of cores in the machine.
- MASTER_PORT: Set the port for the master. Default is 8189.
- GROUP: Set the key exchange scheme for openssl. Default is kyber768.

In Locust web server, you need to set 2 variables:
- Number of users to simulate: The number of users to simulate that will hit the server.
- Hatch rate: The rate per second in which users are spawned.

After that, you can start the test:

STATISTICS
![img.png](images/img.png)

CHARTS
![img.png](images/img_charts.png)

### HOW TO CREATE A PERFORMANCE SCENARIO IN LOCUST

Using Locust, you can configure a performance scenario. For this, you can use the following structure. Note: This is just a basic example, and the real implementation might use subprocess and openssl to handle post-quantum cryptographic curves, as in the actual [locustfile.py](scenarios/locustfile.py).

```python
from locust import HttpUser, TaskSet, task, between
class UserBehavior(TaskSet):
# on_start is called when a Locust starts, before any task is scheduled
def on_start(self):
self.index()
self.about()

# tasks is a list of tasks that a Locust will choose from to execute
# tasks are chosen with the weighted_task_set attribute
@task(1)
def index(self):
self.client.get("/")

# in this case the about task is twice as likely to be chosen as the index task
@task(2)
def about(self):
self.client.get("/about/")


Loading
Loading