-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
284 additions
and
25 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,4 +26,5 @@ Local* | |
*~ | ||
*.swp | ||
/core | ||
gen | ||
gen-* |
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 |
---|---|---|
@@ -1,17 +1,17 @@ | ||
all: gen-cpp gen-python | ||
|
||
gen-cpp: | ||
cd tests/protos && mkdir -p ../gen-cpp && \ | ||
protoc --cpp_out ../gen-cpp --grpc_out ../gen-cpp \ | ||
cd tests/protos && mkdir -p ../gen/cpp && \ | ||
protoc --cpp_out ../gen/cpp --grpc_out ../gen/cpp \ | ||
--plugin=protoc-gen-grpc=/usr/local/bin/grpc_cpp_plugin \ | ||
*.proto | ||
|
||
gen-python: | ||
mkdir -p tests/gen-py && \ | ||
mkdir -p tests/gen/python && \ | ||
python3 -m grpc_tools.protoc -I ./tests/protos \ | ||
--python_out=tests/gen-py \ | ||
--grpc_python_out=tests/gen-py \ | ||
--python_out=tests/gen/python \ | ||
--grpc_python_out=tests/gen/python \ | ||
./tests/protos/*.proto | ||
|
||
clean: | ||
rm -rf ./tests/gen-* | ||
rm -rf ./tests/gen |
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
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 @@ | ||
Cert from <https://github.com/grpc/grpc/tree/master/examples/python/auth> |
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,20 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIDWTCCAkGgAwIBAgIJAPOConZMwykwMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV | ||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29nbGUxDTAL | ||
BgNVBAsMBGdSUEMwIBcNMTkwNjI0MjIyMDA3WhgPMjExOTA1MzEyMjIwMDdaMEIx | ||
CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMQ8wDQYDVQQKDAZHb29n | ||
bGUxDTALBgNVBAsMBGdSUEMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | ||
AQCwqei3TfyLidnQNDJ2lierMYo229K92DuORni7nSjJQ59Jc3dNMsmqGQJjCD8o | ||
6mTlKM/oCbs27Wpx+OxcOLvT95j2kiDGca1fCvaMdguIod09SWiyMpv/hp0trLv7 | ||
NJIKHznath6rHYX2Ii3fZ1yCPzyQbEPSAA+GNpoNm1v1ZWmWKke9v7vLlS3inNlW | ||
Mt9jepK7DrtbNZnVDjeItnppBSbVYRMxIyNHkepFbqXx5TpkCvl4M4XQZw9bfSxQ | ||
i3WZ3q+T1Tw//OUdPNc+OfMhu0MA0QoMwikskP0NaIC3dbJZ5Ogx0RcnaB4E+9C6 | ||
O/znUEh3WuKVl5HXBF+UwWoFAgMBAAGjUDBOMB0GA1UdDgQWBBRm3JIgzgK4G97J | ||
fbMGatWMZc7V3jAfBgNVHSMEGDAWgBRm3JIgzgK4G97JfbMGatWMZc7V3jAMBgNV | ||
HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCNiV8x41if094ry2srS0YucpiN | ||
3rTPk08FOLsENTMYai524TGXJti1P6ofGr5KXCL0uxTByHE3fEiMMud2TIY5iHQo | ||
Y4mzDTTcb+Q7yKHwYZMlcp6nO8W+NeY5t+S0JPHhb8deKWepcN2UpXBUYQLw7AiE | ||
l96T9Gi+vC9h/XE5IVwHFQXTxf5UYzXtW1nfapvrOONg/ms41dgmrRKIi+knWfiJ | ||
FdHpHX2sfDAoJtnpEISX+nxRGNVTLY64utXWm4yxaZJshvy2s8zWJgRg7rtwAhTT | ||
Np9E9MnihXLEmDI4Co9XlLPJyZFmqImsbmVuKFeQOCiLAoPJaMI2lbi7fiTo | ||
-----END CERTIFICATE----- |
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,109 @@ | ||
import os | ||
import asyncio | ||
import grpc | ||
import sys | ||
|
||
DIR = os.path.dirname(os.path.abspath(os.path.join(__file__, ".."))) | ||
sys.path.insert(0, os.path.join(DIR, "gen/python")) | ||
|
||
import msg_pb2 as P | ||
import auth_pb2_grpc as G | ||
|
||
host = "localhost" | ||
port = 50051 | ||
TOKEN = "Basic dXNlcjpwYXNzd2Q=" | ||
|
||
# TODO | ||
|
||
|
||
def _load_credential_from_file(filepath): | ||
real_path = os.path.join(os.path.dirname(__file__), filepath) | ||
with open(real_path, "rb") as f: | ||
return f.read() | ||
|
||
|
||
SERVER_CERTIFICATE = _load_credential_from_file("credentials/localhost.crt") | ||
SERVER_CERTIFICATE_KEY = _load_credential_from_file("credentials/localhost.key") | ||
ROOT_CERTIFICATE = _load_credential_from_file("credentials/root.crt") | ||
|
||
|
||
class BasicAuth(grpc.AuthMetadataPlugin): | ||
def __init__(self, token): | ||
self.token = token | ||
|
||
def __call__( | ||
self, | ||
context: grpc.AuthMetadataContext, | ||
callback: grpc.AuthMetadataPluginCallback, | ||
) -> None: | ||
callback((("authorization", self.token),), None) | ||
|
||
|
||
def create_secure_channel(addr, token=None) -> grpc.aio.Channel: | ||
# Channel credential will be valid for the entire channel | ||
channel_credential = grpc.ssl_channel_credentials( | ||
root_certificates=ROOT_CERTIFICATE, | ||
# private_key=SERVER_CERTIFICATE_KEY, | ||
# certificate_chain=SERVER_CERTIFICATE, | ||
) | ||
# Call credential object will be invoked for every single RPC | ||
if token: | ||
call_credentials = grpc.metadata_call_credentials( | ||
BasicAuth(token), name="basic auth" | ||
) | ||
# Combining channel credentials and call credentials together | ||
composite_credentials = grpc.composite_channel_credentials( | ||
channel_credential, | ||
call_credentials, | ||
) | ||
channel = grpc.aio.secure_channel(addr, composite_credentials) | ||
else: | ||
channel = grpc.aio.secure_channel(addr, channel_credential) | ||
return channel | ||
|
||
|
||
async def unary(): | ||
channel = grpc.aio.insecure_channel(f"{host}:{port}") | ||
stub = G.AuthServiceStub(channel) | ||
req = P.Request(msg="x") | ||
r = await stub.Unary(req) | ||
assert r.msg == "x" | ||
|
||
|
||
async def secure_unary(): | ||
channel = create_secure_channel(f"{host}:{port}") | ||
stub = G.AuthServiceStub(channel) | ||
req = P.Request(msg="x") | ||
r = await stub.Unary(req) | ||
assert r.msg == "x" | ||
|
||
|
||
async def secure_token_unary(): | ||
channel = create_secure_channel(f"{host}:{port}", token=TOKEN) | ||
stub = G.AuthServiceStub(channel) | ||
req = P.Request(msg="x") | ||
r = await stub.Unary(req) | ||
assert r.msg == "x" | ||
|
||
|
||
async def token_bidi(): | ||
channel = grpc.aio.insecure_channel(f"{host}:{port}") | ||
stub = G.AuthServiceStub(channel) | ||
|
||
async def reqs(): | ||
for _ in range(2): | ||
req = P.Request(msg="hi") | ||
yield req | ||
|
||
_call = stub.BidiStream(reqs(), metadata=[("authorization", TOKEN)]) | ||
count = 0 | ||
async for r in _call: | ||
count += 1 | ||
print("=> ", count) | ||
|
||
|
||
def test(): | ||
# asyncio.run(unary()) | ||
# asyncio.run(secure_unary()) | ||
# asyncio.run(secure_token_unary()) | ||
asyncio.run(token_bidi()) |
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,84 @@ | ||
module Main (main) where | ||
|
||
import Control.Monad | ||
import Data.ByteString (ByteString) | ||
import qualified Data.ByteString as BS | ||
import Data.Either | ||
import Data.ProtoLens (defMessage) | ||
import Lens.Micro | ||
|
||
import HsGrpc.Common.Log | ||
import HsGrpc.Server | ||
import HsGrpc.Server.Types | ||
import Proto.Auth as P | ||
import Proto.Auth_Fields as P | ||
import Proto.Msg as P | ||
import Proto.Msg_Fields as P | ||
|
||
main :: IO () | ||
main = do | ||
let tokens = [ "dXNlcjpwYXNzd2Q=" -- echo -n "user:passwd" | base64 | ||
, "dXNlcjE6cGFzc3dkMQ==" -- echo -n "user1:passwd1" | base64 | ||
] | ||
--sslOptions <- Just <$>readTlsPemFile | ||
-- "tests/cases/credentials/localhost.key" | ||
-- "tests/cases/credentials/localhost.crt" | ||
-- Nothing | ||
-- (Just "tests/cases/credentials/root.crt") | ||
sslOptions <- pure Nothing | ||
|
||
let opts = defaultServerOpts | ||
{ serverHost = "127.0.0.1" | ||
, serverPort = 50051 | ||
, serverSslOptions = sslOptions | ||
, serverAuthTokens = tokens | ||
, serverParallelism = 1 | ||
, serverOnStarted = Just onStarted | ||
} | ||
runServer opts handlers | ||
|
||
readTlsPemFile | ||
:: String -> String -> Maybe String | ||
-> IO SslServerCredentialsOptions | ||
readTlsPemFile keyPath certPath caPath = do | ||
key <- BS.readFile keyPath | ||
cert <- BS.readFile certPath | ||
ca <- mapM BS.readFile caPath | ||
let authType = maybe GrpcSslDontRequestClientCertificate | ||
(const GrpcSslRequestAndRequireClientCertificateAndVerify) | ||
caPath | ||
pure $ SslServerCredentialsOptions{ pemKeyCertPairs = [(key, cert)] | ||
, pemRootCerts = ca | ||
, clientAuthType = authType | ||
} | ||
|
||
|
||
onStarted :: IO () | ||
onStarted = putStrLn "Server listening on 0.0.0.0:50051" | ||
|
||
|
||
handlers :: [ServiceHandler] | ||
handlers = | ||
[ unary (GRPC :: GRPC P.AuthService "unary") handleUnary | ||
, clientStream (GRPC :: GRPC P.AuthService "clientStream") handleClientStream | ||
, serverStream (GRPC :: GRPC P.AuthService "serverStream") handleServerStream | ||
, bidiStream (GRPC :: GRPC P.AuthService "bidiStream") handleBidiStream | ||
] | ||
|
||
handleUnary :: UnaryHandler P.Request P.Reply | ||
handleUnary _ctx req = pure $ defMessage & P.msg .~ (req ^. P.msg) | ||
|
||
handleClientStream :: ClientStreamHandler P.Request P.Reply | ||
handleClientStream = undefined | ||
|
||
handleServerStream :: ServerStreamHandler P.Request P.Reply () | ||
handleServerStream = undefined | ||
|
||
handleBidiStream :: BidiStreamHandler P.Request P.Reply () | ||
handleBidiStream _ctx stream = whileM $ do | ||
m_req <- streamRead stream | ||
case m_req of | ||
Just req -> do | ||
let reply = defMessage & P.msg .~ ("hi, " <> req ^. P.msg) | ||
isRight <$> streamWrite stream (Just reply) | ||
Nothing -> putStrLn "Client closed" >> pure False |
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 |
---|---|---|
@@ -1,17 +1,10 @@ | ||
syntax = "proto3"; | ||
|
||
package test; | ||
|
||
service Service { | ||
import "msg.proto"; | ||
|
||
service AsyncScheduleService { | ||
rpc SlowUnary(Request) returns (Reply) {} | ||
rpc DepUnary(Request) returns (Reply) {} | ||
rpc BidiStream(stream Request) returns (stream Reply) {} | ||
} | ||
|
||
message Request { | ||
string msg = 1; | ||
} | ||
|
||
message Reply { | ||
string msg = 1; | ||
} |
Oops, something went wrong.