Repository: stackrox/stackrox
Pull request #14766: ROX-28698: Fix wrong default value of node index mapping URL
Author: login: vikin91
Labels: name: ci-all-qa-tests
description: Tells CI to run all API tests (not just BAT).
name: area/sensor
name: backport release-4.7
Created: 2025-03-26T15:56:19Z | Merged: 2025-04-03T08:35:08Z

### Description

The value of `ROX_NODE_INDEX_MAPPING_URL` must point to Sensor's https endpoint for obtaining repo to CPE mapping for node indexing. This env var was defaulting to `sensor.stackrox.svc` which worked only when Sensor was installed in the stackrox namespace. For other namespaces, we should have change the Sensor host part in Helm charts, but apparently that has never been done.

In this PR I leave out the Sensor host address from this var and keep only the URL-path. The entire address is now concatenated from  `ROX_ADVERTISED_ENDPOINT` (which contains a correct address) and the new var `ROX_NODE_INDEX_MAPPING_URL_PATH` that defaults to `/scanner/definitions?file=repo2cpe`.


### User-facing documentation

- [x] CHANGELOG is updated **OR** update is not needed
- [x] [documentation PR](https://spaces.redhat.com/display/StackRox/Submitting+a+User+Documentation+Pull+Request) is created and is linked above **OR** is not needed

### Testing and quality

- [x] the change is production ready: the change is GA or otherwise the functionality is gated by a feature flag
- [ ] CI results are inspected

#### Automated testing

- [x] added unit tests
- [ ] added e2e tests
- [ ] added regression tests
- [ ] added compatibility tests
- [ ] modified existing tests

#### How I validated my change

- [x] Unit test
- [x] Manually on a cluster by deploying to non-stackrox namespace and looking into the logs of compliance pod to check that node indexes are successfully being sent to Sensor; i.e., not seeing the log message:
```
{"level":"error","version":"1.2","component":"rhel/internal/common/Updater.Get","error":"Get \"https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe\": dial tcp: lookup sensor.stackrox.svc on 172.30.0.10:53: no such host","message":"error updating mapping
```

![Screenshot 2025-04-02 at 13 28 58](https://github.com/user-attachments/assets/7b5db94a-5e9b-437e-83c0-aa536dd5808d)
Those Compliance logs confirm that the mapping was downloaded successfully and v4 indexing is working properly (installation in `rhacs-operator` namespace).



Diff:
diff --git a/compliance/cmd/compliance/main.go b/compliance/cmd/compliance/main.go
index 25c32159394b0..64180efb53a13 100644
--- a/compliance/cmd/compliance/main.go
+++ b/compliance/cmd/compliance/main.go
@@ -28,7 +28,7 @@ func main() {
 	}
 
 	np := &node.EnvNodeNameProvider{}
-	cfg := index.DefaultNodeIndexerConfig
+	cfg := index.DefaultNodeIndexerConfig()
 
 	scanner := inventory.NewNodeInventoryComponentScanner(np)
 	scanner.Connect(env.NodeScanningEndpoint.Setting())
diff --git a/compliance/node/index/indexer.go b/compliance/node/index/indexer.go
index 4d33f9eb66649..a1f06151b2381 100644
--- a/compliance/node/index/indexer.go
+++ b/compliance/node/index/indexer.go
@@ -29,6 +29,7 @@ import (
 	"github.com/stackrox/rox/pkg/mtls"
 	"github.com/stackrox/rox/pkg/scannerv4/mappers"
 	"github.com/stackrox/rox/pkg/sync"
+	"github.com/stackrox/rox/pkg/urlfmt"
 	pkgutils "github.com/stackrox/rox/pkg/utils"
 	"go.uber.org/zap/zapcore"
 )
@@ -37,6 +38,11 @@ const (
 	layerMediaType = "application/vnd.claircore.filesystem"
 
 	rhcosPackageDB = "sqlite:usr/share/rpm"
+
+	// scannerDefinitionsRouteInSensor should be in sync with `scannerDefinitionsRoute` in sensor/sensor.go
+	// Direct import is prohibited by import rules
+	scannerDefinitionsRouteInSensor = "/scanner/definitions"
+	sensorMappingsFile              = "repo2cpe"
 )
 
 var (
@@ -108,13 +114,23 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	if len(env.NodeIndexMappingURL.Setting()) > 0 {
+		return urlfmt.FormatURL(env.NodeIndexMappingURL.Setting(), urlfmt.HTTPS, urlfmt.NoTrailingSlash)
+	}
+	u := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
+	return urlfmt.FormatURL(u, urlfmt.HTTPS, urlfmt.NoTrailingSlash)
 }
 
 type localNodeIndexer struct {
diff --git a/compliance/node/index/indexer_test.go b/compliance/node/index/indexer_test.go
index 9d7b570a0a3c3..366aa89483b46 100644
--- a/compliance/node/index/indexer_test.go
+++ b/compliance/node/index/indexer_test.go
@@ -152,11 +152,57 @@ func (s *nodeIndexerSuite) TestRunPackageScannerAnyPath() {
 	s.Len(packages, 0)
 }
 
+func (s *nodeIndexerSuite) TestBuildMappingURL() {
+	tcs := map[string]struct {
+		advertisedEndpointSetting string
+		mappingURLSetting         string
+		expectedURL               string
+	}{
+		"Empty": {
+			advertisedEndpointSetting: "",
+			mappingURLSetting:         "",
+			expectedURL:               "https://sensor.stackrox.svc:443/scanner/definitions?file=repo2cpe",
+		},
+		"Host with port": {
+			advertisedEndpointSetting: "example.com:8080",
+			mappingURLSetting:         "",
+			expectedURL:               "https://example.com:8080/scanner/definitions?file=repo2cpe",
+		},
+		"Host without port": {
+			advertisedEndpointSetting: "sensor.rhacs.svc",
+			mappingURLSetting:         "",
+			expectedURL:               "https://sensor.rhacs.svc/scanner/definitions?file=repo2cpe",
+		},
+		"HTTP scheme": {
+			advertisedEndpointSetting: "http://example.com",
+			mappingURLSetting:         "",
+			expectedURL:               "https://example.com/scanner/definitions?file=repo2cpe",
+		},
+		"Mapping setting provided": {
+			advertisedEndpointSetting: "sensor.namespace.svc:443",
+			mappingURLSetting:         "https://example.com/download",
+			expectedURL:               "https://example.com/download",
+		},
+		"Mapping setting provided with no scheme and trailing slash": {
+			advertisedEndpointSetting: "sensor.namespace.svc:443",
+			mappingURLSetting:         "example.com/download/",
+			expectedURL:               "https://example.com/download",
+		},
+	}
+	for name, tc := range tcs {
+		s.T().Run(name, func(t *testing.T) {
+			s.T().Setenv("ROX_ADVERTISED_ENDPOINT", tc.advertisedEndpointSetting)
+			s.T().Setenv("ROX_NODE_INDEX_MAPPING_URL", tc.mappingURLSetting)
+			s.Equal(tc.expectedURL, buildMappingURL())
+		})
+	}
+}
+
 func (s *nodeIndexerSuite) TestIndexerE2E() {
 	s.T().Setenv(mtls.CertFilePathEnvName, filepath.Join("testdata", "certs", "client-cert.pem"))
 	s.T().Setenv(mtls.KeyFileEnvName, filepath.Join("testdata", "certs", "client-key.pem"))
 	server := s.createTestServer(true)
-	cfg := DefaultNodeIndexerConfig
+	cfg := DefaultNodeIndexerConfig()
 	cfg.HostPath = "testdata"
 	cfg.Repo2CPEMappingURL = server.URL
 	indexer := NewNodeIndexer(cfg)
@@ -172,7 +218,7 @@ func (s *nodeIndexerSuite) TestIndexerE2E() {
 
 func (s *nodeIndexerSuite) TestIndexerE2ENoPath() {
 	server := s.createTestServer(false)
-	cfg := DefaultNodeIndexerConfig
+	cfg := DefaultNodeIndexerConfig()
 	cfg.Client = server.Client()
 	cfg.HostPath = "doesnotexist"
 	cfg.Repo2CPEMappingURL = server.URL
diff --git a/pkg/env/node_index.go b/pkg/env/node_index.go
index bda547c863c89..7dbfac21243bb 100644
--- a/pkg/env/node_index.go
+++ b/pkg/env/node_index.go
@@ -8,7 +8,9 @@ var (
 	NodeIndexHostPath = RegisterSetting("ROX_NODE_INDEX_HOST_PATH", WithDefault("/host"))
 
 	// NodeIndexMappingURL defines the endpoint for the RepositoryScanner to download mapping information from.
-	NodeIndexMappingURL = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL", WithDefault("https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe"))
+	// If left empty, the URL will be computed based on Sensor's ROX_ADVERTISED_ENDPOINT.
+	// The default "https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe" is not set here to not hardcode the namespace of Sensor.
+	NodeIndexMappingURL = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL", AllowEmpty())
 
 	// NodeIndexCacheDuration defines the time a cached node index will be considered fresh and served from file.
 	// Defaults to 75% of the default rescan interval.
diff --git a/pkg/env/sensor.go b/pkg/env/sensor.go
index ecf56bb0fdfd8..c539cd490f8a9 100644
--- a/pkg/env/sensor.go
+++ b/pkg/env/sensor.go
@@ -11,7 +11,8 @@ var (
 
 	// AdvertisedEndpoint is used to provide the Sensor with the endpoint it
 	// should advertise to services that need to contact it, within its own cluster.
-	AdvertisedEndpoint = RegisterSetting("ROX_ADVERTISED_ENDPOINT", WithDefault("sensor.stackrox.svc:443"))
+	AdvertisedEndpoint = RegisterSetting("ROX_ADVERTISED_ENDPOINT", WithDefault("sensor.stackrox.svc:443"),
+		StripAnyPrefix("https://", "http://"))
 
 	// SensorEndpoint is used to communicate the sensor endpoint to other services in the same cluster.
 	SensorEndpoint = RegisterSetting("ROX_SENSOR_ENDPOINT", WithDefault("sensor.stackrox.svc:443"))
diff --git a/sensor/common/sensor/sensor.go b/sensor/common/sensor/sensor.go
index ff6e06aadc9ce..8aa038505c456 100644
--- a/sensor/common/sensor/sensor.go
+++ b/sensor/common/sensor/sensor.go
@@ -46,6 +46,8 @@ const (
 	publicAPIEndpoint = ":8443"
 
 	publicWebhookEndpoint = ":9443"
+
+	scannerDefinitionsRoute = "/scanner/definitions"
 )
 
 var (
@@ -327,7 +329,7 @@ func (s *Sensor) newScannerDefinitionsRoute(centralEndpoint string, centralCerti
 	s.AddNotifiable(handler)
 	// We rely on central to handle content encoding negotiation.
 	return &routes.CustomRoute{
-		Route:         "/scanner/definitions",
+		Route:         scannerDefinitionsRoute,
 		Authorizer:    or.Or(idcheck.ScannerOnly(), idcheck.ScannerV4IndexerOnly(), idcheck.CollectorOnly()),
 		ServerHandler: handler,
 	}, nil


Reviews:
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T13:34:57Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T08:03:03Z
user: login: parametalol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T08:55:58Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T09:34:26Z
user: login: parametalol
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T09:40:36Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T09:55:55Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T09:56:53Z
user: login: RTann
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T00:19:20Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T07:34:08Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T07:34:26Z
user: login: janisz
body: LGTM but let's wait for @parametalol and @RTann 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T10:54:51Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T11:06:31Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T11:06:39Z
user: login: RTann
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T18:08:57Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T06:59:37Z
user: login: vikin91
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T06:59:41Z
user: login: parametalol
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T07:59:03Z

Review comments:
diff_hunk: @@ -109,12 +109,14 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: "https://" + env.AdvertisedEndpoint.Setting() + env.NodeIndexMappingURLPath.Setting(),
path: compliance/node/index/indexer.go
user: login: vikin91
body: TODO: Add task for unifying `AdvertisedEndpoint` with its copy variable. Consider further ideas:
- guessing the namespace
- remove the hardcoding of `/scanner/definitions?file=repo2cpe` - it is hardcoded in the server part in Sensor.
created_at: 2025-03-27T13:34:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +109,14 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: "https://" + env.AdvertisedEndpoint.Setting() + env.NodeIndexMappingURLPath.Setting(),
path: compliance/node/index/indexer.go
user: login: vikin91
body: The followup has been created: https://issues.redhat.com/browse/ROX-28780
created_at: 2025-04-01T08:03:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +115,19 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
path: compliance/node/index/indexer.go
user: login: parametalol
body: Why is this a function now? All fields seem to be constants.
created_at: 2025-04-01T08:55:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +115,19 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
path: compliance/node/index/indexer.go
user: login: vikin91
body: This is a function for lazy evaluation and better testability. It does not strictly has to be a function - let me know if you want me to revert it back to a var.
created_at: 2025-04-01T09:34:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +115,19 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
path: compliance/node/index/indexer.go
user: login: parametalol
body: I have no preference. Please adjust the comment.

BTW, I think the naming convention for constructors is to start with `Make...`.
created_at: 2025-04-01T09:40:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +115,19 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
path: compliance/node/index/indexer.go
user: login: vikin91
body: I feel it sounds weird with `MakeDefaultNodeIndexerConfig()`. I would leave the name as it is - we use it like this also for functions.
![Screenshot 2025-04-01 at 11 55 24](https://github.com/user-attachments/assets/32ea68c8-b9b2-4963-8cfc-8c54f3794642)

created_at: 2025-04-01T09:55:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,12 +115,19 @@ type NodeIndexerConfig struct {
 }
 
 // DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
path: compliance/node/index/indexer.go
user: login: vikin91
body: Here is the comment adjustment: [0063f48](https://github.com/stackrox/stackrox/pull/14766/commits/0063f48b402f5f190ae9bfcb47bb09f5a0bba771)
created_at: 2025-04-01T09:56:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,8 +7,8 @@ var (
 	// that should be scanned by Scanners NodeIndexer
 	NodeIndexHostPath = RegisterSetting("ROX_NODE_INDEX_HOST_PATH", WithDefault("/host"))
 
-	// NodeIndexMappingURL defines the endpoint for the RepositoryScanner to download mapping information from.
-	NodeIndexMappingURL = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL", WithDefault("https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe"))
+	// NodeIndexMappingURLPath defines the Sensor URL path for the RepositoryScanner to download mapping information from.
+	NodeIndexMappingURLPath = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL_PATH", WithDefault("/scanner/definitions?file=repo2cpe"))
path: pkg/env/node_index.go
user: login: RTann
body: Do we need to go through any kind of deprecation process for this? I actually just don't know our policy
created_at: 2025-04-02T00:15:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,13 +114,20 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	URL := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
path: compliance/node/index/indexer.go
user: login: RTann
body: Is `NodeIndexMappingURLPath` used?
created_at: 2025-04-02T00:19:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,8 +7,8 @@ var (
 	// that should be scanned by Scanners NodeIndexer
 	NodeIndexHostPath = RegisterSetting("ROX_NODE_INDEX_HOST_PATH", WithDefault("/host"))
 
-	// NodeIndexMappingURL defines the endpoint for the RepositoryScanner to download mapping information from.
-	NodeIndexMappingURL = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL", WithDefault("https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe"))
+	// NodeIndexMappingURLPath defines the Sensor URL path for the RepositoryScanner to download mapping information from.
+	NodeIndexMappingURLPath = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL_PATH", WithDefault("/scanner/definitions?file=repo2cpe"))
path: pkg/env/node_index.go
user: login: vikin91
body: ~No, I am not deprecating this. This was added recently in 4.7 and it was never added to the Helm charts, so if someone used that setting, they did that only to fix the issues that this fix addresses.
Why? Because the only part that would be changed to make this work is the Sensor host name.  The path that comes after the host address is hardcoded in Sensor, so I see no scenario in which that would be changed (unless someone wanted to point that to the Internet).~

You know what, I will keep the old setting and remove the default. If someone would like to use that - for example to get the definitions from the Internet - then they can. If `ROX_NODE_INDEX_MAPPING_URL` is unset, I will compute the address the way I do it in this PR. 
created_at: 2025-04-02T07:34:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,13 +114,20 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	URL := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
path: compliance/node/index/indexer.go
user: login: vikin91
body: no, not anymore. Good catch, I will remove it.
created_at: 2025-04-02T07:34:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,13 +114,20 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	URL := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
path: compliance/node/index/indexer.go
user: login: vikin91
body: Done in https://github.com/stackrox/stackrox/pull/14766/commits/9a63299fc4e5fd1ce0b79394791fd68f5d8ec21b
created_at: 2025-04-02T11:06:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -7,8 +7,8 @@ var (
 	// that should be scanned by Scanners NodeIndexer
 	NodeIndexHostPath = RegisterSetting("ROX_NODE_INDEX_HOST_PATH", WithDefault("/host"))
 
-	// NodeIndexMappingURL defines the endpoint for the RepositoryScanner to download mapping information from.
-	NodeIndexMappingURL = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL", WithDefault("https://sensor.stackrox.svc/scanner/definitions?file=repo2cpe"))
+	// NodeIndexMappingURLPath defines the Sensor URL path for the RepositoryScanner to download mapping information from.
+	NodeIndexMappingURLPath = RegisterSetting("ROX_NODE_INDEX_MAPPING_URL_PATH", WithDefault("/scanner/definitions?file=repo2cpe"))
path: pkg/env/node_index.go
user: login: vikin91
body: PTAL at https://github.com/stackrox/stackrox/pull/14766/commits/9a63299fc4e5fd1ce0b79394791fd68f5d8ec21b
created_at: 2025-04-02T11:06:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,11 +152,57 @@ func (s *nodeIndexerSuite) TestRunPackageScannerAnyPath() {
 	s.Len(packages, 0)
 }
 
+func (s *nodeIndexerSuite) TestMappingURL() {
path: compliance/node/index/indexer_test.go
user: login: RTann
body: nit: TestBuildMappingURL
created_at: 2025-04-02T18:07:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,13 +114,23 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	if len(env.NodeIndexMappingURL.Setting()) > 0 {
+		return urlfmt.FormatURL(env.NodeIndexMappingURL.Setting(), urlfmt.HTTPS, urlfmt.NoTrailingSlash)
+	}
+	URL := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
path: compliance/node/index/indexer.go
user: login: RTann
body: nit: `u` or even `url`
created_at: 2025-04-02T18:08:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -152,11 +152,57 @@ func (s *nodeIndexerSuite) TestRunPackageScannerAnyPath() {
 	s.Len(packages, 0)
 }
 
+func (s *nodeIndexerSuite) TestMappingURL() {
path: compliance/node/index/indexer_test.go
user: login: vikin91
body: done in https://github.com/stackrox/stackrox/pull/14766/commits/e9a7e5b7ae38decdf433743904983b75e26b2eb4
created_at: 2025-04-03T06:59:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,13 +114,23 @@ type NodeIndexerConfig struct {
 	Timeout time.Duration
 }
 
-// DefaultNodeIndexerConfig is the default configuration for a node indexer.
-var DefaultNodeIndexerConfig = NodeIndexerConfig{
-	HostPath: env.NodeIndexHostPath.Setting(),
-	// The default, mTLS-capable client will be used.
-	Client:             nil,
-	Repo2CPEMappingURL: env.NodeIndexMappingURL.Setting(),
-	Timeout:            10 * time.Second,
+// DefaultNodeIndexerConfig provides the default configuration for a node indexer.
+func DefaultNodeIndexerConfig() NodeIndexerConfig {
+	return NodeIndexerConfig{
+		HostPath: env.NodeIndexHostPath.Setting(),
+		// The default, mTLS-capable client will be used.
+		Client:             nil,
+		Repo2CPEMappingURL: buildMappingURL(),
+		Timeout:            10 * time.Second,
+	}
+}
+
+func buildMappingURL() string {
+	if len(env.NodeIndexMappingURL.Setting()) > 0 {
+		return urlfmt.FormatURL(env.NodeIndexMappingURL.Setting(), urlfmt.HTTPS, urlfmt.NoTrailingSlash)
+	}
+	URL := env.AdvertisedEndpoint.Setting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
path: compliance/node/index/indexer.go
user: login: vikin91
body: done in https://github.com/stackrox/stackrox/pull/14766/commits/e9a7e5b7ae38decdf433743904983b75e26b2eb4
created_at: 2025-04-03T06:59:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: openshift-ci[bot]
created_at: 2025-03-26T15:56:24Z
body: Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with `/test all`
author_association: NONE
user: login: rhacs-bot
created_at: 2025-03-26T16:21:57Z
body: [//]: # (meta:type=build)

Images are ready for the commit at e9a7e5b.

To use with deploy scripts, first `export MAIN_IMAGE_TAG=4.8.x-339-ge9a7e5b7ae`.
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-03-26T17:45:10Z
body: ## [Codecov](https://app.codecov.io/gh/stackrox/stackrox/pull/14766?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) Report
Attention: Patch coverage is `93.33333%` with `1 line` in your changes missing coverage. Please review.
> Project coverage is 48.90%. Comparing base [(`eadcbdf`)](https://app.codecov.io/gh/stackrox/stackrox/commit/eadcbdf72205c97391dcdd47479a5868837a9de1?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) to head [(`e9a7e5b`)](https://app.codecov.io/gh/stackrox/stackrox/commit/e9a7e5b7ae38decdf433743904983b75e26b2eb4?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox).
> Report is 42 commits behind head on master.

| [Files with missing lines](https://app.codecov.io/gh/stackrox/stackrox/pull/14766?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) | Patch % | Lines |
|---|---|---|
| [sensor/common/sensor/sensor.go](https://app.codecov.io/gh/stackrox/stackrox/pull/14766?src=pr&el=tree&filepath=sensor%2Fcommon%2Fsensor%2Fsensor.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox#diff-c2Vuc29yL2NvbW1vbi9zZW5zb3Ivc2Vuc29yLmdv) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/stackrox/stackrox/pull/14766?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) |

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master   #14766   +/-   ##
=======================================
  Coverage   48.89%   48.90%           
=======================================
  Files        2547     2547           
  Lines      186977   186917   -60     
=======================================
- Hits        91421    91403   -18     
+ Misses      88315    88279   -36     
+ Partials     7241     7235    -6     
```

| [Flag](https://app.codecov.io/gh/stackrox/stackrox/pull/14766/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) | Coverage Δ | |
|---|---|---|
| [go-unit-tests](https://app.codecov.io/gh/stackrox/stackrox/pull/14766/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox) | `48.90% <93.33%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/stackrox/stackrox/pull/14766?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=stackrox).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: vikin91
created_at: 2025-03-27T08:50:13Z
body: Unit tests flaked with:

```
=== RUN   TestSecuredClusterTLSIssuerIntegrationTests/TestSensorOnlineOfflineModes
kubernetes/certrefresh: 2025/03/26 17:15:50.442447 securedcluster_tls_issuer.go:189: Info: Component runs now in Online mode
kubernetes/certrefresh: 2025/03/26 17:15:50.443071 cert_refresher.go:110: Warn: secured cluster not found (this is expected on a new deployment), will refresh certificates immediately: 7 errors occurred:
	* secrets "tls-cert-scanner-v4-db" not found
	* secrets "tls-cert-sensor" not found
	* secrets "tls-cert-collector" not found
	* secrets "tls-cert-admission-control" not found
	* secrets "tls-cert-scanner" not found
	* secrets "tls-cert-scanner-db" not found
	* secrets "tls-cert-scanner-v4-indexer" not found


kubernetes/certrefresh: 2025/03/26 17:15:50.443274 securedcluster_tls_issuer.go:189: Info: Component runs now in Offline mode
kubernetes/certrefresh: 2025/03/26 17:15:50.443351 securedcluster_tls_issuer.go:189: Info: Component runs now in Online mode
kubernetes/certrefresh: 2025/03/26 17:15:50.443537 cert_refresher.go:42: Error: refreshing secured cluster: context canceled
kubernetes/certrefresh: 2025/03/26 17:15:50.443799 cert_refresher.go:110: Warn: secured cluster not found (this is expected on a new deployment), will refresh certificates immediately: 7 errors occurred:
	* secrets "tls-cert-admission-control" not found
	* secrets "tls-cert-scanner" not found
	* secrets "tls-cert-scanner-db" not found
	* secrets "tls-cert-scanner-v4-indexer" not found
	* secrets "tls-cert-scanner-v4-db" not found
	* secrets "tls-cert-sensor" not found
	* secrets "tls-cert-collector" not found


kubernetes/certrefresh: 2025/03/26 17:15:50.443947 cert_refresher.go:42: Error: refreshing secured cluster: central refused to issue certificates: forced error
kubernetes/certrefresh: 2025/03/26 17:15:50.444046 securedcluster_tls_issuer.go:238: Warn: Received a response for request ID "4ce641d8-d5b7-49a8-874b-630a3fd51abe", but there is no ongoing RequestCertificates call.
kubernetes/certrefresh: 2025/03/26 17:15:50.445377 cert_refresher.go:110: Warn: secured cluster not found (this is expected on a new deployment), will refresh certificates immediately: 7 errors occurred:
	* secrets "tls-cert-scanner-v4-db" not found
	* secrets "tls-cert-sensor" not found
	* secrets "tls-cert-collector" not found
	* secrets "tls-cert-admission-control" not found
	* secrets "tls-cert-scanner" not found
	* secrets "tls-cert-scanner-db" not found
	* secrets "tls-cert-scanner-v4-indexer" not found


    securedcluster_tls_issuer_test.go:669: 
        	Error Trace:	/__w/stackrox/stackrox/sensor/kubernetes/certrefresh/securedcluster_tls_issuer_test.go:669
        	            				/__w/stackrox/stackrox/sensor/kubernetes/certrefresh/securedcluster_tls_issuer_test.go:475
        	Error:      	Condition never satisfied
        	Test:       	TestSecuredClusterTLSIssuerIntegrationTests/TestSensorOnlineOfflineModes
        	Messages:   	expected exactly 7 secrets with non-empty data available in the k8s API
kubernetes/certrefresh: 2025/03/26 17:15:52.008965 cert_refresher.go:42: Error: refreshing secured cluster: context canceled
```

This is a know issue (see #14642) and local rerun was green, so I retriggered the tests in CI.
author_association: CONTRIBUTOR
user: login: vikin91
created_at: 2025-04-01T17:25:01Z
body: /retest
author_association: CONTRIBUTOR
user: login: openshift-ci[bot]
created_at: 2025-04-03T08:33:20Z
body: @vikin91: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
ci/prow/gke-qa-e2e-tests | 9a63299fc4e5fd1ce0b79394791fd68f5d8ec21b | [link](https://prow.ci.openshift.org/view/gs/test-platform-results/pr-logs/pull/stackrox_stackrox/14766/pull-ci-stackrox-stackrox-master-gke-qa-e2e-tests/1907340582238294016) | false | `/test gke-qa-e2e-tests`
ci/prow/gke-sensor-integration-tests | e9a7e5b7ae38decdf433743904983b75e26b2eb4 | [link](https://prow.ci.openshift.org/view/gs/test-platform-results/pr-logs/pull/stackrox_stackrox/14766/pull-ci-stackrox-stackrox-master-gke-sensor-integration-tests/1907689467137757184) | false | `/test gke-sensor-integration-tests`

[Full PR test history](https://prow.ci.openshift.org/pr-history?org=stackrox&repo=stackrox&pr=14766). [Your PR dashboard](https://prow.ci.openshift.org/pr?query=is:pr+state:open+author:vikin91).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-03T19:25:27Z
body: Merge commit has been cherry-picked to branch `release-4.7`.
author_association: CONTRIBUTOR
user: login: davdhacs
created_at: 2025-04-03T19:40:48Z
body: > Merge commit has been cherry-picked to branch `release-4.7`.

the cherry-pick automation failed (https://github.com/stackrox/stackrox/actions/runs/14249263097/job/39943874854).

I'll re-do this as a backport pr and fix merge-conflicts there.
author_association: CONTRIBUTOR