Procházet zdrojové kódy

feature: Better guest handling (#472)

* feature: Better guest handling

* bugfix: Better handling of requiring guests to login
James Read před 1 rokem
rodič
revize
13e48dded2

+ 5 - 0
internal/acl/acl.go

@@ -33,6 +33,10 @@ type AuthenticatedUser struct {
 	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) {
 	if cfg.LogDebugOptions.AclNotMatched {
 		log.WithFields(log.Fields{
@@ -162,6 +166,7 @@ func UserFromContext(ctx context.Context, cfg *config.Config) *AuthenticatedUser
 		"username":  ret.Username,
 		"usergroup": ret.Usergroup,
 		"provider":  ret.Provider,
+		"acls":      ret.acls,
 	}).Debugf("UserFromContext")
 
 	return ret

+ 2 - 2
internal/config/config.go

@@ -117,7 +117,7 @@ type Config struct {
 	AuthHttpHeaderUserGroup         string
 	AuthLocalUsers                  AuthLocalUsersConfig
 	AuthLoginUrl                    string
-	AuthAllowGuest                  bool
+	AuthRequireGuestsToLogin        bool
 	AuthOAuth2RedirectURL           string
 	AuthOAuth2Providers             map[string]*OAuth2Provider
 	DefaultPermissions              PermissionsList
@@ -214,7 +214,7 @@ func DefaultConfigWithBasePort(basePort int) *Config {
 	config.DefaultPermissions.Logs = true
 	config.AuthJwtClaimUsername = "name"
 	config.AuthJwtClaimUserGroup = "group"
-	config.AuthAllowGuest = true
+	config.AuthRequireGuestsToLogin = false
 	config.WebUIDir = "./webui"
 	config.CronSupportForSeconds = false
 	config.SectionNavigationStyle = "sidebar"

+ 8 - 0
internal/config/config_reloader.go

@@ -36,6 +36,14 @@ func Reload(cfg *Config) {
 		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()
 	metricConfigActionCount.Set(float64(len(cfg.Actions)))
 

+ 4 - 7
internal/grpcapi/grpcApi.go

@@ -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) {
 	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)
 
 	if len(res.Actions) == 0 {
@@ -306,13 +310,6 @@ func (api *oliveTinAPI) GetDashboardComponents(ctx ctx.Context, req *pb.GetDashb
 
 	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
 }
 

+ 4 - 1
internal/grpcapi/grpcApiActions.go

@@ -10,7 +10,10 @@ import (
 )
 
 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()
 

+ 1 - 1
webui.dev/index.html

@@ -164,7 +164,7 @@
 			<section id = "content-login" title = "Login" hidden>
 				<div class = "flex-col">
 					<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>
 							<h2>OAuth Login</h2>

+ 21 - 8
webui.dev/js/marshaller.js

@@ -65,25 +65,38 @@ export function initMarshaller () {
   window.addEventListener('EventOutputChunk', onOutputChunk)
 }
 
-export function marshalDashboardComponentsJsonToHtml (json) {
-  marshalActionsJsonToHtml(json)
-  marshalDashboardStructureToHtml(json)
-
-  document.getElementById('username').innerText = json.authenticatedUser
+function setUsername (username, provider) {
+  document.getElementById('username').innerText = username
+  document.getElementById('username').setAttribute('title', provider)
 
   if (window.settings.AuthLocalLogin || window.settings.AuthOAuth2Providers !== null) {
-    if (json.authenticatedUser === 'guest') {
+    if (username === 'guest') {
       document.getElementById('link-login').hidden = false
       document.getElementById('link-logout').hidden = true
     } else {
       document.getElementById('link-login').hidden = true
 
-      if (json.authenticatedUserProvider === 'local' || json.authenticatedUserProvider === 'oauth2') {
+      if (provider === 'local' || provider === 'oauth2') {
         document.getElementById('link-logout').hidden = false
       }
     }
+  }
+}
+
+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)
 
-    document.getElementById('username').setAttribute('title', json.authenticatedUserProvider)
+    marshalActionsJsonToHtml(json)
+    marshalDashboardStructureToHtml(json)
   }
 
   document.body.setAttribute('initial-marshal-complete', 'true')

+ 2 - 1
webui.dev/main.js

@@ -61,8 +61,9 @@ function fetchGetDashboardComponents () {
     cors: 'cors'
   }).then(res => {
     if (!res.ok && res.status === 403) {
-      window.location.href = window.settings.AuthLoginUrl
+      return null
     }
+
     return res.json()
   }).then(res => {
     if (!window.restAvailable) {