Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling HTTPS in python HTTP client library #1684

Merged
merged 2 commits into from
Jun 19, 2020
Merged
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
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