Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compliance/compliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (c *Compliance) Start() {
metrics.GatherThrottleMetricsForever(metrics.ComplianceSubsystem.String())

// Set up Compliance <-> Sensor connection
conn, err := clientconn.AuthenticatedGRPCConnection(context.Background(), env.AdvertisedEndpoint.Setting(), mtls.SensorSubject)
conn, err := clientconn.AuthenticatedGRPCConnection(context.Background(), env.SensorEndpointSetting(), mtls.SensorSubject)
if err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -535,7 +535,7 @@ func (c *Compliance) initializeStream(ctx context.Context, cli sensor.Compliance
if err != nil {
return nil, nil, errors.Wrap(err, "Failed to initialize sensor connection")
}
log.Infof("Successfully connected to Sensor at %s", env.AdvertisedEndpoint.Setting())
log.Infof("Successfully connected to Sensor at %s", env.SensorEndpointSetting())

return client, config, nil
}
Expand Down
2 changes: 1 addition & 1 deletion compliance/node/index/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ 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
u := env.SensorEndpointSetting() + scannerDefinitionsRouteInSensor + "?file=" + sensorMappingsFile
return urlfmt.FormatURL(u, urlfmt.HTTPS, urlfmt.NoTrailingSlash)
}

Expand Down
49 changes: 31 additions & 18 deletions compliance/node/index/indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,44 +181,57 @@ func (s *nodeIndexerSuite) TestRunPackageScannerAnyPath() {

func (s *nodeIndexerSuite) TestBuildMappingURL() {
tcs := map[string]struct {
sensorEndpointSetting string
advertisedEndpointSetting string
useLegacyAdvertised bool
mappingURLSetting string
expectedURL string
}{
"Empty": {
advertisedEndpointSetting: "",
mappingURLSetting: "",
expectedURL: "https://sensor.stackrox.svc:443/scanner/definitions?file=repo2cpe",
sensorEndpointSetting: "",
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",
sensorEndpointSetting: "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",
sensorEndpointSetting: "sensor.rhacs.svc",
mappingURLSetting: "",
expectedURL: "https://sensor.rhacs.svc/scanner/definitions?file=repo2cpe",
},
"HTTP scheme": {
advertisedEndpointSetting: "http://example.com",
sensorEndpointSetting: "http://example.com",
mappingURLSetting: "",
expectedURL: "https://example.com/scanner/definitions?file=repo2cpe",
},
"Legacy advertised endpoint only": {
advertisedEndpointSetting: "sensor.legacy.svc:443",
useLegacyAdvertised: true,
mappingURLSetting: "",
expectedURL: "https://example.com/scanner/definitions?file=repo2cpe",
expectedURL: "https://sensor.legacy.svc:443/scanner/definitions?file=repo2cpe",
},
"Mapping setting provided": {
advertisedEndpointSetting: "sensor.namespace.svc:443",
mappingURLSetting: "https://example.com/download",
expectedURL: "https://example.com/download",
sensorEndpointSetting: "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",
sensorEndpointSetting: "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_SENSOR_ENDPOINT", tc.sensorEndpointSetting)
if tc.useLegacyAdvertised {
s.T().Setenv("ROX_ADVERTISED_ENDPOINT", tc.advertisedEndpointSetting)
} else {
s.T().Setenv("ROX_ADVERTISED_ENDPOINT", "")
}
s.T().Setenv("ROX_NODE_INDEX_MAPPING_URL", tc.mappingURLSetting)
s.Equal(tc.expectedURL, buildMappingURL())
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ spec:
fieldPath: spec.nodeName
- name: ROX_ADVERTISED_ENDPOINT
value: {{ quote ._rox.sensor.endpoint }}
- name: ROX_SENSOR_ENDPOINT
value: {{ quote ._rox.sensor.endpoint }}
- name: ROX_NODE_SCANNING_ENDPOINT
value: {{ quote ._rox.collector.nodescanningEndpoint }}
{{- include "srox.envVars" (list . "daemonset" "collector" "compliance") | nindent 8 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ spec:
value: {{ ._rox.centralEndpoint }}
- name: ROX_ADVERTISED_ENDPOINT
value: {{ ._rox.sensor.endpoint }}
- name: ROX_SENSOR_ENDPOINT
value: {{ ._rox.sensor.endpoint }}
- name: GRPC_ENFORCE_ALPN_ENABLED
value: {{ quote ._rox.env.grpcEnforceALPN }}
{{- if ._rox.env.openshift }}
Expand Down
2 changes: 1 addition & 1 deletion pkg/env/node_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var (
NodeIndexHostPath = RegisterSetting("ROX_NODE_INDEX_HOST_PATH", WithDefault("/host"))

// NodeIndexMappingURL defines the endpoint for the RepositoryScanner to download mapping information from.
// If left empty, the URL will be computed based on Sensor's ROX_ADVERTISED_ENDPOINT.
// If left empty, the URL will be computed based on Sensor's ROX_SENSOR_ENDPOINT (see SensorEndpointSetting).
// 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())

Expand Down
8 changes: 5 additions & 3 deletions pkg/env/sensor.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import "time"
// These environment variables are used in the deployment file.
// Please check the files before deleting.
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 is deprecated; use SensorEndpointSetting() or SensorEndpoint instead.
// Kept for backward compatibility with manual installs and Central kubectl bundle rendering.
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"))
// Prefer SensorEndpointSetting() for the effective endpoint (legacy fallback and namespace derivation).
SensorEndpoint = RegisterSetting("ROX_SENSOR_ENDPOINT", WithDefault("sensor.stackrox.svc:443"),
StripAnyPrefix("https://", "http://"))

// ScannerSlimGRPCEndpoint is used to communicate the scanner endpoint to other services in the same cluster.
// This is typically used for Sensor to communicate with a local Scanner-slim's gRPC server.
Expand Down
50 changes: 50 additions & 0 deletions pkg/env/sensor_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package env

import (
"fmt"
"os"
"strings"
)

const (
sensorEndpointEnvVar = "ROX_SENSOR_ENDPOINT"
legacyAdvertisedSensorEndpoint = "ROX_ADVERTISED_ENDPOINT"
defaultSensorEndpoint = "sensor.stackrox.svc:443"
)

// SensorEndpointSetting returns the effective in-cluster Sensor host:port endpoint by checking:
// 1. ROX_SENSOR_ENDPOINT (canonical)
// 2. ROX_ADVERTISED_ENDPOINT (legacy fallback)
// 3. sensor.{POD_NAMESPACE}.svc:443 (runtime derivation)
// 4. sensor.stackrox.svc:443 (hard default)
func SensorEndpointSetting() string {
if endpoint := sensorEndpointFromEnv(sensorEndpointEnvVar); endpoint != "" {
return endpoint
}
if endpoint := sensorEndpointFromEnv(legacyAdvertisedSensorEndpoint); endpoint != "" {
return endpoint
}
if ns := Namespace.Setting(); ns != "" {
return fmt.Sprintf("sensor.%s.svc:443", ns)
}
return defaultSensorEndpoint
}

func sensorEndpointFromEnv(envVar string) string {
val, ok := os.LookupEnv(envVar)
if !ok || val == "" {
return ""
}
return stripSchemePrefix(val)
}

func stripSchemePrefix(val string) string {
for _, prefix := range []string{"https://", "http://"} {
prev := val
val = strings.TrimPrefix(val, prefix)
if prev != val {
break
}
}
return val
}
77 changes: 77 additions & 0 deletions pkg/env/sensor_endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package env

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestSensorEndpointSetting(t *testing.T) {
cases := map[string]struct {
sensorEndpoint string
advertisedEndpoint string
namespace string
setSensor bool
setAdvertised bool
setNamespace bool
expected string
}{
"canonical endpoint": {
sensorEndpoint: "sensor.custom.svc:8443",
setSensor: true,
expected: "sensor.custom.svc:8443",
},
"canonical strips https prefix": {
sensorEndpoint: "https://sensor.custom.svc:8443",
setSensor: true,
expected: "sensor.custom.svc:8443",
},
"legacy advertised endpoint only": {
advertisedEndpoint: "sensor.legacy.svc:443",
setAdvertised: true,
expected: "sensor.legacy.svc:443",
},
"canonical wins over legacy": {
sensorEndpoint: "sensor.canonical.svc:443",
advertisedEndpoint: "sensor.legacy.svc:443",
setSensor: true,
setAdvertised: true,
expected: "sensor.canonical.svc:443",
},
"derive from namespace when unset": {
namespace: "rhacs",
setNamespace: true,
expected: "sensor.rhacs.svc:443",
},
"empty canonical falls through to legacy": {
sensorEndpoint: "",
advertisedEndpoint: "sensor.legacy.svc:443",
setSensor: true,
setAdvertised: true,
expected: "sensor.legacy.svc:443",
},
"namespace default stackrox when unset": {
expected: defaultSensorEndpoint,
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
t.Setenv(sensorEndpointEnvVar, "")
t.Setenv(legacyAdvertisedSensorEndpoint, "")
t.Setenv(Namespace.EnvVar(), "")

if tc.setSensor {
t.Setenv(sensorEndpointEnvVar, tc.sensorEndpoint)
}
if tc.setAdvertised {
t.Setenv(legacyAdvertisedSensorEndpoint, tc.advertisedEndpoint)
}
if tc.setNamespace {
t.Setenv(Namespace.EnvVar(), tc.namespace)
}

assert.Equal(t, tc.expected, SensorEndpointSetting())
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ defs: |
[
(envVars(.deployments["admission-control"]; "admission-control")["ROX_SENSOR_ENDPOINT"]
| assertThat(. == ep)),
(envVars(.deployments.sensor; "sensor")["ROX_SENSOR_ENDPOINT"]
| assertThat(. == ep)),
(envVars(.daemonsets.collector; "collector")["GRPC_SERVER"] | assertThat(. == ep)),
(envVars(.daemonsets.collector; "compliance")["ROX_ADVERTISED_ENDPOINT"]
| assertThat(. == ep)),
(envVars(.daemonsets.collector; "compliance")["ROX_SENSOR_ENDPOINT"]
| assertThat(. == ep))
][];

Expand Down
2 changes: 1 addition & 1 deletion scanner/internal/httputil/transport_mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func transportMux(defaultTransport http.RoundTripper, o options) (http.RoundTrip
if err != nil {
return nil, err
}
sensorHostname, err := hostname(env.SensorEndpoint.Setting(), fmt.Sprintf("sensor.%s.svc", env.Namespace.Setting()))
sensorHostname, err := hostname(env.SensorEndpointSetting(), fmt.Sprintf("sensor.%s.svc", env.Namespace.Setting()))
if err != nil {
return nil, err
}
Expand Down
13 changes: 6 additions & 7 deletions scanner/internal/httputil/transport_mux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,13 @@ func TestTransportMux(t *testing.T) {
},
},
{
// ROX_SENSOR_ENDPOINT is not allowed to be empty, so we'll use the default value of
// sensor.stackrox.svc:443 for this test.
// This test will hopefully catch any changes and trigger the author of the change
// to notify us to ensure we are all on the same page.
// When ROX_SENSOR_ENDPOINT is unset, SensorEndpointSetting derives from POD_NAMESPACE.
name: "Sensor (default)",
msg: "Sensor",
url: "https://sensor.stackrox.svc/api/extensions/scannerdefinitions?file=repo2cpe",
url: "https://sensor.something-else.svc/api/extensions/scannerdefinitions?file=repo2cpe",
envs: map[string]string{
env.SensorEndpoint.EnvVar(): "",
env.SensorEndpoint.EnvVar(): "",
env.AdvertisedEndpoint.EnvVar(): "",
},
},
{
Expand Down Expand Up @@ -124,6 +122,7 @@ func TestTransportMux_deny(t *testing.T) {
t.Setenv(env.Namespace.EnvVar(), "something-else")
t.Setenv(env.CentralEndpoint.EnvVar(), "")
t.Setenv(env.SensorEndpoint.EnvVar(), "")
t.Setenv(env.AdvertisedEndpoint.EnvVar(), "")

defaultTransport, _, _ := testTransports()

Expand All @@ -146,7 +145,7 @@ func TestTransportMux_deny(t *testing.T) {
},
{
name: "Sensor",
url: "https://sensor.stackrox.svc/api/extensions/scannerdefinitions?file=repo2cpe",
url: "https://sensor.something-else.svc/api/extensions/scannerdefinitions?file=repo2cpe",
wantPanic: true,
},
{
Expand Down
2 changes: 1 addition & 1 deletion sensor/admission-control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func mainCmd() error {

// Note that the following call returns immediately (connecting happens in the background), hence this does not
// delay readiness of the admission-control service even if sensor is unavailable.
sensorConn, err := clientconn.AuthenticatedGRPCConnection(context.Background(), env.SensorEndpoint.Setting(), mtls.SensorSubject)
sensorConn, err := clientconn.AuthenticatedGRPCConnection(context.Background(), env.SensorEndpointSetting(), mtls.SensorSubject)
if err != nil {
log.Errorf("Could not establish a gRPC connection to Sensor: %v. Some features, including recording"+
" violations generated by admission control, will not work.", err)
Expand Down
8 changes: 3 additions & 5 deletions sensor/common/sensor/sensor.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ var (
// A Sensor object configures a StackRox Sensor.
// Its functions execute common tasks across supported platforms.
type Sensor struct {
centralEndpoint string
advertisedEndpoint string
centralEndpoint string

configHandler config.Handler
detector detector.Detector
Expand Down Expand Up @@ -110,9 +109,8 @@ func NewSensor(
return nil, errors.Errorf("%q is enabled but the PubSubDispatcher is `nil`", features.SensorInternalPubSub.EnvVar())
}
return &Sensor{
clusterID: clusterID,
centralEndpoint: env.CentralEndpoint.Setting(),
advertisedEndpoint: env.AdvertisedEndpoint.Setting(),
clusterID: clusterID,
centralEndpoint: env.CentralEndpoint.Setting(),

pubSub: pubSub,
pubSubDispatcher: pubSubDispatcher,
Expand Down
Loading