[demos] Add grpc tls demo

This commit is contained in:
Zheng, Qi 2022-01-04 13:44:54 +08:00 committed by Zongmin.Gu
parent 1229de1fd1
commit 731b2e1ae2
10 changed files with 490 additions and 0 deletions

@ -0,0 +1,64 @@
--- Makefile-orig 2022-01-04 08:37:31.975521982 +0000
+++ Makefile 2022-01-04 08:37:58.709192999 +0000
@@ -16,29 +16,32 @@
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
-CXX = g++
-CPPFLAGS += `pkg-config --cflags protobuf grpc`
+CXX = occlum-g++
+CPPFLAGS += -I/usr/local/occlum/x86_64-linux-musl/include
CXXFLAGS += -std=c++11
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-pthread\
-lgrpc++_reflection\
- -ldl
+ -ldl \
+ -lssl -lcrypto
else
-LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
+LDFLAGS += -L/usr/local/occlum/x86_64-linux-musl/lib -lgrpc++ -lgrpc -lprotobuf -lgpr \
+ -lcares -lz -laddress_sorting -pie\
-pthread\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
- -ldl
+ -ldl \
+ -lssl -lcrypto
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
-PROTOS_PATH = ../../protos
+PROTOS_PATH = .
vpath %.proto $(PROTOS_PATH)
-all: system-check greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server
+all: system-check greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server greeter_secure_client greeter_secure_server
greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o
$(CXX) $^ $(LDFLAGS) -o $@
@@ -55,6 +58,12 @@ greeter_async_client2: helloworld.pb.o h
greeter_async_server: helloworld.pb.o helloworld.grpc.pb.o greeter_async_server.o
$(CXX) $^ $(LDFLAGS) -o $@
+greeter_secure_client: helloworld.pb.o helloworld.grpc.pb.o greeter_secure_client.o
+ $(CXX) $^ $(LDFLAGS) -o $@
+
+greeter_secure_server: helloworld.pb.o helloworld.grpc.pb.o greeter_secure_server.o
+ $(CXX) $^ $(LDFLAGS) -o $@
+
.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
@@ -64,7 +73,7 @@ greeter_async_server: helloworld.pb.o he
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<
clean:
- rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server
+ rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server greeter_async_client greeter_async_client2 greeter_async_server greeter_secure_server greeter_secure_client
# The following is to test your system and ensure a smoother experience.

@ -0,0 +1,35 @@
# Run gRPC TLS C++ Client/Server on Occlum
## Step 1:
Downlaod, build and install openssl into `/usr/local/occlum/x86_64-linux-musl/lib`:
```
./download_and_install_openssl.sh
```
## Step 2:
Download, build and install cares, protobuf and finally gRPC into `/usr/local/occlum/x86_64-linux-musl/lib`:
```
./download_and_install_grpc.sh
```
## Step 3:
Prepare the gRPC TLS C++ Hello World demo Occlum instance, which consists of a client and server:
```
./prepare_occlum_instance.sh
```
Then you can see two occlum instance created for server(`occlum_server`) and client(`occlum_client`).
## Step 4:
Start `tls server` which will listen on port `50051` on occlum:
```
cd occlum_server
occlum run /bin/greeter_secure_server
```
Then you can invoke gRPC service by running `tls client` in a different terminal on occlum:
```
cd occlum_client
occlum run /bin/greeter_secure_client
```
And you will see the "Greeter received: Hello world" in the client side output.

@ -0,0 +1,65 @@
#!/bin/bash
set -e
INSTALL_DIR=/usr/local/occlum/x86_64-linux-musl
GRPC_VER=1.24.3
GRPC_SRC_DIR=$PWD/grpc-src
CARES_VER=1_15_0
RPOTOBUF_VER=3.10.0
export PATH=$PATH:$INSTALL_DIR/bin
# Tell CMake to search for packages in Occlum toolchain's directory only
export PKG_CONFIG_LIBDIR=$INSTALL_DIR/lib
# Download grpc
wget https://github.com/grpc/grpc/archive/refs/tags/v${GRPC_VER}.tar.gz
rm -rf ${GRPC_SRC_DIR} && mkdir ${GRPC_SRC_DIR}
tar zxvf v${GRPC_VER}.tar.gz -C ${GRPC_SRC_DIR} --strip-components 1
# Download and Install c-ares
wget https://github.com/c-ares/c-ares/archive/refs/tags/cares-${CARES_VER}.tar.gz
tar zxvf cares-${CARES_VER}.tar.gz -C ${GRPC_SRC_DIR}/third_party/cares/cares/ --strip-components 1
cd $GRPC_SRC_DIR/third_party/cares/cares
mkdir -p build
cd build
cmake ../ \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=occlum-gcc \
-DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
make -j$(nproc)
make install
cd $PWD
# Download and Install protobuf
wget https://github.com/protocolbuffers/protobuf/archive/refs/tags/v${RPOTOBUF_VER}.tar.gz
tar zxvf v${RPOTOBUF_VER}.tar.gz -C $GRPC_SRC_DIR/third_party/protobuf/ --strip-components 1
cd $GRPC_SRC_DIR/third_party/protobuf
cd cmake
mkdir -p build
cd build
cmake ../ \
-Dprotobuf_BUILD_TESTS=OFF -DBUILD_SHARED_LIBS=TRUE \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=occlum-gcc \
-DCMAKE_CXX_COMPILER=occlum-g++ -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR \
-DCMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE
make -j$(nproc)
make install
cp $INSTALL_DIR/bin/protoc /usr/bin
# Install gRPC
cd $GRPC_SRC_DIR/cmake
mkdir -p build
cd build
cmake ../.. \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=occlum-gcc \
-DCMAKE_CXX_COMPILER=occlum-g++ -DgRPC_INSTALL=ON -DgRPC_PROTOBUF_PROVIDER=package \
-DgRPC_ZLIB_PROVIDER=package -DgRPC_CARES_PROVIDER=package \
-DgRPC_SSL_PROVIDER=package -DCMAKE_PREFIX_PATH=$INSTALL_DIR \
-DCMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR
make -j$(nproc)
make install
echo "gRPC build success"

@ -0,0 +1,17 @@
#!/bin/bash
#copyright@antfinancial:adopted from a script written by geding
set -e
git clone http://github.com/openssl/openssl
cd openssl
git checkout tags/OpenSSL_1_1_1
CC=occlum-gcc ./config \
--prefix=/usr/local/occlum/x86_64-linux-musl \
--openssldir=/usr/local/occlum/x86_64-linux-musl/ssl \
--with-rand-seed=rdcpu \
no-async no-zlib
make -j$(nproc)
make install
echo "build and install openssl success!"

26
demos/grpc/grpc_tls/gen-cert.sh Executable file

@ -0,0 +1,26 @@
#!/bin/bash
pushd ~
openssl rand -writerand .rnd
popd
# Generate valid CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/OU=Test/CN=Root CA"
# Generate valid Server Key/Cert
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr -subj "/OU=Server/CN=localhost"
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# Remove passphrase from the Server Key
openssl rsa -in server.key -out server.key
# Generate valid Client Key/Cert
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr -subj "/OU=Client/CN=localhost"
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt
# Remove passphrase from Client Key
openssl rsa -in client.key -out client.key

@ -0,0 +1,104 @@
#include <memory>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <grpc++/grpc++.h>
#include "helloworld.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient
{
public:
GreeterClient ( const std::string& cert,
const std::string& key,
const std::string& root,
const std::string& server )
{
grpc::SslCredentialsOptions opts =
{
root,
key,
cert
};
stub_ = Greeter::NewStub ( grpc::CreateChannel (
server, grpc::SslCredentials ( opts ) ) );
}
std::string
SayHello ( const std::string& user )
{
HelloRequest request;
request.set_name(user);
HelloReply reply;
ClientContext context;
Status status = stub_->SayHello ( &context, request, &reply );
if ( status.ok () )
{
return reply.message ();
}
else
{
std::cout << status.error_code () << ": "
<< status.error_message () << std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
void
read ( const std::string& filename, std::string& data )
{
std::ifstream file ( filename.c_str (), std::ios::in );
if ( file.is_open () )
{
std::stringstream ss;
ss << file.rdbuf ();
file.close ();
data = ss.str ();
}
return;
}
int
main ( int argc, char** argv )
{
std::string cert;
std::string key;
std::string root;
std::string server { "localhost:50051" };
read ( "client.crt", cert );
read ( "client.key", key );
read ( "ca.crt", root );
GreeterClient greeter ( cert, key, root, server );
std::string user ( "world" );
std::string reply = greeter.SayHello ( user );
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}

@ -0,0 +1,98 @@
#include <memory>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <grpc++/grpc++.h>
#include "helloworld.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterServiceImpl final : public Greeter::Service
{
Status SayHello ( ServerContext* context,
const HelloRequest* request,
HelloReply* reply ) override
{
std::string prefix ( "Hello " );
reply->set_message ( prefix + request->name () );
return Status::OK;
}
};
void
read ( const std::string& filename, std::string& data )
{
std::ifstream file ( filename.c_str (), std::ios::in );
if ( file.is_open () )
{
std::stringstream ss;
ss << file.rdbuf ();
file.close ();
data = ss.str ();
}
return;
}
void
runServer()
{
/**
* [!] Be carefull here using one cert with the CN != localhost. [!]
**/
std::string server_address ( "localhost:50051" );
std::string key;
std::string cert;
std::string root;
read ( "server.crt", cert );
read ( "server.key", key );
read ( "ca.crt", root );
ServerBuilder builder;
grpc::SslServerCredentialsOptions::PemKeyCertPair keycert =
{
key,
cert
};
grpc::SslServerCredentialsOptions sslOps;
sslOps.pem_root_certs = root;
sslOps.pem_key_cert_pairs.push_back ( keycert );
builder.AddListeningPort(server_address, grpc::SslServerCredentials( sslOps ));
GreeterServiceImpl service;
builder.RegisterService(&service);
std::unique_ptr < Server > server ( builder.BuildAndStart () );
std::cout << "Server listening on " << server_address << std::endl;
server->Wait ();
}
int
main ( int argc, char** argv )
{
runServer();
return 0;
}

@ -0,0 +1,13 @@
includes:
- base.yaml
targets:
- target: /bin/
copy:
- files:
- ../build/greeter_secure_client
- target: /
copy:
- files:
- ../client.crt
- ../client.key
- ../ca.crt

@ -0,0 +1,13 @@
includes:
- base.yaml
targets:
- target: /bin/
copy:
- files:
- ../build/greeter_secure_server
- target: /
copy:
- files:
- ../server.crt
- ../server.key
- ../ca.crt

@ -0,0 +1,55 @@
#!/bin/bash
set -e
INSTALL_DIR=/usr/local/occlum/x86_64-linux-musl
export PATH=$PATH:$INSTALL_DIR/bin
GRPC_SRC_DIR=$PWD/grpc-src
WORK_DIR=$PWD
rm -rf build && mkdir build
pushd build
cp -R ${GRPC_SRC_DIR}/examples/cpp/helloworld/. .
patch Makefile -i ${WORK_DIR}/Makefile.patch
cp ${GRPC_SRC_DIR}/examples/protos/helloworld.proto .
cp ${WORK_DIR}/*.cc .
make -j$(nproc)
popd
# Generate demo ca/csr/crt
./gen-cert.sh
# Build server occlum instance
rm -rf occlum_server
occlum new occlum_server
cd occlum_server
rm -rf image && \
copy_bom -f ../grpc_secure_server.yaml --root image --include-dir /opt/occlum/etc/template && \
occlum build
if [ $? -ne 0 ]
then
echo "occlum build failed"
exit 1
fi
# Build client occlum instance
cd $WORK_DIR
rm -rf occlum_client
occlum new occlum_client
cd occlum_client
rm -rf image && \
copy_bom -f ../grpc_secure_client.yaml --root image --include-dir /opt/occlum/etc/template && \
occlum build
if [ $? -ne 0 ]
then
echo "occlum build failed"
exit 1
fi