You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/08/18 06:30:25 UTC

[servicecomb-kie] branch master updated: support jwt authentication (#151)

This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git


The following commit(s) were added to refs/heads/master by this push:
     new 32bc378  support jwt authentication (#151)
32bc378 is described below

commit 32bc378a2d37b711e81af2498a7725c10cd52ab3
Author: Shawn <xi...@gmail.com>
AuthorDate: Tue Aug 18 14:30:15 2020 +0800

    support jwt authentication (#151)
---
 cmd/kieserver/main.go                              |  79 ++------------
 docs/configurations/rbac.md                        |  45 ++++++++
 examples/dev/conf/chassis.yaml                     |   2 +-
 examples/dev/kie-conf.yaml                         |   6 +-
 examples/dev/public.key                            |  14 +++
 go.mod                                             |   8 +-
 go.sum                                             | 120 +++++++++++++++++++++
 scripts/start.sh                                   |   2 +-
 cmd/kieserver/main.go => server/command/command.go |  47 +-------
 server/config/config.go                            |   5 +
 server/config/struct.go                            |  10 +-
 server/handler/noop_auth_handler.go                |  55 ----------
 server/handler/track_handler.go                    |  18 ++--
 server/rbac/rbac.go                                |  93 ++++++++++++++++
 server/resource/v1/admin_resource.go               |  78 ++++++++++++++
 .../v1/admin_resource_test.go}                     |  46 ++++----
 server/resource/v1/common.go                       |  38 ++++---
 server/resource/v1/history_resource.go             |  62 ++---------
 server/resource/v1/history_resource_test.go        |  27 +----
 server/resource/v1/kv_resource.go                  |  20 ++--
 server/resource/v1/kv_resource_test.go             |  99 +++++------------
 server/server.go                                   |  54 ++++++++++
 22 files changed, 539 insertions(+), 389 deletions(-)

diff --git a/cmd/kieserver/main.go b/cmd/kieserver/main.go
index dc69f85..4810199 100644
--- a/cmd/kieserver/main.go
+++ b/cmd/kieserver/main.go
@@ -20,89 +20,24 @@ package main
 import (
 	"os"
 
-	"github.com/apache/servicecomb-kie/pkg/validate"
-	"github.com/apache/servicecomb-kie/server/config"
-	"github.com/apache/servicecomb-kie/server/pubsub"
-	"github.com/apache/servicecomb-kie/server/resource/v1"
-	"github.com/apache/servicecomb-kie/server/service"
-	"github.com/go-chassis/go-chassis"
-	"github.com/go-chassis/go-chassis/core/common"
+	"github.com/apache/servicecomb-kie/server"
+	"github.com/apache/servicecomb-kie/server/command"
 	"github.com/go-mesh/openlogging"
-	"github.com/urfave/cli"
-
 	//custom handlers
 	_ "github.com/apache/servicecomb-kie/server/handler"
+	_ "github.com/go-chassis/go-chassis/middleware/jwt"
 	_ "github.com/go-chassis/go-chassis/middleware/monitoring"
 	_ "github.com/go-chassis/go-chassis/middleware/ratelimiter"
 	//storage
 	_ "github.com/apache/servicecomb-kie/server/service/mongo"
-
+	//quota management
 	_ "github.com/apache/servicecomb-kie/server/plugin/qms"
 )
 
-const (
-	defaultConfigFile = "/etc/servicecomb-kie/kie-conf.yaml"
-)
-
-// parseConfigFromCmd
-func parseConfigFromCmd(args []string) (err error) {
-	app := cli.NewApp()
-	app.HideVersion = true
-	app.Usage = "servicecomb-kie server cmd line."
-	app.Flags = []cli.Flag{
-		cli.StringFlag{
-			Name:        "config",
-			Usage:       "config file, example: --config=kie-conf.yaml",
-			Destination: &config.Configurations.ConfigFile,
-			Value:       defaultConfigFile,
-		},
-		cli.StringFlag{
-			Name:        "name",
-			Usage:       "node name, example: --name=kie0",
-			Destination: &config.Configurations.NodeName,
-			EnvVar:      "NODE_NAME",
-		},
-		cli.StringFlag{
-			Name:        "peer-addr",
-			Usage:       "kie use this ip port to join a kie cluster, example: --peer-addr=10.1.1.10:5000",
-			Destination: &config.Configurations.PeerAddr,
-			EnvVar:      "PEER_ADDR",
-		}, cli.StringFlag{
-			Name:        "listen-peer-addr",
-			Usage:       "listen on ip port, kie receive events example: --listen-peer-addr=10.1.1.10:5000",
-			Destination: &config.Configurations.ListenPeerAddr,
-			EnvVar:      "LISTEN_PEER_ADDR",
-		},
-	}
-	app.Action = func(c *cli.Context) error {
-		return nil
-	}
-
-	err = app.Run(args)
-	return
-}
-
 func main() {
-	if err := parseConfigFromCmd(os.Args); err != nil {
+	if err := command.ParseConfig(os.Args); err != nil {
 		openlogging.Fatal(err.Error())
 	}
-	chassis.RegisterSchema(common.ProtocolRest, &v1.KVResource{})
-	chassis.RegisterSchema(common.ProtocolRest, &v1.HistoryResource{})
-	if err := chassis.Init(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := config.Init(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := service.DBInit(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := validate.Init(); err != nil {
-		openlogging.Fatal("validate init failed: " + err.Error())
-	}
-	pubsub.Init()
-	pubsub.Start()
-	if err := chassis.Run(); err != nil {
-		openlogging.Fatal("service exit: " + err.Error())
-	}
+
+	server.Run()
 }
diff --git a/docs/configurations/rbac.md b/docs/configurations/rbac.md
new file mode 100644
index 0000000..e1e1482
--- /dev/null
+++ b/docs/configurations/rbac.md
@@ -0,0 +1,45 @@
+# RBAC
+if you enabled service center [RBAC](https://service-center.readthedocs.io/en/latest/user-guides/rbac.html).
+
+you can choose to enable kie RBAC feature, after enable RBAC, all request to kie must be authenticated
+
+### Configuration file
+follow steps to enable service center [RBAC](https://service-center.readthedocs.io/en/latest/user-guides/rbac.html).
+
+1.get public key file which is exactly same with service center public key file
+
+2.edit kie-conf.yaml
+```ini
+db:
+  uri: mongodb://kie:123@127.0.0.1:27017/kie
+  type: mongodb
+rbac:
+  enabled: true
+  rsaPublicKeyFile: ./examples/dev/public.key
+```
+
+To distribute your public key, you can use kubernetes config map to manage public key
+### Generate a token 
+token is the only credential to access rest API, before you access any API, you need to get a token from service center
+```shell script
+curl -X POST \
+  http://127.0.0.1:30100/v4/token \
+  -d '{"name":"root",
+"password":"rootpwd"}'
+```
+will return a token, token will expired after 30m
+```json
+{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTI4MzIxODUsInVzZXIiOiJyb290In0.G65mgb4eQ9hmCAuftVeVogN9lT_jNg7iIOF_EAyAhBU"}
+```
+
+### Authentication
+For each request you must add token to http header:
+```
+Authorization: Bearer {token}
+```
+for example:
+```shell script
+curl -X GET \
+  'http://127.0.0.1:30110/v1/default/kie/kv' \
+  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTI4OTQ1NTEsInVzZXIiOiJyb290In0.FfLOSvVmHT9qCZSe_6iPf4gNjbXLwCrkXxKHsdJoQ8w' 
+```
\ No newline at end of file
diff --git a/examples/dev/conf/chassis.yaml b/examples/dev/conf/chassis.yaml
index b562acb..2b221ab 100755
--- a/examples/dev/conf/chassis.yaml
+++ b/examples/dev/conf/chassis.yaml
@@ -10,7 +10,7 @@ cse:
   handler:
     chain:
       Provider:
-        default: ratelimiter-provider,monitoring,auth-handler,track-handler
+        default: ratelimiter-provider,monitoring,jwt,track-handler
   transport:
     maxBodyBytes:
       rest: 2621440 #2.5M
diff --git a/examples/dev/kie-conf.yaml b/examples/dev/kie-conf.yaml
index 4fef6b2..4e967b7 100644
--- a/examples/dev/kie-conf.yaml
+++ b/examples/dev/kie-conf.yaml
@@ -1,8 +1,10 @@
 db:
-  #uri: mongodb://rwuser:xxx@x.x.x.x:8635/test?authSource=admin
   uri: mongodb://kie:123@127.0.0.1:27017/kie
   type: mongodb
   poolSize: 10
   timeout:  5m
   sslEnabled: false
-  rootCAFile: /opt/kie/ca.crt
\ No newline at end of file
+  rootCAFile: /opt/kie/ca.crt
+rbac:
+  enabled: false
+  rsaPublicKeyFile: ./examples/dev/public.key
\ No newline at end of file
diff --git a/examples/dev/public.key b/examples/dev/public.key
new file mode 100644
index 0000000..d2b48eb
--- /dev/null
+++ b/examples/dev/public.key
@@ -0,0 +1,14 @@
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs4ml6MCyHOTKZFUFXEO1
+qejCWVacu2LTNd2mWxoXdF3vP7T73hLvDxMmnUKh83M2D9oxOISnXl9fVTrMregp
+EKxxzP8lnxow0/PkfmkUUsmKrYJJpeNcA5gkaaENGbkskH0glDMUZGhMLcSZkt9v
+SWlwyBMXbuUKq/AE6n2CZzWMhQ7ydTnEDDamRocO/B9xuOwKUCnWrHuc7nPXA1Be
+OFZWpE7rUX5tbxpamtDbL9GY0zYZNqRXxcg5UViQq7HmOky3dur6lTkKS/1IExRA
+Tns3GGXaBTkdgz8ayAw7pzdyzDdL9xNeYfYjDEjPdiTtmFEYUgJLiPw4Ykg1h6G0
+EdgysteB1go5lrGen0ih04FWanAG7rca5Na1erDlO8kL0XrGSSBR14VmB2g4j8vX
+X3kZ+uOvwmEaL3Xp46wZV5eeKtmtf0eIPKKd4E485KjtNOXpQm0ukh92W+JupvVD
+ccH8KiZv65Jbmbtlg3F4xmVFkehUvjH/+sTez+ilB/YydEQgWi5SDc6WvXB0KFVA
+lMgcLEiB0/rnO04d7QojqWwwF7VTJRKhmxP8nPTqs6rWVuSnHvFQX8XEYJFXkYaw
+lOYsR5XcZQFLXybghN4OEx21G3jBKLv+ivHBYK0skisPHFvc9BCYenB5Efq3MwTM
+wyIh55JOSbhQJ8xuA+fN7sMCAwEAAQ==
+-----END PUBLIC KEY-----
diff --git a/go.mod b/go.mod
index cb72750..96263af 100644
--- a/go.mod
+++ b/go.mod
@@ -1,19 +1,19 @@
 module github.com/apache/servicecomb-kie
 
 require (
+	github.com/apache/servicecomb-service-center v0.0.0-20200817025835-7bb8c4eb9421
 	github.com/emicklei/go-restful v2.12.0+incompatible
-	github.com/go-chassis/go-archaius v1.2.2-0.20200409030209-a48668e4a025
-	github.com/go-chassis/go-chassis v1.8.2-0.20200426111522-0f37ad3d79e5
+	github.com/go-chassis/go-archaius v1.3.2
+	github.com/go-chassis/go-chassis v0.0.0-20200818014813-890265d94a1c
 	github.com/go-chassis/paas-lager v1.1.1
 	github.com/go-mesh/openlogging v1.0.1
 	github.com/go-playground/universal-translator v0.17.0
 	github.com/go-playground/validator v9.31.0+incompatible
-	github.com/hashicorp/mdns v1.0.1 // indirect
 	github.com/hashicorp/serf v0.8.5
 	github.com/leodido/go-urn v1.2.0 // indirect
 	github.com/satori/go.uuid v1.2.0
 	github.com/stretchr/testify v1.4.0
-	github.com/urfave/cli v1.20.0
+	github.com/urfave/cli v1.22.4
 	github.com/xdg/stringprep v1.0.0 // indirect
 	go.mongodb.org/mongo-driver v1.3.0
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
diff --git a/go.sum b/go.sum
index a084eb7..761e471 100644
--- a/go.sum
+++ b/go.sum
@@ -10,18 +10,33 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/NYTimes/gziphandler v1.0.2-0.20180820182813-253f1acb9d9f h1:JliTHSbyp6SvSqw5Kdkd+kq2jJueTlDNQCyyr+4+/0o=
+github.com/NYTimes/gziphandler v1.0.2-0.20180820182813-253f1acb9d9f/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shonminh/apollo-client v0.2.0/go.mod h1:Jk6K99uIGxQm7Uyy1gCQTvM/kc1YLp4Qo9/jtGkEXvI=
+github.com/Shonminh/apollo-client v0.4.0/go.mod h1:Jk6K99uIGxQm7Uyy1gCQTvM/kc1YLp4Qo9/jtGkEXvI=
+github.com/Shopify/sarama v1.18.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/apache/servicecomb-service-center v0.0.0-20200710073115-6116a2ef5fdf/go.mod h1:AfixmoGz97+4vRyDJEoV4t3k0NUljIaELR2iEXU1hqU=
+github.com/apache/servicecomb-service-center v0.0.0-20200717014253-66215bb9917b h1:X6s9WrKO+hVZSJRTJ8v4noq6xoulzO6cJBryGH4umW0=
+github.com/apache/servicecomb-service-center v0.0.0-20200717014253-66215bb9917b/go.mod h1:jiw0zTHphl1PVLX+LgftTSebaECo7XX6qwCNUONSMvE=
+github.com/apache/servicecomb-service-center v0.0.0-20200723031815-784c3533a8f2 h1:zTED7VqI+WD+gLXvbXoEV3ItUGRoQ54qlPghTo2HmhM=
+github.com/apache/servicecomb-service-center v0.0.0-20200723031815-784c3533a8f2/go.mod h1:jiw0zTHphl1PVLX+LgftTSebaECo7XX6qwCNUONSMvE=
+github.com/apache/servicecomb-service-center v0.0.0-20200817025835-7bb8c4eb9421 h1:mdc3hngmwShPlG0z7NCdLre63Ll/jbL6/xQNoIiqJe8=
+github.com/apache/servicecomb-service-center v0.0.0-20200817025835-7bb8c4eb9421/go.mod h1:jiw0zTHphl1PVLX+LgftTSebaECo7XX6qwCNUONSMvE=
+github.com/apache/thrift v0.0.0-20180125231006-3d556248a8b9/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/astaxie/beego v1.8.0 h1:Rc5qRXMy5fpxq3FEi+4nmykYIMtANthRJ8hcoY+1VWM=
+github.com/astaxie/beego v1.8.0/go.mod h1:0R4++1tUqERR0WYFWdfkcrsyoVBCG4DgpDGokT3yb+U=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
@@ -29,14 +44,27 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
 github.com/cenkalti/backoff v2.0.0+incompatible h1:5IIPUHhlnUZbcHQsQou5k1Tn58nJkeJL9U+ig5CHJbY=
 github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/cheggaaa/pb v1.0.25/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/coocood/freecache v1.0.1/go.mod h1:ePwxCDzOYvARfHdr1pByNct1at3CoKnsipOHwKlNbzI=
+github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.22+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20180828140353-eee3db372b31/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 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/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
 github.com/emicklei/go-restful v2.12.0+incompatible h1:SIvoTSbsMEwuM3dzFirLwKc4BH6VXP5CNf+G1FfJVr4=
@@ -46,7 +74,9 @@ github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 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/fzipp/gocyclo v0.0.0-20150627053110-6acd4345c835/go.mod h1:BjL/N0+C+j9uNX+1xcNuM9vdSIcXCZrQZUYbXOFbgN8=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
 github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
 github.com/go-chassis/foundation v0.1.1-0.20191113114104-2b05871e9ec4 h1:wx8JXvg/n4i8acXsBJ5zIkiK7EO2kn/HuEjKK3kSgv8=
@@ -56,12 +86,30 @@ github.com/go-chassis/go-archaius v1.2.1-0.20200309104817-8c3d4e87d33c/go.mod h1
 github.com/go-chassis/go-archaius v1.2.1/go.mod h1:gVP52u/jCU0fgUjXdUW1VLp5YLLJ+Yl2zoOPrLM/WOM=
 github.com/go-chassis/go-archaius v1.2.2-0.20200409030209-a48668e4a025 h1:zzqQeCKkslJwW0/QuOLQyZVqiCl7tgTTrdTbMEb0+kI=
 github.com/go-chassis/go-archaius v1.2.2-0.20200409030209-a48668e4a025/go.mod h1:gVP52u/jCU0fgUjXdUW1VLp5YLLJ+Yl2zoOPrLM/WOM=
+github.com/go-chassis/go-archaius v1.3.2 h1:b52voYtSL+fukmvg/rsn/quw/hgDWtV945adl0VV8Lg=
+github.com/go-chassis/go-archaius v1.3.2/go.mod h1:nzRL1sSodtgeCZMzCNu0y2LPH5zz7chp8uaQ0GS0x6I=
 github.com/go-chassis/go-chassis v0.0.0-20200318142212-4ca7f5fb7745 h1:BDHDeJBW+0/iC/1otn4XQ7ndfqzeGrFFi6SLSBuhRvs=
 github.com/go-chassis/go-chassis v0.0.0-20200318142212-4ca7f5fb7745/go.mod h1:UsROzOZPD9YgTpVUE/jFclVxDwHWESLNdwwbfKQ8aMs=
 github.com/go-chassis/go-chassis v0.0.0-20200320074343-30f669c0c47b h1:ZH88vLcGL4bNc+Vbm1g3jrhtTxBSnGvyZCpbbkVa5a0=
 github.com/go-chassis/go-chassis v0.0.0-20200320074343-30f669c0c47b/go.mod h1:UsROzOZPD9YgTpVUE/jFclVxDwHWESLNdwwbfKQ8aMs=
 github.com/go-chassis/go-chassis v0.0.0-20200322084331-36849ab2cb10 h1:l3bUZf0Hjh1+7b2Ed5Fqb/cCOjMGBe8WmPd/ucyoGgQ=
 github.com/go-chassis/go-chassis v0.0.0-20200322084331-36849ab2cb10/go.mod h1:UsROzOZPD9YgTpVUE/jFclVxDwHWESLNdwwbfKQ8aMs=
+github.com/go-chassis/go-chassis v0.0.0-20200701101447-f47108e3903d h1:ynz1G/YO61f/u34J08oeXhLANKzSicduvRSdPDhQ1sg=
+github.com/go-chassis/go-chassis v0.0.0-20200701101447-f47108e3903d/go.mod h1:S7RbnpeTWBqZ4+UxGAs05a6qdhDyWKpTNuil8FYNiME=
+github.com/go-chassis/go-chassis v0.0.0-20200709095636-48e710908928 h1:y464C11Trvr8uZcsRVKu8grVeXbwFdftSA5BAKYVR+8=
+github.com/go-chassis/go-chassis v0.0.0-20200709095636-48e710908928/go.mod h1:S7RbnpeTWBqZ4+UxGAs05a6qdhDyWKpTNuil8FYNiME=
+github.com/go-chassis/go-chassis v0.0.0-20200716073336-4183d5dd1246 h1:yxtoclu0QclYtwXxo4AYTCPJsYFM/Xo2/5C1HLRnzqg=
+github.com/go-chassis/go-chassis v0.0.0-20200716073336-4183d5dd1246/go.mod h1:S7RbnpeTWBqZ4+UxGAs05a6qdhDyWKpTNuil8FYNiME=
+github.com/go-chassis/go-chassis v0.0.0-20200728122719-5c6c673368c5 h1:HVDP4+W7InMwxTorvBjJxuKOJY/L+z4zy2IIiDcmpfs=
+github.com/go-chassis/go-chassis v0.0.0-20200728122719-5c6c673368c5/go.mod h1:nMWwWrgDEyDKnMQLE5Gt65RdwbgrQg5amt4BqNFY09g=
+github.com/go-chassis/go-chassis v0.0.0-20200803103444-d7b1d63e60bc h1:5k+qm8uj2jOJff2tiUlprtMwpLiwukjThoZ3KXacK8c=
+github.com/go-chassis/go-chassis v0.0.0-20200803103444-d7b1d63e60bc/go.mod h1:nMWwWrgDEyDKnMQLE5Gt65RdwbgrQg5amt4BqNFY09g=
+github.com/go-chassis/go-chassis v0.0.0-20200812055904-70406395b783 h1:zFQcB2BGZJLSOfKk4Pq2cJSXu9fSZWUbeYtoFoBnBI4=
+github.com/go-chassis/go-chassis v0.0.0-20200812055904-70406395b783/go.mod h1:nMWwWrgDEyDKnMQLE5Gt65RdwbgrQg5amt4BqNFY09g=
+github.com/go-chassis/go-chassis v0.0.0-20200817095942-bf386412b79e h1:OElheBuqH8OL3//IlPwrM+AKfeEXlnIgXMypW1N2CLk=
+github.com/go-chassis/go-chassis v0.0.0-20200817095942-bf386412b79e/go.mod h1:nMWwWrgDEyDKnMQLE5Gt65RdwbgrQg5amt4BqNFY09g=
+github.com/go-chassis/go-chassis v0.0.0-20200818014813-890265d94a1c h1:aAokQ5cgL/6a8tJsj3W6qr7M3EBoMs3MzlfYqalLLto=
+github.com/go-chassis/go-chassis v0.0.0-20200818014813-890265d94a1c/go.mod h1:nMWwWrgDEyDKnMQLE5Gt65RdwbgrQg5amt4BqNFY09g=
 github.com/go-chassis/go-chassis v1.8.2-0.20200310060113-4b383ba3d3f0 h1:YD9MtuYIpQb+EKxIzV/swdXUhnV5PtXtSW696JiwW1c=
 github.com/go-chassis/go-chassis v1.8.2-0.20200310060113-4b383ba3d3f0/go.mod h1:sFnVxSvprpy6umPFK4uSdfCDdfqdgbp3FdW/CG0VNnE=
 github.com/go-chassis/go-chassis v1.8.2-0.20200331092516-8cf0b374128b h1:AvZjvPQdla1KoLrxbU8bohR3Y9FYnScZFY5KnK2HnSU=
@@ -74,7 +122,9 @@ github.com/go-chassis/go-restful-swagger20 v1.0.3-0.20200310030431-17d80f34264f/
 github.com/go-chassis/paas-lager v1.1.1 h1:/6wqawUGjPCpd57A/tzJzgC4MnEhNuigbayQS+2VWPQ=
 github.com/go-chassis/paas-lager v1.1.1/go.mod h1:tILYbn3+0jjCxhY6/ue9L8eRq+VJ60U6VYIdugqchB4=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-mesh/openlogging v1.0.1 h1:6raaXo8SK+wuQX1VoNi6QJCSf1fTOFWh7f5f6b2ZEmY=
 github.com/go-mesh/openlogging v1.0.1/go.mod h1:qaKi+amO+hsGin2q1GmW+/NcbZpMPnTufwrWzDmIuuU=
@@ -115,10 +165,12 @@ github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGt
 github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
 github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 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 v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -126,6 +178,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -138,15 +191,20 @@ github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSN
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 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/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
 github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
@@ -177,13 +235,17 @@ github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8=
 github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
 github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
 github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
 github.com/hashicorp/serf v0.8.5 h1:ZynDUIQiA8usmRgPdGPHFdPnb1wgGI9tK3mO9hcAJjc=
 github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
+github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
+github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -193,8 +255,11 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
 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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/karlseguin/ccache v2.0.3-0.20170217060820-3ba9789cfd2c+incompatible/go.mod h1:CM9tNPzT6EdRh14+jiW8mEF9mkNZuuE51qmgGYUB93w=
+github.com/karlseguin/expect v1.0.1/go.mod h1:zNBxMY8P21owkeogJELCLeHIt+voOSduHYTFUbwRAV8=
 github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
 github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.9.5 h1:U+CaK85mrNNb4k8BNOfgJtJ/gr6kswUCFj6miSzVC6M=
@@ -207,6 +272,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/labstack/echo v3.2.2-0.20180316170059-a5d81b8d4a62+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
+github.com/labstack/gommon v0.2.1/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
 github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -218,6 +285,7 @@ github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
 github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
@@ -237,6 +305,9 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
+github.com/natefinch/lumberjack v0.0.0-20170531160350-a96e63847dc3 h1:BDvcX7oM8ZWOS08LQXaW8ucGblfoSG4srpoW6pKhvqs=
+github.com/natefinch/lumberjack v0.0.0-20170531160350-a96e63847dc3/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
+github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
@@ -244,14 +315,20 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
 github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
 github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/openzipkin/zipkin-go-opentracing v0.3.3-0.20180123190626-6bb822a7f15f/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 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=
@@ -265,30 +342,44 @@ github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDB
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
+github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
 github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
+github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rs/cors v0.0.0-20170608165155-8dd4211afb5d/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/satori/go.uuid v1.1.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
 github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
+github.com/spf13/cobra v0.0.0-20170624150100-4d647c8944eb/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -303,19 +394,35 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
+github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
+github.com/widuu/gojson v0.0.0-20170212122013-7da9d2cd949b/go.mod h1:9W1pyetRkwXqjR9tjOSrSuhGHBK0EqXoQSwWbhBHHwA=
+github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
 github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+go.etcd.io/etcd v3.3.22+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
 go.mongodb.org/mongo-driver v1.3.0 h1:ew6uUIeJOo+qdUUv7LxFCUhtWmVv7ZV/Xuy4FAUsw2E=
 go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/ratelimit v0.1.0/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
+go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -328,6 +435,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
 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-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -372,6 +480,8 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 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=
@@ -380,6 +490,7 @@ 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/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -392,6 +503,7 @@ golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3
 golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U=
 golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -401,19 +513,25 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 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-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
 gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/karlseguin/expect.v1 v1.0.1/go.mod h1:uB7QIJBcclvYbwlUDkSCsGjAOMis3fP280LyhuDEf2I=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
 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.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -434,5 +552,7 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6 h1:p0Ai3qVtkbCG/Af26dBmU0E1W58NID3hSSh7cMyylpM=
+k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/scripts/start.sh b/scripts/start.sh
index 0b752dc..93a4b01 100755
--- a/scripts/start.sh
+++ b/scripts/start.sh
@@ -38,7 +38,7 @@ cse:
   handler:
     chain:
       Provider:
-        default: ratelimiter-provider,monitoring,auth-handler,track-handler
+        default: ratelimiter-provider,monitoring,jwt,track-handler
 servicecomb:
   service:
     quota:
diff --git a/cmd/kieserver/main.go b/server/command/command.go
similarity index 59%
copy from cmd/kieserver/main.go
copy to server/command/command.go
index dc69f85..9062581 100644
--- a/cmd/kieserver/main.go
+++ b/server/command/command.go
@@ -15,29 +15,11 @@
  * limitations under the License.
  */
 
-package main
+package command
 
 import (
-	"os"
-
-	"github.com/apache/servicecomb-kie/pkg/validate"
 	"github.com/apache/servicecomb-kie/server/config"
-	"github.com/apache/servicecomb-kie/server/pubsub"
-	"github.com/apache/servicecomb-kie/server/resource/v1"
-	"github.com/apache/servicecomb-kie/server/service"
-	"github.com/go-chassis/go-chassis"
-	"github.com/go-chassis/go-chassis/core/common"
-	"github.com/go-mesh/openlogging"
 	"github.com/urfave/cli"
-
-	//custom handlers
-	_ "github.com/apache/servicecomb-kie/server/handler"
-	_ "github.com/go-chassis/go-chassis/middleware/monitoring"
-	_ "github.com/go-chassis/go-chassis/middleware/ratelimiter"
-	//storage
-	_ "github.com/apache/servicecomb-kie/server/service/mongo"
-
-	_ "github.com/apache/servicecomb-kie/server/plugin/qms"
 )
 
 const (
@@ -45,7 +27,7 @@ const (
 )
 
 // parseConfigFromCmd
-func parseConfigFromCmd(args []string) (err error) {
+func ParseConfig(args []string) (err error) {
 	app := cli.NewApp()
 	app.HideVersion = true
 	app.Usage = "servicecomb-kie server cmd line."
@@ -81,28 +63,3 @@ func parseConfigFromCmd(args []string) (err error) {
 	err = app.Run(args)
 	return
 }
-
-func main() {
-	if err := parseConfigFromCmd(os.Args); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	chassis.RegisterSchema(common.ProtocolRest, &v1.KVResource{})
-	chassis.RegisterSchema(common.ProtocolRest, &v1.HistoryResource{})
-	if err := chassis.Init(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := config.Init(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := service.DBInit(); err != nil {
-		openlogging.Fatal(err.Error())
-	}
-	if err := validate.Init(); err != nil {
-		openlogging.Fatal("validate init failed: " + err.Error())
-	}
-	pubsub.Init()
-	pubsub.Start()
-	if err := chassis.Run(); err != nil {
-		openlogging.Fatal("service exit: " + err.Error())
-	}
-}
diff --git a/server/config/config.go b/server/config/config.go
index 37ebaaf..27b6fd2 100644
--- a/server/config/config.go
+++ b/server/config/config.go
@@ -41,3 +41,8 @@ func Init() error {
 func GetDB() DB {
 	return Configurations.DB
 }
+
+//GetRBAC return rbac config
+func GetRBAC() RBAC {
+	return Configurations.RBAC
+}
diff --git a/server/config/struct.go b/server/config/struct.go
index 054ead3..fac1519 100644
--- a/server/config/struct.go
+++ b/server/config/struct.go
@@ -19,8 +19,8 @@ package config
 
 //Config is yaml file struct
 type Config struct {
-	DB DB `yaml:"db"`
-
+	DB   DB   `yaml:"db"`
+	RBAC RBAC `yaml:"rbac"`
 	//config from cli
 	ConfigFile     string
 	NodeName       string
@@ -38,3 +38,9 @@ type DB struct {
 	Timeout    string `yaml:"timeout"`
 	VerifyPeer bool   `yaml:"verifyPeer"`
 }
+
+//RBAC is rbac config
+type RBAC struct {
+	Enabled    bool   `yaml:"enabled"`
+	PubKeyFile string `yaml:"rsaPublicKeyFile"`
+}
diff --git a/server/handler/noop_auth_handler.go b/server/handler/noop_auth_handler.go
deleted file mode 100644
index e35abab..0000000
--- a/server/handler/noop_auth_handler.go
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package handler
-
-import (
-	"github.com/apache/servicecomb-kie/server/resource/v1"
-	"github.com/go-chassis/go-chassis/core/handler"
-	"github.com/go-chassis/go-chassis/core/invocation"
-	"github.com/go-mesh/openlogging"
-)
-
-//const of noop auth handler
-const (
-	NoopAuthHandlerName = "auth-handler"
-	DefaultDomain       = "default"
-)
-
-//NoopAuthHandler not need implement any logic
-//developer can extend authenticate and authorization by set new handler in chassis.yaml
-type NoopAuthHandler struct{}
-
-//Handle set local attribute to http request
-func (bk *NoopAuthHandler) Handle(chain *handler.Chain, inv *invocation.Invocation, cb invocation.ResponseCallBack) {
-	inv.SetMetadata(v1.AttributeDomainKey, DefaultDomain)
-	chain.Next(inv, cb)
-}
-
-func newDomainResolver() handler.Handler {
-	return &NoopAuthHandler{}
-}
-
-//Name is handler name
-func (bk *NoopAuthHandler) Name() string {
-	return NoopAuthHandlerName
-}
-func init() {
-	if err := handler.RegisterHandler(NoopAuthHandlerName, newDomainResolver); err != nil {
-		openlogging.Fatal("register auth-handler failed: " + err.Error())
-	}
-}
diff --git a/server/handler/track_handler.go b/server/handler/track_handler.go
index d02a829..472dba0 100644
--- a/server/handler/track_handler.go
+++ b/server/handler/track_handler.go
@@ -59,7 +59,7 @@ func (h *TrackHandler) Handle(chain *handler.Chain, inv *invocation.Invocation,
 		chain.Next(inv, cb)
 		return
 	}
-	chain.Next(inv, func(ir *invocation.Response) error {
+	chain.Next(inv, func(ir *invocation.Response) {
 		resp, _ := ir.Result.(*restful.Response)
 		revStr := req.QueryParameter(common.QueryParamRev)
 		wait := req.QueryParameter(common.QueryParamWait)
@@ -67,7 +67,7 @@ func (h *TrackHandler) Handle(chain *handler.Chain, inv *invocation.Invocation,
 		data.URLPath = req.Request.Method + " " + req.Request.URL.Path
 		data.SessionID = sessionID
 		data.UserAgent = req.HeaderParameter(v1.HeaderUserAgent)
-		data.Domain = inv.Metadata[v1.AttributeDomainKey].(string)
+		data.Domain = v1.ReadDomain(req.Request.Context())
 		data.IP = iputil.ClientIP(req.Request)
 		data.ResponseBody = req.Attribute(common.RespBodyContextKey).([]*model.KVDoc)
 		data.ResponseCode = ir.Status
@@ -82,17 +82,11 @@ func (h *TrackHandler) Handle(chain *handler.Chain, inv *invocation.Invocation,
 		_, err := track.CreateOrUpdate(inv.Ctx, data)
 		if err != nil {
 			openlogging.Warn("record polling detail failed:" + err.Error())
-			err := cb(ir)
-			if err != nil {
-				return err
-			}
-			return nil
+			cb(ir)
+			return
 		}
-		err = cb(ir)
-		if err != nil {
-			return err
-		}
-		return nil
+		cb(ir)
+
 	})
 
 }
diff --git a/server/rbac/rbac.go b/server/rbac/rbac.go
new file mode 100644
index 0000000..f0e55a3
--- /dev/null
+++ b/server/rbac/rbac.go
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package rbac
+
+import (
+	"github.com/apache/servicecomb-kie/server/config"
+	"github.com/apache/servicecomb-service-center/pkg/rbacframe"
+	"github.com/go-chassis/go-archaius"
+	"github.com/go-chassis/go-chassis/middleware/jwt"
+	"github.com/go-chassis/go-chassis/security/secret"
+	"github.com/go-chassis/go-chassis/security/token"
+	"github.com/go-mesh/openlogging"
+	"io/ioutil"
+	"net/http"
+	"path/filepath"
+	"strings"
+)
+
+const (
+	pubContentKey = "rbac.publicKey"
+)
+
+//Init initialize the rbac module
+func Init() {
+	if !config.GetRBAC().Enabled {
+		openlogging.Info("rbac is disabled")
+		return
+	}
+
+	jwt.Use(&jwt.Auth{
+		MustAuth: func(req *http.Request) bool {
+			if !config.GetRBAC().Enabled {
+				return false
+			}
+			if strings.Contains(req.URL.Path, "/v1/health") {
+				return false
+			}
+			return true
+		},
+		Realm: "servicecomb-kie-realm",
+		SecretFunc: func(claims interface{}, method token.SigningMethod) (interface{}, error) {
+			p, err := secret.ParseRSAPPublicKey(PublicKey())
+			if err != nil {
+				openlogging.Error("can not parse public key:" + err.Error())
+				return nil, err
+			}
+			return p, nil
+		},
+		Authorize: func(payload map[string]interface{}, req *http.Request) error {
+			payload["domain"] = "default" //TODO eliminate dead code
+			newReq := req.WithContext(rbacframe.NewContext(req.Context(), payload))
+			*req = *newReq
+			//TODO role perm check
+			return nil
+		},
+	})
+	loadPublicKey()
+	openlogging.Info("rbac is enabled")
+}
+
+//loadPublicKey read key to memory
+func loadPublicKey() {
+	pf := config.GetRBAC().PubKeyFile
+	content, err := ioutil.ReadFile(filepath.Clean(pf))
+	if err != nil {
+		openlogging.Fatal(err.Error())
+		return
+	}
+	err = archaius.Set(pubContentKey, string(content))
+	if err != nil {
+		openlogging.Fatal(err.Error())
+	}
+}
+
+//PublicKey get public key to verify a token
+func PublicKey() string {
+	return archaius.GetString(pubContentKey, "")
+}
diff --git a/server/resource/v1/admin_resource.go b/server/resource/v1/admin_resource.go
new file mode 100644
index 0000000..f3b0624
--- /dev/null
+++ b/server/resource/v1/admin_resource.go
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package v1
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service"
+	goRestful "github.com/emicklei/go-restful"
+	"github.com/go-chassis/go-chassis/pkg/runtime"
+	"github.com/go-chassis/go-chassis/server/restful"
+	"github.com/go-mesh/openlogging"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+type AdminResource struct {
+}
+
+//URLPatterns defined config operations
+func (r *AdminResource) URLPatterns() []restful.Route {
+	return []restful.Route{
+		{
+			Method:       http.MethodGet,
+			Path:         "/v1/health",
+			ResourceFunc: r.HealthCheck,
+			FuncDesc:     "health check return version and revision",
+			Parameters:   []*restful.Parameters{},
+			Returns: []*restful.Returns{
+				{
+					Code:  http.StatusOK,
+					Model: model.DocHealthCheck{},
+				},
+			},
+			Consumes: []string{goRestful.MIME_JSON},
+			Produces: []string{goRestful.MIME_JSON},
+		},
+	}
+}
+
+//HealthCheck provider version info and time info
+func (r *AdminResource) HealthCheck(context *restful.Context) {
+	domain := ReadDomain(context.Ctx)
+	resp := &model.DocHealthCheck{}
+	latest, err := service.RevisionService.GetRevision(context.Ctx, domain)
+	if err != nil {
+		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+		return
+	}
+	resp.Revision = strconv.FormatInt(latest, 10)
+	resp.Version = runtime.Version
+	resp.Timestamp = time.Now().Unix()
+	total, err := service.KVService.Total(context.Ctx, domain)
+	if err != nil {
+		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
+		return
+	}
+	resp.Total = total
+	err = writeResponse(context, resp)
+	if err != nil {
+		openlogging.Error(err.Error())
+	}
+}
diff --git a/server/config/config.go b/server/resource/v1/admin_resource_test.go
similarity index 52%
copy from server/config/config.go
copy to server/resource/v1/admin_resource_test.go
index 37ebaaf..b1eb7a4 100644
--- a/server/config/config.go
+++ b/server/resource/v1/admin_resource_test.go
@@ -15,29 +15,33 @@
  * limitations under the License.
  */
 
-package config
+package v1_test
 
 import (
-	"github.com/go-chassis/go-archaius"
-	"github.com/go-chassis/go-archaius/source/util"
-	"gopkg.in/yaml.v2"
-	"path/filepath"
+	"encoding/json"
+	"fmt"
+	"github.com/apache/servicecomb-kie/pkg/model"
+	v1 "github.com/apache/servicecomb-kie/server/resource/v1"
+	"github.com/go-chassis/go-chassis/server/restful/restfultest"
+	"github.com/stretchr/testify/assert"
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"testing"
 )
 
-//Configurations is kie config items
-var Configurations = &Config{}
-
-//Init initiate config files
-func Init() error {
-	if err := archaius.AddFile(Configurations.ConfigFile, archaius.WithFileHandler(util.UseFileNameAsKeyContentAsValue)); err != nil {
-		return err
-	}
-	_, filename := filepath.Split(Configurations.ConfigFile)
-	content := archaius.GetString(filename, "")
-	return yaml.Unmarshal([]byte(content), Configurations)
-}
-
-//GetDB return db configs
-func GetDB() DB {
-	return Configurations.DB
+func Test_HeathCheck(t *testing.T) {
+	path := fmt.Sprintf("/v1/health")
+	r, _ := http.NewRequest("GET", path, nil)
+	revision := &v1.AdminResource{}
+	c, err := restfultest.New(revision, nil)
+	assert.NoError(t, err)
+	resp := httptest.NewRecorder()
+	c.ServeHTTP(resp, r)
+	body, err := ioutil.ReadAll(resp.Body)
+	assert.NoError(t, err)
+	data := &model.DocHealthCheck{}
+	err = json.Unmarshal(body, &data)
+	assert.NoError(t, err)
+	assert.NotEmpty(t, data)
 }
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index ac4d4e2..06f52be 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -23,6 +23,7 @@ import (
 	"errors"
 	"github.com/apache/servicecomb-kie/pkg/model"
 	"github.com/apache/servicecomb-kie/server/service/mongo/session"
+	"github.com/apache/servicecomb-service-center/pkg/rbacframe"
 	"net/http"
 	"strconv"
 	"strings"
@@ -52,22 +53,22 @@ var (
 	ErrInvalidRev = errors.New(common.MsgInvalidRev)
 )
 
-//ReadDomain get domain info from attribute
-func ReadDomain(context *restful.Context) interface{} {
-	return context.ReadRestfulRequest().Attribute(AttributeDomainKey)
+//ReadClaims get auth info
+func ReadClaims(ctx context.Context) map[string]interface{} {
+	i := rbacframe.FromContext(ctx)
+	if i != nil {
+		return rbacframe.FromContext(ctx).(map[string]interface{})
+	}
+	return nil
 }
 
-//ReadFindDepth get find depth
-func ReadFindDepth(context *restful.Context) (int, error) {
-	d := context.ReadRestfulRequest().HeaderParameter(common.HeaderDepth)
-	if d == "" {
-		return 1, nil
+//ReadDomain get domain info
+func ReadDomain(ctx context.Context) string {
+	c := ReadClaims(ctx)
+	if c != nil {
+		return c["domain"].(string)
 	}
-	depth, err := strconv.Atoi(d)
-	if err != nil {
-		return 0, err
-	}
-	return depth, nil
+	return "default"
 }
 
 //ReadLabelCombinations get query combination from url
@@ -101,8 +102,15 @@ func ReadLabelCombinations(req *goRestful.Request) ([]map[string]string, error)
 func WriteErrResponse(context *restful.Context, status int, msg string) {
 	context.Resp.Header().Set(goRestful.HEADER_ContentType, goRestful.MIME_JSON)
 	context.WriteHeader(status)
-	b, _ := json.MarshalIndent(&ErrorMsg{Msg: msg}, "", " ")
-	context.Write(b)
+	b, err := json.MarshalIndent(&ErrorMsg{Msg: msg}, "", " ")
+	if err != nil {
+		openlogging.Error("can not marshal:" + err.Error())
+		return
+	}
+	err = context.Write(b)
+	if err != nil {
+		openlogging.Error("can not marshal:" + err.Error())
+	}
 }
 
 func readRequest(ctx *restful.Context, v interface{}) error {
diff --git a/server/resource/v1/history_resource.go b/server/resource/v1/history_resource.go
index 7772dc7..d36620d 100644
--- a/server/resource/v1/history_resource.go
+++ b/server/resource/v1/history_resource.go
@@ -18,15 +18,11 @@
 package v1
 
 import (
+	"github.com/apache/servicecomb-kie/pkg/common"
 	"github.com/apache/servicecomb-kie/pkg/model"
+	"github.com/apache/servicecomb-kie/server/service"
 	"github.com/apache/servicecomb-kie/server/service/mongo/track"
-	"github.com/go-chassis/go-chassis/pkg/runtime"
 	"net/http"
-	"strconv"
-	"time"
-
-	"github.com/apache/servicecomb-kie/pkg/common"
-	"github.com/apache/servicecomb-kie/server/service"
 
 	goRestful "github.com/emicklei/go-restful"
 	"github.com/go-chassis/go-chassis/server/restful"
@@ -89,12 +85,12 @@ func (r *HistoryResource) GetPollingData(context *restful.Context) {
 	if userAgent != "" {
 		query.UserAgent = userAgent
 	}
-	domain := ReadDomain(context)
-	if domain == nil {
+	domain := ReadDomain(context.Ctx)
+	if domain == "" {
 		WriteErrResponse(context, http.StatusInternalServerError, common.MsgDomainMustNotBeEmpty)
 		return
 	}
-	query.Domain = domain.(string)
+	query.Domain = domain
 	records, err := track.Get(context.Ctx, query)
 	if err != nil {
 		if err == service.ErrRecordNotExists {
@@ -113,30 +109,6 @@ func (r *HistoryResource) GetPollingData(context *restful.Context) {
 	}
 }
 
-//HealthCheck provider version info and time info
-func (r *HistoryResource) HealthCheck(context *restful.Context) {
-	domain := ReadDomain(context)
-	resp := &model.DocHealthCheck{}
-	latest, err := service.RevisionService.GetRevision(context.Ctx, domain.(string))
-	if err != nil {
-		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
-		return
-	}
-	resp.Revision = strconv.FormatInt(latest, 10)
-	resp.Version = runtime.Version
-	resp.Timestamp = time.Now().Unix()
-	total, err := service.KVService.Total(context.Ctx, domain.(string))
-	if err != nil {
-		WriteErrResponse(context, http.StatusInternalServerError, err.Error())
-		return
-	}
-	resp.Total = total
-	err = writeResponse(context, resp)
-	if err != nil {
-		openlogging.Error(err.Error())
-	}
-}
-
 //URLPatterns defined config operations
 func (r *HistoryResource) URLPatterns() []restful.Route {
 	return []restful.Route{
@@ -154,24 +126,10 @@ func (r *HistoryResource) URLPatterns() []restful.Route {
 					Model: model.DocResponseGetKey{},
 				},
 			},
-			Consumes: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
-			Produces: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
-		},
-		{
-			Method:       http.MethodGet,
-			Path:         "/v1/health",
-			ResourceFunc: r.HealthCheck,
-			FuncDesc:     "health check return version and revision",
-			Parameters:   []*restful.Parameters{},
-			Returns: []*restful.Returns{
-				{
-					Code:  http.StatusOK,
-					Model: model.DocHealthCheck{},
-				},
-			},
-			Consumes: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
-			Produces: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
+			Consumes: []string{goRestful.MIME_JSON},
+			Produces: []string{goRestful.MIME_JSON},
 		},
+
 		{
 			Method:       http.MethodGet,
 			Path:         "/v1/{project}/kie/track",
@@ -187,8 +145,8 @@ func (r *HistoryResource) URLPatterns() []restful.Route {
 					Model:   []model.PollingDataResponse{},
 				},
 			},
-			Consumes: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
-			Produces: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
+			Consumes: []string{goRestful.MIME_JSON},
+			Produces: []string{goRestful.MIME_JSON},
 		},
 	}
 }
diff --git a/server/resource/v1/history_resource_test.go b/server/resource/v1/history_resource_test.go
index 6b993f1..00a1ab2 100644
--- a/server/resource/v1/history_resource_test.go
+++ b/server/resource/v1/history_resource_test.go
@@ -97,11 +97,10 @@ func TestHistoryResource_GetRevisions(t *testing.T) {
 func TestHistoryResource_GetPollingData(t *testing.T) {
 	t.Run("list kv by service label, to create a polling data", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/history_test/kie/kv", nil)
-		noopH := &handler2.NoopAuthHandler{}
 		trackH := &handler2.TrackHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain3", noopH.Name(), trackH.Name())
+		chain, _ := handler.CreateChain(common.Provider, "testchain3", trackH.Name())
 		r.Header.Set("Content-Type", "application/json")
-		r.Header.Set("X-Session-Id", "test")
+		r.Header.Set(v1.HeaderSessionID, "test")
 		kvr := &v1.KVResource{}
 		c, err := restfultest.New(kvr, chain)
 		assert.NoError(t, err)
@@ -115,8 +114,7 @@ func TestHistoryResource_GetPollingData(t *testing.T) {
 	})
 	t.Run("get polling data", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/history_test/kie/track?sessionId=test", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain3", noopH.Name())
+		chain, _ := handler.CreateChain(common.Provider, "testchain3", "")
 		r.Header.Set("Content-Type", "application/json")
 		revision := &v1.HistoryResource{}
 		c, err := restfultest.New(revision, chain)
@@ -132,22 +130,3 @@ func TestHistoryResource_GetPollingData(t *testing.T) {
 	})
 
 }
-
-func Test_HeathCheck(t *testing.T) {
-	path := fmt.Sprintf("/v1/health")
-	r, _ := http.NewRequest("GET", path, nil)
-	noopH := &handler2.NoopAuthHandler{}
-	revision := &v1.HistoryResource{}
-	chain, err := handler.CreateChain(common.Provider, "default", noopH.Name())
-	assert.NoError(t, err)
-	c, err := restfultest.New(revision, chain)
-	assert.NoError(t, err)
-	resp := httptest.NewRecorder()
-	c.ServeHTTP(resp, r)
-	body, err := ioutil.ReadAll(resp.Body)
-	assert.NoError(t, err)
-	data := &model.DocHealthCheck{}
-	err = json.Unmarshal(body, &data)
-	assert.NoError(t, err)
-	assert.NotEmpty(t, data)
-}
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index 4925906..d11b348 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -49,8 +49,8 @@ func (r *KVResource) Post(rctx *restful.Context) {
 		WriteErrResponse(rctx, http.StatusBadRequest, fmt.Sprintf(FmtReadRequestError, err))
 		return
 	}
-	domain := ReadDomain(rctx)
-	kv.Domain = domain.(string)
+	domain := ReadDomain(rctx.Ctx)
+	kv.Domain = domain
 	kv.Project = project
 	if kv.Status == "" {
 		kv.Status = common.StatusDisabled
@@ -110,9 +110,9 @@ func (r *KVResource) Put(rctx *restful.Context) {
 		WriteErrResponse(rctx, http.StatusBadRequest, fmt.Sprintf(FmtReadRequestError, err))
 		return
 	}
-	domain := ReadDomain(rctx)
+	domain := ReadDomain(rctx.Ctx)
 	kvReq.ID = kvID
-	kvReq.Domain = domain.(string)
+	kvReq.Domain = domain
 	kvReq.Project = project
 	err = validate.Validate(kvReq)
 	if err != nil {
@@ -148,7 +148,7 @@ func (r *KVResource) Put(rctx *restful.Context) {
 func (r *KVResource) Get(rctx *restful.Context) {
 	request := &model.GetKVRequest{
 		Project: rctx.ReadPathParameter(common.PathParameterProject),
-		Domain:  ReadDomain(rctx).(string),
+		Domain:  ReadDomain(rctx.Ctx),
 		ID:      rctx.ReadPathParameter(common.PathParamKVID),
 	}
 	err := validate.Validate(request)
@@ -179,7 +179,7 @@ func (r *KVResource) List(rctx *restful.Context) {
 	var err error
 	request := &model.ListKVRequest{
 		Project: rctx.ReadPathParameter(common.PathParameterProject),
-		Domain:  ReadDomain(rctx).(string),
+		Domain:  ReadDomain(rctx.Ctx),
 		Key:     rctx.ReadQueryParameter(common.QueryParamKey),
 		Status:  rctx.ReadQueryParameter(common.QueryParamStatus),
 	}
@@ -268,7 +268,7 @@ func returnData(rctx *restful.Context, request *model.ListKVRequest) {
 //Delete deletes one kv by id
 func (r *KVResource) Delete(rctx *restful.Context) {
 	project := rctx.ReadPathParameter(common.PathParameterProject)
-	domain := ReadDomain(rctx).(string)
+	domain := ReadDomain(rctx.Ctx)
 	kvID := rctx.ReadPathParameter(common.PathParamKVID)
 	err := validateDelete(domain, project, kvID)
 	if err != nil {
@@ -304,7 +304,7 @@ func (r *KVResource) Delete(rctx *restful.Context) {
 //DeleteList deletes multiple kvs by ids
 func (r *KVResource) DeleteList(rctx *restful.Context) {
 	project := rctx.ReadPathParameter(common.PathParameterProject)
-	domain := ReadDomain(rctx).(string)
+	domain := ReadDomain(rctx.Ctx)
 	b := new(DeleteBody)
 	if err := json.NewDecoder(rctx.ReadRequest().Body).Decode(b); err != nil {
 		WriteErrResponse(rctx, http.StatusBadRequest, fmt.Sprintf(FmtReadRequestError, err))
@@ -402,7 +402,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
 					Message: "key value not found",
 				},
 			},
-			Produces: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
+			Produces: []string{goRestful.MIME_JSON},
 		}, {
 			Method:       http.MethodGet,
 			Path:         "/v1/{project}/kie/kv",
@@ -424,7 +424,7 @@ func (r *KVResource) URLPatterns() []restful.Route {
 					Message: "empty body",
 				},
 			},
-			Produces: []string{goRestful.MIME_JSON, common.ContentTypeYaml},
+			Produces: []string{goRestful.MIME_JSON},
 		}, {
 			Method:       http.MethodDelete,
 			Path:         "/v1/{project}/kie/kv/{kv_id}",
diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go
index a7d81a0..e05be71 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -24,14 +24,11 @@ import (
 	"github.com/apache/servicecomb-kie/pkg/model"
 	"github.com/apache/servicecomb-kie/pkg/validate"
 	"github.com/apache/servicecomb-kie/server/config"
-	handler2 "github.com/apache/servicecomb-kie/server/handler"
 	"github.com/apache/servicecomb-kie/server/plugin/qms"
 	"github.com/apache/servicecomb-kie/server/pubsub"
 	v1 "github.com/apache/servicecomb-kie/server/resource/v1"
 	"github.com/apache/servicecomb-kie/server/service"
 	"github.com/go-chassis/go-archaius"
-	"github.com/go-chassis/go-chassis/core/common"
-	"github.com/go-chassis/go-chassis/core/handler"
 	"github.com/go-chassis/go-chassis/pkg/backends/quota"
 	"github.com/go-chassis/go-chassis/server/restful/restfultest"
 	log "github.com/go-chassis/paas-lager"
@@ -93,11 +90,9 @@ func TestKVResource_Post(t *testing.T) {
 		}
 		j, _ := json.Marshal(kv)
 		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 
@@ -118,11 +113,9 @@ func TestKVResource_Post(t *testing.T) {
 		}
 		j, _ := json.Marshal(kv)
 		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 
@@ -145,11 +138,9 @@ func TestKVResource_Post(t *testing.T) {
 		}
 		j, _ := json.Marshal(kv)
 		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 
@@ -164,11 +155,9 @@ func TestKVResource_Post(t *testing.T) {
 func TestKVResource_List(t *testing.T) {
 	t.Run("list kv by service label, should return 3 kvs", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -184,11 +173,9 @@ func TestKVResource_List(t *testing.T) {
 	var rev string
 	t.Run("list kv by service label, exact match,should return 2 kv", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&match=exact", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -202,11 +189,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with current rev param,should return 304 ", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&"+common2.QueryParamRev+"="+rev, nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -215,11 +200,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with old rev param,should return latest revision", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&"+common2.QueryParamRev+"=1", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -228,11 +211,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with wait and old rev param,should return latest revision,no wait", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&wait=1s&"+common2.QueryParamRev+"=1", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		start := time.Now()
@@ -243,11 +224,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with wait and current rev param,should wait and return 304 ", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&wait=1s&"+common2.QueryParamRev+"="+rev, nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		start := time.Now()
@@ -258,11 +237,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with wait param,will exceed 1s and return 304", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&wait=1s", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		start := time.Now()
@@ -272,11 +249,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label offset, should return 1kv", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=service:utService&offset=1&limit=1", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -289,11 +264,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("list kv by service label, with wait and match param,not exact match and return 304", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?label=match:test&wait=10s&match=exact", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain-match", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		var wg sync.WaitGroup
@@ -306,11 +279,9 @@ func TestKVResource_List(t *testing.T) {
 			}
 			j, _ := json.Marshal(kv)
 			r2, _ := http.NewRequest("POST", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-			noopH2 := &handler2.NoopAuthHandler{}
-			chain2, _ := handler.CreateChain(common.Provider, "testchain-match", noopH2.Name())
 			r2.Header.Set("Content-Type", "application/json")
 			kvr2 := &v1.KVResource{}
-			c2, _ := restfultest.New(kvr2, chain2)
+			c2, _ := restfultest.New(kvr2, nil)
 			resp2 := httptest.NewRecorder()
 			c2.ServeHTTP(resp2, r2)
 			body, _ := ioutil.ReadAll(resp2.Body)
@@ -331,11 +302,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("get one key by label, exact match,should return 1 kv", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?key=timeout&label=service:utService&match=exact", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -348,11 +317,9 @@ func TestKVResource_List(t *testing.T) {
 	})
 	t.Run("get one key by service label should return 2 kv,delete one", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv?key=timeout&label=service:utService", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -364,7 +331,7 @@ func TestKVResource_List(t *testing.T) {
 		assert.Equal(t, 2, len(result.Data))
 
 		r2, _ := http.NewRequest("DELETE", "/v1/kv_test/kie/kv/"+result.Data[0].ID, nil)
-		c2, err := restfultest.New(kvr, chain)
+		c2, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp2 := httptest.NewRecorder()
 		c2.ServeHTTP(resp2, r2)
@@ -382,11 +349,9 @@ func TestKVResource_PutAndGet(t *testing.T) {
 	t.Run("create a kv, the value of user is guest", func(t *testing.T) {
 		j, _ := json.Marshal(kv)
 		r, _ := http.NewRequest("POST", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 
@@ -401,11 +366,9 @@ func TestKVResource_PutAndGet(t *testing.T) {
 	})
 	t.Run("get one key by kv_id", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv/"+id, nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -422,11 +385,9 @@ func TestKVResource_PutAndGet(t *testing.T) {
 	t.Run("update the kv, set the value of user to admin", func(t *testing.T) {
 		j, _ := json.Marshal(kvUpdate)
 		r, _ := http.NewRequest("PUT", "/v1/kv_test/kie/kv/"+id, bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 
@@ -439,11 +400,10 @@ func TestKVResource_PutAndGet(t *testing.T) {
 	})
 	t.Run("get one key by kv_id again", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv/"+id, nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
+
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -463,11 +423,9 @@ func TestKVResource_PutAndGet(t *testing.T) {
 			Value: "1",
 		})
 		r, _ := http.NewRequest("POST", "/v1/test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, _ := restfultest.New(kvr, chain)
+		c, _ := restfultest.New(kvr, nil)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
 		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code)
@@ -477,11 +435,9 @@ func TestKVResource_DeleteList(t *testing.T) {
 	var ids []string
 	t.Run("get ids of all kvs", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -498,11 +454,10 @@ func TestKVResource_DeleteList(t *testing.T) {
 	t.Run("delete all kvs by ids", func(t *testing.T) {
 		j, _ := json.Marshal(v1.DeleteBody{IDs: ids})
 		r, _ := http.NewRequest("DELETE", "/v1/kv_test/kie/kv", bytes.NewBuffer(j))
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
+
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
@@ -511,11 +466,9 @@ func TestKVResource_DeleteList(t *testing.T) {
 	})
 	t.Run("get all kvs again, should return 0 kv", func(t *testing.T) {
 		r, _ := http.NewRequest("GET", "/v1/kv_test/kie/kv", nil)
-		noopH := &handler2.NoopAuthHandler{}
-		chain, _ := handler.CreateChain(common.Provider, "testchain1", noopH.Name())
 		r.Header.Set("Content-Type", "application/json")
 		kvr := &v1.KVResource{}
-		c, err := restfultest.New(kvr, chain)
+		c, err := restfultest.New(kvr, nil)
 		assert.NoError(t, err)
 		resp := httptest.NewRecorder()
 		c.ServeHTTP(resp, r)
diff --git a/server/server.go b/server/server.go
new file mode 100644
index 0000000..516030e
--- /dev/null
+++ b/server/server.go
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package server
+
+import (
+	"github.com/apache/servicecomb-kie/pkg/validate"
+	"github.com/apache/servicecomb-kie/server/config"
+	"github.com/apache/servicecomb-kie/server/pubsub"
+	"github.com/apache/servicecomb-kie/server/rbac"
+	v1 "github.com/apache/servicecomb-kie/server/resource/v1"
+	"github.com/apache/servicecomb-kie/server/service"
+	"github.com/go-chassis/go-chassis"
+	"github.com/go-chassis/go-chassis/core/common"
+	"github.com/go-mesh/openlogging"
+)
+
+func Run() {
+	chassis.RegisterSchema(common.ProtocolRest, &v1.KVResource{})
+	chassis.RegisterSchema(common.ProtocolRest, &v1.HistoryResource{})
+	chassis.RegisterSchema(common.ProtocolRest, &v1.AdminResource{})
+	if err := chassis.Init(); err != nil {
+		openlogging.Fatal(err.Error())
+	}
+	if err := config.Init(); err != nil {
+		openlogging.Fatal(err.Error())
+	}
+	if err := service.DBInit(); err != nil {
+		openlogging.Fatal(err.Error())
+	}
+	if err := validate.Init(); err != nil {
+		openlogging.Fatal("validate init failed: " + err.Error())
+	}
+	rbac.Init()
+	pubsub.Init()
+	pubsub.Start()
+	if err := chassis.Run(); err != nil {
+		openlogging.Fatal("service exit: " + err.Error())
+	}
+}