diff --git a/src/frontend/packages/core/src/app.component.spec.ts b/src/frontend/packages/core/src/app.component.spec.ts
index 1894f848e5..4b08b3b607 100644
--- a/src/frontend/packages/core/src/app.component.spec.ts
+++ b/src/frontend/packages/core/src/app.component.spec.ts
@@ -4,6 +4,7 @@ import { createBasicStoreModule } from '@stratosui/store/testing';
import { CoreTestingModule } from '../test-framework/core-test.modules';
import { AppComponent } from './app.component';
+import { CurrentUserPermissionsService } from './core/permissions/current-user-permissions.service';
import { LoggedInService } from './logged-in.service';
import { SharedModule } from './shared/shared.module';
@@ -15,7 +16,8 @@ describe('AppComponent', () => {
AppComponent
],
providers: [
- LoggedInService
+ LoggedInService,
+ CurrentUserPermissionsService,
],
imports: [
SharedModule,
diff --git a/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts b/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts
index 98735c99cb..d8eb49e153 100644
--- a/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts
+++ b/src/frontend/packages/core/src/core/permissions/stratos-user-permissions.checker.ts
@@ -22,10 +22,12 @@ import {
export enum StratosCurrentUserPermissions {
ENDPOINT_REGISTER = 'register.endpoint',
PASSWORD_CHANGE = 'change-password',
+ EDIT_PROFILE = 'edit-profile',
/**
* Does the user have permission to view/create/delete their own API Keys?
*/
- API_KEYS = 'api-keys'
+ API_KEYS = 'api-keys',
+ CAN_NOT_LOGOUT = 'no-logout'
}
export enum StratosPermissionStrings {
@@ -36,7 +38,9 @@ export enum StratosPermissionStrings {
export enum StratosScopeStrings {
STRATOS_CHANGE_PASSWORD = 'password.write',
- SCIM_READ = 'scim.read'
+ SCIM_READ = 'scim.read',
+ SCIM_WRITE = 'scim.write',
+ STRATOS_NOAUTH = 'stratos.noauth'
}
export enum StratosPermissionTypes {
@@ -57,7 +61,15 @@ export const stratosPermissionConfigs: IPermissionConfigs = {
StratosPermissionTypes.STRATOS_SCOPE,
StratosScopeStrings.STRATOS_CHANGE_PASSWORD
),
- [StratosCurrentUserPermissions.API_KEYS]: new PermissionConfig(StratosPermissionTypes.API_KEY, '')
+ [StratosCurrentUserPermissions.EDIT_PROFILE]: new PermissionConfig(
+ StratosPermissionTypes.STRATOS_SCOPE,
+ StratosScopeStrings.SCIM_WRITE
+ ),
+ [StratosCurrentUserPermissions.API_KEYS]: new PermissionConfig(StratosPermissionTypes.API_KEY, ''),
+ [StratosCurrentUserPermissions.CAN_NOT_LOGOUT]: new PermissionConfig(
+ StratosPermissionTypes.STRATOS_SCOPE,
+ StratosScopeStrings.STRATOS_NOAUTH
+ ),
};
export class StratosUserPermissionsChecker extends BaseCurrentUserPermissionsChecker implements ICurrentUserPermissionsChecker {
diff --git a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.html b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.html
index c08c7704c5..8c4cf894bf 100644
--- a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.html
+++ b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.html
@@ -54,8 +54,8 @@
User Profile
-
-
+
+
diff --git a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts
index 915ecd6aea..d696e016dd 100644
--- a/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts
+++ b/src/frontend/packages/core/src/features/user-profile/profile-info/profile-info.component.ts
@@ -1,6 +1,6 @@
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
-import { Observable } from 'rxjs';
+import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SetPollingEnabledAction, SetSessionTimeoutAction } from '../../../../../store/src/actions/dashboard-actions';
@@ -8,6 +8,8 @@ import { DashboardOnlyAppState } from '../../../../../store/src/app-state';
import { selectDashboardState } from '../../../../../store/src/selectors/dashboard.selectors';
import { ThemeService } from '../../../../../store/src/theme.service';
import { UserProfileInfo } from '../../../../../store/src/types/user-profile.types';
+import { CurrentUserPermissionsService } from '../../../core/permissions/current-user-permissions.service';
+import { StratosCurrentUserPermissions } from '../../../core/permissions/stratos-user-permissions.checker';
import { UserProfileService } from '../../../core/user-profile.service';
import { UserService } from '../../../core/user.service';
import { SetGravatarEnabledAction } from './../../../../../store/src/actions/dashboard-actions';
@@ -72,11 +74,15 @@ export class ProfileInfoComponent {
private userProfileService: UserProfileService,
private store: Store
,
public userService: UserService,
- public themeService: ThemeService
+ public themeService: ThemeService,
+ private currentUserPermissionsService: CurrentUserPermissionsService,
) {
this.isError$ = userProfileService.isError$;
this.userProfile$ = userProfileService.userProfile$;
- this.canEdit$ = this.isError$.pipe(map(e => !e));
+
+ const canEdit = this.isError$.pipe(map(e => !e));
+ const hasEditPermissions = this.currentUserPermissionsService.can(StratosCurrentUserPermissions.EDIT_PROFILE);
+ this.canEdit$ = combineLatest([canEdit, hasEditPermissions]).pipe(map(([a, b]) => a && b));
this.primaryEmailAddress$ = this.userProfile$.pipe(
map((profile: UserProfileInfo) => userProfileService.getPrimaryEmailAddress(profile))
diff --git a/src/frontend/packages/core/src/logged-in.service.spec.ts b/src/frontend/packages/core/src/logged-in.service.spec.ts
index 9d4deef54d..5fba856de1 100644
--- a/src/frontend/packages/core/src/logged-in.service.spec.ts
+++ b/src/frontend/packages/core/src/logged-in.service.spec.ts
@@ -4,6 +4,7 @@ import { createBasicStoreModule } from '@stratosui/store/testing';
import { CoreTestingModule } from '../test-framework/core-test.modules';
import { CoreModule } from './core/core.module';
+import { CurrentUserPermissionsService } from './core/permissions/current-user-permissions.service';
import { LoggedInService } from './logged-in.service';
describe('LoggedInService', () => {
@@ -12,6 +13,7 @@ describe('LoggedInService', () => {
TestBed.configureTestingModule({
providers: [
LoggedInService,
+ CurrentUserPermissionsService,
],
imports: [
CoreModule,
diff --git a/src/frontend/packages/core/src/logged-in.service.ts b/src/frontend/packages/core/src/logged-in.service.ts
index b9b36cab62..e795c26601 100644
--- a/src/frontend/packages/core/src/logged-in.service.ts
+++ b/src/frontend/packages/core/src/logged-in.service.ts
@@ -2,7 +2,7 @@ import { DOCUMENT } from '@angular/common';
import { Inject, Injectable, NgZone } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
-import { fromEvent, interval, merge, Subscription } from 'rxjs';
+import { combineLatest, fromEvent, interval, merge, Subscription } from 'rxjs';
import { tap, withLatestFrom } from 'rxjs/operators';
import { VerifySession } from '../../store/src/actions/auth.actions';
@@ -12,6 +12,8 @@ import { selectDashboardState } from '../../store/src/selectors/dashboard.select
import { DashboardState } from './../../store/src/reducers/dashboard-reducer';
import { LogOutDialogComponent } from './core/log-out-dialog/log-out-dialog.component';
import { PageVisible } from './core/page-visible';
+import { CurrentUserPermissionsService } from './core/permissions/current-user-permissions.service';
+import { StratosCurrentUserPermissions } from './core/permissions/stratos-user-permissions.checker';
@Injectable()
export class LoggedInService {
@@ -19,9 +21,9 @@ export class LoggedInService {
@Inject(DOCUMENT) private document: Document,
private store: Store,
private dialog: MatDialog,
- private ngZone: NgZone
- ) {
- }
+ private ngZone: NgZone,
+ private currentUserPermissionsService: CurrentUserPermissionsService,
+ ) { }
private userInteractionChecker: Subscription;
@@ -53,24 +55,25 @@ export class LoggedInService {
return fromEvent(document, eventName);
});
- this.sub = this.store.select(s => s.auth)
- .subscribe((auth: AuthState) => {
- if (auth.loggedIn && auth.sessionData && auth.sessionData.valid && !auth.error) {
- if (!this.sessionChecker || this.sessionChecker.closed) {
- this.openSessionCheckerPoll();
- }
- if (!this.userInteractionChecker) {
- this.userInteractionChecker = merge(...eventStreams).subscribe(() => {
- this.lastUserInteraction = Date.now();
- });
- }
- } else {
- this.closeSessionCheckerPoll();
- if (this.userInteractionChecker) {
- this.userInteractionChecker.unsubscribe();
- }
+ const auth$ = this.store.select(s => s.auth);
+ const canNotLogout$ = this.currentUserPermissionsService.can(StratosCurrentUserPermissions.CAN_NOT_LOGOUT);
+ this.sub = combineLatest([auth$, canNotLogout$]).subscribe(([auth, canNotLogout]) => {
+ if (!canNotLogout && auth.loggedIn && auth.sessionData && auth.sessionData.valid && !auth.error) {
+ if (!this.sessionChecker || this.sessionChecker.closed) {
+ this.openSessionCheckerPoll();
+ }
+ if (!this.userInteractionChecker) {
+ this.userInteractionChecker = merge(...eventStreams).subscribe(() => {
+ this.lastUserInteraction = Date.now();
+ });
+ }
+ } else {
+ this.closeSessionCheckerPoll();
+ if (this.userInteractionChecker) {
+ this.userInteractionChecker.unsubscribe();
}
- });
+ }
+ });
}
destroy() {
diff --git a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html
index 5f6c34fe7d..2f3e65cd54 100644
--- a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html
+++ b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.html
@@ -78,9 +78,9 @@
-
+
-
diff --git a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.ts b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.ts
index 010c2b9b90..8607daee2b 100644
--- a/src/frontend/packages/core/src/shared/components/page-header/page-header.component.ts
+++ b/src/frontend/packages/core/src/shared/components/page-header/page-header.component.ts
@@ -117,6 +117,7 @@ export class PageHeaderComponent implements OnDestroy, AfterViewInit {
public username$: Observable
;
public user$: Observable;
public allowGravatar$: Observable;
+ public canLogout$: Observable;
public actionsKey: string;
@@ -162,6 +163,7 @@ export class PageHeaderComponent implements OnDestroy, AfterViewInit {
private userProfileService: UserProfileService,
private cups: CurrentUserPermissionsService,
private endpointsService: EndpointsService,
+ private currentUserPermissionsService: CurrentUserPermissionsService,
) {
this.events$ = eventService.events$.pipe(
startWith([])
@@ -199,6 +201,11 @@ export class PageHeaderComponent implements OnDestroy, AfterViewInit {
]).pipe(
map(([disabled, permission]) => !disabled && permission)
);
+
+ this.canLogout$ = this.currentUserPermissionsService.can(StratosCurrentUserPermissions.CAN_NOT_LOGOUT).pipe(
+ map(noLogout => !noLogout)
+ );
+
}
ngOnDestroy() {
diff --git a/src/jetstream/auth.go b/src/jetstream/auth.go
index 6b6365c629..27eadb5762 100644
--- a/src/jetstream/auth.go
+++ b/src/jetstream/auth.go
@@ -36,6 +36,11 @@ func (p *portalProxy) InitStratosAuthService(t interfaces.AuthEndpointType) erro
databaseConnectionPool: p.DatabaseConnectionPool,
p: p,
}
+ case interfaces.AuthNone:
+ auth = &noAuth{
+ databaseConnectionPool: p.DatabaseConnectionPool,
+ p: p,
+ }
default:
err := fmt.Errorf("Invalid auth endpoint type: %v", t)
return err
diff --git a/src/jetstream/auth_test.go b/src/jetstream/auth_test.go
index 2394f95f8a..07cf174a5d 100644
--- a/src/jetstream/auth_test.go
+++ b/src/jetstream/auth_test.go
@@ -811,6 +811,12 @@ func TestVerifySessionNoDate(t *testing.T) {
res, _, ctx, pp, db, _ := setupHTTPTest(req)
defer db.Close()
+ //Init the auth service
+ err := pp.InitStratosAuthService(interfaces.Local)
+ if err != nil {
+ log.Fatalf("Could not initialise auth service: %v", err)
+ }
+
// Set a dummy userid in session - normally the login to UAA would do this.
sessionValues := make(map[string]interface{})
sessionValues["user_id"] = mockUserGUID
@@ -822,7 +828,7 @@ func TestVerifySessionNoDate(t *testing.T) {
So(errSession, ShouldBeNil)
})
- err := pp.verifySession(ctx)
+ err = pp.verifySession(ctx)
Convey("Should not fail to verify session.", func() {
So(err, ShouldBeNil)
})
diff --git a/src/jetstream/authlocal.go b/src/jetstream/authlocal.go
index 8724274341..e36c731a23 100644
--- a/src/jetstream/authlocal.go
+++ b/src/jetstream/authlocal.go
@@ -27,6 +27,11 @@ type localAuth struct {
p *portalProxy
}
+func (a *localAuth) ShowConfig(config *interfaces.ConsoleConfig) {
+ log.Infof("... Local User : %s", config.LocalUser)
+ log.Infof("... Local User Scope : %s", config.LocalUserScope)
+}
+
//Login provides Local-auth specific Stratos login
func (a *localAuth) Login(c echo.Context) error {
@@ -99,9 +104,10 @@ func (a *localAuth) GetUser(userGUID string) (*interfaces.ConnectedUser, error)
uaaAdmin := (user.Scope == a.p.Config.ConsoleConfig.ConsoleAdminScope)
var scopes []string
- scopes = make([]string, 2)
+ scopes = make([]string, 3)
scopes[0] = user.Scope
scopes[1] = "password.write"
+ scopes[2] = "scim.write"
connectdUser := &interfaces.ConnectedUser{
GUID: userGUID,
@@ -113,6 +119,8 @@ func (a *localAuth) GetUser(userGUID string) (*interfaces.ConnectedUser, error)
return connectdUser, nil
}
+func (a *localAuth) BeforeVerifySession(c echo.Context) {}
+
//VerifySession verifies the session the specified local user, currently just verifies user exists
func (a *localAuth) VerifySession(c echo.Context, sessionUser string, sessionExpireTime int64) error {
localUsersRepo, err := localusers.NewPgsqlLocalUsersRepository(a.databaseConnectionPool)
diff --git a/src/jetstream/authnone.go b/src/jetstream/authnone.go
new file mode 100644
index 0000000000..10f4fb6cd4
--- /dev/null
+++ b/src/jetstream/authnone.go
@@ -0,0 +1,155 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "errors"
+ "math"
+ "net/http"
+
+ log "github.com/sirupsen/logrus"
+
+ "github.com/labstack/echo/v4"
+
+ "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
+)
+
+const (
+ noAuthUserID = "10000000-1111-2222-3333-444444444444"
+)
+
+//More fields will be moved into here as global portalProxy struct is phased out
+type noAuth struct {
+ databaseConnectionPool *sql.DB
+ localUserScope string
+ consoleAdminScope string
+ p *portalProxy
+}
+
+func (a *noAuth) ShowConfig(config *interfaces.ConsoleConfig) {
+ log.Info("... !!!!! No Authentication !!!!!")
+}
+
+//Login provides no-auth specific Stratos login
+func (a *noAuth) Login(c echo.Context) error {
+ return errors.New("Can not login when there is no auth")
+}
+
+//Logout provides no-auth specific Stratos login
+func (a *noAuth) Logout(c echo.Context) error {
+ return a.logout(c)
+}
+
+//GetUsername gets the user name for the specified local user
+func (a *noAuth) GetUsername(userid string) (string, error) {
+ return interfaces.DefaultAdminUserName, nil
+}
+
+//GetUser gets the user guid for the specified local user
+func (a *noAuth) GetUser(userGUID string) (*interfaces.ConnectedUser, error) {
+ var scopes []string
+ scopes = make([]string, 1)
+ scopes[0] = "stratos.noauth"
+
+ connectdUser := &interfaces.ConnectedUser{
+ GUID: noAuthUserID,
+ Name: interfaces.DefaultAdminUserName,
+ Admin: true,
+ Scopes: scopes,
+ }
+
+ return connectdUser, nil
+}
+
+func (a *noAuth) BeforeVerifySession(c echo.Context) {
+ var err error
+ var expiry int64
+ expiry = math.MaxInt64
+
+ session, err := a.p.GetSession(c)
+ if err != nil {
+ // No session, so create one
+ session, err = a.p.NewSession(c)
+ a.p.SaveSession(c, session)
+ }
+
+ sessionValues := make(map[string]interface{})
+ sessionValues["user_id"] = noAuthUserID
+ sessionValues["exp"] = expiry
+
+ // Ensure that login disregards cookies from the request
+ req := c.Request()
+ req.Header.Set("Cookie", "")
+ if err = a.p.setSessionValues(c, sessionValues); err == nil {
+ //Makes sure the client gets the right session expiry time
+ a.p.handleSessionExpiryHeader(c)
+ }
+}
+
+//VerifySession for no authentication - always passes
+func (a *noAuth) VerifySession(c echo.Context, sessionUser string, sessionExpireTime int64) error {
+ return nil
+}
+
+//generateLoginSuccessResponse
+func (a *noAuth) generateLoginSuccessResponse(c echo.Context, userGUID string, username string) error {
+ log.Debug("generateLoginResponse")
+
+ var err error
+ var expiry int64
+ expiry = math.MaxInt64
+
+ sessionValues := make(map[string]interface{})
+ sessionValues["user_id"] = userGUID
+ sessionValues["exp"] = expiry
+
+ // Ensure that login disregards cookies from the request
+ req := c.Request()
+ req.Header.Set("Cookie", "")
+ if err = a.p.setSessionValues(c, sessionValues); err != nil {
+ return err
+ }
+
+ //Makes sure the client gets the right session expiry time
+ if err = a.p.handleSessionExpiryHeader(c); err != nil {
+ return err
+ }
+
+ resp := &interfaces.LoginRes{
+ Account: username,
+ TokenExpiry: expiry,
+ APIEndpoint: nil,
+ Admin: true,
+ }
+
+ if jsonString, err := json.Marshal(resp); err == nil {
+ // Add XSRF Token
+ a.p.ensureXSRFToken(c)
+ c.Response().Header().Set("Content-Type", "application/json")
+ c.Response().Write(jsonString)
+ }
+
+ return err
+}
+
+//logout
+func (a *noAuth) logout(c echo.Context) error {
+ log.Debug("logout")
+
+ a.p.removeEmptyCookie(c)
+
+ // Remove the XSRF Token from the session
+ a.p.unsetSessionValue(c, XSRFTokenSessionName)
+
+ err := a.p.clearSession(c)
+ if err != nil {
+ log.Errorf("Unable to clear session: %v", err)
+ }
+
+ // Send JSON document
+ resp := &LogoutResponse{
+ IsSSO: a.p.Config.SSOLogin,
+ }
+
+ return c.JSON(http.StatusOK, resp)
+}
diff --git a/src/jetstream/authuaa.go b/src/jetstream/authuaa.go
index a0640e715d..a0775beb53 100644
--- a/src/jetstream/authuaa.go
+++ b/src/jetstream/authuaa.go
@@ -30,6 +30,14 @@ type uaaAuth struct {
skipSSLValidation bool
}
+func (a *uaaAuth) ShowConfig(config *interfaces.ConsoleConfig) {
+ log.Infof("... UAA Endpoint : %s", config.UAAEndpoint)
+ log.Infof("... Authorization Endpoint : %s", config.AuthorizationEndpoint)
+ log.Infof("... Console Client : %s", config.ConsoleClient)
+ log.Infof("... Admin Scope : %s", config.ConsoleAdminScope)
+ log.Infof("... Use SSO Login : %t", config.UseSSO)
+}
+
//Login provides UAA-auth specific Stratos login
func (a *uaaAuth) Login(c echo.Context) error {
log.Debug("UAA Login")
@@ -114,6 +122,8 @@ func (a *uaaAuth) GetUser(userGUID string) (*interfaces.ConnectedUser, error) {
}
+func (a *uaaAuth) BeforeVerifySession(c echo.Context) {}
+
//VerifySession verifies the session the specified UAA user and refreshes the token if necessary
func (a *uaaAuth) VerifySession(c echo.Context, sessionUser string, sessionExpireTime int64) error {
diff --git a/src/jetstream/main.go b/src/jetstream/main.go
index bb5425392d..0014731cc9 100644
--- a/src/jetstream/main.go
+++ b/src/jetstream/main.go
@@ -363,7 +363,7 @@ func main() {
log.Info("Console does not have a complete configuration - going to enter setup mode (adding `setup` route and middleware)")
} else {
needSetupMiddleware = false
- showStratosConfig(portalProxy.Config.ConsoleConfig)
+ showStratosConfig(portalProxy, portalProxy.Config.ConsoleConfig)
showSSOConfig(portalProxy)
}
@@ -431,21 +431,13 @@ func initialiseConsoleConfiguration(portalProxy *portalProxy) error {
return nil
}
-func showStratosConfig(config *interfaces.ConsoleConfig) {
+func showStratosConfig(portalProxy *portalProxy, config *interfaces.ConsoleConfig) {
log.Infof("Stratos is initialized with the following setup:")
log.Infof("... Auth Endpoint Type : %s", config.AuthEndpointType)
- if val, found := interfaces.AuthEndpointTypes[config.AuthEndpointType]; found {
- if val == interfaces.Local {
- log.Infof("... Local User : %s", config.LocalUser)
- log.Infof("... Local User Scope : %s", config.LocalUserScope)
- } else { //Auth type is set to remote
- log.Infof("... UAA Endpoint : %s", config.UAAEndpoint)
- log.Infof("... Authorization Endpoint : %s", config.AuthorizationEndpoint)
- log.Infof("... Console Client : %s", config.ConsoleClient)
- log.Infof("... Admin Scope : %s", config.ConsoleAdminScope)
- log.Infof("... Use SSO Login : %t", config.UseSSO)
- }
- }
+
+ // Ask the auto provider to display their config
+ portalProxy.StratosAuthService.ShowConfig(config)
+
log.Infof("... Skip SSL Validation : %t", config.SkipSSLValidation)
log.Infof("... Setup Complete : %t", config.IsSetupComplete())
}
@@ -598,7 +590,7 @@ func loadPortalConfig(pc interfaces.PortalConfig, env *env.VarSet) (interfaces.P
if endpointTypeSupported {
pc.AuthEndpointType = string(val)
} else {
- return pc, fmt.Errorf("AUTH_ENDPOINT_TYPE: %v is not valid. Must be set to local or remote (defaults to remote)", val)
+ return pc, fmt.Errorf("AUTH_ENDPOINT_TYPE: '%v' is not valid. Must be set to local or remote (defaults to remote)", pc.AuthEndpointType)
}
}
diff --git a/src/jetstream/mock_server_test.go b/src/jetstream/mock_server_test.go
index 1e49e0ed2a..751961d1f2 100644
--- a/src/jetstream/mock_server_test.go
+++ b/src/jetstream/mock_server_test.go
@@ -38,6 +38,14 @@ type mockPGStore struct {
StoredSession *sessions.Session
}
+func (m *mockPGStore) New(r *http.Request, name string) (*sessions.Session, error) {
+ session := &sessions.Session{
+ Values: make(map[interface{}]interface{}),
+ Options: &sessions.Options{},
+ }
+ return session, nil
+}
+
func (m *mockPGStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error {
m.StoredSession = session
return nil
diff --git a/src/jetstream/plugins/userinfo/main.go b/src/jetstream/plugins/userinfo/main.go
index c01c5768dd..8624ecbed6 100644
--- a/src/jetstream/plugins/userinfo/main.go
+++ b/src/jetstream/plugins/userinfo/main.go
@@ -64,10 +64,11 @@ func (userInfo *UserInfo) Init() error {
}
func (userInfo *UserInfo) getProvider(c echo.Context) Provider {
-
log.Debugf("getUserInfoProvider: %v", userInfo.portalProxy.GetConfig().AuthEndpointType)
if interfaces.AuthEndpointTypes[userInfo.portalProxy.GetConfig().AuthEndpointType] == interfaces.Local {
return InitLocalUserInfo(userInfo.portalProxy)
+ } else if interfaces.AuthEndpointTypes[userInfo.portalProxy.GetConfig().AuthEndpointType] == interfaces.AuthNone {
+ return InitNoAuthUserInfo(userInfo.portalProxy)
}
return InitUaaUserInfo(userInfo.portalProxy, c)
diff --git a/src/jetstream/plugins/userinfo/noauth_user.go b/src/jetstream/plugins/userinfo/noauth_user.go
new file mode 100644
index 0000000000..b5112109a2
--- /dev/null
+++ b/src/jetstream/plugins/userinfo/noauth_user.go
@@ -0,0 +1,57 @@
+package userinfo
+
+import (
+ "encoding/json"
+ "errors"
+ "net/http"
+
+ "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces"
+)
+
+// NoAuthUserInfo is a plugin for no authentication
+type NoAuthUserInfo struct {
+ portalProxy interfaces.PortalProxy
+}
+
+// InitNoAuthUserInfo creates a new no auth user info provider
+func InitNoAuthUserInfo(portalProxy interfaces.PortalProxy) Provider {
+ return &NoAuthUserInfo{portalProxy: portalProxy}
+}
+
+// GetUserInfo gets info for the specified user
+func (userInfo *NoAuthUserInfo) GetUserInfo(id string) (int, []byte, *http.Header, error) {
+
+ uaaUser := &uaaUser{
+ ID: id,
+ Origin: "noauth",
+ Username: interfaces.DefaultAdminUserName,
+ }
+
+ emails := make([]uaaUserEmail, 0)
+ uaaUser.Emails = emails
+
+ uaaUser.Name.GivenName = "Admin"
+ uaaUser.Name.FamilyName = "User"
+
+ groups := make([]uaaUserGroup, 0)
+ uaaUser.Groups = groups
+
+ uaaUser.Meta.Version = 0
+
+ jsonString, err := json.Marshal(uaaUser)
+ if err != nil {
+ return 500, nil, nil, err
+ }
+
+ return 200, jsonString, nil, nil
+}
+
+// UpdateUserInfo updates the user's info
+func (userInfo *NoAuthUserInfo) UpdateUserInfo(profile *uaaUser) (int, error) {
+ return 0, errors.New("Update not supported")
+}
+
+// UpdatePassword updates the user's password
+func (userInfo *NoAuthUserInfo) UpdatePassword(id string, passwordInfo *passwordChangeInfo) (int, error) {
+ return 0, errors.New("Update not supported")
+}
diff --git a/src/jetstream/repository/interfaces/auth.go b/src/jetstream/repository/interfaces/auth.go
index fc8be5a177..e43f67a9db 100644
--- a/src/jetstream/repository/interfaces/auth.go
+++ b/src/jetstream/repository/interfaces/auth.go
@@ -2,11 +2,18 @@ package interfaces
import "github.com/labstack/echo/v4"
+const (
+ // DefaultAdminUserName is the default admin user name
+ DefaultAdminUserName = "admin"
+)
+
//StratosAuth provides common access to Stratos login/logout functionality
type StratosAuth interface {
+ ShowConfig(config *ConsoleConfig)
Login(c echo.Context) error
Logout(c echo.Context) error
GetUsername(userGUID string) (string, error)
GetUser(userGUID string) (*ConnectedUser, error)
VerifySession(c echo.Context, sessionUser string, sessionExpireTime int64) error
+ BeforeVerifySession(c echo.Context)
}
diff --git a/src/jetstream/repository/interfaces/config/config.go b/src/jetstream/repository/interfaces/config/config.go
index 0e4dbe75ad..37b1dd87be 100644
--- a/src/jetstream/repository/interfaces/config/config.go
+++ b/src/jetstream/repository/interfaces/config/config.go
@@ -243,7 +243,7 @@ func NewConfigFileLookup(path string) env.Lookup {
return env.NoopLookup
}
- log.Infof("Loaded configuration from file: %s", path)
+ log.Debugf("Loaded configuration from file: %s", path)
return func(k string) (string, bool) {
v, ok := loadedConfig[k]
diff --git a/src/jetstream/repository/interfaces/structs.go b/src/jetstream/repository/interfaces/structs.go
index 87782e1003..82b2bf0f31 100644
--- a/src/jetstream/repository/interfaces/structs.go
+++ b/src/jetstream/repository/interfaces/structs.go
@@ -168,6 +168,7 @@ type ProxyRequestInfo struct {
}
type SessionStorer interface {
+ New(r *http.Request, name string) (*sessions.Session, error)
Get(r *http.Request, name string) (*sessions.Session, error)
Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error
}
@@ -248,6 +249,8 @@ const (
Remote AuthEndpointType = "remote"
//Local - String representation of remote auth endpoint type
Local AuthEndpointType = "local"
+ //AuthNone - String representation of no authentication
+ AuthNone AuthEndpointType = "none"
)
//AuthEndpointTypes - Allows lookup of internal string representation by the
@@ -255,6 +258,7 @@ const (
var AuthEndpointTypes = map[string]AuthEndpointType{
"remote": Remote,
"local": Local,
+ "none": AuthNone,
}
// ConsoleConfig is essential configuration settings
@@ -277,6 +281,11 @@ const defaultAdminScope = "stratos.admin"
// IsSetupComplete indicates if we have enough config
func (consoleConfig *ConsoleConfig) IsSetupComplete() bool {
+ // No auth, then setup is complete
+ if AuthEndpointTypes[consoleConfig.AuthEndpointType] == AuthNone {
+ return true
+ }
+
// Local user - check setup complete
if AuthEndpointTypes[consoleConfig.AuthEndpointType] == Local {
diff --git a/src/jetstream/repository/mock_interfaces/mock_auth.go b/src/jetstream/repository/mock_interfaces/mock_auth.go
index 74be4c6c1b..73f4b7699d 100644
--- a/src/jetstream/repository/mock_interfaces/mock_auth.go
+++ b/src/jetstream/repository/mock_interfaces/mock_auth.go
@@ -105,3 +105,27 @@ func (mr *MockStratosAuthMockRecorder) VerifySession(c, sessionUser, sessionExpi
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifySession", reflect.TypeOf((*MockStratosAuth)(nil).VerifySession), c, sessionUser, sessionExpireTime)
}
+
+// BeforeVerifySession mocks base method
+func (m *MockStratosAuth) BeforeVerifySession(c echo.Context) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "BeforeVerifySession", c)
+}
+
+// BeforeVerifySession indicates an expected call of BeforeVerifySession
+func (mr *MockStratosAuthMockRecorder) BeforeVerifySession(c interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeforeVerifySession", reflect.TypeOf((*MockStratosAuth)(nil).BeforeVerifySession), c)
+}
+
+// ShowConfig mocks base method
+func (m *MockStratosAuth) ShowConfig(config *interfaces.ConsoleConfig) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "ShowConfig", config)
+}
+
+// ShowConfig indicates an expected call of ShowConfig
+func (mr *MockStratosAuthMockRecorder) ShowConfig(c interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ShowConfig", reflect.TypeOf((*MockStratosAuth)(nil).ShowConfig), c)
+}
diff --git a/src/jetstream/session.go b/src/jetstream/session.go
index 0d1bdfb3f9..48e1e8482a 100644
--- a/src/jetstream/session.go
+++ b/src/jetstream/session.go
@@ -54,6 +54,11 @@ func (e *SessionValueNotFound) Error() string {
return fmt.Sprintf("Session value not found %s", e.msg)
}
+func (p *portalProxy) NewSession(c echo.Context) (*sessions.Session, error) {
+ req := c.Request()
+ return p.SessionStore.New(req, p.SessionCookieName)
+}
+
func (p *portalProxy) GetSession(c echo.Context) (*sessions.Session, error) {
log.Debug("getSession")
req := c.Request()
@@ -109,6 +114,7 @@ func (p *portalProxy) GetSessionStringValue(c echo.Context, key string) (string,
}
func (p *portalProxy) SaveSession(c echo.Context, session *sessions.Session) error {
+ log.Debug("SaveSession")
// Update the cached session and mark that it has been updated
// We're not calling the real session save, so we need to set the session expiry ourselves
@@ -148,6 +154,7 @@ func (p *portalProxy) setSessionValues(c echo.Context, values map[string]interfa
log.Debug("setSessionValues")
session, err := p.GetSession(c)
if err != nil {
+ log.Debug("No session - can not set session values")
return err
}
@@ -241,6 +248,8 @@ func (p *portalProxy) ensureXSRFToken(c echo.Context) {
func (p *portalProxy) verifySession(c echo.Context) error {
log.Debug("verifySession")
+ p.StratosAuthService.BeforeVerifySession(c)
+
collectErrors := func(p *portalProxy, c echo.Context) (*interfaces.Info, error) {
sessionExpireTime, err := p.GetSessionInt64Value(c, "exp")
if err != nil {
diff --git a/src/jetstream/setup_console.go b/src/jetstream/setup_console.go
index 1c28460907..10965bf79b 100644
--- a/src/jetstream/setup_console.go
+++ b/src/jetstream/setup_console.go
@@ -257,7 +257,9 @@ func (p *portalProxy) initialiseConsoleConfig(envLookup *env.VarSet) (*interface
val, endpointTypeSupported := interfaces.AuthEndpointTypes[consoleConfig.AuthEndpointType]
if endpointTypeSupported {
- if val == interfaces.Local {
+ if val == interfaces.AuthNone {
+ return consoleConfig, nil
+ } else if val == interfaces.Local {
//Auth endpoint type is set to "local", so load the local user config
err := initialiseLocalUsersConfiguration(consoleConfig, p)
if err != nil {
@@ -417,7 +419,7 @@ func checkSetupComplete(portalProxy *portalProxy) bool {
// If setup is complete, then store the config
if consoleConfig.IsSetupComplete() {
- showStratosConfig(consoleConfig)
+ showStratosConfig(portalProxy, consoleConfig)
portalProxy.Config.ConsoleConfig = consoleConfig
portalProxy.Config.SSOLogin = consoleConfig.UseSSO
portalProxy.Config.AuthEndpointType = consoleConfig.AuthEndpointType