Skip to content

Commit

Permalink
Adding Locust as performance OQS tool (#304)
Browse files Browse the repository at this point in the history
* Adding Locust as performance OQS tool

Signed-off-by: davidgca <[email protected]>

* Add contributor in oqs-demo README

Signed-off-by: davidgca <[email protected]>

* Modify USAGE.md to add a basic Locust example

Signed-off-by: davidgca <[email protected]>

* Changes some version numbers as suggested by @ajbozarth and style changes

Signed-off-by: davidgca <[email protected]>

* Refactor curve to group

Signed-off-by: davidgca <[email protected]>

* Moved CI DockerHub image push to a future PR

Signed-off-by: davidgca <[email protected]>

---------

Signed-off-by: davidgca <[email protected]>
Signed-off-by: davidgca <[email protected]>
  • Loading branch information
davidgca authored Oct 31, 2024
1 parent 7c913f8 commit 22966f6
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 17 deletions.
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


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
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

0 comments on commit 22966f6

Please sign in to comment.