Add gRPC backend.

This commit is contained in:
Ignacio Gómez 2019-06-13 17:55:21 -04:00
parent 0cb001eeff
commit 97c35e82a6
13 changed files with 1113 additions and 17 deletions

View File

@ -14,4 +14,8 @@ test:
go test ./backends -v -bench=none -count=1
benchmark:
go test ./backends -v -bench=. -run=^a
go test ./backends -v -bench=. -run=^a
service:
@echo "Generating gRPC code from .proto files"
@go generate grpc/grpc.go

View File

@ -19,15 +19,12 @@ It was intended for use with [brocaar's](https://github.com/brocaar) [Loraserver
* SQLite3
* MongoDB
* Custom (experimental)
* gRPC
**Every backend offers user, superuser and acl checks, and include proper tests.**
Please open an issue with the `feature` or `enhancement` tag to request new backends or additions to existing ones.
#### Why?
The plugin was developed because I needed a JWT local mode and it was faster to write it in Go than to patch [jpmens'](https://github.com/jpmens) plugin at the time. Being written in Go, it was easy to extend too. Also, I wanted to give `cgo` a try.
### Table of contents
@ -65,6 +62,9 @@ The plugin was developed because I needed a JWT local mode and it was faster to
- [Testing MongoDB](#testing-mongodb)
- [Custom \(experimental\)](#custom-experimental)
- [Testing Custom](#testing-custom)
- [gRPC](#grpc)
- [Service](#service)
- [Testing gRPC](#testing-grpc)
- [Benchmarks](#benchmarks)
- [Using with loraserver](#using-with-loraserver)
- [License](#license)
@ -979,6 +979,87 @@ Check the plugin directory for dummy example and makefile.
As this option is custom written by yourself, there are no tests included in the project.
### gRPC
The `grpc` allows to check for user auth, superuser and acls against a gRPC service.
| Option | default | Mandatory | Meaning |
| ------------------ | ----------------- | :---------: | ------------------------------ |
| grpc_host | | Y | gRPC server hostname |
| grpc_port | | Y | gRPC server port number |
| grpc_ca_cert | | N | gRPC server CA cert path |
| grpc_tls_cert | | N | gRPC server TLS cert path |
| grpc_tls_key | | N | gRPC server TLS key path |
#### Service
The gRPC server should implement the service defined at `grpc/auth.proto`, which looks like this:
```proto
syntax = "proto3";
package grpc;
import "google/protobuf/empty.proto";
// AuthService is the service providing the auth interface.
service AuthService {
// GetUser tries to authenticate a user.
rpc GetUser(GetUserRequest) returns (AuthResponse) {}
// GetSuperuser checks if a user is a superuser.
rpc GetSuperuser(GetSuperuserRequest) returns (AuthResponse) {}
// CheckAcl checks user's authorization for the given topic.
rpc CheckAcl(CheckAclRequest) returns (AuthResponse) {}
// GetName retrieves the name of the backend.
rpc GetName(google.protobuf.Empty) returns (NameResponse) {}
// Halt signals the backend to halt.
rpc Halt(google.protobuf.Empty) returns (google.protobuf.Empty) {}
}
message GetUserRequest {
// Username.
string username = 1;
// Plain text password.
string password = 2;
}
message GetSuperuserRequest {
// Username.
string username = 1;
}
message CheckAclRequest {
// Username.
string username = 1;
// Topic to be checked for.
string topic = 2;
// The client connection's id.
string clientid = 3;
// Topic access.
int32 acc = 4;
}
message AuthResponse {
// If the user is authorized/authenticated.
bool ok = 1;
}
message NameResponse {
// The name of the gRPC backend.
string name = 1;
}
```
#### Testing gRPC
This backend has no special requirements as a gRPC server is mocked to test different scenarios.
### Benchmarks

150
backends/grpc.go Normal file
View File

@ -0,0 +1,150 @@
package backends
import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"time"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
gs "github.com/iegomez/mosquitto-go-auth/grpc"
)
// GRPC holds a client for the service and implements the Backend interface.
type GRPC struct {
client gs.AuthServiceClient
conn *grpc.ClientConn
}
// NewGRPC tries to connect to the gRPC service at the given host.
func NewGRPC(authOpts map[string]string, logLevel log.Level) (GRPC, error) {
var g GRPC
if authOpts["grpc_host"] == "" || authOpts["grpc_port"] == "" {
return g, errors.New("grpc must have a host and port")
}
caCert := []byte(authOpts["grpc_ca_cert"])
tlsCert := []byte(authOpts["grpc_tls_cert"])
tlsKey := []byte(authOpts["grpc_tls_key"])
addr := fmt.Sprintf("%s:%s", authOpts["grpc_host"], authOpts["grpc_port"])
conn, gsClient, err := createClient(addr, caCert, tlsCert, tlsKey)
if err != nil {
return g, err
}
g.client = gsClient
g.conn = conn
return g, nil
}
// GetUser checks that the username exists and the given password hashes to the same password.
func (o GRPC) GetUser(username, password string) bool {
req := gs.GetUserRequest{
Username: username,
Password: password,
}
resp, err := o.client.GetUser(context.Background(), &req)
if err != nil {
log.Errorf("grpc get user error: %s", err)
return false
}
return resp.Ok
}
// GetSuperuser checks that the user is a superuser.
func (o GRPC) GetSuperuser(username string) bool {
req := gs.GetSuperuserRequest{
Username: username,
}
resp, err := o.client.GetSuperuser(context.Background(), &req)
if err != nil {
log.Errorf("grpc get superuser error: %s", err)
return false
}
return resp.Ok
}
// CheckAcl checks if the user has access to the given topic.
func (o GRPC) CheckAcl(username, topic, clientid string, acc int32) bool {
req := gs.CheckAclRequest{
Username: username,
Topic: topic,
Clientid: clientid,
Acc: acc,
}
resp, err := o.client.CheckAcl(context.Background(), &req)
if err != nil {
log.Errorf("grpc check acl error: %s", err)
return false
}
return resp.Ok
}
func createClient(hostname string, caCert, tlsCert, tlsKey []byte) (*grpc.ClientConn, gs.AuthServiceClient, error) {
logrusEntry := log.NewEntry(log.StandardLogger())
logrusOpts := []grpc_logrus.Option{
grpc_logrus.WithLevels(grpc_logrus.DefaultCodeToLevel),
}
nsOpts := []grpc.DialOption{
grpc.WithBlock(),
grpc.WithUnaryInterceptor(
grpc_logrus.UnaryClientInterceptor(logrusEntry, logrusOpts...),
),
}
if len(caCert) == 0 && len(tlsCert) == 0 && len(tlsKey) == 0 {
nsOpts = append(nsOpts, grpc.WithInsecure())
log.WithField("server", hostname).Warning("creating insecure grpc client")
} else {
log.WithField("server", hostname).Info("creating grpc client")
cert, err := tls.X509KeyPair(tlsCert, tlsKey)
if err != nil {
return nil, nil, errors.Wrap(err, "load x509 keypair error")
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, nil, errors.Wrap(err, "append ca cert to pool error")
}
nsOpts = append(nsOpts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: caCertPool,
})))
}
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
gsClient, err := grpc.DialContext(ctx, hostname, nsOpts...)
if err != nil {
return nil, nil, errors.Wrap(err, "dial grpc api error")
}
return gsClient, gs.NewAuthServiceClient(gsClient), nil
}

132
backends/grpc_test.go Normal file
View File

@ -0,0 +1,132 @@
package backends
import (
"context"
"net"
"testing"
"github.com/golang/protobuf/ptypes/empty"
"google.golang.org/grpc"
log "github.com/sirupsen/logrus"
gs "github.com/iegomez/mosquitto-go-auth/grpc"
. "github.com/smartystreets/goconvey/convey"
)
var (
grpcUsername string = "test_user"
grpcSuperuser string = "superuser"
grpcPassword string = "test_password"
grpcTopic string = "test/topic"
grpcAcc int32 = 1
grpcClientId string = "test_client"
)
type AuthServiceAPI struct{}
func NewAuthServiceAPI() *AuthServiceAPI {
return &AuthServiceAPI{}
}
func (a *AuthServiceAPI) GetUser(ctx context.Context, req *gs.GetUserRequest) (*gs.AuthResponse, error) {
if req.Username == grpcUsername && req.Password == grpcPassword {
return &gs.AuthResponse{
Ok: true,
}, nil
}
return &gs.AuthResponse{
Ok: false,
}, nil
}
func (a *AuthServiceAPI) GetSuperuser(ctx context.Context, req *gs.GetSuperuserRequest) (*gs.AuthResponse, error) {
if req.Username == grpcSuperuser {
return &gs.AuthResponse{
Ok: true,
}, nil
}
return &gs.AuthResponse{
Ok: false,
}, nil
}
func (a *AuthServiceAPI) CheckAcl(ctx context.Context, req *gs.CheckAclRequest) (*gs.AuthResponse, error) {
if req.Username == grpcUsername && req.Topic == grpcTopic && req.Clientid == grpcClientId && req.Acc == grpcAcc {
return &gs.AuthResponse{
Ok: true,
}, nil
}
return &gs.AuthResponse{
Ok: false,
}, nil
}
func (a *AuthServiceAPI) GetName(ctx context.Context, req *empty.Empty) (*gs.NameResponse, error) {
return &gs.NameResponse{
Name: "MyGRPCBackend",
}, nil
}
func (a *AuthServiceAPI) Halt(ctx context.Context, req *empty.Empty) (*empty.Empty, error) {
return &empty.Empty{}, nil
}
func TestGRPC(t *testing.T) {
Convey("given a mock grpc server", t, func(c C) {
grpcServer := grpc.NewServer()
gs.RegisterAuthServiceServer(grpcServer, NewAuthServiceAPI())
lis, err := net.Listen("tcp", ":3123")
So(err, ShouldBeNil)
go grpcServer.Serve(lis)
defer grpcServer.Stop()
authOpts := make(map[string]string)
authOpts["grpc_host"] = "localhost"
authOpts["grpc_port"] = "3123"
Convey("given a correct host grpc backend should be able to initialize", func(c C) {
g, err := NewGRPC(authOpts, log.DebugLevel)
c.So(err, ShouldBeNil)
Convey("given incorrect credentials user should not be authenticated", func(c C) {
auth := g.GetUser(grpcUsername, "wrong")
c.So(auth, ShouldBeFalse)
Convey("given correct credential user should be authenticated", func(c C) {
auth := g.GetUser(grpcUsername, grpcPassword)
c.So(auth, ShouldBeTrue)
Convey("given a non superuser user the service should respond false", func(c C) {
auth = g.GetSuperuser(grpcUsername)
So(auth, ShouldBeFalse)
Convey("switching to a superuser should return true", func(c C) {
auth = g.GetSuperuser(grpcSuperuser)
So(auth, ShouldBeTrue)
Convey("authorizing a wrong topic should fail", func(c C) {
auth = g.CheckAcl(grpcUsername, "wrong/topic", grpcClientId, grpcAcc)
So(auth, ShouldBeFalse)
Convey("switching to a correct one should succedd", func(c C) {
auth = g.CheckAcl(grpcUsername, grpcTopic, grpcClientId, grpcAcc)
So(auth, ShouldBeTrue)
})
})
})
})
})
})
})
})
}

View File

@ -66,7 +66,6 @@ func TestHTTPAllJsonServer(t *testing.T) {
httpResponse.Error = "Not a superuser."
}
} else if r.URL.Path == "/acl" {
//uAcc := float64.(params["acc"])
paramsAcc := int64(params["acc"].(float64))
if params["username"].(string) == username && params["topic"].(string) == topic && params["clientid"].(string) == clientId && paramsAcc <= acc {
httpResponse.Ok = true

View File

@ -28,7 +28,7 @@ func init() {
"redis_host": "localhost",
"redis_port": "6379",
"redis_db": "2",
"redis_password": "go_auth_test",
"redis_password": "",
}
var err error
redis, err = NewRedis(authOpts, log.ErrorLevel)

View File

@ -14,7 +14,7 @@ func TestRedis(t *testing.T) {
authOpts["redis_host"] = "localhost"
authOpts["redis_port"] = "6379"
authOpts["redis_db"] = "2"
authOpts["redis_password"] = "go_auth_test"
authOpts["redis_password"] = ""
Convey("Given valid params NewRedis should return a Redis backend instance", t, func() {
redis, err := NewRedis(authOpts, log.DebugLevel)

25
go.mod
View File

@ -3,27 +3,34 @@ module github.com/iegomez/mosquitto-go-auth
go 1.12
require (
github.com/brocaar/lora-app-server v2.5.1+incompatible
github.com/brocaar/loraserver v2.5.0+incompatible // indirect
github.com/brocaar/lorawan v0.0.0-20190523144945-4c051b1fa597 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/eclipse/paho.mqtt.golang v1.2.0 // indirect
github.com/go-redis/redis v6.14.1+incompatible
github.com/go-sql-driver/mysql v1.4.0
github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/protobuf v1.3.1
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-cmp v0.3.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/googleapis/gax-go v2.0.2+incompatible // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0
github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
github.com/lib/pq v1.0.0
github.com/mattn/go-sqlite3 v1.9.0
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/pkg/errors v0.8.0
github.com/sirupsen/logrus v1.1.0
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac // indirect
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.3.0
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
github.com/xdg/stringprep v1.0.0 // indirect
go.mongodb.org/mongo-driver v1.0.0
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4
golang.org/x/sys v0.0.0-20181003145944-af653ce8b74f // indirect
google.golang.org/appengine v1.2.0 // indirect
go.opencensus.io v0.22.0 // indirect
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c
google.golang.org/api v0.6.0 // indirect
google.golang.org/grpc v1.21.1
)

141
go.sum
View File

@ -1,32 +1,86 @@
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5/go.mod h1:w5D10RxC0NmPYxmQ438CC1S07zaC1zpvuNW7s5sUk2Q=
github.com/brocaar/lora-app-server v2.5.1+incompatible h1:F//0TncqDS9uKC4yTrJTTnlwfvM9Ie/KgRDSgWPA6as=
github.com/brocaar/lora-app-server v2.5.1+incompatible/go.mod h1:Thw3wBnUbdwaTporobKVwffFSfHvdrjpOSIvbaO2YMU=
github.com/brocaar/loraserver v2.5.0+incompatible h1:Fna4CF0jW2Vl4UpjLIhR5ifW4g+oZD/w3Dq09TiJ8Z8=
github.com/brocaar/loraserver v2.5.0+incompatible/go.mod h1:VBTim0YtfWAKehjJ6k17jCnG44DzXVdL4iu+hwxg2ik=
github.com/brocaar/lorawan v0.0.0-20190523144945-4c051b1fa597 h1:bYzV3+MYStooVxZwloCHvOUDsFjTKS8vdRJ9jZkEd/s=
github.com/brocaar/lorawan v0.0.0-20190523144945-4c051b1fa597/go.mod h1:Fm+51pxK6mZoAQjIaWJqPmnRuXecozsM5Mf9c+kr/ko=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-redis/redis v6.14.1+incompatible h1:kSJohAREGMr344uMa8PzuIg5OU6ylCbyDkWkkNOfEik=
github.com/go-redis/redis v6.14.1+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4 h1:hU4mGcQI4DaAYW+IbTun+2qEZVFxK0ySjQLTbS0VQKc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jacobsa/crypto v0.0.0-20180924003735-d95898ceee07 h1:/PaS1RNKtbBEndIvzCqIgYh6GAH9ZFc8Mj4tVRVyfOA=
github.com/jacobsa/crypto v0.0.0-20180924003735-d95898ceee07/go.mod h1:LadVJg0XuawGk+8L1rYnIED8451UyNxEMdTWCEt5kmU=
github.com/jacobsa/oglematchers v0.0.0-20150720000706-141901ea67cd/go.mod h1:TlmyIZDpGmwRoTWiakdr+HA1Tukze6C6XbRVidYq02M=
github.com/jacobsa/oglemock v0.0.0-20150831005832-e94d794d06ff/go.mod h1:gJWba/XXGl0UoOmBQKRWCJdHrr3nE0T65t6ioaj3mLI=
github.com/jacobsa/ogletest v0.0.0-20170503003838-80d50a735a11/go.mod h1:+DBdDyfoO2McrOyDemRBq0q9CMEByef7sYl7JH5Q3BI=
github.com/jacobsa/reqtrace v0.0.0-20150505043853-245c9e0234cb/go.mod h1:ivcmUvxXWjb27NsPEaiYK7AidlZXS7oQ5PowUS9z3I4=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs=
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
@ -38,17 +92,30 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/sirupsen/logrus v1.1.0 h1:65VZabgUiV9ktjGM5nTq0+YurgTyX+YI2lSSfDjI+qU=
github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac h1:wbW+Bybf9pXxnCFAOWZTqkRjAc7rAIwo2e1ArUhiHxg=
github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 h1:hBSHahWMEgzwRyS6dRpxY0XyjZsHyQ61s084wo5PJe0=
github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff h1:86HlEv0yBCry9syNuylzqznKXDK11p6D0DT596yNMys=
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 h1:rQ229MBgvW68s1/g6f1/63TgYwYxfF4E+bi/KC19P8g=
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
@ -57,27 +124,101 @@ github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
go.mongodb.org/mongo-driver v1.0.0 h1:KxPRDyfB2xXnDE2My8acoOWBQkfv3tz0SaWTRZjJR0c=
go.mongodb.org/mongo-driver v1.0.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4 h1:Vk3wNqEZwyGyei9yq5ekj7frek2u7HUfffJ1/opblzc=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181003145944-af653ce8b74f h1:zAtpFwFDtnvBWPPelq8CSiqRN1wrIzMUk9dwzbpjpNM=
golang.org/x/sys v0.0.0-20181003145944-af653ce8b74f/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190402054613-e4093980e83e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.6.0 h1:2tJEkRfnZL5g1GeBUlITh/rqT5HG3sFcoVCUUxmgJ2g=
google.golang.org/api v0.6.0/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

509
grpc/auth.pb.go Normal file
View File

@ -0,0 +1,509 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: auth.proto
package grpc
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type GetUserRequest struct {
// Username.
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
// Plain text password.
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetUserRequest) Reset() { *m = GetUserRequest{} }
func (m *GetUserRequest) String() string { return proto.CompactTextString(m) }
func (*GetUserRequest) ProtoMessage() {}
func (*GetUserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbd6f3875b0e874, []int{0}
}
func (m *GetUserRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetUserRequest.Unmarshal(m, b)
}
func (m *GetUserRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetUserRequest.Marshal(b, m, deterministic)
}
func (m *GetUserRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetUserRequest.Merge(m, src)
}
func (m *GetUserRequest) XXX_Size() int {
return xxx_messageInfo_GetUserRequest.Size(m)
}
func (m *GetUserRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetUserRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetUserRequest proto.InternalMessageInfo
func (m *GetUserRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *GetUserRequest) GetPassword() string {
if m != nil {
return m.Password
}
return ""
}
type GetSuperuserRequest struct {
// Username.
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetSuperuserRequest) Reset() { *m = GetSuperuserRequest{} }
func (m *GetSuperuserRequest) String() string { return proto.CompactTextString(m) }
func (*GetSuperuserRequest) ProtoMessage() {}
func (*GetSuperuserRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbd6f3875b0e874, []int{1}
}
func (m *GetSuperuserRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetSuperuserRequest.Unmarshal(m, b)
}
func (m *GetSuperuserRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetSuperuserRequest.Marshal(b, m, deterministic)
}
func (m *GetSuperuserRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetSuperuserRequest.Merge(m, src)
}
func (m *GetSuperuserRequest) XXX_Size() int {
return xxx_messageInfo_GetSuperuserRequest.Size(m)
}
func (m *GetSuperuserRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetSuperuserRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetSuperuserRequest proto.InternalMessageInfo
func (m *GetSuperuserRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
type CheckAclRequest struct {
// Username.
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
// Topic to be checked for.
Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"`
// The client connection's id.
Clientid string `protobuf:"bytes,3,opt,name=clientid,proto3" json:"clientid,omitempty"`
// Topic access.
Acc int32 `protobuf:"varint,4,opt,name=acc,proto3" json:"acc,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CheckAclRequest) Reset() { *m = CheckAclRequest{} }
func (m *CheckAclRequest) String() string { return proto.CompactTextString(m) }
func (*CheckAclRequest) ProtoMessage() {}
func (*CheckAclRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbd6f3875b0e874, []int{2}
}
func (m *CheckAclRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CheckAclRequest.Unmarshal(m, b)
}
func (m *CheckAclRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CheckAclRequest.Marshal(b, m, deterministic)
}
func (m *CheckAclRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CheckAclRequest.Merge(m, src)
}
func (m *CheckAclRequest) XXX_Size() int {
return xxx_messageInfo_CheckAclRequest.Size(m)
}
func (m *CheckAclRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CheckAclRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CheckAclRequest proto.InternalMessageInfo
func (m *CheckAclRequest) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *CheckAclRequest) GetTopic() string {
if m != nil {
return m.Topic
}
return ""
}
func (m *CheckAclRequest) GetClientid() string {
if m != nil {
return m.Clientid
}
return ""
}
func (m *CheckAclRequest) GetAcc() int32 {
if m != nil {
return m.Acc
}
return 0
}
type AuthResponse struct {
// If the user is authorized/authenticated.
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AuthResponse) Reset() { *m = AuthResponse{} }
func (m *AuthResponse) String() string { return proto.CompactTextString(m) }
func (*AuthResponse) ProtoMessage() {}
func (*AuthResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbd6f3875b0e874, []int{3}
}
func (m *AuthResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AuthResponse.Unmarshal(m, b)
}
func (m *AuthResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AuthResponse.Marshal(b, m, deterministic)
}
func (m *AuthResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_AuthResponse.Merge(m, src)
}
func (m *AuthResponse) XXX_Size() int {
return xxx_messageInfo_AuthResponse.Size(m)
}
func (m *AuthResponse) XXX_DiscardUnknown() {
xxx_messageInfo_AuthResponse.DiscardUnknown(m)
}
var xxx_messageInfo_AuthResponse proto.InternalMessageInfo
func (m *AuthResponse) GetOk() bool {
if m != nil {
return m.Ok
}
return false
}
type NameResponse struct {
// The name of the gRPC backend.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *NameResponse) Reset() { *m = NameResponse{} }
func (m *NameResponse) String() string { return proto.CompactTextString(m) }
func (*NameResponse) ProtoMessage() {}
func (*NameResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_8bbd6f3875b0e874, []int{4}
}
func (m *NameResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NameResponse.Unmarshal(m, b)
}
func (m *NameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NameResponse.Marshal(b, m, deterministic)
}
func (m *NameResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_NameResponse.Merge(m, src)
}
func (m *NameResponse) XXX_Size() int {
return xxx_messageInfo_NameResponse.Size(m)
}
func (m *NameResponse) XXX_DiscardUnknown() {
xxx_messageInfo_NameResponse.DiscardUnknown(m)
}
var xxx_messageInfo_NameResponse proto.InternalMessageInfo
func (m *NameResponse) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func init() {
proto.RegisterType((*GetUserRequest)(nil), "grpc.GetUserRequest")
proto.RegisterType((*GetSuperuserRequest)(nil), "grpc.GetSuperuserRequest")
proto.RegisterType((*CheckAclRequest)(nil), "grpc.CheckAclRequest")
proto.RegisterType((*AuthResponse)(nil), "grpc.AuthResponse")
proto.RegisterType((*NameResponse)(nil), "grpc.NameResponse")
}
func init() { proto.RegisterFile("auth.proto", fileDescriptor_8bbd6f3875b0e874) }
var fileDescriptor_8bbd6f3875b0e874 = []byte{
// 331 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xdf, 0x4e, 0xc2, 0x30,
0x14, 0xc6, 0x61, 0x0c, 0xc5, 0x23, 0x41, 0x53, 0xd1, 0x4c, 0x4c, 0x0c, 0xe9, 0x15, 0x57, 0x23,
0x6a, 0x8c, 0xde, 0x19, 0x62, 0x0c, 0x5c, 0x79, 0x31, 0xe2, 0x03, 0x8c, 0x72, 0x84, 0x85, 0x41,
0x4b, 0xff, 0x68, 0x7c, 0x2c, 0xdf, 0xd0, 0x74, 0x65, 0xcb, 0x24, 0x59, 0xc2, 0x5d, 0xcf, 0x77,
0xfa, 0x9d, 0xaf, 0xfd, 0xe5, 0x00, 0xc4, 0x46, 0x2f, 0x43, 0x21, 0xb9, 0xe6, 0xc4, 0x5f, 0x48,
0xc1, 0x7a, 0x37, 0x0b, 0xce, 0x17, 0x29, 0x0e, 0x33, 0x6d, 0x66, 0x3e, 0x87, 0xb8, 0x16, 0xfa,
0xc7, 0x5d, 0xa1, 0x13, 0xe8, 0x8c, 0x51, 0x7f, 0x28, 0x94, 0x11, 0x6e, 0x0d, 0x2a, 0x4d, 0x7a,
0xd0, 0x32, 0x0a, 0xe5, 0x26, 0x5e, 0x63, 0x50, 0xef, 0xd7, 0x07, 0x27, 0x51, 0x51, 0xdb, 0x9e,
0x88, 0x95, 0xfa, 0xe6, 0x72, 0x1e, 0x78, 0xae, 0x97, 0xd7, 0xf4, 0x0e, 0x2e, 0xc6, 0xa8, 0xa7,
0x46, 0xa0, 0x34, 0x87, 0x8d, 0xa3, 0x5b, 0x38, 0x7b, 0x5d, 0x22, 0x5b, 0x8d, 0x58, 0x7a, 0x48,
0x7a, 0x17, 0x9a, 0x9a, 0x8b, 0x84, 0xed, 0xa2, 0x5d, 0x61, 0x1d, 0x2c, 0x4d, 0x70, 0xa3, 0x93,
0x79, 0xd0, 0x70, 0x8e, 0xbc, 0x26, 0xe7, 0xd0, 0x88, 0x19, 0x0b, 0xfc, 0x7e, 0x7d, 0xd0, 0x8c,
0xec, 0x91, 0xde, 0x42, 0x7b, 0x64, 0xf4, 0x32, 0x42, 0x25, 0xf8, 0x46, 0x21, 0xe9, 0x80, 0xc7,
0x57, 0x59, 0x52, 0x2b, 0xf2, 0xf8, 0x8a, 0x52, 0x68, 0xbf, 0xc7, 0x6b, 0x2c, 0xfa, 0x04, 0xfc,
0xd2, 0x5b, 0xb2, 0xf3, 0xfd, 0xaf, 0x07, 0xa7, 0x76, 0xc8, 0x14, 0xe5, 0x57, 0xc2, 0x90, 0x3c,
0xc2, 0xf1, 0x8e, 0x21, 0xe9, 0x86, 0x16, 0x79, 0xf8, 0x1f, 0x69, 0x8f, 0x38, 0xb5, 0x1c, 0x4c,
0x6b, 0xe4, 0x05, 0xda, 0x65, 0x60, 0xe4, 0xba, 0xf0, 0xee, 0x43, 0xac, 0x18, 0xf0, 0x04, 0xad,
0x1c, 0x1f, 0xb9, 0x74, 0x37, 0xf6, 0x70, 0x56, 0x1a, 0xed, 0x83, 0xed, 0x3f, 0xc9, 0x55, 0xe8,
0xb6, 0x23, 0xcc, 0xb7, 0x23, 0x7c, 0xb3, 0xdb, 0x91, 0x1b, 0xcb, 0x2c, 0x68, 0x8d, 0x3c, 0x83,
0x3f, 0x89, 0x53, 0x5d, 0xe9, 0xaa, 0xd0, 0x69, 0x6d, 0x76, 0x94, 0x29, 0x0f, 0x7f, 0x01, 0x00,
0x00, 0xff, 0xff, 0xc9, 0x8a, 0xd9, 0x7b, 0x9f, 0x02, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// AuthServiceClient is the client API for AuthService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AuthServiceClient interface {
// GetUser tries to authenticate a user.
GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*AuthResponse, error)
// GetSuperuser checks if a user is a superuser.
GetSuperuser(ctx context.Context, in *GetSuperuserRequest, opts ...grpc.CallOption) (*AuthResponse, error)
// CheckAcl checks user's authorization for the given topic.
CheckAcl(ctx context.Context, in *CheckAclRequest, opts ...grpc.CallOption) (*AuthResponse, error)
// GetName retrieves the name of the backend.
GetName(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NameResponse, error)
// Halt signals the backend to halt.
Halt(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*empty.Empty, error)
}
type authServiceClient struct {
cc *grpc.ClientConn
}
func NewAuthServiceClient(cc *grpc.ClientConn) AuthServiceClient {
return &authServiceClient{cc}
}
func (c *authServiceClient) GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*AuthResponse, error) {
out := new(AuthResponse)
err := c.cc.Invoke(ctx, "/grpc.AuthService/GetUser", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) GetSuperuser(ctx context.Context, in *GetSuperuserRequest, opts ...grpc.CallOption) (*AuthResponse, error) {
out := new(AuthResponse)
err := c.cc.Invoke(ctx, "/grpc.AuthService/GetSuperuser", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) CheckAcl(ctx context.Context, in *CheckAclRequest, opts ...grpc.CallOption) (*AuthResponse, error) {
out := new(AuthResponse)
err := c.cc.Invoke(ctx, "/grpc.AuthService/CheckAcl", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) GetName(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*NameResponse, error) {
out := new(NameResponse)
err := c.cc.Invoke(ctx, "/grpc.AuthService/GetName", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) Halt(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*empty.Empty, error) {
out := new(empty.Empty)
err := c.cc.Invoke(ctx, "/grpc.AuthService/Halt", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
type AuthServiceServer interface {
// GetUser tries to authenticate a user.
GetUser(context.Context, *GetUserRequest) (*AuthResponse, error)
// GetSuperuser checks if a user is a superuser.
GetSuperuser(context.Context, *GetSuperuserRequest) (*AuthResponse, error)
// CheckAcl checks user's authorization for the given topic.
CheckAcl(context.Context, *CheckAclRequest) (*AuthResponse, error)
// GetName retrieves the name of the backend.
GetName(context.Context, *empty.Empty) (*NameResponse, error)
// Halt signals the backend to halt.
Halt(context.Context, *empty.Empty) (*empty.Empty, error)
}
func RegisterAuthServiceServer(s *grpc.Server, srv AuthServiceServer) {
s.RegisterService(&_AuthService_serviceDesc, srv)
}
func _AuthService_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetUserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).GetUser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AuthService/GetUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).GetUser(ctx, req.(*GetUserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_GetSuperuser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetSuperuserRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).GetSuperuser(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AuthService/GetSuperuser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).GetSuperuser(ctx, req.(*GetSuperuserRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_CheckAcl_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CheckAclRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).CheckAcl(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AuthService/CheckAcl",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).CheckAcl(ctx, req.(*CheckAclRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_GetName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(empty.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).GetName(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AuthService/GetName",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).GetName(ctx, req.(*empty.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_Halt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(empty.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Halt(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.AuthService/Halt",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Halt(ctx, req.(*empty.Empty))
}
return interceptor(ctx, in, info, handler)
}
var _AuthService_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpc.AuthService",
HandlerType: (*AuthServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetUser",
Handler: _AuthService_GetUser_Handler,
},
{
MethodName: "GetSuperuser",
Handler: _AuthService_GetSuperuser_Handler,
},
{
MethodName: "CheckAcl",
Handler: _AuthService_CheckAcl_Handler,
},
{
MethodName: "GetName",
Handler: _AuthService_GetName_Handler,
},
{
MethodName: "Halt",
Handler: _AuthService_Halt_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "auth.proto",
}

59
grpc/auth.proto Normal file
View File

@ -0,0 +1,59 @@
syntax = "proto3";
package grpc;
import "google/protobuf/empty.proto";
// AuthService is the service providing the auth interface.
service AuthService {
// GetUser tries to authenticate a user.
rpc GetUser(GetUserRequest) returns (AuthResponse) {}
// GetSuperuser checks if a user is a superuser.
rpc GetSuperuser(GetSuperuserRequest) returns (AuthResponse) {}
// CheckAcl checks user's authorization for the given topic.
rpc CheckAcl(CheckAclRequest) returns (AuthResponse) {}
// GetName retrieves the name of the backend.
rpc GetName(google.protobuf.Empty) returns (NameResponse) {}
// Halt signals the backend to halt.
rpc Halt(google.protobuf.Empty) returns (google.protobuf.Empty) {}
}
message GetUserRequest {
// Username.
string username = 1;
// Plain text password.
string password = 2;
}
message GetSuperuserRequest {
// Username.
string username = 1;
}
message CheckAclRequest {
// Username.
string username = 1;
// Topic to be checked for.
string topic = 2;
// The client connection's id.
string clientid = 3;
// Topic access.
int32 acc = 4;
}
message AuthResponse {
// If the user is authorized/authenticated.
bool ok = 1;
}
message NameResponse {
// The name of the gRPC backend.
string name = 1;
}

11
grpc/gen.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
GRPC_GW_PATH=`go list -f '{{ .Dir }}' github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway`
GRPC_GW_PATH="${GRPC_GW_PATH}/../third_party/googleapis"
LS_PATH=`go list -f '{{ .Dir }}' github.com/iegomez/mosquitto-go-auth/grpc`
LS_PATH="${LS_PATH}/../.."
# generate the gRPC code
protoc -I. -I${LS_PATH} -I${GRPC_GW_PATH} --go_out=plugins=grpc:. \
auth.proto

3
grpc/grpc.go Normal file
View File

@ -0,0 +1,3 @@
//go:generate sh gen.sh
package grpc