diff --git a/pkg/scalers/selenium_grid_scaler.go b/pkg/scalers/selenium_grid_scaler.go index 842f0f9ca5a..73b8c88380f 100644 --- a/pkg/scalers/selenium_grid_scaler.go +++ b/pkg/scalers/selenium_grid_scaler.go @@ -28,9 +28,11 @@ type seleniumGridScaler struct { type seleniumGridScalerMetadata struct { triggerIndex int - URL string `keda:"name=url, order=triggerMetadata;authParams"` - Username string `keda:"name=username, order=triggerMetadata;authParams, optional"` - Password string `keda:"name=password, order=triggerMetadata;authParams, optional"` + URL string `keda:"name=url, order=authParams;triggerMetadata"` + AuthType string `keda:"name=authType, order=authParams, optional"` + Username string `keda:"name=username, order=authParams, optional"` + Password string `keda:"name=password, order=authParams, optional"` + AccessToken string `keda:"name=accessToken, order=authParams, optional"` BrowserName string `keda:"name=browserName, order=triggerMetadata"` SessionBrowserName string `keda:"name=sessionBrowserName, order=triggerMetadata, optional"` ActivationThreshold int64 `keda:"name=activationThreshold, order=triggerMetadata, optional"` @@ -196,8 +198,10 @@ func (s *seleniumGridScaler) getSessionsCount(ctx context.Context, logger logr.L return -1, err } - if s.metadata.Username != "" && s.metadata.Password != "" { + if (s.metadata.AuthType == "" || strings.EqualFold(s.metadata.AuthType, "Basic")) && s.metadata.Username != "" && s.metadata.Password != "" { req.SetBasicAuth(s.metadata.Username, s.metadata.Password) + } else if !strings.EqualFold(s.metadata.AuthType, "Basic") && s.metadata.AccessToken != "" { + req.Header.Set("Authorization", fmt.Sprintf("%s %s", s.metadata.AuthType, s.metadata.AccessToken)) } res, err := s.httpClient.Do(req) diff --git a/pkg/scalers/selenium_grid_scaler_test.go b/pkg/scalers/selenium_grid_scaler_test.go index c31c151be31..b1abdd12d93 100644 --- a/pkg/scalers/selenium_grid_scaler_test.go +++ b/pkg/scalers/selenium_grid_scaler_test.go @@ -1761,13 +1761,11 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { }, }, { - name: "valid url, browsername, unsafeSsl, activationThreshold, nodeMaxSessions and platformName should return metadata", + name: "valid url, browsername, unsafeSsl, activationThreshold, nodeMaxSessions and platformName with trigger auth params should return metadata", args: args{ config: &scalersconfig.ScalerConfig{ TriggerMetadata: map[string]string{ "url": "http://selenium-hub:4444/graphql", - "username": "user", - "password": "password", "browserName": "chrome", "browserVersion": "91.0", "unsafeSsl": "true", @@ -1775,6 +1773,45 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { "platformName": "Windows 11", "nodeMaxSessions": "3", }, + AuthParams: map[string]string{ + "username": "user", + "password": "password", + }, + }, + }, + wantErr: false, + want: &seleniumGridScalerMetadata{ + URL: "http://selenium-hub:4444/graphql", + Username: "user", + Password: "password", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "Windows 11", + NodeMaxSessions: 3, + }, + }, + { + name: "url in trigger auth param takes precedence over url in trigger metadata", + args: args{ + config: &scalersconfig.ScalerConfig{ + TriggerMetadata: map[string]string{ + "url": "http://invalid.dns:4444/graphql", + "browserName": "chrome", + "browserVersion": "91.0", + "unsafeSsl": "true", + "activationThreshold": "10", + "platformName": "Windows 11", + "nodeMaxSessions": "3", + }, + AuthParams: map[string]string{ + "url": "http://selenium-hub:4444/graphql", + "username": "user", + "password": "password", + }, }, }, wantErr: false, @@ -1792,6 +1829,75 @@ func Test_parseSeleniumGridScalerMetadata(t *testing.T) { NodeMaxSessions: 3, }, }, + { + name: "auth type is not Basic and access token is provided", + args: args{ + config: &scalersconfig.ScalerConfig{ + TriggerMetadata: map[string]string{ + "url": "http://selenium-hub:4444/graphql", + "browserName": "chrome", + "browserVersion": "91.0", + "unsafeSsl": "true", + "activationThreshold": "10", + "platformName": "Windows 11", + "nodeMaxSessions": "3", + }, + AuthParams: map[string]string{ + "url": "http://selenium-hub:4444/graphql", + "authType": "OAuth2", + "accessToken": "my-access-token", + }, + }, + }, + wantErr: false, + want: &seleniumGridScalerMetadata{ + URL: "http://selenium-hub:4444/graphql", + AuthType: "OAuth2", + AccessToken: "my-access-token", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "Windows 11", + NodeMaxSessions: 3, + }, + }, + { + name: "authenticating with bearer access token", + args: args{ + config: &scalersconfig.ScalerConfig{ + TriggerMetadata: map[string]string{ + "browserName": "chrome", + "browserVersion": "91.0", + "unsafeSsl": "true", + "activationThreshold": "10", + "platformName": "Windows 11", + "nodeMaxSessions": "3", + }, + AuthParams: map[string]string{ + "url": "http://selenium-hub:4444/graphql", + "authType": "Bearer", + "accessToken": "my-access-token", + }, + }, + }, + wantErr: false, + want: &seleniumGridScalerMetadata{ + URL: "http://selenium-hub:4444/graphql", + AuthType: "Bearer", + AccessToken: "my-access-token", + BrowserName: "chrome", + SessionBrowserName: "chrome", + TargetValue: 1, + ActivationThreshold: 10, + BrowserVersion: "91.0", + UnsafeSsl: true, + PlatformName: "Windows 11", + NodeMaxSessions: 3, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/tests/scalers/selenium/selenium_test.go b/tests/scalers/selenium/selenium_test.go index b5751ff2159..a5bb01bdd97 100644 --- a/tests/scalers/selenium/selenium_test.go +++ b/tests/scalers/selenium/selenium_test.go @@ -24,37 +24,47 @@ const ( ) var ( - testNamespace = fmt.Sprintf("%s-ns", testName) - chromeDeploymentName = fmt.Sprintf("%s-chrome", testName) - firefoxDeploymentName = fmt.Sprintf("%s-firefox", testName) - edgeDeploymentName = fmt.Sprintf("%s-edge", testName) - hubDeploymentName = fmt.Sprintf("%s-hub", testName) - scaledObjectName = fmt.Sprintf("%s-so", testName) - hubHost = fmt.Sprintf("selenium-hub.%s", testNamespace) - hubPort = 4444 - hubGraphURL = fmt.Sprintf("http://%s:%d/graphql", hubHost, hubPort) - HubBasicAuthUsername = "admin" - HubBasicAuthPassword = "admin" - minReplicaCount = 0 - maxReplicaCount = 1 + testNamespace = fmt.Sprintf("%s-ns", testName) + secretName = fmt.Sprintf("%s-secret", testName) + triggerAuthName = fmt.Sprintf("%s-trigger-auth", testName) + chromeDeploymentName = fmt.Sprintf("%s-chrome", testName) + firefoxDeploymentName = fmt.Sprintf("%s-firefox", testName) + edgeDeploymentName = fmt.Sprintf("%s-edge", testName) + hubDeploymentName = fmt.Sprintf("%s-hub", testName) + scaledObjectName = fmt.Sprintf("%s-so", testName) + hubHost = fmt.Sprintf("%s:%s@selenium-hub.%s", hubBasicAuthUsername, hubBasicAuthPassword, testNamespace) + hubPort = 4444 + hubGraphURL = fmt.Sprintf("http://%s:%d/graphql", hubHost, hubPort) + hubBasicAuthUsername = "admin" + hubBasicAuthPassword = "admin" + hubBasicAuthUsernameB64enc = "YWRtaW4=" + hubBasicAuthPasswordB64enc = "YWRtaW4=" + hubBasicAuthHeader = "YWRtaW46YWRtaW4=" + minReplicaCount = 0 + maxReplicaCount = 1 ) type templateData struct { - TestNamespace string - ChromeDeploymentName string - FirefoxDeploymentName string - EdgeDeploymentName string - HubDeploymentName string - HubHost string - HubPort int - HubGraphURL string - HubBasicAuthUsername string - HubBasicAuthPassword string - WithVersion bool - JobName string - ScaledObjectName string - MinReplicaCount int - MaxReplicaCount int + TestNamespace string + SecretName string + TriggerAuthName string + ChromeDeploymentName string + FirefoxDeploymentName string + EdgeDeploymentName string + HubDeploymentName string + HubHost string + HubPort int + HubGraphURL string + HubBasicAuthUsername string + HubBasicAuthPassword string + HubBasicAuthUsernameB64enc string + HubBasicAuthPasswordB64enc string + HubBasicAuthHeader string + WithVersion bool + JobName string + ScaledObjectName string + MinReplicaCount int + MaxReplicaCount int } const ( @@ -145,6 +155,34 @@ spec: sizeLimit: 1Gi ` + secretTemplate = ` +apiVersion: v1 +kind: Secret +metadata: + name: {{.SecretName}} + namespace: {{.TestNamespace}} +type: Opaque +data: + username: '{{.HubBasicAuthUsernameB64enc}}' + password: '{{.HubBasicAuthPasswordB64enc}}' +` + + scaledTriggerAuthTemplate = ` +apiVersion: keda.sh/v1alpha1 +kind: TriggerAuthentication +metadata: + name: {{.TriggerAuthName}} + namespace: {{.TestNamespace}} +spec: + secretTargetRef: + - parameter: username + name: {{.SecretName}} + key: username + - parameter: password + name: {{.SecretName}} + key: password +` + chromeScaledObjectTemplate = ` apiVersion: keda.sh/v1alpha1 kind: ScaledObject @@ -161,10 +199,10 @@ spec: - type: selenium-grid metadata: url: '{{.HubGraphURL}}' - username: '{{.HubBasicAuthUsername}}' - password: '{{.HubBasicAuthPassword}}' browserName: 'chrome' activationThreshold: '1' + authenticationRef: + name: '{{.TriggerAuthName}}' ` firefoxNodeServiceTemplate = ` @@ -251,10 +289,10 @@ spec: - type: selenium-grid metadata: url: '{{.HubGraphURL}}' - username: '{{.HubBasicAuthUsername}}' - password: '{{.HubBasicAuthPassword}}' browserName: 'firefox' activationThreshold: '1' + authenticationRef: + name: '{{.TriggerAuthName}}' ` edgeNodeServiceTemplate = ` @@ -342,11 +380,11 @@ spec: - type: selenium-grid metadata: url: '{{.HubGraphURL}}' - username: '{{.HubBasicAuthUsername}}' - password: '{{.HubBasicAuthPassword}}' browserName: 'MicrosoftEdge' sessionBrowserName: 'msedge' activationThreshold: '1' + authenticationRef: + name: '{{.TriggerAuthName}}' ` hubServiceTemplate = ` @@ -409,10 +447,10 @@ spec: image: selenium/hub:latest imagePullPolicy: IfNotPresent env: - - name: SE_ROUTER_USERNAME - value: '{{.HubBasicAuthUsername}}' - - name: SE_ROUTER_PASSWORD - value: '{{.HubBasicAuthPassword}}' + - name: SE_ROUTER_USERNAME + value: '{{.HubBasicAuthUsername}}' + - name: SE_ROUTER_PASSWORD + value: '{{.HubBasicAuthPassword}}' ports: - containerPort: 4444 protocol: TCP @@ -424,6 +462,9 @@ spec: httpGet: path: /wd/hub/status port: 4444 + httpHeaders: + - name: Authorization + value: Basic {{.HubBasicAuthHeader}} initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 10 @@ -433,6 +474,9 @@ spec: httpGet: path: /wd/hub/status port: 4444 + httpHeaders: + - name: Authorization + value: Basic {{.HubBasicAuthHeader}} initialDelaySeconds: 12 periodSeconds: 10 timeoutSeconds: 10 @@ -534,20 +578,27 @@ func testScaleIn(t *testing.T, kc *kubernetes.Clientset) { func getTemplateData() (templateData, []Template) { return templateData{ - TestNamespace: testNamespace, - ChromeDeploymentName: chromeDeploymentName, - FirefoxDeploymentName: firefoxDeploymentName, - EdgeDeploymentName: edgeDeploymentName, - HubDeploymentName: hubDeploymentName, - HubHost: hubHost, - HubPort: hubPort, - HubGraphURL: hubGraphURL, - HubBasicAuthUsername: HubBasicAuthUsername, - HubBasicAuthPassword: HubBasicAuthPassword, - ScaledObjectName: scaledObjectName, - MinReplicaCount: minReplicaCount, - MaxReplicaCount: maxReplicaCount, + TestNamespace: testNamespace, + SecretName: secretName, + TriggerAuthName: triggerAuthName, + ChromeDeploymentName: chromeDeploymentName, + FirefoxDeploymentName: firefoxDeploymentName, + EdgeDeploymentName: edgeDeploymentName, + HubDeploymentName: hubDeploymentName, + HubHost: hubHost, + HubPort: hubPort, + HubGraphURL: hubGraphURL, + HubBasicAuthUsername: hubBasicAuthUsername, + HubBasicAuthPassword: hubBasicAuthPassword, + HubBasicAuthUsernameB64enc: hubBasicAuthUsernameB64enc, + HubBasicAuthPasswordB64enc: hubBasicAuthPasswordB64enc, + HubBasicAuthHeader: hubBasicAuthHeader, + ScaledObjectName: scaledObjectName, + MinReplicaCount: minReplicaCount, + MaxReplicaCount: maxReplicaCount, }, []Template{ + {Name: "secretTemplate", Config: secretTemplate}, + {Name: "scaledTriggerAuthTemplate", Config: scaledTriggerAuthTemplate}, {Name: "eventBusConfigTemplate", Config: eventBusConfigTemplate}, {Name: "hubDeploymentTemplate", Config: hubDeploymentTemplate}, {Name: "hubServiceTemplate", Config: hubServiceTemplate},