-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
Showing
9 changed files
with
343 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/") | ||
|
||
|
Oops, something went wrong.