-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathplugins.go
98 lines (81 loc) · 3.83 KB
/
plugins.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package plugins
import (
"net/http"
"strings"
authContext "github.com/kobsio/kobs/pkg/hub/middleware/userauth/context"
"github.com/kobsio/kobs/pkg/hub/satellites"
"github.com/kobsio/kobs/pkg/hub/store"
"github.com/kobsio/kobs/pkg/log"
"github.com/kobsio/kobs/pkg/middleware/errresponse"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"go.uber.org/zap"
)
// Router implements the router for the resources plugin, which can be registered in the router for our rest api.
type Router struct {
*chi.Mux
httpClient *http.Client
satellitesClient satellites.Client
storeClient store.Client
}
// getPlugins returns all plugins saved in the store.
func (router *Router) getPlugins(w http.ResponseWriter, r *http.Request) {
plugins, err := router.storeClient.GetPlugins(r.Context())
if err != nil {
log.Error(r.Context(), "Could not get plugins from store", zap.Error(err))
errresponse.Render(w, r, err, http.StatusInternalServerError, "Could not get plugins")
return
}
log.Debug(r.Context(), "Return plugins from store", zap.Int("pluginsCount", len(plugins)))
render.JSON(w, r, plugins)
}
// proxyPlugins proxies all plugin related requests to the satellite, where the plugin was registered. To determine the
// correct satellite, we are using the "x-kobs-satellite" header to get the satellite from the satellites client. Then
// we are adding the plugin and user to the request header and calling the "Proxy" method of the satellite client.
func (router *Router) proxyPlugins(w http.ResponseWriter, r *http.Request) {
satelliteName := r.Header.Get("x-kobs-satellite")
pluginName := r.Header.Get("x-kobs-plugin")
pluginType := strings.Split(r.URL.RawPath, "/")
if len(pluginType) < 4 {
log.Warn(r.Context(), "The user is not authorized to access the plugin", zap.String("satellite", satelliteName), zap.String("plugin", pluginName), zap.Strings("pluginTypes", pluginType))
errresponse.Render(w, r, nil, http.StatusUnauthorized, "You are not authorized to access the plugin")
return
}
if satelliteName == "" && pluginName == "" {
satelliteName = r.URL.Query().Get("x-kobs-satellite")
pluginName = r.URL.Query().Get("x-kobs-plugin")
}
user, err := authContext.GetUser(r.Context())
if err != nil {
log.Warn(r.Context(), "The user is not authorized to access the plugin", zap.String("satellite", satelliteName), zap.String("plugin", pluginName), zap.String("pluginType", pluginType[3]), zap.Error(err))
errresponse.Render(w, r, err, http.StatusUnauthorized, "You are not authorized to access the plugin")
return
}
if !user.HasPluginAccess(satelliteName, pluginType[3], pluginName) {
log.Warn(r.Context(), "The user is not allowed to access the plugin", zap.String("satellite", satelliteName), zap.String("plugin", pluginName), zap.String("pluginType", pluginType[3]), zap.Error(err))
errresponse.Render(w, r, err, http.StatusForbidden, "You are not allowed to access the plugin")
return
}
satellite := router.satellitesClient.GetSatellite(satelliteName)
if satellite == nil {
log.Error(r.Context(), "Satellite was not found", zap.String("satellite", satelliteName), zap.String("plugin", pluginName), zap.String("pluginType", pluginType[3]))
errresponse.Render(w, r, nil, http.StatusInternalServerError, "Satellite was not found")
return
}
r.Header.Add("x-kobs-plugin", pluginName)
r.Header.Add("x-kobs-user", user.ToString())
satellite.Proxy(w, r)
}
// Mount returns a chi.Router which can be used to interact with the plugins of the satellites. It returns all the
// loaded plugins from the satellites and proxies the plugin requests to the satellites.
func Mount(satellitesClient satellites.Client, storeClient store.Client) chi.Router {
router := Router{
chi.NewRouter(),
&http.Client{},
satellitesClient,
storeClient,
}
router.Get("/", router.getPlugins)
router.HandleFunc("/*", router.proxyPlugins)
return router
}