feature: Better guest handling (#472)
* feature: Better guest handling * bugfix: Better handling of requiring guests to login
This commit is contained in:
parent
344df3739d
commit
13e48dded2
|
|
@ -33,6 +33,10 @@ type AuthenticatedUser struct {
|
||||||
acls []string
|
acls []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *AuthenticatedUser) IsGuest() bool {
|
||||||
|
return u.Username == "guest" && u.Provider == "system"
|
||||||
|
}
|
||||||
|
|
||||||
func logAclNotMatched(cfg *config.Config, aclFunction string, user *AuthenticatedUser, action *config.Action, acl *config.AccessControlList) {
|
func logAclNotMatched(cfg *config.Config, aclFunction string, user *AuthenticatedUser, action *config.Action, acl *config.AccessControlList) {
|
||||||
if cfg.LogDebugOptions.AclNotMatched {
|
if cfg.LogDebugOptions.AclNotMatched {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
|
|
@ -162,6 +166,7 @@ func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser
|
||||||
"username": ret.Username,
|
"username": ret.Username,
|
||||||
"usergroup": ret.Usergroup,
|
"usergroup": ret.Usergroup,
|
||||||
"provider": ret.Provider,
|
"provider": ret.Provider,
|
||||||
|
"acls": ret.acls,
|
||||||
}).Debugf("UserFromContext")
|
}).Debugf("UserFromContext")
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ type Config struct {
|
||||||
AuthHttpHeaderUserGroup string
|
AuthHttpHeaderUserGroup string
|
||||||
AuthLocalUsers AuthLocalUsersConfig
|
AuthLocalUsers AuthLocalUsersConfig
|
||||||
AuthLoginUrl string
|
AuthLoginUrl string
|
||||||
AuthAllowGuest bool
|
AuthRequireGuestsToLogin bool
|
||||||
AuthOAuth2RedirectURL string
|
AuthOAuth2RedirectURL string
|
||||||
AuthOAuth2Providers map[string]*OAuth2Provider
|
AuthOAuth2Providers map[string]*OAuth2Provider
|
||||||
DefaultPermissions PermissionsList
|
DefaultPermissions PermissionsList
|
||||||
|
|
@ -214,7 +214,7 @@ func DefaultConfigWithBasePort(basePort int) *Config {
|
||||||
config.DefaultPermissions.Logs = true
|
config.DefaultPermissions.Logs = true
|
||||||
config.AuthJwtClaimUsername = "name"
|
config.AuthJwtClaimUsername = "name"
|
||||||
config.AuthJwtClaimUserGroup = "group"
|
config.AuthJwtClaimUserGroup = "group"
|
||||||
config.AuthAllowGuest = true
|
config.AuthRequireGuestsToLogin = false
|
||||||
config.WebUIDir = "./webui"
|
config.WebUIDir = "./webui"
|
||||||
config.CronSupportForSeconds = false
|
config.CronSupportForSeconds = false
|
||||||
config.SectionNavigationStyle = "sidebar"
|
config.SectionNavigationStyle = "sidebar"
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,14 @@ func Reload(cfg *Config) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg.AuthRequireGuestsToLogin {
|
||||||
|
log.Infof("AuthRequireGuestsToLogin is enabled. All defaultPermissions will be set to false")
|
||||||
|
|
||||||
|
cfg.DefaultPermissions.View = false
|
||||||
|
cfg.DefaultPermissions.Exec = false
|
||||||
|
cfg.DefaultPermissions.Logs = false
|
||||||
|
}
|
||||||
|
|
||||||
metricConfigReloadedCount.Inc()
|
metricConfigReloadedCount.Inc()
|
||||||
metricConfigActionCount.Set(float64(len(cfg.Actions)))
|
metricConfigActionCount.Set(float64(len(cfg.Actions)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,10 @@ func (api *oliveTinAPI) Logout(ctx ctx.Context, req *pb.LogoutRequest) (*httpbod
|
||||||
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashboardComponentsRequest) (*pb.GetDashboardComponentsResponse, error) {
|
||||||
user := acl.UserFromContext(ctx, cfg)
|
user := acl.UserFromContext(ctx, cfg)
|
||||||
|
|
||||||
|
if user.IsGuest() && cfg.AuthRequireGuestsToLogin {
|
||||||
|
return nil, status.Errorf(codes.PermissionDenied, "Guests are not allowed to access the dashboard.")
|
||||||
|
}
|
||||||
|
|
||||||
res := buildDashboardResponse(api.executor, cfg, user)
|
res := buildDashboardResponse(api.executor, cfg, user)
|
||||||
|
|
||||||
if len(res.Actions) == 0 {
|
if len(res.Actions) == 0 {
|
||||||
|
|
@ -306,13 +310,6 @@ func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashb
|
||||||
|
|
||||||
dashboardCfgToPb(res, cfg.Dashboards, cfg)
|
dashboardCfgToPb(res, cfg.Dashboards, cfg)
|
||||||
|
|
||||||
res.AuthenticatedUser = user.Username
|
|
||||||
res.AuthenticatedUserProvider = user.Provider
|
|
||||||
|
|
||||||
if res.AuthenticatedUser == "guest" && !cfg.AuthAllowGuest {
|
|
||||||
return nil, status.Errorf(codes.PermissionDenied, "Unauthenticated")
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse {
|
func buildDashboardResponse(ex *executor.Executor, cfg *config.Config, user *acl.AuthenticatedUser) *pb.GetDashboardComponentsResponse {
|
||||||
res := &pb.GetDashboardComponentsResponse{}
|
res := &pb.GetDashboardComponentsResponse{
|
||||||
|
AuthenticatedUser: user.Username,
|
||||||
|
AuthenticatedUserProvider: user.Provider,
|
||||||
|
}
|
||||||
|
|
||||||
ex.MapActionIdToBindingLock.RLock()
|
ex.MapActionIdToBindingLock.RLock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@
|
||||||
<section id = "content-login" title = "Login" hidden>
|
<section id = "content-login" title = "Login" hidden>
|
||||||
<div class = "flex-col">
|
<div class = "flex-col">
|
||||||
<form class = "box-shadow padded-content border-radius" id = "local-user-login">
|
<form class = "box-shadow padded-content border-radius" id = "local-user-login">
|
||||||
<p class = "login-disabled">Login with OAuth or Local users is not enabled on this server.</p>
|
<p class = "login-disabled">This server is not configured with either OAuth, or local users, so you cannot login.</p>
|
||||||
|
|
||||||
<div class = "login-oauth2" hidden>
|
<div class = "login-oauth2" hidden>
|
||||||
<h2>OAuth Login</h2>
|
<h2>OAuth Login</h2>
|
||||||
|
|
|
||||||
|
|
@ -65,25 +65,38 @@ export function initMarshaller () {
|
||||||
window.addEventListener('EventOutputChunk', onOutputChunk)
|
window.addEventListener('EventOutputChunk', onOutputChunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function marshalDashboardComponentsJsonToHtml (json) {
|
function setUsername (username, provider) {
|
||||||
marshalActionsJsonToHtml(json)
|
document.getElementById('username').innerText = username
|
||||||
marshalDashboardStructureToHtml(json)
|
document.getElementById('username').setAttribute('title', provider)
|
||||||
|
|
||||||
document.getElementById('username').innerText = json.authenticatedUser
|
|
||||||
|
|
||||||
if (window.settings.AuthLocalLogin || window.settings.AuthOAuth2Providers !== null) {
|
if (window.settings.AuthLocalLogin || window.settings.AuthOAuth2Providers !== null) {
|
||||||
if (json.authenticatedUser === 'guest') {
|
if (username === 'guest') {
|
||||||
document.getElementById('link-login').hidden = false
|
document.getElementById('link-login').hidden = false
|
||||||
document.getElementById('link-logout').hidden = true
|
document.getElementById('link-logout').hidden = true
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('link-login').hidden = true
|
document.getElementById('link-login').hidden = true
|
||||||
|
|
||||||
if (json.authenticatedUserProvider === 'local' || json.authenticatedUserProvider === 'oauth2') {
|
if (provider === 'local' || provider === 'oauth2') {
|
||||||
document.getElementById('link-logout').hidden = false
|
document.getElementById('link-logout').hidden = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('username').setAttribute('title', json.authenticatedUserProvider)
|
export function marshalDashboardComponentsJsonToHtml (json) {
|
||||||
|
if (json == null) { // eg: HTTP 403
|
||||||
|
setUsername('guest', 'system')
|
||||||
|
|
||||||
|
if (window.settings.AuthLoginUrl !== '') {
|
||||||
|
window.location = window.settings.AuthLoginUrl
|
||||||
|
} else {
|
||||||
|
showSection('/login')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setUsername(json.authenticatedUser, json.authenticatedUserProvider)
|
||||||
|
|
||||||
|
marshalActionsJsonToHtml(json)
|
||||||
|
marshalDashboardStructureToHtml(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.setAttribute('initial-marshal-complete', 'true')
|
document.body.setAttribute('initial-marshal-complete', 'true')
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,9 @@ function fetchGetDashboardComponents () {
|
||||||
cors: 'cors'
|
cors: 'cors'
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (!res.ok && res.status === 403) {
|
if (!res.ok && res.status === 403) {
|
||||||
window.location.href = window.settings.AuthLoginUrl
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json()
|
return res.json()
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (!window.restAvailable) {
|
if (!window.restAvailable) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue