Skip to content

Commit 22966f6

Browse files
authored
Adding Locust as performance OQS tool (#304)
* 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]>
1 parent 7c913f8 commit 22966f6

File tree

9 files changed

+343
-17
lines changed

9 files changed

+343
-17
lines changed

README.md

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,25 @@ We are explicitly soliciting contributors to maintain those integrations labelle
1717

1818
Currently available integrations at their respective support level:
1919

20-
| | **Build instructions** | **Pre-built Docker image or binary files** | Support? |
21-
| ---------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------- |
22-
| **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
23-
| **Apache httpd** | [Github: oqs-demos/httpd](httpd) | [Dockerhub: openquantumsafe/httpd](https://hub.docker.com/repository/docker/openquantumsafe/httpd) | @baentsch
24-
| **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
25-
| **Chromium** | [Github: oqs-demos/chromium](chromium) (limited support) | - | @pi-314159 |
26-
| **OpenSSH** | [Github: oqs-demos/openssh](openssh) | [Dockerhub: openquantumsafe/openssh](https://hub.docker.com/repository/docker/openquantumsafe/openssh) | unsupported
27-
| **Wireshark** | [Github: oqs-demos/wireshark](wireshark) | [Dockerhub: openquantumsafe/wireshark](https://hub.docker.com/repository/docker/openquantumsafe/wireshark) | unsupported
28-
| **Epiphany** | [Github: oqs-demos/epiphany](epiphany) | [Dockerhub: openquantumsafe/epiphany](https://hub.docker.com/repository/docker/openquantumsafe/epiphany) | unsupported
29-
| **OpenVPN** | [Github: oqs-demos/openvpn](openvpn) | [Dockerhub: openquantumsafe/openvpn](https://hub.docker.com/repository/docker/openquantumsafe/openvpn) | unsupported
30-
| **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
31-
| **OpenLiteSpeed** | [Github: oqs-demos/openlitespeed](openlitespeed) | [ Dockerhub: openquantumsafe/openlitespeed](https://hub.docker.com/repository/docker/openquantumsafe/openlitespeed) | unsupported
32-
| **h2load** | [Github: oqs-demos/h2load](h2load) | [ Dockerhub: openquantumsafe/h2load](https://hub.docker.com/repository/docker/openquantumsafe/h2load) | unsupported
33-
| **HAproxy** | [Github: oqs-demos/haproxy](haproxy) | [Dockerhub: openquantumsafe/haproxy](https://hub.docker.com/repository/docker/openquantumsafe/haproxy) | unsupported
34-
| **Mosquitto** | [Github: oqs-demos/mosquitto](mosquitto) | [Dockerhub: openquantumsafe/mosquitto](https://hub.docker.com/repository/docker/openquantumsafe/mosquitto) | unsupported
35-
| **Envoy** | [Github: oqs-demos/envoy](envoy) | [ Dockerhub: openquantumsafe/envoy](https://hub.docker.com/repository/docker/openquantumsafe/envoy) | unsupported
36-
| **Unbound** | [Github: oqs-demos/unbound](unbound) | [ Dockerhub: openquantumsafe/unbound](https://hub.docker.com/repository/docker/openquantumsafe/unbound) | unsupported
20+
| | **Build instructions** | **Pre-built Docker image or binary files** | Support? |
21+
|-------------------|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -------- |
22+
| **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
23+
| **Apache httpd** | [Github: oqs-demos/httpd](httpd) | [Dockerhub: openquantumsafe/httpd](https://hub.docker.com/repository/docker/openquantumsafe/httpd) | @baentsch
24+
| **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
25+
| **Chromium** | [Github: oqs-demos/chromium](chromium) (limited support) | - | @pi-314159 |
26+
| **Locust** | [Github: oqs-demos/locust](locust) | - | @davidgca|
27+
| **OpenSSH** | [Github: oqs-demos/openssh](openssh) | [Dockerhub: openquantumsafe/openssh](https://hub.docker.com/repository/docker/openquantumsafe/openssh) | unsupported
28+
| **Wireshark** | [Github: oqs-demos/wireshark](wireshark) | [Dockerhub: openquantumsafe/wireshark](https://hub.docker.com/repository/docker/openquantumsafe/wireshark) | unsupported
29+
| **Epiphany** | [Github: oqs-demos/epiphany](epiphany) | [Dockerhub: openquantumsafe/epiphany](https://hub.docker.com/repository/docker/openquantumsafe/epiphany) | unsupported
30+
| **OpenVPN** | [Github: oqs-demos/openvpn](openvpn) | [Dockerhub: openquantumsafe/openvpn](https://hub.docker.com/repository/docker/openquantumsafe/openvpn) | unsupported
31+
| **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
32+
| **OpenLiteSpeed** | [Github: oqs-demos/openlitespeed](openlitespeed) | [ Dockerhub: openquantumsafe/openlitespeed](https://hub.docker.com/repository/docker/openquantumsafe/openlitespeed) | unsupported
33+
| **h2load** | [Github: oqs-demos/h2load](h2load) | [ Dockerhub: openquantumsafe/h2load](https://hub.docker.com/repository/docker/openquantumsafe/h2load) | unsupported
34+
| **HAproxy** | [Github: oqs-demos/haproxy](haproxy) | [Dockerhub: openquantumsafe/haproxy](https://hub.docker.com/repository/docker/openquantumsafe/haproxy) | unsupported
35+
| **Mosquitto** | [Github: oqs-demos/mosquitto](mosquitto) | [Dockerhub: openquantumsafe/mosquitto](https://hub.docker.com/repository/docker/openquantumsafe/mosquitto) | unsupported
36+
| **Envoy** | [Github: oqs-demos/envoy](envoy) | [ Dockerhub: openquantumsafe/envoy](https://hub.docker.com/repository/docker/openquantumsafe/envoy) | unsupported
37+
| **Unbound** | [Github: oqs-demos/unbound](unbound) | [ Dockerhub: openquantumsafe/unbound](https://hub.docker.com/repository/docker/openquantumsafe/unbound) | unsupported
38+
3739

3840
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.
3941

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

6669
## Acknowledgments
6770

locust/Dockerfile

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# define the liboqs tag to be used
2+
ARG LIBOQS_TAG=0.11.0
3+
4+
# define the oqsprovider tag to be used
5+
ARG OQSPROVIDER_TAG=0.7.0
6+
7+
# define the openssl version to be baked in
8+
ARG OPENSSL_BRANCH=openssl-3.3.2
9+
10+
# Default location where all binaries wind up:
11+
ARG INSTALLDIR=/opt/oqssa
12+
13+
# Default Python version to be used
14+
ARG PYTHON_VERSION=3.12.6
15+
16+
# liboqs build type variant; maximum portability of image:
17+
ARG LIBOQS_BUILD_DEFINES="-DOQS_DIST_BUILD=ON"
18+
19+
# Default root CA signature algorithm; can be set to any listed at https://github.com/open-quantum-safe/oqs-provider#algorithms
20+
ARG SIG_ALG="dilithium3"
21+
22+
# Default KEM algorithms; can be set to any listed at https://github.com/open-quantum-safe/oqs-provider#algorithms
23+
ARG DEFAULT_GROUPS="x25519:x448:kyber512:p256_kyber512:kyber768:p384_kyber768:kyber1024:p521_kyber1024"
24+
25+
# Define the degree of parallelism when building the image; leave the number away only if you know what you are doing
26+
ARG MAKE_DEFINES="-j 16"
27+
28+
# Define the Alpine version to be used
29+
ARG ALPINE_VERSION=3.20.3
30+
31+
FROM alpine:${ALPINE_VERSION}
32+
# Take in all global args
33+
ARG LIBOQS_TAG
34+
ARG OQSPROVIDER_TAG
35+
ARG INSTALLDIR
36+
ARG LIBOQS_BUILD_DEFINES
37+
ARG SIG_ALG
38+
ARG DEFAULT_GROUPS
39+
ARG MAKE_DEFINES
40+
ARG PYTHON_VERSION
41+
ARG OPENSSL_BRANCH
42+
43+
LABEL version="1"
44+
45+
ENV DEBIAN_FRONTEND noninteractive
46+
ENV LD_LIBRARY_PATH=${INSTALLDIR}/lib
47+
48+
RUN apk update && apk upgrade
49+
50+
# Get all software packages required for builing all components:
51+
RUN apk add build-base linux-headers \
52+
libtool automake autoconf cmake ninja \
53+
make \
54+
git wget vim nano zlib-dev py3-pip tcpdump python3-dev
55+
56+
# get all sources
57+
WORKDIR /opt
58+
RUN git clone --depth 1 --branch ${LIBOQS_TAG} https://github.com/open-quantum-safe/liboqs && \
59+
git clone --depth 1 --branch ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git && \
60+
git clone --depth 1 --branch ${OQSPROVIDER_TAG} https://github.com/open-quantum-safe/oqs-provider.git
61+
62+
# build OpenSSL3
63+
WORKDIR /opt/openssl
64+
RUN LDFLAGS="-Wl,-rpath -Wl,${INSTALLDIR}/lib64" ./config shared enable-zlib no-comp --prefix=${INSTALLDIR} && \
65+
make ${MAKE_DEFINES} && make install_sw install_ssldirs install_dev && \
66+
if [ -d ${INSTALLDIR}/lib64 ]; then ln -s ${INSTALLDIR}/lib64 ${INSTALLDIR}/lib; fi && \
67+
if [ -d ${INSTALLDIR}/lib ]; then ln -s ${INSTALLDIR}/lib ${INSTALLDIR}/lib64; fi
68+
69+
70+
# build liboqs
71+
WORKDIR /opt/liboqs
72+
RUN mkdir build && \
73+
cd build && \
74+
cmake -G"Ninja" .. ${LIBOQS_BUILD_DEFINES} -DCMAKE_INSTALL_PREFIX=${INSTALLDIR} && \
75+
ninja install
76+
77+
# set path to use 'new' openssl. Dyn libs have been properly linked in to match
78+
ENV PATH="${INSTALLDIR}/bin:${PATH}"
79+
ENV LD_LIBRARY_PATH=${INSTALLDIR}/lib
80+
81+
# build & install provider (and activate by default)
82+
WORKDIR /opt/oqs-provider
83+
RUN ln -s ../openssl . && \
84+
cmake -DOPENSSL_ROOT_DIR=${INSTALLDIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=${INSTALLDIR} -S . -B _build && \
85+
cmake --build _build && \
86+
cp _build/lib/oqsprovider.so ${INSTALLDIR}/lib64/ossl-modules && \
87+
sed -i "s/default = default_sect/default = default_sect\noqsprovider = oqsprovider_sect/g" /opt/oqssa/ssl/openssl.cnf && \
88+
sed -i "s/\[default_sect\]/\[default_sect\]\nactivate = 1\n\[oqsprovider_sect\]\nactivate = 1\n/g" /opt/oqssa/ssl/openssl.cnf && \
89+
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 && \
90+
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 && \
91+
sed -i "s/HOME\t\t\t= ./HOME\t\t= .\nDEFAULT_GROUPS\t= ${DEFAULT_GROUPS}/g" /opt/oqssa/ssl/openssl.cnf
92+
93+
# generate certificates for openssl s_server
94+
ENV OPENSSL=${INSTALLDIR}/bin/openssl
95+
ENV OPENSSL_CNF=${INSTALLDIR}/ssl/openssl.cnf
96+
97+
WORKDIR ${INSTALLDIR}/bin
98+
# generate CA key and cert
99+
RUN set -x; \
100+
${OPENSSL} req -x509 -new -newkey ${SIG_ALG} -keyout CA.key -out CA.crt -nodes -subj "/CN=oqstest CA" -days 365 -config ${OPENSSL_CNF}
101+
102+
# Download current test.openquantumsafe.org test CA cert
103+
WORKDIR ${INSTALLDIR}
104+
RUN wget --no-check-certificate https://test.openquantumsafe.org/CA.crt && \
105+
mv CA.crt oqs-testca.pem
106+
107+
# Install Locust
108+
RUN mkdir /home/locust && cd /home/locust
109+
ENV CFLAGS="-I/opt/python-${PYTHON_VERSION}-custom/include/${PYTHON_VERSION}"
110+
ENV LDFLAGS="-L/opt/python-${PYTHON_VERSION}-custom/lib"
111+
COPY requirements.txt /home/locust
112+
RUN pip3 install --break-system-packages --upgrade pip
113+
RUN pip3 install --break-system-packages -r /home/locust/requirements.txt
114+
ADD / /mnt/locust
115+

locust/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Purpose
2+
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.
3+
4+
For more information on `Locust`, see the [official Locust project](https://github.com/locustio/locust).
5+
6+
## Quick start
7+
8+
1) Be sure to have [docker installed](https://docs.docker.com/install).
9+
2) Run `docker build -t oqs-locust:0.0.1 .` to create a post quantum-enabled Locust docker image.
10+
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)
11+
4) To verify all components perform quantum-safe operations, first start the container with docker compose
12+
13+
```
14+
LOGGER_LEVEL=DEBUG HOST=https://YOUR_QS_HOST:4433 docker compose up --scale worker=8
15+
```
16+
4) Connect to the locust web interface at `http://localhost:8189` and start a load test.
17+
18+
19+
## Notes on this Version:
20+
21+
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.
22+
23+
For further reference on the Locust API, please refer to the official documentation [here](https://docs.locust.io/en/stable/).
24+
25+
## Usage
26+
27+
Information how to use locust: [available in the separate file USAGE.md](USAGE.md).
28+
29+
## Disclaimer
30+
31+
[THIS IS NOT FIT FOR PRODUCTION USE]
32+

locust/USAGE.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## Purpose
2+
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.
3+
4+
## Start
5+
1) Run `docker build -t oqs-locust:0.0.1 .` to create a post quantum-enabled Locust docker image.
6+
2) To verify all components perform quantum-safe operations, first start the container with docker compose, setting all environment variables as needed. For example:
7+
```
8+
LOGGER_LEVEL=DEBUG HOST=https://YOUR_QS_HOST:4433 GROUP=kyber1024 docker compose up --scale worker=8
9+
```
10+
3) Connect to the locust web interface at `http://localhost:8189` and start a load test.
11+
12+
By default, Locust supports all algorithms supported by the OQS openssl.
13+
14+
Some environments variables you need to know
15+
- LOGGER_LEVEL: Set the log level for the locust master and worker. Default is ERROR.
16+
- HOST: Set the host to test. Default is https://test:4433
17+
- 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.
18+
- MASTER_PORT: Set the port for the master. Default is 8189.
19+
- GROUP: Set the key exchange scheme for openssl. Default is kyber768.
20+
21+
In Locust web server, you need to set 2 variables:
22+
- Number of users to simulate: The number of users to simulate that will hit the server.
23+
- Hatch rate: The rate per second in which users are spawned.
24+
25+
After that, you can start the test:
26+
27+
STATISTICS
28+
![img.png](images/img.png)
29+
30+
CHARTS
31+
![img.png](images/img_charts.png)
32+
33+
### HOW TO CREATE A PERFORMANCE SCENARIO IN LOCUST
34+
35+
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).
36+
37+
```python
38+
from locust import HttpUser, TaskSet, task, between
39+
class UserBehavior(TaskSet):
40+
# on_start is called when a Locust starts, before any task is scheduled
41+
def on_start(self):
42+
self.index()
43+
self.about()
44+
45+
# tasks is a list of tasks that a Locust will choose from to execute
46+
# tasks are chosen with the weighted_task_set attribute
47+
@task(1)
48+
def index(self):
49+
self.client.get("/")
50+
51+
# in this case the about task is twice as likely to be chosen as the index task
52+
@task(2)
53+
def about(self):
54+
self.client.get("/about/")
55+
56+

0 commit comments

Comments
 (0)