Skip to content
Draft
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
48 changes: 48 additions & 0 deletions samples/security/pqc/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
FROM docker.io/redhat/ubi9:9.6 AS builder

ARG LIBOQS_TAG=0.12.0
ARG OQSPROVIDER_TAG=0.8.0
ARG INSTALLDIR_OPENSSL=/usr/lib64
ARG INSTALLDIR_LIBOQS=/opt/liboqs

RUN dnf install -y git make cmake ninja-build
RUN dnf install -y openssl-devel
RUN dnf install -y gcc gcc-c++

WORKDIR /optbuild
RUN git clone --depth 1 --branch ${LIBOQS_TAG} https://github.com/open-quantum-safe/liboqs

WORKDIR /optbuild/liboqs/build
RUN cmake -G "Ninja" .. \
-DOPENSSL_ROOT_DIR=${INSTALLDIR_OPENSSL} \
-DCMAKE_INSTALL_PREFIX=${INSTALLDIR_LIBOQS} && \
ninja install

WORKDIR /optbuild
RUN git clone --depth 1 --branch ${OQSPROVIDER_TAG} https://github.com/open-quantum-safe/oqs-provider.git

WORKDIR /optbuild/oqs-provider
RUN liboqs_DIR=${INSTALLDIR_LIBOQS} cmake \
-DOPENSSL_ROOT_DIR=${INSTALLDIR_OPENSSL} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=${INSTALLDIR_OPENSSL} \
-S . -B _build && \
cmake --build _build && \
cmake --install _build && \
cp _build/lib/oqsprovider.so ${INSTALLDIR_OPENSSL}/ossl-modules

FROM registry.redhat.io/openshift-service-mesh/istio-proxyv2-rhel9:1.26.2 AS final

ARG INSTALLDIR_OPENSSL=/usr/lib64
ARG INSTALLDIR_LIBOQS=/opt/liboqs

COPY --from=builder ${INSTALLDIR_LIBOQS} ${INSTALLDIR_LIBOQS}
COPY --from=builder ${INSTALLDIR_OPENSSL}/ossl-modules ${INSTALLDIR_OPENSSL}/ossl-modules

USER root
RUN sed '/^default = default_sect$/a oqsprovider = oqsprovider_sect' /etc/pki/tls/openssl.cnf > /tmp/openssl.cnf && \
printf "\n[oqsprovider_sect]\n" >> /tmp/openssl.cnf && \
echo "module = /usr/lib64/ossl-modules/oqsprovider.so" >> /tmp/openssl.cnf && \
echo "activate = 1" >> /tmp/openssl.cnf && \
cp /tmp/openssl.cnf /etc/pki/tls/openssl.cnf
USER 1000
196 changes: 196 additions & 0 deletions samples/security/pqc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Quantum-Safe Gateway

## Prerequisites

1. Install OpenShift Service Mesh Operator 3.1+.
1. Install Gateway API CRDs (not required on OCP 4.19+).

```shell
oc apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
```

## Customize istio-proxy image

OpenShift Service Mesh 3.1 does not deliver istio-proxy image with built-in support for PQC.
Enabling post-quantum safe algorithms requires configuring [OQS provider](https://github.com/open-quantum-safe/oqs-provider) in the proxy container.

1. Get pull secret from OCP and build the proxy image with OQS provider:

```shell
oc get secret pull-secret -n openshift-config -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d > /tmp/config.json
podman --config /tmp build -t localhost:5000/istio-system/istio-proxyv2-rhel9-oqs:1.26.2 .
```

1. Configure permissions for pushing images to OCP image registry:

```shell
oc new-project istio-system
oc policy add-role-to-user system:image-pusher -z default -n istio-system
TOKEN=$(oc create token default -n istio-system)
```

1. Create an image stream for custom istio-proxy and expose the registry:

```shell
oc patch configs.imageregistry.operator.openshift.io/cluster --type=merge -p '{"spec":{"defaultRoute":true}}'
oc create imagestream istio-proxyv2-rhel9-oqs -n istio-system
```

1. Push the local image:

```shell
HOST=$(oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}')
podman login --tls-verify=false -u default -p $TOKEN $HOST
podman push --tls-verify=false istio-proxyv2-rhel9-oqs:1.26.2 $HOST/istio-system/istio-proxyv2-rhel9-oqs:1.26.2
```

## Install Service Mesh

1. Install CNI:

```shell
oc new-project istio-cni
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: IstioCNI
metadata:
name: default
spec:
version: v1.26.2
namespace: istio-cni
EOF
```

1. Install control plane:

```shell
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: default
spec:
version: v1.26.2
namespace: istio-system
updateStrategy:
type: InPlace
values:
meshConfig:
accessLogFile: /dev/stdout
tlsDefaults:
ecdhCurves:
- X25519MLKEM768
EOF
```

1. Generate certificates:

```shell
mkdir certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout certs/example.com.key -out certs/example.com.crt
openssl req -out certs/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout certs/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -sha256 -days 365 -CA certs/example.com.crt -CAkey certs/example.com.key -set_serial 0 -in certs/httpbin.example.com.csr -out certs/httpbin.example.com.crt
openssl req -out certs/helloworld.example.com.csr -newkey rsa:2048 -nodes -keyout certs/helloworld.example.com.key -subj "/CN=helloworld.example.com/O=helloworld organization"
openssl x509 -req -sha256 -days 365 -CA certs/example.com.crt -CAkey certs/example.com.key -set_serial 1 -in certs/helloworld.example.com.csr -out certs/helloworld.example.com.crt
```

1. Create a secret for a gateway:

```shell
oc create -n istio-system secret tls httpbin-credential \
--key=certs/httpbin.example.com.key \
--cert=certs/httpbin.example.com.crt
```

1. Deploy a Gateway:

```shell
oc apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: pqc-gateway
namespace: istio-system
annotations:
sidecar.istio.io/proxyImage: "image-registry.openshift-image-registry.svc:5000/istio-system/istio-proxyv2-rhel9-oqs:1.26.2"
spec:
gatewayClassName: istio
listeners:
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
namespace: istio-system
allowedRoutes:
namespaces:
from: All
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: httpbin-route
namespace: default
spec:
parentRefs:
- name: pqc-gateway
namespace: istio-system
hostnames:
- "httpbin.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: httpbin
port: 8000
EOF
```

1. Deploy the backend server:

```shell
oc label ns default istio-injection=enabled
oc apply -n default -f https://raw.githubusercontent.com/openshift-service-mesh/istio/master/samples/httpbin/httpbin.yaml
```

## Verification steps

1. Get the gateway address depending on your LB provider:

```shell
INGRESS_ADDR=$(kubectl get svc pqc-gateway-istio -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
```
```shell
INGRESS_ADDR=$(kubectl get svc pqc-gateway-istio -n istio-system -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
```

1. Connect to the gateway with PQC-enabled client using `X25519MLKEM768` for key exchange - it should succeed:

```shell
podman run --rm -it \
-v ./certs/example.com.crt:/etc/certs/example.com.crt \
docker.io/openquantumsafe/curl \
curl -vk "https://$INGRESS_ADDR:443/headers" \
-H "Host: httpbin.example.com" \
--curves X25519MLKEM768 \
--cacert /etc/certs/example.com.crt
```

1. Connect to the gateway with `curl` without any PQC-specific algorithms - it should fail:

```shell
curl -vk "https://$INGRESS_ADDR:443/headers" \
-H "Host: httpbin.example.com" \
--cacert ./certs/example.com.crt
```
```text
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, handshake failure (552):
* TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure
* closing connection #0
curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure
```