Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSO: Add an option to the setup screen to enable SSO #2963

Merged
merged 5 commits into from
Sep 11, 2018
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ e2e-reports/
.stratos-git-metadata.json
src/jetstream/jetstream
src/jetstream/console-database.db
src/jetstream/config.properties

# Customisations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@
<input matInput type="password" formControlName="adminPassword" placeholder="Admin Password">
</mat-form-field>
</div>
<!-- Single Sign-on -->
<p class="uaa-wizard__form-section">UAA Single Sign On (SSO)</p>
<div class="uaa-wizard__form-block">
<mat-checkbox matInput formControlName="useSSO">Use SSO (Use the UAA's UI to login rather than the Stratos login UI)</mat-checkbox>
<p *ngIf="uaaForm.value.useSSO" class="uaa-wizard__sso-block">You must ensure that the client specified above has its 'redirect_uri' configured to include the Stratos SSO Callback URL:
<code>{{ clientRedirectURI }}</code>
</p>
</div>

</form>
</div>
</app-step>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
margin: 0 100px;
padding-top: 56px;
&__form {
display: flex;
display: block;
flex-direction: column;
width: 100%;
}
Expand All @@ -21,6 +21,14 @@
font-weight: 600;
padding-top: 36px;
}
&__sso-block {
margin-left: 28px;
margin-top: 6px;
code {
font-size: 14px;
padding-left: 6px;
}
}
form {
min-width: 400px;
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ import { UAASetupState } from '../../../store/types/uaa-setup.types';
})
export class ConsoleUaaWizardComponent implements OnInit {

constructor(private store: Store<AppState>, private router: Router) { }
private clientRedirectURI: string;

constructor(private store: Store<AppState>, private router: Router) {
// Client Redirect URI for SSO
this.clientRedirectURI = window.location.protocol + '//' + window.location.hostname +
(window.location.port ? ':' + window.location.port : '') + '/pp/v1/auth/sso_login_callback';
}

uaaForm: FormGroup;
validateUAAForm: Observable<boolean>;
Expand All @@ -36,6 +42,7 @@ export class ConsoleUaaWizardComponent implements OnInit {
skip_ssl_validation: this.uaaForm.get('skipSll').value,
username: this.uaaForm.get('adminUsername').value,
console_client_secret: this.uaaForm.get('clientSecret').value,
use_sso: this.uaaForm.get('useSSO').value,
}));
return this.store.select('uaaSetup').pipe(
skipWhile((state: UAASetupState) => {
Expand Down Expand Up @@ -97,6 +104,7 @@ export class ConsoleUaaWizardComponent implements OnInit {
clientSecret: new FormControl(''),
adminUsername: new FormControl('', [<any>Validators.required]),
adminPassword: new FormControl('', [<any>Validators.required]),
useSSO: new FormControl(false),
});

let observer;
Expand Down
1 change: 1 addition & 0 deletions src/frontend/app/store/effects/uaa-setup.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class UAASetupEffect {
params.set('password', setupData.password);
params.set('skip_ssl_validation', setupData.skip_ssl_validation.toString() || 'false');
params.set('uaa_endpoint', setupData.uaa_endpoint);
params.set('use_sso', setupData.use_sso.toString() || 'false');

if (setupData.console_client_secret) {
params.set('console_client_secret', setupData.console_client_secret);
Expand Down
1 change: 1 addition & 0 deletions src/frontend/app/store/types/uaa-setup.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export interface UaaSetupData {
uaa_endpoint: string;
username: string;
console_client_secret?: string;
use_sso: boolean;
}
16 changes: 16 additions & 0 deletions src/jetstream/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ func (p *portalProxy) GetUsername(userid string) (string, error) {

// Login via UAA
func (p *portalProxy) initSSOlogin(c echo.Context) error {
if !p.Config.SSOLogin {
err := interfaces.NewHTTPShadowError(
http.StatusNotFound,
"SSO Login is not enabled",
"SSO Login is not enabled")
return err
}

state := c.QueryParam("state")
if len(state) == 0 {
err := interfaces.NewHTTPShadowError(
Expand Down Expand Up @@ -119,6 +127,14 @@ func getSSORedirectURI(base string, state string, endpointGUID string) string {

// Logout of the UAA
func (p *portalProxy) ssoLogoutOfUAA(c echo.Context) error {
if !p.Config.SSOLogin {
err := interfaces.NewHTTPShadowError(
http.StatusNotFound,
"SSO Login is not enabled",
"SSO Login is not enabled")
return err
}

state := c.QueryParam("state")
if len(state) == 0 {
err := interfaces.NewHTTPShadowError(
Expand Down
5 changes: 5 additions & 0 deletions src/jetstream/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,8 @@ func LoadConfigFile(path string) error {

return nil
}

// SetConfigValue will update/set a value in the loaded configuration
func SetConfigValue(name, value string) {
loadedConfig[name] = value
}
20 changes: 20 additions & 0 deletions src/jetstream/datastore/20180907123000_SSOSetupFlag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package datastore

import (
"database/sql"

"bitbucket.org/liamstask/goose/lib/goose"
)

func init() {
RegisterMigration(20180813110300, "SSOSetupFlag", func(txn *sql.Tx, conf *goose.DBConf) error {

addTokenID := "ALTER TABLE console_config ADD use_sso BOOLEAN NOT NULL DEFAULT FALSE"
_, err := txn.Exec(addTokenID)
if err != nil {
return err
}

return nil
})
}
18 changes: 13 additions & 5 deletions src/jetstream/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ func initialiseConsoleConfiguration(portalProxy *portalProxy) (*setupMiddleware,
} else {
showStratosConfig(consoleConfig)
portalProxy.Config.ConsoleConfig = consoleConfig
setSSOFromConfig(portalProxy, consoleConfig)
}

} else if err == nil && isInitialised {
Expand All @@ -246,18 +247,27 @@ func initialiseConsoleConfiguration(portalProxy *portalProxy) (*setupMiddleware,
}
showStratosConfig(consoleConfig)
portalProxy.Config.ConsoleConfig = consoleConfig
setSSOFromConfig(portalProxy, consoleConfig)
}

return addSetupMiddleware, nil
}

func setSSOFromConfig(portalProxy *portalProxy, configuration *interfaces.ConsoleConfig) {
// For SSO, override the value loaded from the config file, so that this is what we use
if !config.IsSet("SSO_LOGIN") {
portalProxy.Config.SSOLogin = configuration.UseSSO
}
}

func showStratosConfig(config *interfaces.ConsoleConfig) {
log.Infof("Stratos is intialised with the following setup:")
log.Infof("... UAA Endpoint : %s", config.UAAEndpoint)
log.Infof("... Console Client : %s", config.ConsoleClient)
log.Infof("... Skip SSL Validation : %t", config.SkipSSLValidation)
log.Infof("... Setup Complete : %t", config.IsSetupComplete)
log.Infof("... Admin Scope : %s", config.ConsoleAdminScope)
log.Infof("... Use SSO Login : %t", config.UseSSO)
}

func showSSOConfig(portalProxy *portalProxy) {
Expand Down Expand Up @@ -674,11 +684,9 @@ func (p *portalProxy) registerRoutes(e *echo.Echo, addSetupMiddleware *setupMidd
pp.POST("/v1/auth/login/uaa", p.loginToUAA)
pp.POST("/v1/auth/logout", p.logout)

// Only add SSO routes if SSO Login is enabled
if p.Config.SSOLogin {
pp.GET("/v1/auth/sso_login", p.initSSOlogin)
pp.GET("/v1/auth/sso_logout", p.ssoLogoutOfUAA)
}
// SSO Routes will only respond if SSO is enabled
pp.GET("/v1/auth/sso_login", p.initSSOlogin)
pp.GET("/v1/auth/sso_logout", p.ssoLogoutOfUAA)

// Callback is use dby both login to Stratos and login to an Endpoint
pp.GET("/v1/auth/sso_login_callback", p.ssoLoginToUAA)
Expand Down
10 changes: 5 additions & 5 deletions src/jetstream/repository/console_config/psql_console_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import (
"github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
)

var getConsoleConfig = `SELECT uaa_endpoint, console_admin_scope, console_client, console_client_secret, skip_ssl_validation
var getConsoleConfig = `SELECT uaa_endpoint, console_admin_scope, console_client, console_client_secret, skip_ssl_validation, use_sso
FROM console_config`

var saveConsoleConfig = `INSERT INTO console_config (uaa_endpoint, console_admin_scope, console_client, console_client_secret, skip_ssl_validation, is_setup_complete)
VALUES ($1, $2, $3, $4, $5, $6)`
var saveConsoleConfig = `INSERT INTO console_config (uaa_endpoint, console_admin_scope, console_client, console_client_secret, skip_ssl_validation, is_setup_complete, use_sso)
VALUES ($1, $2, $3, $4, $5, $6, $7)`

var updateConsoleConfig = `UPDATE console_config SET console_admin_scope = $1, is_setup_complete = '1'`

Expand Down Expand Up @@ -72,7 +72,7 @@ func (c *ConsoleConfigRepository) GetConsoleConfig() (*interfaces.ConsoleConfig,

consoleConfig = new(interfaces.ConsoleConfig)
err := rows.Scan(&authEndpoint, &consoleConfig.ConsoleAdminScope, &consoleConfig.ConsoleClient,
&consoleConfig.ConsoleClientSecret, &consoleConfig.SkipSSLValidation)
&consoleConfig.ConsoleClientSecret, &consoleConfig.SkipSSLValidation, &consoleConfig.UseSSO)
if err != nil {
return nil, fmt.Errorf("Unable to scan config record: %v", err)
}
Expand All @@ -97,7 +97,7 @@ func (c *ConsoleConfigRepository) SaveConsoleConfig(config *interfaces.ConsoleCo
isComplete := config.ConsoleAdminScope != ""

if _, err := c.db.Exec(saveConsoleConfig, fmt.Sprintf("%s", config.UAAEndpoint),
config.ConsoleAdminScope, config.ConsoleClient, config.ConsoleClientSecret, config.SkipSSLValidation, isComplete); err != nil {
config.ConsoleAdminScope, config.ConsoleClient, config.ConsoleClientSecret, config.SkipSSLValidation, isComplete, config.UseSSO); err != nil {
return fmt.Errorf("Unable to Save Console Config record: %v", err)
}

Expand Down
1 change: 1 addition & 0 deletions src/jetstream/repository/interfaces/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ type ConsoleConfig struct {
ConsoleClientSecret string `json:"console_client_secret"`
SkipSSLValidation bool `json:"skip_ssl_validation"`
IsSetupComplete bool `json:"is_setup_complete"`
UseSSO bool `json:"use_sso"`
}

// CNSIRequest
Expand Down
8 changes: 8 additions & 0 deletions src/jetstream/setup_console.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ func (p *portalProxy) setupConsole(c echo.Context) error {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid Skip SSL Validation value")
}
consoleConfig.SkipSSLValidation = skipSSLValidation
ssoLogin, err := strconv.ParseBool(c.FormValue("use_sso"))
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid Use SSO value")
}
consoleConfig.UseSSO = ssoLogin

if err != nil {
return fmt.Errorf("Unable to intialise console backend config due to: %+v", err)
Expand Down Expand Up @@ -102,6 +107,9 @@ func (p *portalProxy) setupConsole(c echo.Context) error {
"Failed to store Console configuration data",
"Console configuration data storage failed due to %s", err)
}

setSSOFromConfig(p, consoleConfig)

c.JSON(http.StatusOK, userTokenInfo)
return nil
}
Expand Down