Remote Cluster Service
- provides ability for multiple Mattermost cluster instances to create a trusted connection with each other and exchange messages
- trusted connections are managed via slash commands (for now)
- facilitates features requiring inter-cluster communication, such as Shared Channels
Shared Channels Service
- provides ability to shared channels between one or more Mattermost cluster instances (using trusted connection)
- sharing/unsharing of channels is managed via slash commands (for now)
Этот коммит содержится в:
Doug Lauder
2021-04-01 13:44:56 -04:00
коммит произвёл GitHub
родитель ff980266ac
Коммит 02196e04fa
137 изменённых файлов: 15137 добавлений и 262 удалений

Просмотреть файл

@@ -131,6 +131,13 @@ func (c *Context) CloudKeyRequired() {
}
}
func (c *Context) RemoteClusterTokenRequired() {
if license := c.App.Srv().License(); license == nil || !*license.Features.RemoteClusterService || c.App.Session().Props[model.SESSION_PROP_TYPE] != model.SESSION_TYPE_REMOTECLUSTER_TOKEN {
c.Err = model.NewAppError("", "api.context.session_expired.app_error", nil, "TokenRequired", http.StatusUnauthorized)
return
}
}
func (c *Context) MfaRequired() {
// Must be licensed for MFA and have it configured for enforcement
if license := c.App.Srv().License(); license == nil || !*license.Features.MFA || !*c.App.Config().ServiceSettings.EnableMultifactorAuthentication || !*c.App.Config().ServiceSettings.EnforceMultifactorAuthentication {
@@ -209,6 +216,18 @@ func (c *Context) SetServerBusyError() {
c.Err = NewServerBusyError()
}
func (c *Context) SetInvalidRemoteIdError(id string) {
c.Err = NewInvalidRemoteIdError(id)
}
func (c *Context) SetInvalidRemoteClusterTokenError() {
c.Err = NewInvalidRemoteClusterTokenError()
}
func (c *Context) SetJSONEncodingError() {
c.Err = NewJSONEncodingError()
}
func (c *Context) SetCommandNotFoundError() {
c.Err = model.NewAppError("GetCommand", "store.sql_command.save.get.app_error", nil, "", http.StatusNotFound)
}
@@ -246,6 +265,21 @@ func NewServerBusyError() *model.AppError {
return err
}
func NewInvalidRemoteIdError(parameter string) *model.AppError {
err := model.NewAppError("Context", "api.context.remote_id_invalid.app_error", map[string]interface{}{"RemoteId": parameter}, "", http.StatusBadRequest)
return err
}
func NewInvalidRemoteClusterTokenError() *model.AppError {
err := model.NewAppError("Context", "api.context.remote_id_invalid.app_error", nil, "", http.StatusUnauthorized)
return err
}
func NewJSONEncodingError() *model.AppError {
err := model.NewAppError("Context", "api.context.json_encoding.app_error", nil, "", http.StatusInternalServerError)
return err
}
func (c *Context) SetPermissionError(permissions ...*model.Permission) {
c.Err = c.App.MakePermissionError(permissions)
}
@@ -685,3 +719,7 @@ func (c *Context) RequireInvoiceId() *Context {
return c
}
func (c *Context) GetRemoteID(r *http.Request) string {
return r.Header.Get(model.HEADER_REMOTECLUSTER_ID)
}

Просмотреть файл

@@ -70,16 +70,17 @@ func (w *Web) NewStaticHandler(h func(*Context, http.ResponseWriter, *http.Reque
}
type Handler struct {
GetGlobalAppOptions app.AppOptionCreator
HandleFunc func(*Context, http.ResponseWriter, *http.Request)
HandlerName string
RequireSession bool
RequireCloudKey bool
TrustRequester bool
RequireMfa bool
IsStatic bool
IsLocal bool
DisableWhenBusy bool
GetGlobalAppOptions app.AppOptionCreator
HandleFunc func(*Context, http.ResponseWriter, *http.Request)
HandlerName string
RequireSession bool
RequireCloudKey bool
RequireRemoteClusterToken bool
TrustRequester bool
RequireMfa bool
IsStatic bool
IsLocal bool
DisableWhenBusy bool
cspShaDirective string
}
@@ -204,7 +205,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
token, tokenLocation := app.ParseAuthTokenFromRequest(r)
if token != "" && tokenLocation != app.TokenLocationCloudHeader {
if token != "" && tokenLocation != app.TokenLocationCloudHeader && tokenLocation != app.TokenLocationRemoteClusterHeader {
session, err := c.App.GetSession(token)
defer app.ReturnSessionToPool(session)
@@ -237,6 +238,21 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} else {
c.App.SetSession(session)
}
} else if token != "" && c.App.Srv().License() != nil && *c.App.Srv().License().Features.RemoteClusterService && tokenLocation == app.TokenLocationRemoteClusterHeader {
// Get the remote cluster
if remoteId := c.GetRemoteID(r); remoteId == "" {
c.Logger.Warn("Missing remote cluster id") //
c.Err = model.NewAppError("ServeHTTP", "api.context.remote_id_missing.app_error", nil, "", http.StatusUnauthorized)
} else {
// Check the token is correct for the remote cluster id.
session, err := c.App.GetRemoteClusterSession(token, remoteId)
if err != nil {
c.Logger.Warn("Invalid remote cluster token", mlog.Err(err))
c.Err = err
} else {
c.App.SetSession(session)
}
}
}
c.Logger = c.App.Log().With(
@@ -263,6 +279,10 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c.CloudKeyRequired()
}
if c.Err == nil && h.RequireRemoteClusterToken {
c.RemoteClusterTokenRequired()
}
if c.Err == nil && h.IsLocal {
// if the connection is local, RemoteAddr shouldn't have the
// shape IP:PORT (it will be "@" in Linux, for example)