// NewClusterV3 returns a launched cluster with a grpc client connection // for each cluster member. func NewClusterV3(t *testing.T, cfg *ClusterConfig) *ClusterV3 { cfg.UseGRPC = true clus := &ClusterV3{cluster: NewClusterByConfig(t, cfg)} for _, m := range clus.Members { client, err := NewClientV3(m) if err != nil { t.Fatalf("cannot create client: %v", err) } clus.clients = append(clus.clients, client) } clus.Launch(t) // manually enable v3 capability since we know we are starting a v3 cluster here. api.EnableCapability(api.V3rpcCapability) return clus }
func init() { // manually enable v3 capability since we know the cluster members all support v3. api.EnableCapability(api.V3rpcCapability) }
func TestAuthFlow(t *testing.T) { api.EnableCapability(api.AuthCapability) var testCases = []struct { req *http.Request store mockAuthStore wcode int wbody string }{ { req: mustJSONRequest(t, "PUT", "users/alice", `{{{{{{{`), store: mockAuthStore{}, wcode: http.StatusBadRequest, wbody: `{"message":"Invalid JSON in request body."}`, }, { req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "******", "password": "******"}`), store: mockAuthStore{enabled: true}, wcode: http.StatusUnauthorized, wbody: `{"message":"Insufficient credentials"}`, }, // Users { req: mustJSONRequest(t, "GET", "users", ""), store: mockAuthStore{ users: map[string]*auth.User{ "alice": { User: "******", Roles: []string{"alicerole", "guest"}, Password: "******", }, "bob": { User: "******", Roles: []string{"guest"}, Password: "******", }, "root": { User: "******", Roles: []string{"root"}, Password: "******", }, }, roles: map[string]*auth.Role{ "alicerole": { Role: "alicerole", }, "guest": { Role: "guest", }, "root": { Role: "root", }, }, }, wcode: http.StatusOK, wbody: `{"users":[` + `{"user":"******","roles":[` + `{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}},` + `{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}` + `]},` + `{"user":"******","roles":[{"role":"guest","permissions":{"kv":{"read":null,"write":null}}}]},` + `{"user":"******","roles":[{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}]}`, }, { req: mustJSONRequest(t, "GET", "users/alice", ""), store: mockAuthStore{ users: map[string]*auth.User{ "alice": { User: "******", Roles: []string{"alicerole"}, Password: "******", }, }, roles: map[string]*auth.Role{ "alicerole": { Role: "alicerole", }, }, }, wcode: http.StatusOK, wbody: `{"user":"******","roles":[{"role":"alicerole","permissions":{"kv":{"read":null,"write":null}}}]}`, }, { req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "******", "password": "******"}`), store: mockAuthStore{}, wcode: http.StatusCreated, wbody: `{"user":"******","roles":null}`, }, { req: mustJSONRequest(t, "DELETE", "users/alice", ``), store: mockAuthStore{}, wcode: http.StatusOK, wbody: ``, }, { req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "******", "password": "******"}`), store: mockAuthStore{ users: map[string]*auth.User{ "alice": { User: "******", Roles: []string{"alicerole", "guest"}, Password: "******", }, }, }, wcode: http.StatusOK, wbody: `{"user":"******","roles":["alicerole","guest"]}`, }, { req: mustJSONRequest(t, "PUT", "users/alice", `{"user": "******", "grant": ["alicerole"]}`), store: mockAuthStore{ users: map[string]*auth.User{ "alice": { User: "******", Roles: []string{"alicerole", "guest"}, Password: "******", }, }, }, wcode: http.StatusOK, wbody: `{"user":"******","roles":["alicerole","guest"]}`, }, { req: mustJSONRequest(t, "GET", "users/alice", ``), store: mockAuthStore{ users: map[string]*auth.User{}, err: auth.Error{Status: http.StatusNotFound, Errmsg: "auth: User alice doesn't exist."}, }, wcode: http.StatusNotFound, wbody: `{"message":"auth: User alice doesn't exist."}`, }, { req: mustJSONRequest(t, "GET", "roles/manager", ""), store: mockAuthStore{ roles: map[string]*auth.Role{ "manager": { Role: "manager", }, }, }, wcode: http.StatusOK, wbody: `{"role":"manager","permissions":{"kv":{"read":null,"write":null}}}`, }, { req: mustJSONRequest(t, "DELETE", "roles/manager", ``), store: mockAuthStore{}, wcode: http.StatusOK, wbody: ``, }, { req: mustJSONRequest(t, "PUT", "roles/manager", `{"role":"manager","permissions":{"kv":{"read":[],"write":[]}}}`), store: mockAuthStore{}, wcode: http.StatusCreated, wbody: `{"role":"manager","permissions":{"kv":{"read":[],"write":[]}}}`, }, { req: mustJSONRequest(t, "PUT", "roles/manager", `{"role":"manager","revoke":{"kv":{"read":["foo"],"write":[]}}}`), store: mockAuthStore{ roles: map[string]*auth.Role{ "manager": { Role: "manager", }, }, }, wcode: http.StatusOK, wbody: `{"role":"manager","permissions":{"kv":{"read":null,"write":null}}}`, }, { req: mustJSONRequest(t, "GET", "roles", ""), store: mockAuthStore{ roles: map[string]*auth.Role{ "awesome": { Role: "awesome", }, "guest": { Role: "guest", }, "root": { Role: "root", }, }, }, wcode: http.StatusOK, wbody: `{"roles":[{"role":"awesome","permissions":{"kv":{"read":null,"write":null}}},` + `{"role":"guest","permissions":{"kv":{"read":null,"write":null}}},` + `{"role":"root","permissions":{"kv":{"read":null,"write":null}}}]}`, }, { req: mustJSONRequest(t, "GET", "enable", ""), store: mockAuthStore{ enabled: true, }, wcode: http.StatusOK, wbody: `{"enabled":true}`, }, { req: mustJSONRequest(t, "PUT", "enable", ""), store: mockAuthStore{ enabled: false, }, wcode: http.StatusOK, wbody: ``, }, { req: (func() *http.Request { req := mustJSONRequest(t, "DELETE", "enable", "") req.SetBasicAuth("root", "good") return req })(), store: mockAuthStore{ enabled: true, users: map[string]*auth.User{ "root": { User: "******", Password: goodPassword, Roles: []string{"root"}, }, }, roles: map[string]*auth.Role{ "root": { Role: "root", }, }, }, wcode: http.StatusOK, wbody: ``, }, { req: (func() *http.Request { req := mustJSONRequest(t, "DELETE", "enable", "") req.SetBasicAuth("root", "bad") return req })(), store: mockAuthStore{ enabled: true, users: map[string]*auth.User{ "root": { User: "******", Password: goodPassword, Roles: []string{"root"}, }, }, roles: map[string]*auth.Role{ "root": { Role: "guest", }, }, }, wcode: http.StatusUnauthorized, wbody: `{"message":"Insufficient credentials"}`, }, } for i, tt := range testCases { mux := http.NewServeMux() h := &authHandler{ sec: &tt.store, cluster: &fakeCluster{id: 1}, } handleAuth(mux, h) rw := httptest.NewRecorder() mux.ServeHTTP(rw, tt.req) if rw.Code != tt.wcode { t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode) } g := rw.Body.String() g = strings.TrimSpace(g) if g != tt.wbody { t.Errorf("#%d: got body=%s, want %s", i, g, tt.wbody) } } }