Skip to content

Commit

Permalink
Enabling HTTPS in python HTTP client library (#1684)
Browse files Browse the repository at this point in the history
* Enabling HTTPS in python HTTP client library

* Stop the proxy server when done
  • Loading branch information
tanmayv25 committed Jun 19, 2020
1 parent c2b3a45 commit 1c5ed99
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 4 deletions.
3 changes: 3 additions & 0 deletions Dockerfile.QA
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ RUN mkdir -p qa/common && \
cp -r /workspace/docs/examples/model_repository/simple qa/L0_http/models && \
cp -r /workspace/docs/examples/model_repository/inception_graphdef qa/L0_http/models && \
cp -r /workspace/docs/examples/model_repository/simple_string qa/L0_http/models && \
mkdir qa/L0_https/models && \
cp -r docs/examples/model_repository/simple qa/L0_https/models/. && \
cp -r /workspace/docs/examples/ensemble_model_repository qa/L0_perf_client/ && \
cp /opt/tritonserver/bin/simple qa/L0_simple_lib/. && \
cp /opt/tritonserver/bin/memory_alloc qa/L0_io/. && \
Expand Down Expand Up @@ -267,6 +269,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python3-setuptools \
swig \
golang-go \
nginx \
protobuf-compiler && \
rm -rf /var/lib/apt/lists/*

Expand Down
38 changes: 38 additions & 0 deletions qa/L0_https/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

server {
listen 443 ssl;
server_name localhost;

ssl_certificate /etc/nginx/cert.crt;
ssl_certificate_key /etc/nginx/cert.key;

location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
}
}
109 changes: 109 additions & 0 deletions qa/L0_https/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/bin/bash
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

REPO_VERSION=${NVIDIA_TRITON_SERVER_VERSION}
if [ "$#" -ge 1 ]; then
REPO_VERSION=$1
fi
if [ -z "$REPO_VERSION" ]; then
echo -e "Repository version must be specified"
echo -e "\n***\n*** Test Failed\n***"
exit 1
fi

export CUDA_VISIBLE_DEVICES=0

RET=0

SIMPLE_INFER_CLIENT_PY=../clients/simple_http_infer_client.py

NGINX_CONF=`pwd`/nginx.conf
CLIENT_LOG=`pwd`/client.log
DATADIR=`pwd`/models
SERVER=/opt/tritonserver/bin/tritonserver
SERVER_ARGS="--model-repository=$DATADIR"
source ../common/util.sh


# Generate a passphrase
openssl rand -base64 48 > passphrase.txt

# Generate a Private Key
openssl genrsa -aes128 -passout file:passphrase.txt -out server.key 2048

# Generate a CSR (Certificate Signing Request)
openssl req -new -passin file:passphrase.txt -key server.key -out server.csr \
-subj "/C=FR/O=krkr/OU=Domain Control Validated/CN=*.krkr.io"

# Remove Passphrase from Key
cp server.key server.key.org
openssl rsa -in server.key.org -passin file:passphrase.txt -out server.key

# Generating a Self-Signed Certificate for 100 years
openssl x509 -req -days 36500 -in server.csr -signkey server.key -out server.crt

mv server.crt /etc/nginx/cert.crt
mv server.key /etc/nginx/cert.key

run_server
if [ "$SERVER_PID" == "0" ]; then
echo -e "\n***\n*** Failed to start $SERVER\n***"
cat $SERVER_LOG
exit 1
fi

# Setup the new configuration for the proxy. The HTTPS traffic will be
# redirected to the running instance of server at localhost:8000
cp ${NGINX_CONF} /etc/nginx/sites-available/default

# Start the proxy server
service nginx restart

set +e

# Test basic inference with https
python $SIMPLE_INFER_CLIENT_PY -v -u localhost --ssl >> ${CLIENT_LOG}.ssl_infer 2>&1
if [ $? -ne 0 ]; then
cat ${CLIENT_LOG}.ssl_infer
RET=1
fi

set -e

kill $SERVER_PID
wait $SERVER_PID

# Stop the proxy server
service nginx stop

if [ $RET -eq 0 ]; then
echo -e "\n***\n*** Test Passed\n***"
else
echo -e "\n***\n*** Test FAILED\n***"
fi

exit $RET
16 changes: 15 additions & 1 deletion src/clients/python/examples/simple_http_infer_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import argparse
import numpy as np
import sys
import gevent.ssl

import tritonhttpclient
from tritonclientutils import InferenceServerException
Expand Down Expand Up @@ -94,14 +95,27 @@ def test_infer_no_outputs(model_name, input0_data, input1_data, headers=None):
required=False,
default='localhost:8000',
help='Inference server URL. Default is localhost:8000.')
parser.add_argument('-s',
'--ssl',
action="store_true",
required=False,
default=False,
help='Enable encrypted link to the server using HTTPS')
parser.add_argument('-H', dest='http_headers', metavar="HTTP_HEADER",
required=False, action='append',
help='HTTP headers to add to inference server requests. ' +
'Format is -H"Header:Value".')

FLAGS = parser.parse_args()
try:
triton_client = tritonhttpclient.InferenceServerClient(url=FLAGS.url,
if FLAGS.ssl:
triton_client = tritonhttpclient.InferenceServerClient(url=FLAGS.url,
verbose=FLAGS.verbose,
ssl=True,
ssl_context_factory=gevent.ssl._create_unverified_context,
insecure=True)
else:
triton_client = tritonhttpclient.InferenceServerClient(url=FLAGS.url,
verbose=FLAGS.verbose)
except Exception as e:
print("channel creation failed: " + str(e))
Expand Down
29 changes: 26 additions & 3 deletions src/clients/python/library/httpclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ class InferenceServerClient:
for handling asynchronous inference requests. Default value
is None, which means there will be no restriction on the
number of greenlets created.
ssl : bool
If True, channels the requests to encrypted https scheme.
Default value is False.
ssl_options : dict
Any options supported by `ssl.wrap_socket` specified as
dictionary. The argument is ignored if 'ssl' is specified
False.
ssl_context_factory : SSLContext callable
It must be a callbable that returns a SSLContext. The default
value is None which use `ssl.create_default_context`. The
argument is ignored if 'ssl' is specified False.
insecure : bool
If True, then does not match the host name with the certificate.
Default value is False. The argument is ignored if 'ssl' is
specified False.
Raises
------
Expand All @@ -157,13 +172,21 @@ def __init__(self,
connection_timeout=60.0,
network_timeout=60.0,
verbose=False,
max_greenlets=None):
self._parsed_url = URL("http://" + url)
max_greenlets=None,
ssl=False,
ssl_options=None,
ssl_context_factory=None,
insecure=False):
scheme = "https://" if ssl else "http://"
self._parsed_url = URL(scheme + url)
self._client_stub = HTTPClient.from_url(
self._parsed_url,
concurrency=connection_count,
connection_timeout=connection_timeout,
network_timeout=network_timeout)
network_timeout=network_timeout,
ssl_options=ssl_options,
ssl_context_factory=ssl_context_factory,
insecure=insecure)
self._pool = gevent.pool.Pool(max_greenlets)
self._verbose = verbose

Expand Down

0 comments on commit 1c5ed99

Please sign in to comment.