From 1744f96fe53e7290a7db65e4b48138a5e305b088 Mon Sep 17 00:00:00 2001 From: Michael Cambria Date: Tue, 16 Apr 2019 14:22:12 -0400 Subject: [PATCH] Convert to cniservice --- Makefile | 2 +- api/api.proto | 36 ++++++++++++++++++++++++- api/handler.go | 23 ++++++++++++++++ client/main.go | 20 +++++++++++++- server/main.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 147 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 8ab9d00..1532458 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CLIENT_OUT := "bin/client" API_OUT := "api/api.pb.go" API_REST_OUT := "api/api.pb.gw.go" API_SWAG_OUT := "api/api.swagger.json" -PKG := "gitlab.com/pantomath-io/demo-grpc" +PKG := "github.com/mccv1r0/demo-grpc" SERVER_PKG_BUILD := "${PKG}/server" CLIENT_PKG_BUILD := "${PKG}/client" PKG_LIST := $(shell go list ${PKG}/... | grep -v /vendor/) diff --git a/api/api.proto b/api/api.proto index 2c6c20d..81596ca 100644 --- a/api/api.proto +++ b/api/api.proto @@ -14,4 +14,38 @@ service Ping { body: "*" }; } -} \ No newline at end of file +} + + +service CNIserver { + // Process CNI message + rpc CNIop (CNImsg) returns (CNIresult) {} +} + +enum CmdType { + VERSION = 0; + ADD = 1; + CHECK = 2; + DEL = 3; +} + +message CNIargs { + string name = 1; + string value = 2; +} + +message CNImsg { + CmdType cmd = 1; + string containerID = 2; + string netNS = 3; + string ifName = 4; + repeated CNIargs args = 5; + string stdIn = 6; +} + +message CNIresult { + CmdType cmd = 1; + string error = 2; + string stdOut = 3; +} + diff --git a/api/handler.go b/api/handler.go index f123180..5026e61 100644 --- a/api/handler.go +++ b/api/handler.go @@ -15,3 +15,26 @@ func (s *Server) SayHello(ctx context.Context, in *PingMessage) (*PingMessage, e log.Printf("Receive message %s", in.Greeting) return &PingMessage{Greeting: "bar"}, nil } + +// Server represents the gRPC server +type CNIServer struct { +} + +// CNIop generates result to a CNImsg +func (s *CNIServer) CNIop(ctx context.Context, in *CNImsg) (*CNIresult, error) { + log.Printf("Receive message Cmd: %s", in.Cmd) + log.Printf("Receive message ContainerID: %s", in.ContainerID) + log.Printf("Receive message NetNS: %s", in.NetNS) + log.Printf("Receive message IfName: %s", in.IfName) + log.Printf("Receive message StdIn: %s", in.StdIn) + + cniResult := CNIresult{ + Cmd: in.Cmd, + StdOut: "stdOutStringHere", + } + + log.Printf("Response from server: %s", cniResult.StdOut) + return &cniResult, nil +} + + diff --git a/client/main.go b/client/main.go index d571fef..d28af2d 100644 --- a/client/main.go +++ b/client/main.go @@ -3,7 +3,7 @@ package main import ( "log" - "gitlab.com/pantomath-io/demo-grpc/api" + "github.com/mccv1r0/demo-grpc/api" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -50,6 +50,7 @@ func main() { } defer conn.Close() +/* c := api.NewPingClient(conn) response, err := c.SayHello(context.Background(), &api.PingMessage{Greeting: "foo"}) @@ -57,4 +58,21 @@ func main() { log.Fatalf("error when calling SayHello: %s", err) } log.Printf("Response from server: %s", response.Greeting) +*/ + + // CNI Test + cni := api.NewCNIserverClient(conn) + + cniMsg := api.CNImsg{ + Cmd: api.CmdType_ADD, + ContainerID: "containerOne", + NetNS: "mcc-test-0", + IfName: "ensX", + StdIn: "stdInStringHere", + } + result, err := cni.CNIop(context.Background(), &cniMsg) + if err != nil { + log.Fatalf("error when calling CNIop: %s", err) + } + log.Printf("Response from server: %s", result.StdOut) } diff --git a/server/main.go b/server/main.go index e879387..162b303 100644 --- a/server/main.go +++ b/server/main.go @@ -11,7 +11,7 @@ import ( "golang.org/x/net/context" - "gitlab.com/pantomath-io/demo-grpc/api" + "github.com/mccv1r0/demo-grpc/api" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" @@ -31,6 +31,7 @@ func credMatcher(headerName string) (mdName string, ok bool) { return "", false } +/* // authenticateAgent check the client credentials func authenticateClient(ctx context.Context, s *api.Server) (string, error) { if md, ok := metadata.FromIncomingContext(ctx); ok { @@ -66,6 +67,43 @@ func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServ return handler(ctx, req) } +*/ + +// authenticateAgent check the client credentials +func authenticateClient(ctx context.Context, s *api.CNIServer) (string, error) { + if md, ok := metadata.FromIncomingContext(ctx); ok { + clientLogin := strings.Join(md["login"], "") + clientPassword := strings.Join(md["password"], "") + + if clientLogin != "john" { + return "", fmt.Errorf("unknown user %s", clientLogin) + } + if clientPassword != "doe" { + return "", fmt.Errorf("bad password %s", clientPassword) + } + + log.Printf("authenticated client: %s", clientLogin) + + return "42", nil + } + return "", fmt.Errorf("missing credentials") +} + +// unaryInterceptorCNI call authenticateClient with current context +func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + s, ok := info.Server.(*api.CNIServer) + if !ok { + return nil, fmt.Errorf("unable to cast server") + } + clientID, err := authenticateClient(ctx, s) + if err != nil { + return nil, err + } + + ctx = context.WithValue(ctx, clientIDKey, clientID) + + return handler(ctx, req) +} func startGRPCServer(address, certFile, keyFile string) error { // create a listener on TCP port @@ -74,6 +112,7 @@ func startGRPCServer(address, certFile, keyFile string) error { return fmt.Errorf("failed to listen: %v", err) } +/* // create a server instance s := api.Server{} @@ -92,12 +131,39 @@ func startGRPCServer(address, certFile, keyFile string) error { // attach the Ping service to the server api.RegisterPingServer(grpcServer, &s) - - // start the server +*/ +/* + // Original log.Printf("starting HTTP/2 gRPC server on %s", address) if err := grpcServer.Serve(lis); err != nil { return fmt.Errorf("failed to serve: %s", err) } +*/ + + // create a CNI server instance + cni := api.CNIServer{} + + // Create the TLS credentials + creds, err := credentials.NewServerTLSFromFile(certFile, keyFile) + if err != nil { + return fmt.Errorf("could not load TLS keys: %s", err) + } + + // Create an array of gRPC options with the credentials + opts := []grpc.ServerOption{grpc.Creds(creds), + grpc.UnaryInterceptor(unaryInterceptor)} + + // create a gRPC server object + grpcCNIServer := grpc.NewServer(opts...) + + // attach the CNI service to the server + api.RegisterCNIserverServer(grpcCNIServer, &cni) + + // start the server + log.Printf("starting CNI HTTP/2 gRPC server on %s", address) + if err := grpcCNIServer.Serve(lis); err != nil { + return fmt.Errorf("failed to serve: %s", err) + } return nil } -- 2.44.0