diff options
Diffstat (limited to 'cmd/cashierd')
-rw-r--r-- | cmd/cashierd/main.go | 14 | ||||
-rw-r--r-- | cmd/cashierd/rpc.go | 68 |
2 files changed, 78 insertions, 4 deletions
diff --git a/cmd/cashierd/main.go b/cmd/cashierd/main.go index 8164cf7..d355604 100644 --- a/cmd/cashierd/main.go +++ b/cmd/cashierd/main.go @@ -17,6 +17,7 @@ import ( "strings" "github.com/pkg/errors" + "github.com/soheilhy/cmux" "go4.org/wkfs" "golang.org/x/crypto/acme/autocert" @@ -153,8 +154,7 @@ func signHandler(a *appContext, w http.ResponseWriter, r *http.Request) (int, er token := &oauth2.Token{ AccessToken: t, } - ok := authprovider.Valid(token) - if !ok { + if !authprovider.Valid(token) { return http.StatusUnauthorized, errors.New(http.StatusText(http.StatusUnauthorized)) } @@ -174,7 +174,7 @@ func signHandler(a *appContext, w http.ResponseWriter, r *http.Request) (int, er } if err := json.NewEncoder(w).Encode(&lib.SignResponse{ Status: "ok", - Response: lib.GetPublicKey(cert), + Response: string(lib.GetPublicKey(cert)), }); err != nil { return http.StatusInternalServerError, errors.Wrap(err, "error encoding response") } @@ -425,5 +425,11 @@ func main() { s := &http.Server{ Handler: h, } - log.Fatal(s.Serve(l)) + + cm := cmux.New(l) + httpl := cm.Match(cmux.HTTP1Fast()) + grpcl := cm.Match(cmux.HTTP2HeaderField("content-type", "application/grpc")) + go s.Serve(httpl) + go newGrpcServer(grpcl) + log.Fatal(cm.Serve()) } diff --git a/cmd/cashierd/rpc.go b/cmd/cashierd/rpc.go new file mode 100644 index 0000000..ad8aa5d --- /dev/null +++ b/cmd/cashierd/rpc.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + "net" + + "golang.org/x/net/context" + + "golang.org/x/oauth2" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + + "github.com/nsheridan/cashier/lib" + "github.com/nsheridan/cashier/proto" +) + +type rpcServer struct{} + +type key int + +const usernameKey key = 0 + +func (s *rpcServer) Sign(ctx context.Context, req *proto.SignRequest) (*proto.SignResponse, error) { + username, ok := ctx.Value(usernameKey).(string) + if !ok { + return nil, grpc.Errorf(codes.InvalidArgument, "Error reading username") + } + cert, err := keysigner.SignUserKeyFromRPC(req, username) + if err != nil { + return nil, grpc.Errorf(codes.InvalidArgument, err.Error()) + } + if err := certstore.SetCert(cert); err != nil { + log.Printf("Error recording cert: %v", err) + } + resp := &proto.SignResponse{ + Cert: lib.GetPublicKey(cert), + } + return resp, nil +} + +func authInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + md, ok := metadata.FromContext(ctx) + if !ok { + return nil, grpc.Errorf(codes.Unauthenticated, "request not authenticated") + } + switch md["security"][0] { + case "authorization": + token := &oauth2.Token{ + AccessToken: md["payload"][0], + } + if !authprovider.Valid(token) { + return nil, grpc.Errorf(codes.PermissionDenied, "access denied") + } + authprovider.Revoke(token) + ctx = context.WithValue(ctx, usernameKey, authprovider.Username(token)) + default: + return nil, grpc.Errorf(codes.InvalidArgument, "unknown argument") + } + return handler(ctx, req) +} + +func newGrpcServer(l net.Listener) { + serv := grpc.NewServer(grpc.UnaryInterceptor(authInterceptor)) + proto.RegisterSignerServer(serv, &rpcServer{}) + serv.Serve(l) +} |