diff --git a/cluster/cluster.go b/cluster/cluster.go index b292c8e6..2e54dce0 100644 --- a/cluster/cluster.go +++ b/cluster/cluster.go @@ -73,6 +73,7 @@ type Cluster interface { IAM(superuser iamidentity.User, jwtRealm, jwtSecret string) (iam.IAM, error) ListIdentities() store.Users + ListPolicies() store.Policies AddIdentity(origin string, identity iamidentity.User) error SetPolicies(origin, name string, policies []iamaccess.Policy) error RemoveIdentity(origin string, name string) error @@ -782,6 +783,10 @@ func (c *cluster) ListIdentities() store.Users { return c.store.UserList() } +func (c *cluster) ListPolicies() store.Policies { + return c.store.PolicyList() +} + func (c *cluster) AddIdentity(origin string, identity iamidentity.User) error { if !c.IsRaftLeader() { return c.forwarder.AddIdentity(origin, identity) diff --git a/cluster/iam/adapter.go b/cluster/iam/adapter.go index feff7a9f..d8753a8c 100644 --- a/cluster/iam/adapter.go +++ b/cluster/iam/adapter.go @@ -2,6 +2,7 @@ package iam import ( "strings" + "sync" "github.com/datarhei/core/v16/cluster/store" iamaccess "github.com/datarhei/core/v16/iam/access" @@ -11,12 +12,15 @@ import ( ) type policyAdapter struct { - store store.Store + store store.Store + domains map[string]struct{} + lock sync.RWMutex } func NewPolicyAdapter(store store.Store) (iamaccess.Adapter, error) { a := &policyAdapter{ - store: store, + store: store, + domains: map[string]struct{}{}, } return a, nil @@ -26,6 +30,7 @@ func (a *policyAdapter) LoadPolicy(model model.Model) error { policies := a.store.PolicyList() rules := [][]string{} + domains := map[string]struct{}{} for _, p := range policies.Policies { rule := []string{ @@ -35,12 +40,17 @@ func (a *policyAdapter) LoadPolicy(model model.Model) error { strings.Join(p.Actions, "|"), } + domains[p.Domain] = struct{}{} + rules = append(rules, rule) } - model.ClearPolicy() model.AddPolicies("p", "p", rules) + a.lock.Lock() + a.domains = domains + a.lock.Unlock() + return nil } @@ -69,11 +79,27 @@ func (a *policyAdapter) RemoveFilteredPolicy(sec string, ptype string, fieldInde } func (a *policyAdapter) AllDomains() []string { - return nil + a.lock.RLock() + defer a.lock.RUnlock() + + n := len(a.domains) + domains := make([]string, n) + + for domain := range a.domains { + domains[n-1] = domain + n-- + } + + return domains } func (a *policyAdapter) HasDomain(name string) bool { - return false + a.lock.RLock() + defer a.lock.RUnlock() + + _, ok := a.domains[name] + + return ok } type identityAdapter struct { diff --git a/docs/docs.go b/docs/docs.go index 14541995..a17f80ec 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -160,7 +160,182 @@ const docTemplate = `{ } } }, + "/api/v3/cluster/db/policies": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of policies in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of policies in the cluster", + "operationId": "cluster-3-db-list-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMPolicy" + } + } + } + } + } + }, + "/api/v3/cluster/db/process": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of processes in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of processes in the cluster", + "operationId": "cluster-3-db-list-processes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Process" + } + } + } + } + } + }, + "/api/v3/cluster/db/user": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of identities in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of identities in the cluster", + "operationId": "cluster-3-db-list-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMUser" + } + } + } + } + } + }, + "/api/v3/cluster/iam/policies": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of policies IAM", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of policies in IAM", + "operationId": "cluster-3-iam-list-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMPolicy" + } + } + } + } + } + }, + "/api/v3/cluster/iam/policies/reload": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Reload policies", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "Reload policies", + "operationId": "cluster-3-iam-reload-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/iam/user": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of identities in IAM", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of identities in IAM", + "operationId": "cluster-3-iam-list-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMUser" + } + } + } + } + }, "post": { "security": [ { @@ -206,6 +381,38 @@ const docTemplate = `{ } } }, + "/api/v3/cluster/iam/user/reload": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Reload identities", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "Reload identities", + "operationId": "cluster-3-iam-reload-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/iam/user/{name}": { "delete": { "security": [ @@ -359,35 +566,6 @@ const docTemplate = `{ } } }, - "/api/v3/cluster/node/process": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "List of processes in the cluster", - "produces": [ - "application/json" - ], - "tags": [ - "v16.?.?" - ], - "summary": "List of processes in the cluster", - "operationId": "cluster-3-list-node-processes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/api.ClusterProcess" - } - } - } - } - } - }, "/api/v3/cluster/node/{id}": { "get": { "security": [ @@ -470,6 +648,97 @@ const docTemplate = `{ } } }, + "/api/v3/cluster/node/{id}/process": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of processes in the cluster on a node", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of processes in the cluster on a node", + "operationId": "cluster-3-list-node-processes", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.ClusterProcess" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/api.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, + "/api/v3/cluster/node/{id}/version": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List a proxy node by its ID", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List a proxy node by its ID", + "operationId": "cluster-3-get-node-version", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.ClusterNode" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/process": { "get": { "security": [ @@ -485,14 +754,14 @@ const docTemplate = `{ "v16.?.?" ], "summary": "List of processes in the cluster", - "operationId": "cluster-3-list-processes", + "operationId": "cluster-3-list-all-node-processes", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/api.Process" + "$ref": "#/definitions/api.ClusterProcess" } } } diff --git a/docs/swagger.json b/docs/swagger.json index 9e04ab75..206c9535 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -152,7 +152,182 @@ } } }, + "/api/v3/cluster/db/policies": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of policies in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of policies in the cluster", + "operationId": "cluster-3-db-list-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMPolicy" + } + } + } + } + } + }, + "/api/v3/cluster/db/process": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of processes in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of processes in the cluster", + "operationId": "cluster-3-db-list-processes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Process" + } + } + } + } + } + }, + "/api/v3/cluster/db/user": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of identities in the cluster", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of identities in the cluster", + "operationId": "cluster-3-db-list-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMUser" + } + } + } + } + } + }, + "/api/v3/cluster/iam/policies": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of policies IAM", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of policies in IAM", + "operationId": "cluster-3-iam-list-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMPolicy" + } + } + } + } + } + }, + "/api/v3/cluster/iam/policies/reload": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Reload policies", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "Reload policies", + "operationId": "cluster-3-iam-reload-policies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/iam/user": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of identities in IAM", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of identities in IAM", + "operationId": "cluster-3-iam-list-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.IAMUser" + } + } + } + } + }, "post": { "security": [ { @@ -198,6 +373,38 @@ } } }, + "/api/v3/cluster/iam/user/reload": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Reload identities", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "Reload identities", + "operationId": "cluster-3-iam-reload-identities", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/iam/user/{name}": { "delete": { "security": [ @@ -351,35 +558,6 @@ } } }, - "/api/v3/cluster/node/process": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "List of processes in the cluster", - "produces": [ - "application/json" - ], - "tags": [ - "v16.?.?" - ], - "summary": "List of processes in the cluster", - "operationId": "cluster-3-list-node-processes", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/api.ClusterProcess" - } - } - } - } - } - }, "/api/v3/cluster/node/{id}": { "get": { "security": [ @@ -462,6 +640,97 @@ } } }, + "/api/v3/cluster/node/{id}/process": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List of processes in the cluster on a node", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List of processes in the cluster on a node", + "operationId": "cluster-3-list-node-processes", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.ClusterProcess" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/api.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, + "/api/v3/cluster/node/{id}/version": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "List a proxy node by its ID", + "produces": [ + "application/json" + ], + "tags": [ + "v16.?.?" + ], + "summary": "List a proxy node by its ID", + "operationId": "cluster-3-get-node-version", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.ClusterNode" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/api.Error" + } + } + } + } + }, "/api/v3/cluster/process": { "get": { "security": [ @@ -477,14 +746,14 @@ "v16.?.?" ], "summary": "List of processes in the cluster", - "operationId": "cluster-3-list-processes", + "operationId": "cluster-3-list-all-node-processes", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { - "$ref": "#/definitions/api.Process" + "$ref": "#/definitions/api.ClusterProcess" } } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index e7d90aa0..fe0626cc 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2240,7 +2240,116 @@ paths: summary: List of nodes in the cluster tags: - v16.?.? + /api/v3/cluster/db/policies: + get: + description: List of policies in the cluster + operationId: cluster-3-db-list-policies + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.IAMPolicy' + type: array + security: + - ApiKeyAuth: [] + summary: List of policies in the cluster + tags: + - v16.?.? + /api/v3/cluster/db/process: + get: + description: List of processes in the cluster + operationId: cluster-3-db-list-processes + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.Process' + type: array + security: + - ApiKeyAuth: [] + summary: List of processes in the cluster + tags: + - v16.?.? + /api/v3/cluster/db/user: + get: + description: List of identities in the cluster + operationId: cluster-3-db-list-identities + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.IAMUser' + type: array + security: + - ApiKeyAuth: [] + summary: List of identities in the cluster + tags: + - v16.?.? + /api/v3/cluster/iam/policies: + get: + description: List of policies IAM + operationId: cluster-3-iam-list-policies + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.IAMPolicy' + type: array + security: + - ApiKeyAuth: [] + summary: List of policies in IAM + tags: + - v16.?.? + /api/v3/cluster/iam/policies/reload: + get: + description: Reload policies + operationId: cluster-3-iam-reload-policies + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.Error' + security: + - ApiKeyAuth: [] + summary: Reload policies + tags: + - v16.?.? /api/v3/cluster/iam/user: + get: + description: List of identities in IAM + operationId: cluster-3-iam-list-identities + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/api.IAMUser' + type: array + security: + - ApiKeyAuth: [] + summary: List of identities in IAM + tags: + - v16.?.? post: consumes: - application/json @@ -2345,6 +2454,26 @@ paths: summary: Replace policies of an user tags: - v16.?.? + /api/v3/cluster/iam/user/reload: + get: + description: Reload identities + operationId: cluster-3-iam-reload-identities + produces: + - application/json + responses: + "200": + description: OK + schema: + type: string + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.Error' + security: + - ApiKeyAuth: [] + summary: Reload identities + tags: + - v16.?.? /api/v3/cluster/node: get: description: List of proxy nodes in the cluster @@ -2419,10 +2548,16 @@ paths: summary: List the files of a proxy node by its ID tags: - v16.?.? - /api/v3/cluster/node/process: + /api/v3/cluster/node/{id}/process: get: - description: List of processes in the cluster + description: List of processes in the cluster on a node operationId: cluster-3-list-node-processes + parameters: + - description: Node ID + in: path + name: id + required: true + type: string produces: - application/json responses: @@ -2432,15 +2567,49 @@ paths: items: $ref: '#/definitions/api.ClusterProcess' type: array + "404": + description: Not Found + schema: + $ref: '#/definitions/api.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.Error' security: - ApiKeyAuth: [] - summary: List of processes in the cluster + summary: List of processes in the cluster on a node + tags: + - v16.?.? + /api/v3/cluster/node/{id}/version: + get: + description: List a proxy node by its ID + operationId: cluster-3-get-node-version + parameters: + - description: Node ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/api.ClusterNode' + "404": + description: Not Found + schema: + $ref: '#/definitions/api.Error' + security: + - ApiKeyAuth: [] + summary: List a proxy node by its ID tags: - v16.?.? /api/v3/cluster/process: get: description: List of processes in the cluster - operationId: cluster-3-list-processes + operationId: cluster-3-list-all-node-processes produces: - application/json responses: @@ -2448,7 +2617,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/api.Process' + $ref: '#/definitions/api.ClusterProcess' type: array security: - ApiKeyAuth: [] diff --git a/http/handler/api/cluster.go b/http/handler/api/cluster.go index c919905a..da8dcf81 100644 --- a/http/handler/api/cluster.go +++ b/http/handler/api/cluster.go @@ -47,6 +47,74 @@ func NewCluster(cluster cluster.Cluster, iam iam.IAM) (*ClusterHandler, error) { return h, nil } +// GetCluster returns the list of nodes in the cluster +// @Summary List of nodes in the cluster +// @Description List of nodes in the cluster +// @Tags v16.?.? +// @ID cluster-3-get-cluster +// @Produce json +// @Success 200 {object} api.ClusterAbout +// @Failure 404 {object} api.Error +// @Security ApiKeyAuth +// @Router /api/v3/cluster [get] +func (h *ClusterHandler) About(c echo.Context) error { + state, _ := h.cluster.About() + + about := api.ClusterAbout{ + ID: state.ID, + Address: state.Address, + ClusterAPIAddress: state.ClusterAPIAddress, + CoreAPIAddress: state.CoreAPIAddress, + Server: []api.ClusterServer{}, + Stats: api.ClusterStats{ + State: state.Stats.State, + LastContact: state.Stats.LastContact.Seconds() * 1000, + NumPeers: state.Stats.NumPeers, + }, + } + + for _, n := range state.Nodes { + about.Server = append(about.Server, api.ClusterServer{ + ID: n.ID, + Address: n.Address, + Voter: n.Voter, + Leader: n.Leader, + }) + } + + return c.JSON(http.StatusOK, about) +} + +// ListAllNodeProcesses returns the list of processes running on all nodes of the cluster +// @Summary List of processes in the cluster +// @Description List of processes in the cluster +// @Tags v16.?.? +// @ID cluster-3-list-all-node-processes +// @Produce json +// @Success 200 {array} api.ClusterProcess +// @Security ApiKeyAuth +// @Router /api/v3/cluster/process [get] +func (h *ClusterHandler) ListAllNodeProcesses(c echo.Context) error { + procs := h.proxy.ListProcesses() + + processes := []api.ClusterProcess{} + + for _, p := range procs { + processes = append(processes, api.ClusterProcess{ + ProcessID: p.Config.ID, + NodeID: p.NodeID, + Reference: p.Config.Reference, + Order: p.Order, + State: p.State, + CPU: json.ToNumber(p.CPU), + Memory: p.Mem, + Runtime: int64(p.Runtime.Seconds()), + }) + } + + return c.JSON(http.StatusOK, processes) +} + // GetNodes returns the list of proxy nodes in the cluster // @Summary List of proxy nodes in the cluster // @Description List of proxy nodes in the cluster @@ -122,13 +190,13 @@ func (h *ClusterHandler) GetNode(c echo.Context) error { // @Summary List a proxy node by its ID // @Description List a proxy node by its ID // @Tags v16.?.? -// @ID cluster-3-get-node +// @ID cluster-3-get-node-version // @Produce json // @Param id path string true "Node ID" // @Success 200 {object} api.ClusterNode // @Failure 404 {object} api.Error // @Security ApiKeyAuth -// @Router /api/v3/cluster/node/{id} [get] +// @Router /api/v3/cluster/node/{id}/version [get] func (h *ClusterHandler) GetNodeVersion(c echo.Context) error { id := util.PathParam(c, "id") @@ -192,8 +260,9 @@ func (h *ClusterHandler) GetNodeFiles(c echo.Context) error { // @Param id path string true "Node ID" // @Success 200 {array} api.ClusterProcess // @Failure 404 {object} api.Error +// @Failure 500 {object} api.Error // @Security ApiKeyAuth -// @Router /api/v3/cluster/node/:id/process [get] +// @Router /api/v3/cluster/node/{id}/process [get] func (h *ClusterHandler) ListNodeProcesses(c echo.Context) error { id := util.PathParam(c, "id") @@ -225,53 +294,15 @@ func (h *ClusterHandler) ListNodeProcesses(c echo.Context) error { return c.JSON(http.StatusOK, processes) } -// GetCluster returns the list of nodes in the cluster -// @Summary List of nodes in the cluster -// @Description List of nodes in the cluster -// @Tags v16.?.? -// @ID cluster-3-get-cluster -// @Produce json -// @Success 200 {object} api.ClusterAbout -// @Failure 404 {object} api.Error -// @Security ApiKeyAuth -// @Router /api/v3/cluster [get] -func (h *ClusterHandler) About(c echo.Context) error { - state, _ := h.cluster.About() - - about := api.ClusterAbout{ - ID: state.ID, - Address: state.Address, - ClusterAPIAddress: state.ClusterAPIAddress, - CoreAPIAddress: state.CoreAPIAddress, - Server: []api.ClusterServer{}, - Stats: api.ClusterStats{ - State: state.Stats.State, - LastContact: state.Stats.LastContact.Seconds() * 1000, - NumPeers: state.Stats.NumPeers, - }, - } - - for _, n := range state.Nodes { - about.Server = append(about.Server, api.ClusterServer{ - ID: n.ID, - Address: n.Address, - Voter: n.Voter, - Leader: n.Leader, - }) - } - - return c.JSON(http.StatusOK, about) -} - // ListStoreProcesses returns the list of processes stored in the DB of the cluster // @Summary List of processes in the cluster // @Description List of processes in the cluster // @Tags v16.?.? -// @ID cluster-3-list-processes +// @ID cluster-3-db-list-processes // @Produce json // @Success 200 {array} api.Process // @Security ApiKeyAuth -// @Router /api/v3/cluster/process [get] +// @Router /api/v3/cluster/db/process [get] func (h *ClusterHandler) ListStoreProcesses(c echo.Context) error { procs := h.cluster.ListProcesses() @@ -518,12 +549,104 @@ func (h *ClusterHandler) UpdateIdentityPolicies(c echo.Context) error { return c.JSON(http.StatusOK, policies) } -func (h *ClusterHandler) ListIdentities(c echo.Context) error { +// ListStoreIdentities returns the list of identities stored in the DB of the cluster +// @Summary List of identities in the cluster +// @Description List of identities in the cluster +// @Tags v16.?.? +// @ID cluster-3-db-list-identities +// @Produce json +// @Success 200 {array} api.IAMUser +// @Security ApiKeyAuth +// @Router /api/v3/cluster/db/user [get] +func (h *ClusterHandler) ListStoreIdentities(c echo.Context) error { identities := h.cluster.ListIdentities() return c.JSON(http.StatusOK, identities) } +// ListIdentities returns the list of identities stored in IAM +// @Summary List of identities in IAM +// @Description List of identities in IAM +// @Tags v16.?.? +// @ID cluster-3-iam-list-identities +// @Produce json +// @Success 200 {array} api.IAMUser +// @Security ApiKeyAuth +// @Router /api/v3/cluster/iam/user [get] +func (h *ClusterHandler) ListIdentities(c echo.Context) error { + identities := h.iam.ListIdentities() + + return c.JSON(http.StatusOK, identities) +} + +// ReloadIdentities reloads the identities from the cluster store to IAM +// @Summary Reload identities +// @Description Reload identities +// @Tags v16.?.? +// @ID cluster-3-iam-reload-identities +// @Produce json +// @Success 200 {string} string +// @Success 500 {object} api.Error +// @Security ApiKeyAuth +// @Router /api/v3/cluster/iam/user/reload [get] +func (h *ClusterHandler) ReloadIdentities(c echo.Context) error { + err := h.iam.ReloadIndentities() + if err != nil { + return api.Err(http.StatusInternalServerError, "", "reload identities: %w", err) + } + + return c.JSON(http.StatusOK, "OK") +} + +// ListStorePolicies returns the list of policies stored in the DB of the cluster +// @Summary List of policies in the cluster +// @Description List of policies in the cluster +// @Tags v16.?.? +// @ID cluster-3-db-list-policies +// @Produce json +// @Success 200 {array} api.IAMPolicy +// @Security ApiKeyAuth +// @Router /api/v3/cluster/db/policies [get] +func (h *ClusterHandler) ListStorePolicies(c echo.Context) error { + policies := h.cluster.ListPolicies() + + return c.JSON(http.StatusOK, policies) +} + +// ListPolicies returns the list of policies stored in IAM +// @Summary List of policies in IAM +// @Description List of policies IAM +// @Tags v16.?.? +// @ID cluster-3-iam-list-policies +// @Produce json +// @Success 200 {array} api.IAMPolicy +// @Security ApiKeyAuth +// @Router /api/v3/cluster/iam/policies [get] +func (h *ClusterHandler) ListPolicies(c echo.Context) error { + policies := h.iam.ListPolicies("", "", "", nil) + + return c.JSON(http.StatusOK, policies) +} + +// ReloadPolicies reloads the policies from the cluster store to IAM +// @Summary Reload policies +// @Description Reload policies +// @Tags v16.?.? +// @ID cluster-3-iam-reload-policies +// @Produce json +// @Success 200 {string} string +// @Success 500 {object} api.Error +// @Security ApiKeyAuth +// @Router /api/v3/cluster/iam/policies/reload [get] +func (h *ClusterHandler) ReloadPolicies(c echo.Context) error { + err := h.iam.ReloadPolicies() + if err != nil { + return api.Err(http.StatusInternalServerError, "", "reload policies: %w", err) + } + + return c.JSON(http.StatusOK, "OK") +} + // Delete deletes the identity with the given name from the cluster // @Summary Delete an identity by its name // @Description Delete an identity by its name diff --git a/http/server.go b/http/server.go index e340e8e4..4b2072d9 100644 --- a/http/server.go +++ b/http/server.go @@ -656,8 +656,15 @@ func (s *server) setRoutesV3(v3 *echo.Group) { // v3 Cluster if s.v3handler.cluster != nil { v3.GET("/cluster", s.v3handler.cluster.About) - v3.GET("/cluster/process", s.v3handler.cluster.ListStoreProcesses) + + v3.GET("/cluster/db/process", s.v3handler.cluster.ListStoreProcesses) + v3.GET("/cluster/db/policies", s.v3handler.cluster.ListStorePolicies) + v3.GET("/cluster/db/user", s.v3handler.cluster.ListStoreIdentities) + v3.GET("/cluster/iam/user", s.v3handler.cluster.ListIdentities) + v3.GET("/cluster/iam/policies", s.v3handler.cluster.ListPolicies) + + v3.GET("/cluster/process", s.v3handler.cluster.ListAllNodeProcesses) v3.GET("/cluster/node", s.v3handler.cluster.GetNodes) v3.GET("/cluster/node/:id", s.v3handler.cluster.GetNode) @@ -670,9 +677,11 @@ func (s *server) setRoutesV3(v3 *echo.Group) { v3.PUT("/cluster/process/:id", s.v3handler.cluster.UpdateProcess) v3.DELETE("/cluster/process/:id", s.v3handler.cluster.DeleteProcess) + v3.GET("/cluster/iam/user/reload", s.v3handler.cluster.ReloadIdentities) v3.POST("/cluster/iam/user", s.v3handler.cluster.AddIdentity) v3.PUT("/cluster/iam/user/:name/policies", s.v3handler.cluster.UpdateIdentityPolicies) v3.DELETE("/cluster/iam/user/:name", s.v3handler.cluster.RemoveIdentity) + v3.GET("/cluster/iam/policies/reload", s.v3handler.cluster.ReloadPolicies) } } diff --git a/iam/access/access.go b/iam/access/access.go index c876da5d..02f02284 100644 --- a/iam/access/access.go +++ b/iam/access/access.go @@ -120,9 +120,9 @@ func (am *access) ListPolicies(name, domain, resource string, actions []string) } func (am *access) ReloadPolicies() error { - am.model.ClearPolicy() + am.enforcer.ClearPolicy() - return am.adapter.LoadPolicy(am.model) + return am.enforcer.LoadPolicy() } func (am *access) HasDomain(name string) bool { diff --git a/iam/access/adapter.go b/iam/access/adapter.go index 16526a55..23926df2 100644 --- a/iam/access/adapter.go +++ b/iam/access/adapter.go @@ -80,8 +80,6 @@ func (a *adapter) loadPolicyFile(model model.Model) error { return err } - model.ClearPolicy() - rule := [5]string{} for _, domain := range domains { rule[0] = "p"