Skip to content

Commit

Permalink
Update terminology for SSO Accept List and add to Helm Chart docs (#4797
Browse files Browse the repository at this point in the history
)

* Docuement SSO Accept List and rename terminology

* Use Allow not Accept

* Update log message

* Remove debug logging

* Document SSO_OPTIONS
  • Loading branch information
nwmac authored Nov 26, 2020
1 parent 8a9f015 commit ac08975
Show file tree
Hide file tree
Showing 13 changed files with 49 additions and 33 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ This release contains a number of fixes and improvements:

**Improvements:**

- Apply SSO whitelist to additional places [\#4318](https://github.com/cloudfoundry/stratos/issues/4318)
- Apply SSO allow-list to additional places [\#4318](https://github.com/cloudfoundry/stratos/issues/4318)

**Fixes:**

Expand Down
2 changes: 2 additions & 0 deletions deploy/kubernetes/console/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ The following table lists the configurable parameters of the Stratos Helm chart
|imagePullPolicy|Image pull policy|IfNotPresent|
|console.sessionStoreSecret|Secret to use when encrypting session tokens|auto-generated random value|
|console.ssoLogin|Whether to enable SSO Login and use the UAA Login UI instead of the built-in one|false|
|console.ssoOptions|Advanced options to customize the SSO experience||
|console.ssoAllowList|List of permitted redirect URLs for SSO authentication||
|console.backendLogLevel|Log level for backend (info, debug)|info|
|console.service.externalIPs|External IPs to add to the console service|[]|
|console.service.loadBalancerIP|IP address to assign to the load balancer for the metrics service (if supported)||
Expand Down
6 changes: 5 additions & 1 deletion deploy/kubernetes/console/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,12 @@ spec:
value: {{default "false" .Values.console.ssoLogin | quote}}
- name: SSO_OPTIONS
value: {{default "" .Values.console.ssoOptions | quote}}
- name: SSO_WHITELIST
- name: SSO_ALLOWLIST
{{- if .Values.console.ssoAllowList }}
value: {{ default "" .Values.console.ssoAllowList | quote }}
{{- else }}
value: {{ default "" .Values.console.ssoWhiteList | quote }}
{{- end }}
{{- if .Values.console.templatesConfigMapName }}
- name: TEMPLATE_DIR
value: /etc/templates
Expand Down
2 changes: 1 addition & 1 deletion src/jetstream/authcnsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (p *portalProxy) ssoLoginToCNSI(c echo.Context) error {

if len(code) == 0 {
// First time around
// Use the standard SSO Login Callback endpoint, so this can be whitelisted for Stratos and Endpoint login
// Use the standard SSO Login Callback endpoint, so this can be allow-listed for Stratos and Endpoint login
returnURL := getSSORedirectURI(state, state, endpointGUID)
redirectURL := fmt.Sprintf("%s/oauth/authorize?response_type=code&client_id=%s&redirect_uri=%s",
cnsiRecord.AuthorizationEndpoint, cnsiRecord.ClientId, url.QueryEscape(returnURL))
Expand Down
20 changes: 10 additions & 10 deletions src/jetstream/authuaa.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,11 +442,11 @@ func (p *portalProxy) RefreshUAAToken(userGUID string) (t interfaces.TokenRecord
//SSO Login will be refactored at a later date

// ssoLoginToUAA is a callback invoked after the UAA login flow has completed and during logout
// We use a single callback so this can be whitelisted in the client
// We use a single callback so this can be allow-listed in the client
func (p *portalProxy) ssoLoginToUAA(c echo.Context) error {
state := c.QueryParam("state")

stateErr := validateSSORedirectState(state, p.Config.SSOWhiteList)
stateErr := validateSSORedirectState(state, p.Config.SSOAllowList)
if stateErr != nil {
return stateErr
}
Expand Down Expand Up @@ -526,7 +526,7 @@ func (p *portalProxy) initSSOlogin(c echo.Context) error {
}

state := c.QueryParam("state")
stateErr := validateSSORedirectState(state, p.Config.SSOWhiteList)
stateErr := validateSSORedirectState(state, p.Config.SSOAllowList)
if stateErr != nil {
return stateErr
}
Expand All @@ -536,15 +536,15 @@ func (p *portalProxy) initSSOlogin(c echo.Context) error {
return nil
}

func validateSSORedirectState(state string, whiteListStr string) error {
func validateSSORedirectState(state string, allowListStr string) error {
if len(state) == 0 {
err := interfaces.NewHTTPShadowError(
http.StatusUnauthorized,
"SSO Login: State parameter missing",
"SSO Login: State parameter missing")
return err
}
if !safeSSORedirectState(state, whiteListStr) {
if !safeSSORedirectState(state, allowListStr) {
err := interfaces.NewHTTPShadowError(
http.StatusUnauthorized,
"SSO Login: Disallowed redirect state",
Expand All @@ -555,17 +555,17 @@ func validateSSORedirectState(state string, whiteListStr string) error {
return nil
}

func safeSSORedirectState(state string, whiteListStr string) bool {
if len(whiteListStr) == 0 {
func safeSSORedirectState(state string, allowListStr string) bool {
if len(allowListStr) == 0 {
return true
}

whiteList := strings.Split(whiteListStr, ",")
if len(whiteList) == 0 {
allowList := strings.Split(allowListStr, ",")
if len(allowList) == 0 {
return true
}

for _, n := range whiteList {
for _, n := range allowList {
if stringutils.CompareURL(state, n) {
return true
}
Expand Down
4 changes: 2 additions & 2 deletions src/jetstream/config.dev
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ LOG_TO_JSON=false
LOG_API_REQUESTS=true

SSO_LOGIN=false
# Whitelist for the SSO redirect url. Paths can contain wildcard `*`
SSO_WHITELIST=
# Allow-list for the SSO redirect url. Paths can contain wildcard `*`
SSO_ALLOWLIST=

# Enable feature in tech preview
ENABLE_TECH_PREVIEW=true
Expand Down
4 changes: 2 additions & 2 deletions src/jetstream/config.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ LOG_TO_JSON=false
LOG_API_REQUESTS=true

SSO_LOGIN=false
# Whitelist for the SSO redirect url. Paths can contain wildcard `*`
SSO_WHITELIST=
# Allow-list for the SSO redirect url. Paths can contain wildcard `*`
SSO_ALLOWLIST=

# Enable feature in tech preview
ENABLE_TECH_PREVIEW=false
Expand Down
Binary file added src/jetstream/console-database.db2
Binary file not shown.
2 changes: 1 addition & 1 deletion src/jetstream/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ func showSSOConfig(portalProxy *portalProxy) {
log.Infof("SSO Configuration:")
log.Infof("... SSO Enabled : %t", portalProxy.Config.SSOLogin)
log.Infof("... SSO Options : %s", portalProxy.Config.SSOOptions)
log.Infof("... SSO Redirect Whitelist : %s", portalProxy.Config.SSOWhiteList)
log.Infof("... SSO Redirect Allow-list : %s", portalProxy.Config.SSOAllowList)
}

func getEncryptionKey(pc interfaces.PortalConfig) ([]byte, error) {
Expand Down
6 changes: 3 additions & 3 deletions src/jetstream/plugins/metrics/cloud_foundry.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

var (
cellQueryWhiteList = []string{
cellQueryAllowList = []string{
"firehose_value_metric_rep_unhealthy_cell",
"firehose_value_metric_rep_garden_health_check_failed",
"firehose_value_metric_rep_capacity_remaining_containers",
Expand Down Expand Up @@ -185,8 +185,8 @@ func (m *MetricsSpecification) makePrometheusRequest(c echo.Context, cnsiList []
}

func isAllowedCellMetricsQuery(query string) bool {
for _, whiteListQuery := range cellQueryWhiteList {
if strings.Index(query, whiteListQuery) == 0 {
for _, allowListQuery := range cellQueryAllowList {
if strings.Index(query, allowListQuery) == 0 {
return true
}
}
Expand Down
15 changes: 9 additions & 6 deletions src/jetstream/repository/interfaces/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,17 @@ func Load(intf interface{}, envLookup env.Lookup) error {
return nil
}

func setFieldValue(value reflect.Value, field reflect.Value, tag string, envLookup env.Lookup) error {
val, ok := envLookup(tag)

if !ok {
return nil
func setFieldValue(value reflect.Value, field reflect.Value, tags string, envLookup env.Lookup) error {
// Allow multiple values, separated by ',' to allow fallbacks
tagList := strings.Split(tags, ",")
for _, tag := range tagList {
val, ok := envLookup(strings.TrimSpace(tag))
if ok {
return SetStructFieldValue(value, field, val)
}
}

return SetStructFieldValue(value, field, val)
return nil
}

func SetStructFieldValue(value reflect.Value, field reflect.Value, val string) error {
Expand Down
2 changes: 1 addition & 1 deletion src/jetstream/repository/interfaces/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ type PortalConfig struct {
AutoRegisterCFName string `configName:"AUTO_REG_CF_NAME"`
SSOLogin bool `configName:"SSO_LOGIN"`
SSOOptions string `configName:"SSO_OPTIONS"`
SSOWhiteList string `configName:"SSO_WHITELIST"`
SSOAllowList string `configName:"SSO_ALLOWLIST,SSO_WHITELIST"`
AuthEndpointType string `configName:"AUTH_ENDPOINT_TYPE"`
CookieDomain string `configName:"COOKIE_DOMAIN"`
LogLevel string `configName:"LOG_LEVEL"`
Expand Down
17 changes: 12 additions & 5 deletions website/docs/advanced/sso.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,28 @@ The `authorized_grant_types` value should contain `authorization_code`. If not u
uaac client update cf --authorized_grant_types authorization_code
```

## Adding a Stratos SSO State Whitelist
## Adding a Stratos SSO State Allow-list

When SSO has been configured Stratos's log in request will contain a URL that tells SSO where to return to. When using a browser this is automatically populated. To avoid situations where this can be hijacked or called separately an SSO `state` whitelist can be provided via the environment variable `SSO_WHITELIST`. This is a comma separated list. For example...
When SSO has been configured Stratos's log in request will contain a URL that tells SSO where to return to. When using a browser this is automatically populated. To avoid situations where this can be hijacked or called separately an SSO `state` allow-list can be provided via the environment variable `SSO_ALLOWLIST`. This is a comma separated list. For example...

```
SSO_WHITELIST=https://your.domain/*
SSO_ALLOWLIST=https://your.domain/*
```

```
SSO_WHITELIST=https://your.domain/*,https://your.other.domain/*
SSO_ALLOWLIST=https://your.domain/*,https://your.other.domain/*
```

When set, any requests to log in with a different `state` will be denied.

In order for the SSO `state` to match an entry from the whitelist the schema, hostname, port and path must match exactly. A wildcard `*` can be provided for the path to match anything.
In order for the SSO `state` to match an entry from the allow-list the schema, hostname, port and path must match exactly. A wildcard `*` can be provided for the path to match anything.


## Advanced Configuration

Further configuration of SSO is provided through the `SSO_OPTIONS` environment variable.

Setting this variable to `nosplash` will skip the need for users to press the Login button - users will jump straight to the configured SSO endpoint when accessing Stratos instead of first seeing the Stratos login page.

## Troubleshooting

Expand Down

0 comments on commit ac08975

Please sign in to comment.