From 3f08891ec852113d41a0537f65913d6dbdc174aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 30 Nov 2020 13:49:32 +0100 Subject: [PATCH 01/20] Add a site property to explicitly enable health checks --- pkg/mentix/exchangers/exporters/promsd.go | 6 ++++++ pkg/mentix/meshdata/properties.go | 2 ++ 2 files changed, 8 insertions(+) diff --git a/pkg/mentix/exchangers/exporters/promsd.go b/pkg/mentix/exchangers/exporters/promsd.go index 66d86d269a..67065697e2 100755 --- a/pkg/mentix/exchangers/exporters/promsd.go +++ b/pkg/mentix/exchangers/exporters/promsd.go @@ -24,6 +24,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "github.com/rs/zerolog" @@ -68,6 +69,11 @@ func createBlackboxSDScrapeConfig(site *meshdata.Site, host string, endpoint *me labels := getScrapeTargetLabels(site, endpoint) + // Check if health checks are enabled for the endpoint; if they aren't, skip this endpoint + if enableHealthChecks := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyEnableHealthChecks, "false"); !strings.EqualFold(enableHealthChecks, "true") { + return nil + } + return &prometheus.ScrapeConfig{ Targets: []string{target}, Labels: labels, diff --git a/pkg/mentix/meshdata/properties.go b/pkg/mentix/meshdata/properties.go index 7dfb8f7a57..479a4631c6 100644 --- a/pkg/mentix/meshdata/properties.go +++ b/pkg/mentix/meshdata/properties.go @@ -25,6 +25,8 @@ const ( PropertyOrganization = "organization" // PropertyMetricsPath identifies the metrics path property. PropertyMetricsPath = "metrics_path" + // PropertyEnableHealthChecks identifies the enable health checks property. + PropertyEnableHealthChecks = "enable_health_checks" // PropertyAPIVersion identifies the API version property. PropertyAPIVersion = "api_version" ) From ed873af3998f5764c78c530154a6cc0c21212bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 30 Nov 2020 13:57:39 +0100 Subject: [PATCH 02/20] Add changelog --- changelog/unreleased/mentix-checks.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/mentix-checks.md diff --git a/changelog/unreleased/mentix-checks.md b/changelog/unreleased/mentix-checks.md new file mode 100644 index 0000000000..928533b283 --- /dev/null +++ b/changelog/unreleased/mentix-checks.md @@ -0,0 +1,5 @@ +Enhancement: Support property to enable health checking on a service + +This update introduces a new service property called `ENABLE_HEALTH_CHECKS` that must be explicitly set to `true` if a service should be checked for its health status. This allows us to only enable these checks for partner sites only, skipping vendor sites. + +https://github.com/cs3org/reva/pull/1347 From 1ffc3773de3a2239eab81028e630db67f6c3967d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Tue, 1 Dec 2020 14:11:44 +0100 Subject: [PATCH 03/20] Add some more labels to Prometheus targets --- pkg/mentix/exchangers/exporters/promsd.go | 16 ++++++++++++---- pkg/mentix/meshdata/properties.go | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/pkg/mentix/exchangers/exporters/promsd.go b/pkg/mentix/exchangers/exporters/promsd.go index 67065697e2..2c10c15a35 100755 --- a/pkg/mentix/exchangers/exporters/promsd.go +++ b/pkg/mentix/exchangers/exporters/promsd.go @@ -47,7 +47,7 @@ type PrometheusSDExporter struct { } func createMetricsSDScrapeConfig(site *meshdata.Site, host string, endpoint *meshdata.ServiceEndpoint) *prometheus.ScrapeConfig { - labels := getScrapeTargetLabels(site, endpoint) + labels := getScrapeTargetLabels(site, host, endpoint) // If a metrics path was specified as a property, use that one by setting the corresponding label if metricsPath := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyMetricsPath, ""); len(metricsPath) > 0 { @@ -67,7 +67,7 @@ func createBlackboxSDScrapeConfig(site *meshdata.Site, host string, endpoint *me return nil } - labels := getScrapeTargetLabels(site, endpoint) + labels := getScrapeTargetLabels(site, host, endpoint) // Check if health checks are enabled for the endpoint; if they aren't, skip this endpoint if enableHealthChecks := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyEnableHealthChecks, "false"); !strings.EqualFold(enableHealthChecks, "true") { @@ -80,14 +80,22 @@ func createBlackboxSDScrapeConfig(site *meshdata.Site, host string, endpoint *me } } -func getScrapeTargetLabels(site *meshdata.Site, endpoint *meshdata.ServiceEndpoint) map[string]string { - return map[string]string{ +func getScrapeTargetLabels(site *meshdata.Site, host string, endpoint *meshdata.ServiceEndpoint) map[string]string { + labels := map[string]string{ "__meta_mentix_site": site.Name, "__meta_mentix_site_type": meshdata.GetSiteTypeName(site.Type), "__meta_mentix_site_id": site.GetID(), + "__meta_mentix_host": host, "__meta_mentix_country": site.CountryCode, "__meta_mentix_service_type": endpoint.Type.Name, } + + // Get the gRPC port if the corresponding property has been set + if port := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyGRPCPort, ""); len(port) > 0 { + labels["__meta_mentix_grpc_port"] = port + } + + return labels } func (exporter *PrometheusSDExporter) registerScrapeCreators(conf *config.Configuration) error { diff --git a/pkg/mentix/meshdata/properties.go b/pkg/mentix/meshdata/properties.go index 479a4631c6..b4962b4b0e 100644 --- a/pkg/mentix/meshdata/properties.go +++ b/pkg/mentix/meshdata/properties.go @@ -25,6 +25,8 @@ const ( PropertyOrganization = "organization" // PropertyMetricsPath identifies the metrics path property. PropertyMetricsPath = "metrics_path" + // PropertyGRPCPort identifies the gRPC port property. + PropertyGRPCPort = "grpc_port" // PropertyEnableHealthChecks identifies the enable health checks property. PropertyEnableHealthChecks = "enable_health_checks" // PropertyAPIVersion identifies the API version property. From 83ba2ca59ea3d4ff8266678f70fcd73916576398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Tue, 1 Dec 2020 15:46:26 +0100 Subject: [PATCH 04/20] Skip endpoints for BBE if no gRPC port is set --- pkg/mentix/exchangers/exporters/promsd.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/mentix/exchangers/exporters/promsd.go b/pkg/mentix/exchangers/exporters/promsd.go index 2c10c15a35..6a30cb763d 100755 --- a/pkg/mentix/exchangers/exporters/promsd.go +++ b/pkg/mentix/exchangers/exporters/promsd.go @@ -67,13 +67,18 @@ func createBlackboxSDScrapeConfig(site *meshdata.Site, host string, endpoint *me return nil } - labels := getScrapeTargetLabels(site, host, endpoint) - // Check if health checks are enabled for the endpoint; if they aren't, skip this endpoint if enableHealthChecks := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyEnableHealthChecks, "false"); !strings.EqualFold(enableHealthChecks, "true") { return nil } + labels := getScrapeTargetLabels(site, host, endpoint) + + // For health checks, the gRPC port must be set + if _, ok := labels["__meta_mentix_grpc_port"]; !ok { + return nil + } + return &prometheus.ScrapeConfig{ Targets: []string{target}, Labels: labels, From d67790f82a9699ac911915a9aaef3fadef430182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 4 Jan 2021 16:05:07 +0100 Subject: [PATCH 05/20] Minor TUS adjustments --- pkg/sdk/common/net/tus.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pkg/sdk/common/net/tus.go b/pkg/sdk/common/net/tus.go index 09d96e4892..409a43b77e 100644 --- a/pkg/sdk/common/net/tus.go +++ b/pkg/sdk/common/net/tus.go @@ -52,13 +52,8 @@ func (client *TUSClient) initClient(endpoint string, accessToken string, transpo } client.config.Store = memStore - if accessToken != "" { - client.config.Header.Add(AccessTokenName, accessToken) - } - - if transportToken != "" { - client.config.Header.Add(TransportTokenName, transportToken) - } + client.config.Header.Add(AccessTokenName, accessToken) + client.config.Header.Add(TransportTokenName, transportToken) // Create the TUS client tusClient, err := tus.NewClient(endpoint, client.config) From bf0b0388ea04694bd428d4cb329a6e1de5dc80ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Thu, 14 Jan 2021 13:19:55 +0100 Subject: [PATCH 06/20] Set scheme for Prometheus targets --- changelog/unreleased/mentix-prom-scheme.md | 5 +++++ pkg/mentix/exchangers/exporters/promsd.go | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 changelog/unreleased/mentix-prom-scheme.md diff --git a/changelog/unreleased/mentix-prom-scheme.md b/changelog/unreleased/mentix-prom-scheme.md new file mode 100644 index 0000000000..8c33586ca0 --- /dev/null +++ b/changelog/unreleased/mentix-prom-scheme.md @@ -0,0 +1,5 @@ +Enhancement: Set scheme for Prometheus targets in Mentix + +This enhancement lets Mentix set the scheme for Prometheus targets. This allows us to also support monitoring of sites that do not support the default HTTPS scheme. + +https://github.com/cs3org/reva/pull/1398 diff --git a/pkg/mentix/exchangers/exporters/promsd.go b/pkg/mentix/exchangers/exporters/promsd.go index 6a30cb763d..e8b4746ea2 100755 --- a/pkg/mentix/exchangers/exporters/promsd.go +++ b/pkg/mentix/exchangers/exporters/promsd.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/url" "os" "path/filepath" "strings" @@ -49,6 +50,12 @@ type PrometheusSDExporter struct { func createMetricsSDScrapeConfig(site *meshdata.Site, host string, endpoint *meshdata.ServiceEndpoint) *prometheus.ScrapeConfig { labels := getScrapeTargetLabels(site, host, endpoint) + // Support both HTTP and HTTPS endpoints by setting the scheme label accordingly + if len(endpoint.URL) > 0 { + if url, err := url.Parse(endpoint.URL); err == nil && (url.Scheme == "http" || url.Scheme == "https") { + labels["__scheme__"] = url.Scheme + } + } // If a metrics path was specified as a property, use that one by setting the corresponding label if metricsPath := meshdata.GetPropertyValue(endpoint.Properties, meshdata.PropertyMetricsPath, ""); len(metricsPath) > 0 { labels["__metrics_path__"] = metricsPath From 5fe83509e0483986c46428a33e93cab277602dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 13:50:33 +0100 Subject: [PATCH 07/20] Add site authorization status support --- pkg/mentix/connectors/gocdb.go | 3 +++ pkg/mentix/exchangers/exporters/exporter.go | 19 +++++++++++++++++++ .../exchangers/importers/webapi/query.go | 7 +++++++ pkg/mentix/meshdata/properties.go | 2 ++ 4 files changed, 31 insertions(+) diff --git a/pkg/mentix/connectors/gocdb.go b/pkg/mentix/connectors/gocdb.go index 9ac1a4399c..4fef500127 100755 --- a/pkg/mentix/connectors/gocdb.go +++ b/pkg/mentix/connectors/gocdb.go @@ -127,6 +127,9 @@ func (connector *GOCDBConnector) querySites(meshData *meshdata.MeshData) error { for _, site := range sites.Sites { properties := connector.extensionsToMap(&site.Extensions) + // Sites coming from the GOCDB are always authorized + properties[strings.ToUpper(meshdata.PropertyAuthorized)] = "true" + // See if an organization has been defined using properties; otherwise, use the official name organization := meshdata.GetPropertyValue(properties, meshdata.PropertyOrganization, site.OfficialName) diff --git a/pkg/mentix/exchangers/exporters/exporter.go b/pkg/mentix/exchangers/exporters/exporter.go index a52306d0de..6d76b36f64 100755 --- a/pkg/mentix/exchangers/exporters/exporter.go +++ b/pkg/mentix/exchangers/exporters/exporter.go @@ -20,6 +20,7 @@ package exporters import ( "fmt" + "strings" "github.com/cs3org/reva/pkg/mentix/exchangers" "github.com/cs3org/reva/pkg/mentix/meshdata" @@ -41,6 +42,8 @@ type BaseExporter struct { exchangers.BaseExchanger meshData *meshdata.MeshData + + allowUnauthorizedSites bool } // Update is called whenever the mesh data set has changed to reflect these changes. @@ -65,6 +68,11 @@ func (exporter *BaseExporter) storeMeshDataSet(meshDataSet meshdata.Map) error { if meshDataCloned == nil { return fmt.Errorf("unable to clone the mesh data") } + + if !exporter.allowUnauthorizedSites { + exporter.removeUnauthorizedSites(meshDataCloned) + } + meshDataSetCloned[connectorID] = meshDataCloned } exporter.SetMeshData(meshdata.MergeMeshDataMap(meshDataSetCloned)) @@ -84,3 +92,14 @@ func (exporter *BaseExporter) SetMeshData(meshData *meshdata.MeshData) { exporter.meshData = meshData } + +func (exporter *BaseExporter) removeUnauthorizedSites(meshData *meshdata.MeshData) { + cleanedSites := make([]*meshdata.Site, 0, len(meshData.Sites)) + for _, site := range meshData.Sites { + // Only keep authorized sites + if value := meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false"); strings.EqualFold(value, "true") { + cleanedSites = append(cleanedSites, site) + } + } + meshData.Sites = cleanedSites +} diff --git a/pkg/mentix/exchangers/importers/webapi/query.go b/pkg/mentix/exchangers/importers/webapi/query.go index bc99011a80..f4743b2abd 100755 --- a/pkg/mentix/exchangers/importers/webapi/query.go +++ b/pkg/mentix/exchangers/importers/webapi/query.go @@ -23,6 +23,7 @@ import ( "fmt" "net/http" "net/url" + "strings" "github.com/cs3org/reva/pkg/mentix/meshdata" "github.com/cs3org/reva/pkg/mentix/network" @@ -38,6 +39,12 @@ func decodeQueryData(data []byte) (*meshdata.MeshData, error) { if err := meshData.Verify(); err != nil { return nil, fmt.Errorf("verifying the imported mesh data failed: %v", err) } + + // Set sites imported through the WebAPI to 'unauthorized' by default + for _, site := range meshData.Sites { + site.Properties[strings.ToUpper(meshdata.PropertyAuthorized)] = "false" + } + meshData.InferMissingData() return meshData, nil } diff --git a/pkg/mentix/meshdata/properties.go b/pkg/mentix/meshdata/properties.go index b4962b4b0e..6675b2f997 100644 --- a/pkg/mentix/meshdata/properties.go +++ b/pkg/mentix/meshdata/properties.go @@ -21,6 +21,8 @@ package meshdata import "strings" const ( + // ProperyAuthorized identifies the authorization status property. + PropertyAuthorized = "authorized" // PropertyOrganization identifies the organization property. PropertyOrganization = "organization" // PropertyMetricsPath identifies the metrics path property. From 7ec1186823781cbe3f0d93e20698b9009b44aa4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 14:22:14 +0100 Subject: [PATCH 08/20] Persist authorization status --- pkg/mentix/connectors/gocdb.go | 6 ++++-- pkg/mentix/connectors/localfile.go | 13 +++++++++++++ pkg/mentix/exchangers/importers/reqimporter.go | 4 +++- pkg/mentix/exchangers/importers/webapi/query.go | 9 +++------ pkg/mentix/meshdata/properties.go | 7 ++++++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/pkg/mentix/connectors/gocdb.go b/pkg/mentix/connectors/gocdb.go index 4fef500127..425af0525e 100755 --- a/pkg/mentix/connectors/gocdb.go +++ b/pkg/mentix/connectors/gocdb.go @@ -127,8 +127,10 @@ func (connector *GOCDBConnector) querySites(meshData *meshdata.MeshData) error { for _, site := range sites.Sites { properties := connector.extensionsToMap(&site.Extensions) - // Sites coming from the GOCDB are always authorized - properties[strings.ToUpper(meshdata.PropertyAuthorized)] = "true" + // Sites coming from the GOCDB are always authorized by default + if value := meshdata.GetPropertyValue(properties, meshdata.PropertyAuthorized, ""); len(value) == 0 { + meshdata.SetPropertyValue(properties, meshdata.PropertyAuthorized, "true") + } // See if an organization has been defined using properties; otherwise, use the official name organization := meshdata.GetPropertyValue(properties, meshdata.PropertyOrganization, site.OfficialName) diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index 15918375e3..0a8de0b524 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -93,8 +93,21 @@ func (connector *LocalFileConnector) UpdateMeshData(updatedData *meshdata.MeshDa // Remove data by unmerging meshData.Unmerge(updatedData) } else { + // Store the previous authorization status for already existing sites + siteAuthorizationStatus := make(map[string]string) + for _, site := range meshData.Sites { + siteAuthorizationStatus[site.GetID()] = meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + } + // Add/update data by merging meshData.Merge(updatedData) + + // Restore the authorization status for all sites + for siteID, status := range siteAuthorizationStatus { + if site := meshData.FindSite(siteID); site != nil { + meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, status) + } + } } // Write the updated sites back to the file diff --git a/pkg/mentix/exchangers/importers/reqimporter.go b/pkg/mentix/exchangers/importers/reqimporter.go index 1f4d4767bf..f8c49bcc66 100644 --- a/pkg/mentix/exchangers/importers/reqimporter.go +++ b/pkg/mentix/exchangers/importers/reqimporter.go @@ -50,7 +50,9 @@ func (importer *BaseRequestImporter) HandleRequest(resp http.ResponseWriter, req body, _ := ioutil.ReadAll(req.Body) meshData, status, respData, err := importer.handleQuery(body, req.URL.Query()) if err == nil { - importer.mergeImportedMeshData(meshData) + if len(meshData) > 0 { + importer.mergeImportedMeshData(meshData) + } } else { respData = []byte(err.Error()) } diff --git a/pkg/mentix/exchangers/importers/webapi/query.go b/pkg/mentix/exchangers/importers/webapi/query.go index f4743b2abd..b015b141d8 100755 --- a/pkg/mentix/exchangers/importers/webapi/query.go +++ b/pkg/mentix/exchangers/importers/webapi/query.go @@ -23,7 +23,6 @@ import ( "fmt" "net/http" "net/url" - "strings" "github.com/cs3org/reva/pkg/mentix/meshdata" "github.com/cs3org/reva/pkg/mentix/network" @@ -35,16 +34,14 @@ func decodeQueryData(data []byte) (*meshdata.MeshData, error) { return nil, err } + // Set sites imported through the WebAPI to 'unauthorized' by default + meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + meshData := &meshdata.MeshData{Sites: []*meshdata.Site{site}} if err := meshData.Verify(); err != nil { return nil, fmt.Errorf("verifying the imported mesh data failed: %v", err) } - // Set sites imported through the WebAPI to 'unauthorized' by default - for _, site := range meshData.Sites { - site.Properties[strings.ToUpper(meshdata.PropertyAuthorized)] = "false" - } - meshData.InferMissingData() return meshData, nil } diff --git a/pkg/mentix/meshdata/properties.go b/pkg/mentix/meshdata/properties.go index 6675b2f997..7339d1796c 100644 --- a/pkg/mentix/meshdata/properties.go +++ b/pkg/mentix/meshdata/properties.go @@ -21,7 +21,7 @@ package meshdata import "strings" const ( - // ProperyAuthorized identifies the authorization status property. + // PropertyAuthorized identifies the authorization status property. PropertyAuthorized = "authorized" // PropertyOrganization identifies the organization property. PropertyOrganization = "organization" @@ -45,3 +45,8 @@ func GetPropertyValue(props map[string]string, id string, defValue string) strin return defValue } + +// SetPropertyValue sets a property value. +func SetPropertyValue(props map[string]string, id string, value string) { + props[strings.ToUpper(id)] = value +} From 46b2d5335f07f157d533e887bd14b6c8edf660ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 16:48:53 +0100 Subject: [PATCH 09/20] Admin API for site authorization --- internal/http/services/mentix/mentix.go | 28 +++++-- pkg/mentix/config/config.go | 10 +++ pkg/mentix/config/ids.go | 2 + pkg/mentix/connectors/localfile.go | 70 +++++++++++++----- pkg/mentix/exchangers/exporters/cs3api.go | 2 +- .../exchangers/exporters/sitelocations.go | 2 +- pkg/mentix/exchangers/exporters/webapi.go | 2 +- pkg/mentix/exchangers/importers/adminapi.go | 60 +++++++++++++++ .../exchangers/importers/adminapi/query.go | 73 +++++++++++++++++++ .../exchangers/importers/reqimporter.go | 11 ++- pkg/mentix/exchangers/importers/webapi.go | 16 ++-- .../exchangers/importers/webapi/query.go | 8 +- pkg/mentix/exchangers/reqexchanger.go | 15 +++- pkg/mentix/meshdata/meshdata.go | 18 +++-- 14 files changed, 265 insertions(+), 52 deletions(-) create mode 100755 pkg/mentix/exchangers/importers/adminapi.go create mode 100755 pkg/mentix/exchangers/importers/adminapi/query.go diff --git a/internal/http/services/mentix/mentix.go b/internal/http/services/mentix/mentix.go index 51d8323ef5..4eed621baa 100644 --- a/internal/http/services/mentix/mentix.go +++ b/internal/http/services/mentix/mentix.go @@ -27,6 +27,7 @@ import ( "github.com/cs3org/reva/pkg/mentix" "github.com/cs3org/reva/pkg/mentix/config" + "github.com/cs3org/reva/pkg/mentix/exchangers" "github.com/cs3org/reva/pkg/rhttp/global" ) @@ -63,13 +64,20 @@ func (s *svc) Unprotected() []string { importers := s.mntx.GetRequestImporters() exporters := s.mntx.GetRequestExporters() - endpoints := make([]string, len(importers)+len(exporters)) - for idx, importer := range importers { - endpoints[idx] = importer.Endpoint() - } - for idx, exporter := range exporters { - endpoints[idx] = exporter.Endpoint() + getEndpoints := func(exchangers []exchangers.RequestExchanger) []string { + endpoints := make([]string, 0, len(exchangers)) + for _, exchanger := range exchangers { + if !exchanger.IsProtectedEndpoint() { + endpoints = append(endpoints, exchanger.Endpoint()) + } + } + return endpoints } + + endpoints := make([]string, 0, len(importers)+len(exporters)) + endpoints = append(endpoints, getEndpoints(importers)...) + endpoints = append(endpoints, getEndpoints(exporters)...) + return endpoints } @@ -130,7 +138,11 @@ func applyDefaultConfig(conf *config.Configuration) { // Importers if conf.Importers.WebAPI.Endpoint == "" { - conf.Importers.WebAPI.Endpoint = "/" + conf.Importers.WebAPI.Endpoint = "/sites" + } + + if conf.Importers.AdminAPI.Endpoint == "" { + conf.Importers.AdminAPI.Endpoint = "/admin" } // Exporters @@ -141,7 +153,7 @@ func applyDefaultConfig(conf *config.Configuration) { } if conf.Exporters.WebAPI.Endpoint == "" { - conf.Exporters.WebAPI.Endpoint = "/" + conf.Exporters.WebAPI.Endpoint = "/sites" } addDefaultConnector(&conf.Exporters.WebAPI.EnabledConnectors) diff --git a/pkg/mentix/config/config.go b/pkg/mentix/config/config.go index f43c4e6dfd..7fb38e7ea1 100644 --- a/pkg/mentix/config/config.go +++ b/pkg/mentix/config/config.go @@ -38,23 +38,33 @@ type Configuration struct { Importers struct { WebAPI struct { Endpoint string `mapstructure:"endpoint"` + IsProtected bool `mapstructure:"is_protected"` EnabledConnectors []string `mapstructure:"enabled_connectors"` } `mapstructure:"webapi"` + + AdminAPI struct { + Endpoint string `mapstructure:"endpoint"` + IsProtected bool `mapstructure:"is_protected"` + EnabledConnectors []string `mapstructure:"enabled_connectors"` + } `mapstructure:"adminapi"` } `mapstructure:"importers"` Exporters struct { WebAPI struct { Endpoint string `mapstructure:"endpoint"` + IsProtected bool `mapstructure:"is_protected"` EnabledConnectors []string `mapstructure:"enabled_connectors"` } `mapstructure:"webapi"` CS3API struct { Endpoint string `mapstructure:"endpoint"` + IsProtected bool `mapstructure:"is_protected"` EnabledConnectors []string `mapstructure:"enabled_connectors"` } `mapstructure:"cs3api"` SiteLocations struct { Endpoint string `mapstructure:"endpoint"` + IsProtected bool `mapstructure:"is_protected"` EnabledConnectors []string `mapstructure:"enabled_connectors"` } `mapstructure:"siteloc"` diff --git a/pkg/mentix/config/ids.go b/pkg/mentix/config/ids.go index 979c60885f..a49c242209 100644 --- a/pkg/mentix/config/ids.go +++ b/pkg/mentix/config/ids.go @@ -28,6 +28,8 @@ const ( const ( // ImporterIDWebAPI is the identifier for the WebAPI importer. ImporterIDWebAPI = "webapi" + // ImporterIDAdminAPI is the identifier for the AdminAPI importer. + ImporterIDAdminAPI = "adminapi" ) const ( diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index 0a8de0b524..c6d5b39b54 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -89,25 +89,19 @@ func (connector *LocalFileConnector) UpdateMeshData(updatedData *meshdata.MeshDa meshData = &meshdata.MeshData{} } - if (updatedData.Flags & meshdata.FlagObsolete) == meshdata.FlagObsolete { - // Remove data by unmerging - meshData.Unmerge(updatedData) - } else { - // Store the previous authorization status for already existing sites - siteAuthorizationStatus := make(map[string]string) - for _, site := range meshData.Sites { - siteAuthorizationStatus[site.GetID()] = meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") - } + err = nil + switch updatedData.Status { + case meshdata.StatusDefault: + err = connector.mergeData(meshData, updatedData) - // Add/update data by merging - meshData.Merge(updatedData) + case meshdata.StatusObsolete: + err = connector.unmergeData(meshData, updatedData) - // Restore the authorization status for all sites - for siteID, status := range siteAuthorizationStatus { - if site := meshData.FindSite(siteID); site != nil { - meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, status) - } - } + case meshdata.StatusAuthorize: + err = connector.authorizeData(meshData, updatedData, true) + + case meshdata.StatusUnauthorize: + err = connector.authorizeData(meshData, updatedData, false) } // Write the updated sites back to the file @@ -119,6 +113,48 @@ func (connector *LocalFileConnector) UpdateMeshData(updatedData *meshdata.MeshDa return nil } +func (connector *LocalFileConnector) mergeData(meshData *meshdata.MeshData, updatedData *meshdata.MeshData) error { + // Store the previous authorization status for already existing sites + siteAuthorizationStatus := make(map[string]string) + for _, site := range meshData.Sites { + siteAuthorizationStatus[site.GetID()] = meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + } + + // Add/update data by merging + meshData.Merge(updatedData) + + // Restore the authorization status for all sites + for siteID, status := range siteAuthorizationStatus { + if site := meshData.FindSite(siteID); site != nil { + meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, status) + } + } + return nil +} + +func (connector *LocalFileConnector) unmergeData(meshData *meshdata.MeshData, updatedData *meshdata.MeshData) error { + // Remove data by unmerging + meshData.Unmerge(updatedData) + return nil +} + +func (connector *LocalFileConnector) authorizeData(meshData *meshdata.MeshData, updatedData *meshdata.MeshData, authorize bool) error { + for _, placeholderSite := range updatedData.Sites { + // The site ID is stored in the updated site's name + if site := meshData.FindSite(placeholderSite.Name); site != nil { + if authorize { + meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "true") + } else { + meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + } + } else { + return fmt.Errorf("no site with id '%v' found", placeholderSite.Name) + } + } + + return nil +} + func (connector *LocalFileConnector) setSiteTypes(meshData *meshdata.MeshData) { for _, site := range meshData.Sites { site.Type = meshdata.SiteTypeCommunity // Sites coming from a local file are always community sites diff --git a/pkg/mentix/exchangers/exporters/cs3api.go b/pkg/mentix/exchangers/exporters/cs3api.go index 849de25591..b224eadc65 100755 --- a/pkg/mentix/exchangers/exporters/cs3api.go +++ b/pkg/mentix/exchangers/exporters/cs3api.go @@ -37,7 +37,7 @@ func (exporter *CS3APIExporter) Activate(conf *config.Configuration, log *zerolo } // Store CS3API specifics - exporter.SetEndpoint(conf.Exporters.CS3API.Endpoint) + exporter.SetEndpoint(conf.Exporters.CS3API.Endpoint, conf.Exporters.CS3API.IsProtected) exporter.SetEnabledConnectors(conf.Exporters.CS3API.EnabledConnectors) exporter.defaultActionHandler = cs3api.HandleDefaultQuery diff --git a/pkg/mentix/exchangers/exporters/sitelocations.go b/pkg/mentix/exchangers/exporters/sitelocations.go index fffd6325c1..33ad4c838c 100755 --- a/pkg/mentix/exchangers/exporters/sitelocations.go +++ b/pkg/mentix/exchangers/exporters/sitelocations.go @@ -37,7 +37,7 @@ func (exporter *SiteLocationsExporter) Activate(conf *config.Configuration, log } // Store SiteLocations specifics - exporter.SetEndpoint(conf.Exporters.SiteLocations.Endpoint) + exporter.SetEndpoint(conf.Exporters.SiteLocations.Endpoint, conf.Exporters.SiteLocations.IsProtected) exporter.SetEnabledConnectors(conf.Exporters.SiteLocations.EnabledConnectors) exporter.defaultActionHandler = siteloc.HandleDefaultQuery diff --git a/pkg/mentix/exchangers/exporters/webapi.go b/pkg/mentix/exchangers/exporters/webapi.go index 346cc10907..36cdeabed2 100755 --- a/pkg/mentix/exchangers/exporters/webapi.go +++ b/pkg/mentix/exchangers/exporters/webapi.go @@ -37,7 +37,7 @@ func (exporter *WebAPIExporter) Activate(conf *config.Configuration, log *zerolo } // Store WebAPI specifics - exporter.SetEndpoint(conf.Exporters.WebAPI.Endpoint) + exporter.SetEndpoint(conf.Exporters.WebAPI.Endpoint, conf.Exporters.WebAPI.IsProtected) exporter.SetEnabledConnectors(conf.Exporters.WebAPI.EnabledConnectors) exporter.defaultActionHandler = webapi.HandleDefaultQuery diff --git a/pkg/mentix/exchangers/importers/adminapi.go b/pkg/mentix/exchangers/importers/adminapi.go new file mode 100755 index 0000000000..53ee50748b --- /dev/null +++ b/pkg/mentix/exchangers/importers/adminapi.go @@ -0,0 +1,60 @@ +// Copyright 2018-2020 CERN +// +// Licensed 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. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package importers + +import ( + "github.com/rs/zerolog" + + "github.com/cs3org/reva/pkg/mentix/config" + "github.com/cs3org/reva/pkg/mentix/exchangers/importers/adminapi" +) + +// AdminAPIImporter implements the administrative API importer. +type AdminAPIImporter struct { + BaseRequestImporter +} + +// Activate activates the importer. +func (importer *AdminAPIImporter) Activate(conf *config.Configuration, log *zerolog.Logger) error { + if err := importer.BaseRequestImporter.Activate(conf, log); err != nil { + return err + } + + // Store AdminAPI specifics + importer.SetEndpoint(conf.Importers.AdminAPI.Endpoint, conf.Importers.AdminAPI.IsProtected) + importer.SetEnabledConnectors(conf.Importers.AdminAPI.EnabledConnectors) + + importer.authorizeSiteActionHandler = adminapi.HandleAuthorizeSiteQuery + + return nil +} + +// GetID returns the ID of the importer. +func (importer *AdminAPIImporter) GetID() string { + return config.ImporterIDAdminAPI +} + +// GetName returns the display name of the importer. +func (importer *AdminAPIImporter) GetName() string { + return "AdminAPI" +} + +func init() { + registerImporter(&AdminAPIImporter{}) +} diff --git a/pkg/mentix/exchangers/importers/adminapi/query.go b/pkg/mentix/exchangers/importers/adminapi/query.go new file mode 100755 index 0000000000..f98902c594 --- /dev/null +++ b/pkg/mentix/exchangers/importers/adminapi/query.go @@ -0,0 +1,73 @@ +// Copyright 2018-2020 CERN +// +// Licensed 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. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package adminapi + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/cs3org/reva/pkg/mentix/meshdata" + "github.com/cs3org/reva/pkg/mentix/network" +) + +func decodeAdminQueryData(data []byte) (*meshdata.MeshData, error) { + jsonData := make(map[string]interface{}) + if err := json.Unmarshal(data, &jsonData); err != nil { + return nil, err + } + + if value, ok := jsonData["id"]; ok { + if id, ok := value.(string); ok { + site := &meshdata.Site{} + site.Name = id // Store the provided site ID in the site's name + + meshData := &meshdata.MeshData{Sites: []*meshdata.Site{site}} + return meshData, nil + } else { + return nil, fmt.Errorf("site id invalid") + } + } else { + return nil, fmt.Errorf("site id missing") + } +} + +func handleAdminQuery(data []byte, params url.Values, status int, msg string) (meshdata.Vector, int, []byte, error) { + meshData, err := decodeAdminQueryData(data) + if err != nil { + return nil, http.StatusBadRequest, network.CreateResponse("INVALID_DATA", network.ResponseParams{"error": err.Error()}), nil + } + meshData.Status = status + return meshdata.Vector{meshData}, http.StatusOK, network.CreateResponse(msg, network.ResponseParams{"id": meshData.Sites[0].Name}), nil +} + +// HandleAuthorizeSiteQuery sets the authorization status of a site. +func HandleAuthorizeSiteQuery(data []byte, params url.Values) (meshdata.Vector, int, []byte, error) { + status := params.Get("status") + + if strings.EqualFold(status, "true") { + return handleAdminQuery(data, params, meshdata.StatusAuthorize, "SITE_AUTHORIZED") + } else if strings.EqualFold(status, "false") { + return handleAdminQuery(data, params, meshdata.StatusUnauthorize, "SITE_UNAUTHORIZED") + } + + return nil, http.StatusBadRequest, network.CreateResponse("INVALID_QUERY", network.ResponseParams{}), nil +} diff --git a/pkg/mentix/exchangers/importers/reqimporter.go b/pkg/mentix/exchangers/importers/reqimporter.go index f8c49bcc66..ae4c6c7d65 100644 --- a/pkg/mentix/exchangers/importers/reqimporter.go +++ b/pkg/mentix/exchangers/importers/reqimporter.go @@ -32,6 +32,7 @@ import ( const ( queryActionRegisterSite = "register" queryActionUnregisterSite = "unregister" + queryActionAuthorizeSite = "authorize" ) type queryCallback func([]byte, url.Values) (meshdata.Vector, int, []byte, error) @@ -43,12 +44,13 @@ type BaseRequestImporter struct { registerSiteActionHandler queryCallback unregisterSiteActionHandler queryCallback + authorizeSiteActionHandler queryCallback } // HandleRequest handles the actual HTTP request. func (importer *BaseRequestImporter) HandleRequest(resp http.ResponseWriter, req *http.Request) { body, _ := ioutil.ReadAll(req.Body) - meshData, status, respData, err := importer.handleQuery(body, req.URL.Query()) + meshData, status, respData, err := importer.handleQuery(body, req.URL.Path, req.URL.Query()) if err == nil { if len(meshData) > 0 { importer.mergeImportedMeshData(meshData) @@ -73,7 +75,7 @@ func (importer *BaseRequestImporter) mergeImportedMeshData(meshData meshdata.Vec } } -func (importer *BaseRequestImporter) handleQuery(data []byte, params url.Values) (meshdata.Vector, int, []byte, error) { +func (importer *BaseRequestImporter) handleQuery(data []byte, path string, params url.Values) (meshdata.Vector, int, []byte, error) { action := params.Get("action") switch strings.ToLower(action) { case queryActionRegisterSite: @@ -86,6 +88,11 @@ func (importer *BaseRequestImporter) handleQuery(data []byte, params url.Values) return importer.unregisterSiteActionHandler(data, params) } + case queryActionAuthorizeSite: + if importer.authorizeSiteActionHandler != nil { + return importer.authorizeSiteActionHandler(data, params) + } + default: return nil, http.StatusNotImplemented, []byte{}, fmt.Errorf("unknown action '%v'", action) } diff --git a/pkg/mentix/exchangers/importers/webapi.go b/pkg/mentix/exchangers/importers/webapi.go index ac42fd0750..1a542d59ad 100755 --- a/pkg/mentix/exchangers/importers/webapi.go +++ b/pkg/mentix/exchangers/importers/webapi.go @@ -31,28 +31,28 @@ type WebAPIImporter struct { } // Activate activates the importer. -func (exporter *WebAPIImporter) Activate(conf *config.Configuration, log *zerolog.Logger) error { - if err := exporter.BaseRequestImporter.Activate(conf, log); err != nil { +func (importer *WebAPIImporter) Activate(conf *config.Configuration, log *zerolog.Logger) error { + if err := importer.BaseRequestImporter.Activate(conf, log); err != nil { return err } // Store WebAPI specifics - exporter.SetEndpoint(conf.Importers.WebAPI.Endpoint) - exporter.SetEnabledConnectors(conf.Importers.WebAPI.EnabledConnectors) + importer.SetEndpoint(conf.Importers.WebAPI.Endpoint, conf.Importers.WebAPI.IsProtected) + importer.SetEnabledConnectors(conf.Importers.WebAPI.EnabledConnectors) - exporter.registerSiteActionHandler = webapi.HandleRegisterSiteQuery - exporter.unregisterSiteActionHandler = webapi.HandleUnregisterSiteQuery + importer.registerSiteActionHandler = webapi.HandleRegisterSiteQuery + importer.unregisterSiteActionHandler = webapi.HandleUnregisterSiteQuery return nil } // GetID returns the ID of the importer. -func (exporter *WebAPIImporter) GetID() string { +func (importer *WebAPIImporter) GetID() string { return config.ImporterIDWebAPI } // GetName returns the display name of the importer. -func (exporter *WebAPIImporter) GetName() string { +func (importer *WebAPIImporter) GetName() string { return "WebAPI" } diff --git a/pkg/mentix/exchangers/importers/webapi/query.go b/pkg/mentix/exchangers/importers/webapi/query.go index b015b141d8..9929ce7881 100755 --- a/pkg/mentix/exchangers/importers/webapi/query.go +++ b/pkg/mentix/exchangers/importers/webapi/query.go @@ -46,21 +46,21 @@ func decodeQueryData(data []byte) (*meshdata.MeshData, error) { return meshData, nil } -func handleQuery(data []byte, params url.Values, flags int32, msg string) (meshdata.Vector, int, []byte, error) { +func handleQuery(data []byte, params url.Values, status int, msg string) (meshdata.Vector, int, []byte, error) { meshData, err := decodeQueryData(data) if err != nil { return nil, http.StatusBadRequest, network.CreateResponse("INVALID_DATA", network.ResponseParams{"error": err.Error()}), nil } - meshData.Flags = flags + meshData.Status = status return meshdata.Vector{meshData}, http.StatusOK, network.CreateResponse(msg, network.ResponseParams{"id": meshData.Sites[0].GetID()}), nil } // HandleRegisterSiteQuery registers a site. func HandleRegisterSiteQuery(data []byte, params url.Values) (meshdata.Vector, int, []byte, error) { - return handleQuery(data, params, meshdata.FlagsNone, "SITE_REGISTERED") + return handleQuery(data, params, meshdata.StatusDefault, "SITE_REGISTERED") } // HandleUnregisterSiteQuery unregisters a site. func HandleUnregisterSiteQuery(data []byte, params url.Values) (meshdata.Vector, int, []byte, error) { - return handleQuery(data, params, meshdata.FlagObsolete, "SITE_UNREGISTERED") + return handleQuery(data, params, meshdata.StatusObsolete, "SITE_UNREGISTERED") } diff --git a/pkg/mentix/exchangers/reqexchanger.go b/pkg/mentix/exchangers/reqexchanger.go index c8cd381655..fcbb4daf80 100644 --- a/pkg/mentix/exchangers/reqexchanger.go +++ b/pkg/mentix/exchangers/reqexchanger.go @@ -27,6 +27,8 @@ import ( type RequestExchanger interface { // Endpoint returns the (relative) endpoint of the exchanger. Endpoint() string + // IsProtectedEndpoint returns true if the endpoint can only be accessed with authorization. + IsProtectedEndpoint() bool // WantsRequest returns whether the exchanger wants to handle the incoming request. WantsRequest(r *http.Request) bool // HandleRequest handles the actual HTTP request. @@ -37,7 +39,8 @@ type RequestExchanger interface { type BaseRequestExchanger struct { RequestExchanger - endpoint string + endpoint string + isProtectedEndpoint bool } // Endpoint returns the (relative) endpoint of the exchanger. @@ -50,12 +53,18 @@ func (exchanger *BaseRequestExchanger) Endpoint() string { return strings.TrimSpace(endpoint) } +// IsProtectedEndpoint returns true if the endpoint can only be accessed with authorization. +func (exchanger *BaseRequestExchanger) IsProtectedEndpoint() bool { + return exchanger.isProtectedEndpoint +} + // SetEndpoint sets the (relative) endpoint of the exchanger. -func (exchanger *BaseRequestExchanger) SetEndpoint(endpoint string) { +func (exchanger *BaseRequestExchanger) SetEndpoint(endpoint string, isProtected bool) { exchanger.endpoint = endpoint + exchanger.isProtectedEndpoint = isProtected } -// WantsRequest returns whether the exporter wants to handle the incoming request. +// WantsRequest returns whether the exchanger wants to handle the incoming request. func (exchanger *BaseRequestExchanger) WantsRequest(r *http.Request) bool { return r.URL.Path == exchanger.Endpoint() } diff --git a/pkg/mentix/meshdata/meshdata.go b/pkg/mentix/meshdata/meshdata.go index 5162dab859..83f5344a33 100644 --- a/pkg/mentix/meshdata/meshdata.go +++ b/pkg/mentix/meshdata/meshdata.go @@ -25,11 +25,15 @@ import ( ) const ( - // FlagsNone resets all mesh data flags. - FlagsNone = 0 - - // FlagObsolete flags the mesh data for removal. - FlagObsolete = 0x0001 + // StatusDefault signals that this is just regular data. + StatusDefault = iota + + // StatusObsolete flags the mesh data for removal. + StatusObsolete + // StatusAuthorize flags the mesh data for authorization. + StatusAuthorize + // StatusUnauthorize flags the mesh data for unauthorization. + StatusUnauthorize ) // MeshData holds the entire mesh data managed by Mentix. @@ -37,7 +41,7 @@ type MeshData struct { Sites []*Site ServiceTypes []*ServiceType - Flags int32 `json:"-"` + Status int `json:"-"` } // Clear removes all saved data, leaving an empty mesh. @@ -45,7 +49,7 @@ func (meshData *MeshData) Clear() { meshData.Sites = nil meshData.ServiceTypes = nil - meshData.Flags = FlagsNone + meshData.Status = StatusDefault } // AddSite adds a new site; if a site with the same ID already exists, the existing one is overwritten. From c3e082e8f92e388b02c10dc393c7b5bc87bf803c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 16:52:13 +0100 Subject: [PATCH 10/20] Update changelog --- changelog/unreleased/mentix-prom-scheme.md | 5 ----- changelog/unreleased/mentix-site-auth.md | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) delete mode 100644 changelog/unreleased/mentix-prom-scheme.md create mode 100644 changelog/unreleased/mentix-site-auth.md diff --git a/changelog/unreleased/mentix-prom-scheme.md b/changelog/unreleased/mentix-prom-scheme.md deleted file mode 100644 index 8c33586ca0..0000000000 --- a/changelog/unreleased/mentix-prom-scheme.md +++ /dev/null @@ -1,5 +0,0 @@ -Enhancement: Set scheme for Prometheus targets in Mentix - -This enhancement lets Mentix set the scheme for Prometheus targets. This allows us to also support monitoring of sites that do not support the default HTTPS scheme. - -https://github.com/cs3org/reva/pull/1398 diff --git a/changelog/unreleased/mentix-site-auth.md b/changelog/unreleased/mentix-site-auth.md new file mode 100644 index 0000000000..22372c181a --- /dev/null +++ b/changelog/unreleased/mentix-site-auth.md @@ -0,0 +1,7 @@ +Enhancement: Support site authorization status in Mentix + +This enhancement adds support for a site authorization status to Mentix. This way, sites registered via a web app can now be excluded until authorized manually by an administrator. + +Furthermore, Mentix now sets the scheme for Prometheus targets. This allows us to also support monitoring of sites that do not support the default HTTPS scheme. + +https://github.com/cs3org/reva/pull/1398 From 63836d1941812ad94eb04dca5b0fd167db45966d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 16:54:33 +0100 Subject: [PATCH 11/20] Hound fix --- pkg/mentix/exchangers/importers/adminapi/query.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/mentix/exchangers/importers/adminapi/query.go b/pkg/mentix/exchangers/importers/adminapi/query.go index f98902c594..ede43f9f27 100755 --- a/pkg/mentix/exchangers/importers/adminapi/query.go +++ b/pkg/mentix/exchangers/importers/adminapi/query.go @@ -45,9 +45,9 @@ func decodeAdminQueryData(data []byte) (*meshdata.MeshData, error) { } else { return nil, fmt.Errorf("site id invalid") } - } else { - return nil, fmt.Errorf("site id missing") } + + return nil, fmt.Errorf("site id missing") } func handleAdminQuery(data []byte, params url.Values, status int, msg string) (meshdata.Vector, int, []byte, error) { From c39ee4f9562510b3edaa2bb262cd0b6d3d5bc3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 16:55:23 +0100 Subject: [PATCH 12/20] Hound fix --- pkg/mentix/exchangers/importers/adminapi/query.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/mentix/exchangers/importers/adminapi/query.go b/pkg/mentix/exchangers/importers/adminapi/query.go index ede43f9f27..36c2265849 100755 --- a/pkg/mentix/exchangers/importers/adminapi/query.go +++ b/pkg/mentix/exchangers/importers/adminapi/query.go @@ -42,9 +42,9 @@ func decodeAdminQueryData(data []byte) (*meshdata.MeshData, error) { meshData := &meshdata.MeshData{Sites: []*meshdata.Site{site}} return meshData, nil - } else { - return nil, fmt.Errorf("site id invalid") } + + return nil, fmt.Errorf("site id invalid") } return nil, fmt.Errorf("site id missing") From 0fe77e731f56db478dbd16a4a5296e93ee55b144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Jan 2021 17:11:37 +0100 Subject: [PATCH 13/20] Missing error check --- pkg/mentix/connectors/localfile.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index c6d5b39b54..7642e1897e 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -104,6 +104,10 @@ func (connector *LocalFileConnector) UpdateMeshData(updatedData *meshdata.MeshDa err = connector.authorizeData(meshData, updatedData, false) } + if err != nil { + return err + } + // Write the updated sites back to the file jsonData, _ := json.MarshalIndent(meshData.Sites, "", "\t") if err := ioutil.WriteFile(connector.filePath, jsonData, 0755); err != nil { From 990af828a1e099ec1df6bbc3e89c0b11e2105fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 18 Jan 2021 15:47:10 +0100 Subject: [PATCH 14/20] Expose site ID --- pkg/mentix/connectors/gocdb.go | 1 + pkg/mentix/connectors/localfile.go | 3 ++- pkg/mentix/exchangers/exporters/promsd.go | 2 +- pkg/mentix/exchangers/exporters/webapi.go | 2 ++ pkg/mentix/exchangers/importers/webapi/query.go | 5 ++++- pkg/mentix/meshdata/meshdata.go | 6 +++--- pkg/mentix/meshdata/site.go | 12 +++++++++--- 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/pkg/mentix/connectors/gocdb.go b/pkg/mentix/connectors/gocdb.go index 425af0525e..8b008ec124 100755 --- a/pkg/mentix/connectors/gocdb.go +++ b/pkg/mentix/connectors/gocdb.go @@ -75,6 +75,7 @@ func (connector *GOCDBConnector) RetrieveMeshData() (*meshdata.MeshData, error) } } + meshData.InferMissingData() return meshData, nil } diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index 7642e1897e..1cfeae7ae5 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -78,6 +78,7 @@ func (connector *LocalFileConnector) RetrieveMeshData() (*meshdata.MeshData, err // Update the site types, as these are not part of the JSON data connector.setSiteTypes(meshData) + meshData.InferMissingData() return meshData, nil } @@ -121,7 +122,7 @@ func (connector *LocalFileConnector) mergeData(meshData *meshdata.MeshData, upda // Store the previous authorization status for already existing sites siteAuthorizationStatus := make(map[string]string) for _, site := range meshData.Sites { - siteAuthorizationStatus[site.GetID()] = meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + siteAuthorizationStatus[site.ID] = meshdata.GetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") } // Add/update data by merging diff --git a/pkg/mentix/exchangers/exporters/promsd.go b/pkg/mentix/exchangers/exporters/promsd.go index e8b4746ea2..0cb1fba4c8 100755 --- a/pkg/mentix/exchangers/exporters/promsd.go +++ b/pkg/mentix/exchangers/exporters/promsd.go @@ -96,7 +96,7 @@ func getScrapeTargetLabels(site *meshdata.Site, host string, endpoint *meshdata. labels := map[string]string{ "__meta_mentix_site": site.Name, "__meta_mentix_site_type": meshdata.GetSiteTypeName(site.Type), - "__meta_mentix_site_id": site.GetID(), + "__meta_mentix_site_id": site.ID, "__meta_mentix_host": host, "__meta_mentix_country": site.CountryCode, "__meta_mentix_service_type": endpoint.Type.Name, diff --git a/pkg/mentix/exchangers/exporters/webapi.go b/pkg/mentix/exchangers/exporters/webapi.go index 36cdeabed2..30f2b18bd6 100755 --- a/pkg/mentix/exchangers/exporters/webapi.go +++ b/pkg/mentix/exchangers/exporters/webapi.go @@ -40,6 +40,8 @@ func (exporter *WebAPIExporter) Activate(conf *config.Configuration, log *zerolo exporter.SetEndpoint(conf.Exporters.WebAPI.Endpoint, conf.Exporters.WebAPI.IsProtected) exporter.SetEnabledConnectors(conf.Exporters.WebAPI.EnabledConnectors) + exporter.allowUnauthorizedSites = true + exporter.defaultActionHandler = webapi.HandleDefaultQuery return nil diff --git a/pkg/mentix/exchangers/importers/webapi/query.go b/pkg/mentix/exchangers/importers/webapi/query.go index 9929ce7881..189bb849ef 100755 --- a/pkg/mentix/exchangers/importers/webapi/query.go +++ b/pkg/mentix/exchangers/importers/webapi/query.go @@ -34,6 +34,9 @@ func decodeQueryData(data []byte) (*meshdata.MeshData, error) { return nil, err } + // Imported sites will be assigned an ID automatically + site.ID = "" + // Set sites imported through the WebAPI to 'unauthorized' by default meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") @@ -52,7 +55,7 @@ func handleQuery(data []byte, params url.Values, status int, msg string) (meshda return nil, http.StatusBadRequest, network.CreateResponse("INVALID_DATA", network.ResponseParams{"error": err.Error()}), nil } meshData.Status = status - return meshdata.Vector{meshData}, http.StatusOK, network.CreateResponse(msg, network.ResponseParams{"id": meshData.Sites[0].GetID()}), nil + return meshdata.Vector{meshData}, http.StatusOK, network.CreateResponse(msg, network.ResponseParams{"id": meshData.Sites[0].ID}), nil } // HandleRegisterSiteQuery registers a site. diff --git a/pkg/mentix/meshdata/meshdata.go b/pkg/mentix/meshdata/meshdata.go index 83f5344a33..40832c503f 100644 --- a/pkg/mentix/meshdata/meshdata.go +++ b/pkg/mentix/meshdata/meshdata.go @@ -54,7 +54,7 @@ func (meshData *MeshData) Clear() { // AddSite adds a new site; if a site with the same ID already exists, the existing one is overwritten. func (meshData *MeshData) AddSite(site *Site) { - if siteExisting := meshData.FindSite(site.GetID()); siteExisting != nil { + if siteExisting := meshData.FindSite(site.ID); siteExisting != nil { *siteExisting = *site } else { meshData.Sites = append(meshData.Sites, site) @@ -79,7 +79,7 @@ func (meshData *MeshData) RemoveSite(id string) { // FindSite searches for a site with the given ID. func (meshData *MeshData) FindSite(id string) *Site { for _, site := range meshData.Sites { - if strings.EqualFold(site.GetID(), id) { + if strings.EqualFold(site.ID, id) { return site } } @@ -134,7 +134,7 @@ func (meshData *MeshData) Merge(inData *MeshData) { // Unmerge removes data from another MeshData instance from this one. func (meshData *MeshData) Unmerge(inData *MeshData) { for _, site := range inData.Sites { - meshData.RemoveSite(site.GetID()) + meshData.RemoveSite(site.ID) } for _, serviceType := range inData.ServiceTypes { diff --git a/pkg/mentix/meshdata/site.go b/pkg/mentix/meshdata/site.go index 7fd5c5d120..da6ffce2d6 100644 --- a/pkg/mentix/meshdata/site.go +++ b/pkg/mentix/meshdata/site.go @@ -40,6 +40,7 @@ type SiteType int type Site struct { Type SiteType `json:"-"` + ID string Name string FullName string Organization string @@ -122,15 +123,20 @@ func (site *Site) InferMissingData() { } } + // Automatically assign an ID to this site if it is missing + if len(site.ID) == 0 { + site.GenerateID() + } + // Infer missing for services for _, service := range site.Services { service.InferMissingData() } } -// GetID generates a unique ID for the site; the following fields are used for this: +// GenerateID generates a unique ID for the site; the following fields are used for this: // Name, Domain -func (site *Site) GetID() string { +func (site *Site) GenerateID() { host := site.Domain if site.Homepage != "" { if hostURL, err := url.Parse(site.Homepage); err == nil { @@ -138,7 +144,7 @@ func (site *Site) GetID() string { } } - return fmt.Sprintf("%s::[%s]", host, site.Name) + site.ID = fmt.Sprintf("%s::[%s]", host, site.Name) } // GetSiteTypeName returns the readable name of the given site type. From 177b3bf0971dc5e9371397c99e8320e84744e287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 18 Jan 2021 15:55:12 +0100 Subject: [PATCH 15/20] Update documentation and example --- .../config/http/services/mentix/_index.md | 3 ++ .../http/services/mentix/adminapi/_index.md | 46 +++++++++++++++++++ .../http/services/mentix/cs3api/_index.md | 10 +++- .../http/services/mentix/siteloc/_index.md | 10 +++- .../http/services/mentix/webapi/_index.md | 20 +++++++- examples/mentix/mentix.toml | 6 +++ 6 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 docs/content/en/docs/config/http/services/mentix/adminapi/_index.md diff --git a/docs/content/en/docs/config/http/services/mentix/_index.md b/docs/content/en/docs/config/http/services/mentix/_index.md index 0f696886a2..8e12bc5be7 100644 --- a/docs/content/en/docs/config/http/services/mentix/_index.md +++ b/docs/content/en/docs/config/http/services/mentix/_index.md @@ -45,6 +45,9 @@ __Supported importers:__ - **webapi** Mentix can import mesh data via an HTTP endpoint using the `webapi` importer. Data can be sent to the configured relative endpoint (see [here](webapi)). +- **adminapi** + Some aspects of Mentix can be administered through an HTTP endpoint using the `adminapi` importer. Queries can be sent to the configured relative endpoint (see [here](adminapi)). + ## Exporters Mentix exposes its gathered data by using one or more _exporters_. Such exporters can, for example, write the data to a file in a specific format, or offer the data via an HTTP endpoint. diff --git a/docs/content/en/docs/config/http/services/mentix/adminapi/_index.md b/docs/content/en/docs/config/http/services/mentix/adminapi/_index.md new file mode 100644 index 0000000000..55f29684eb --- /dev/null +++ b/docs/content/en/docs/config/http/services/mentix/adminapi/_index.md @@ -0,0 +1,46 @@ +--- +title: "adminapi" +linkTitle: "adminapi" +weight: 10 +description: > + Configuration for the AdminAPI of the Mentix service +--- + +{{% pageinfo %}} +The AdminAPI of Mentix is a special importer that can be used to administer certain aspects of Mentix. +{{% /pageinfo %}} + +The AdminAPI importer receives instructions/queries through a `POST` request. + +The importer supports one action that must be passed in the URL: +``` +https://sciencemesh.example.com/mentix/admin/?action= +``` +Currently, the following actions are supported: +- `authorize`: Authorizes or unauthorizes a site + +For all actions, the site data must be sent as JSON data. If the call succeeded, status 200 is returned. + +{{% dir name="endpoint" type="string" default="/admin" %}} +The endpoint where the mesh data can be sent to. +{{< highlight toml >}} +[http.services.mentix.importers.adminapi] +endpoint = "/data" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="is_protected" type="bool" default="false" %}} +Whether the endpoint requires authentication. +{{< highlight toml >}} +[http.services.mentix.importers.adminapi] +is_protected = true +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="enabled_connectors" type="[]string" default="" %}} +A list of all enabled connectors for the importer. Must always be provided. +{{< highlight toml >}} +[http.services.mentix.importers.adminapi] +enabled_connectors = ["localfile"] +{{< /highlight >}} +{{% /dir %}} diff --git a/docs/content/en/docs/config/http/services/mentix/cs3api/_index.md b/docs/content/en/docs/config/http/services/mentix/cs3api/_index.md index d2707bae1c..167de32c17 100644 --- a/docs/content/en/docs/config/http/services/mentix/cs3api/_index.md +++ b/docs/content/en/docs/config/http/services/mentix/cs3api/_index.md @@ -10,7 +10,7 @@ description: > The CS3API exporter exposes Mentix data in a format that is compliant with the CS3API `ProviderInfo` structure via an HTTP endpoint. {{% /pageinfo %}} -{{% dir name="endpoint" type="string" default="/" %}} +{{% dir name="endpoint" type="string" default="/cs3" %}} The endpoint where the mesh data can be queried. {{< highlight toml >}} [http.services.mentix.exporters.cs3api] @@ -18,6 +18,14 @@ endpoint = "/data" {{< /highlight >}} {{% /dir %}} +{{% dir name="is_protected" type="bool" default="false" %}} +Whether the endpoint requires authentication. +{{< highlight toml >}} +[http.services.mentix.exporters.cs3api] +is_protected = true +{{< /highlight >}} +{{% /dir %}} + {{% dir name="enabled_connectors" type="[]string" default="*" %}} A list of all enabled connectors for the exporter. {{< highlight toml >}} diff --git a/docs/content/en/docs/config/http/services/mentix/siteloc/_index.md b/docs/content/en/docs/config/http/services/mentix/siteloc/_index.md index d33477dbc2..013d8d3f07 100644 --- a/docs/content/en/docs/config/http/services/mentix/siteloc/_index.md +++ b/docs/content/en/docs/config/http/services/mentix/siteloc/_index.md @@ -10,7 +10,7 @@ description: > The Site Locations exporter exposes location information of all sites to be consumed by Grafana via an HTTP endpoint. {{% /pageinfo %}} -{{% dir name="endpoint" type="string" default="/" %}} +{{% dir name="endpoint" type="string" default="/siteloc" %}} The endpoint where the locations data can be queried. {{< highlight toml >}} [http.services.mentix.exporters.siteloc] @@ -18,6 +18,14 @@ endpoint = "/loc" {{< /highlight >}} {{% /dir %}} +{{% dir name="is_protected" type="bool" default="false" %}} +Whether the endpoint requires authentication. +{{< highlight toml >}} +[http.services.mentix.exporters.siteloc] +is_protected = true +{{< /highlight >}} +{{% /dir %}} + {{% dir name="enabled_connectors" type="[]string" default="*" %}} A list of all enabled connectors for the exporter. {{< highlight toml >}} diff --git a/docs/content/en/docs/config/http/services/mentix/webapi/_index.md b/docs/content/en/docs/config/http/services/mentix/webapi/_index.md index 9cf4eaea6c..03e4c028bc 100644 --- a/docs/content/en/docs/config/http/services/mentix/webapi/_index.md +++ b/docs/content/en/docs/config/http/services/mentix/webapi/_index.md @@ -24,7 +24,7 @@ Currently, the following actions are supported: For all actions, the site data must be sent as JSON data. If the call succeeded, status 200 is returned. -{{% dir name="endpoint" type="string" default="/" %}} +{{% dir name="endpoint" type="string" default="/sites" %}} The endpoint where the mesh data can be sent to. {{< highlight toml >}} [http.services.mentix.importers.webapi] @@ -32,6 +32,14 @@ endpoint = "/data" {{< /highlight >}} {{% /dir %}} +{{% dir name="is_protected" type="bool" default="false" %}} +Whether the endpoint requires authentication. +{{< highlight toml >}} +[http.services.mentix.importers.webapi] +is_protected = true +{{< /highlight >}} +{{% /dir %}} + {{% dir name="enabled_connectors" type="[]string" default="" %}} A list of all enabled connectors for the importer. Must always be provided. {{< highlight toml >}} @@ -44,7 +52,7 @@ enabled_connectors = ["localfile"] The WebAPI exporter exposes the _plain_ Mentix data via an HTTP endpoint. -{{% dir name="endpoint" type="string" default="/" %}} +{{% dir name="endpoint" type="string" default="/sites" %}} The endpoint where the mesh data can be queried. {{< highlight toml >}} [http.services.mentix.exporters.webapi] @@ -52,6 +60,14 @@ endpoint = "/data" {{< /highlight >}} {{% /dir %}} +{{% dir name="is_protected" type="bool" default="false" %}} +Whether the endpoint requires authentication. +{{< highlight toml >}} +[http.services.mentix.exporters.webapi] +is_protected = true +{{< /highlight >}} +{{% /dir %}} + {{% dir name="enabled_connectors" type="[]string" default="*" %}} A list of all enabled connectors for the exporter. {{< highlight toml >}} diff --git a/examples/mentix/mentix.toml b/examples/mentix/mentix.toml index e82c6f8ee1..9baf22bbfc 100644 --- a/examples/mentix/mentix.toml +++ b/examples/mentix/mentix.toml @@ -30,6 +30,12 @@ enabled_connectors = ["gocdb"] # For importers, this is obligatory; the connectors will be used as the target for data updates enabled_connectors = ["localfile"] +# Enable the AdminAPI importer +[http.services.mentix.importers.adminapi] +enabled_connectors = ["localfile"] +# Should never allow access w/o prior authorization +is_protected = true + # Configure the Prometheus Service Discovery: [http.services.mentix.exporters.promsd] # The following files must be made available to Prometheus. From 5839218ab4d9491d1ac11af3dc2778d9edadc995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 18 Jan 2021 16:20:56 +0100 Subject: [PATCH 16/20] Make GenerateId private --- pkg/mentix/meshdata/site.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/mentix/meshdata/site.go b/pkg/mentix/meshdata/site.go index ae8cbeb7ee..ce41174ad5 100644 --- a/pkg/mentix/meshdata/site.go +++ b/pkg/mentix/meshdata/site.go @@ -125,7 +125,7 @@ func (site *Site) InferMissingData() { // Automatically assign an ID to this site if it is missing if len(site.ID) == 0 { - site.GenerateID() + site.generateID() } // Infer missing for services @@ -134,9 +134,8 @@ func (site *Site) InferMissingData() { } } -// GenerateID generates a unique ID for the site; the following fields are used for this: // Name, Domain -func (site *Site) GenerateID() { +func (site *Site) generateID() { host := site.Domain if site.Homepage != "" { if hostURL, err := url.Parse(site.Homepage); err == nil { From d6a74a2c1c5f323846de02d05628f5932b72a0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 18 Jan 2021 21:36:38 +0100 Subject: [PATCH 17/20] Fix crash when (un)registering a site --- pkg/mentix/connectors/gocdb.go | 2 +- pkg/mentix/connectors/localfile.go | 6 +++--- pkg/mentix/exchangers/importers/webapi/query.go | 2 +- pkg/mentix/meshdata/properties.go | 9 +++++++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pkg/mentix/connectors/gocdb.go b/pkg/mentix/connectors/gocdb.go index c7d7e80819..75742f27d3 100755 --- a/pkg/mentix/connectors/gocdb.go +++ b/pkg/mentix/connectors/gocdb.go @@ -130,7 +130,7 @@ func (connector *GOCDBConnector) querySites(meshData *meshdata.MeshData) error { // Sites coming from the GOCDB are always authorized by default if value := meshdata.GetPropertyValue(properties, meshdata.PropertyAuthorized, ""); len(value) == 0 { - meshdata.SetPropertyValue(properties, meshdata.PropertyAuthorized, "true") + meshdata.SetPropertyValue(&properties, meshdata.PropertyAuthorized, "true") } // See if an organization has been defined using properties; otherwise, use the official name diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index e82bf28c07..cbe3da9605 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -131,7 +131,7 @@ func (connector *LocalFileConnector) mergeData(meshData *meshdata.MeshData, upda // Restore the authorization status for all sites for siteID, status := range siteAuthorizationStatus { if site := meshData.FindSite(siteID); site != nil { - meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, status) + meshdata.SetPropertyValue(&site.Properties, meshdata.PropertyAuthorized, status) } } return nil @@ -148,9 +148,9 @@ func (connector *LocalFileConnector) authorizeData(meshData *meshdata.MeshData, // The site ID is stored in the updated site's name if site := meshData.FindSite(placeholderSite.Name); site != nil { if authorize { - meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "true") + meshdata.SetPropertyValue(&site.Properties, meshdata.PropertyAuthorized, "true") } else { - meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + meshdata.SetPropertyValue(&site.Properties, meshdata.PropertyAuthorized, "false") } } else { return fmt.Errorf("no site with id '%v' found", placeholderSite.Name) diff --git a/pkg/mentix/exchangers/importers/webapi/query.go b/pkg/mentix/exchangers/importers/webapi/query.go index 6a2e89e7f7..868d0c8cc3 100755 --- a/pkg/mentix/exchangers/importers/webapi/query.go +++ b/pkg/mentix/exchangers/importers/webapi/query.go @@ -38,7 +38,7 @@ func decodeQueryData(data []byte) (*meshdata.MeshData, error) { site.ID = "" // Set sites imported through the WebAPI to 'unauthorized' by default - meshdata.SetPropertyValue(site.Properties, meshdata.PropertyAuthorized, "false") + meshdata.SetPropertyValue(&site.Properties, meshdata.PropertyAuthorized, "false") meshData := &meshdata.MeshData{Sites: []*meshdata.Site{site}} if err := meshData.Verify(); err != nil { diff --git a/pkg/mentix/meshdata/properties.go b/pkg/mentix/meshdata/properties.go index 1739888300..0374ec2e2f 100644 --- a/pkg/mentix/meshdata/properties.go +++ b/pkg/mentix/meshdata/properties.go @@ -47,6 +47,11 @@ func GetPropertyValue(props map[string]string, id string, defValue string) strin } // SetPropertyValue sets a property value. -func SetPropertyValue(props map[string]string, id string, value string) { - props[strings.ToUpper(id)] = value +func SetPropertyValue(props *map[string]string, id string, value string) { + // If the provided properties map is nil, create an empty one + if *props == nil { + *props = make(map[string]string) + } + + (*props)[strings.ToUpper(id)] = value } From dcc9a946a7d672579351a0517708ce6854966677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Tue, 19 Jan 2021 13:26:02 +0100 Subject: [PATCH 18/20] Use site ID field for authorization --- pkg/mentix/connectors/localfile.go | 3 +-- pkg/mentix/exchangers/importers/adminapi/query.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index cbe3da9605..b968c2fe17 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -145,8 +145,7 @@ func (connector *LocalFileConnector) unmergeData(meshData *meshdata.MeshData, up func (connector *LocalFileConnector) authorizeData(meshData *meshdata.MeshData, updatedData *meshdata.MeshData, authorize bool) error { for _, placeholderSite := range updatedData.Sites { - // The site ID is stored in the updated site's name - if site := meshData.FindSite(placeholderSite.Name); site != nil { + if site := meshData.FindSite(placeholderSite.ID); site != nil { if authorize { meshdata.SetPropertyValue(&site.Properties, meshdata.PropertyAuthorized, "true") } else { diff --git a/pkg/mentix/exchangers/importers/adminapi/query.go b/pkg/mentix/exchangers/importers/adminapi/query.go index 36c2265849..cb7a65a198 100755 --- a/pkg/mentix/exchangers/importers/adminapi/query.go +++ b/pkg/mentix/exchangers/importers/adminapi/query.go @@ -38,7 +38,7 @@ func decodeAdminQueryData(data []byte) (*meshdata.MeshData, error) { if value, ok := jsonData["id"]; ok { if id, ok := value.(string); ok { site := &meshdata.Site{} - site.Name = id // Store the provided site ID in the site's name + site.ID = id // We only need to store the ID of the site meshData := &meshdata.MeshData{Sites: []*meshdata.Site{site}} return meshData, nil From ea1269d5abaee7e27b1e21aa21f0439e0c074bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 5 Feb 2021 13:07:54 +0100 Subject: [PATCH 19/20] Fix Mentix data cloning bug --- changelog/unreleased/mentix-clone-fix.md | 5 +++++ pkg/mentix/connectors/localfile.go | 1 + pkg/mentix/meshdata/meshdata.go | 23 +++++++++++------------ 3 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 changelog/unreleased/mentix-clone-fix.md diff --git a/changelog/unreleased/mentix-clone-fix.md b/changelog/unreleased/mentix-clone-fix.md new file mode 100644 index 0000000000..635f49064d --- /dev/null +++ b/changelog/unreleased/mentix-clone-fix.md @@ -0,0 +1,5 @@ +Fix: Cloning of internal mesh data lost some values + +This update fixes a bug in Mentix that caused some (non-critical) values to be lost during data cloning that happens internally. + +https://github.com/cs3org/reva/pull/1457 diff --git a/pkg/mentix/connectors/localfile.go b/pkg/mentix/connectors/localfile.go index b968c2fe17..6c154adc2c 100755 --- a/pkg/mentix/connectors/localfile.go +++ b/pkg/mentix/connectors/localfile.go @@ -79,6 +79,7 @@ func (connector *LocalFileConnector) RetrieveMeshData() (*meshdata.MeshData, err connector.setSiteTypes(meshData) meshData.InferMissingData() + return meshData, nil } diff --git a/pkg/mentix/meshdata/meshdata.go b/pkg/mentix/meshdata/meshdata.go index 9ab0ecdf4a..05289b72d1 100644 --- a/pkg/mentix/meshdata/meshdata.go +++ b/pkg/mentix/meshdata/meshdata.go @@ -19,8 +19,11 @@ package meshdata import ( + "bytes" + "encoding/gob" "encoding/json" "fmt" + "reflect" "strings" ) @@ -196,10 +199,13 @@ func (meshData *MeshData) FromJSON(data string) error { func (meshData *MeshData) Clone() *MeshData { clone := &MeshData{} - // To avoid any "deep copy" packages, use JSON en- and decoding instead - data, err := meshData.ToJSON() - if err == nil { - if err := clone.FromJSON(data); err != nil { + // To avoid any "deep copy" packages, use gob en- and decoding instead + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + dec := gob.NewDecoder(&buf) + + if err := enc.Encode(meshData); err == nil { + if err := dec.Decode(clone); err != nil { // In case of an error, clear the data clone.Clear() } @@ -210,14 +216,7 @@ func (meshData *MeshData) Clone() *MeshData { // Compare checks whether the stored data equals the data of another MeshData object. func (meshData *MeshData) Compare(other *MeshData) bool { - if other == nil { - return false - } - - // To avoid cumbersome comparisons, just compare the JSON-encoded data - json1, _ := meshData.ToJSON() - json2, _ := other.ToJSON() - return json1 == json2 + return reflect.DeepEqual(meshData, other) } // New returns a new (empty) MeshData object. From 7ab6db27240b65a986359328287caf7004a46f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 5 Feb 2021 13:32:27 +0100 Subject: [PATCH 20/20] Fix changelog --- changelog/unreleased/mentix-clone-fix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/unreleased/mentix-clone-fix.md b/changelog/unreleased/mentix-clone-fix.md index 635f49064d..d5ab1f3232 100644 --- a/changelog/unreleased/mentix-clone-fix.md +++ b/changelog/unreleased/mentix-clone-fix.md @@ -1,4 +1,4 @@ -Fix: Cloning of internal mesh data lost some values +Bugfix: Cloning of internal mesh data lost some values This update fixes a bug in Mentix that caused some (non-critical) values to be lost during data cloning that happens internally.