@@ -2,8 +2,8 @@ package config
22
33import (
44 "fmt"
5- "io/ioutil"
65 "net/url"
6+ "os"
77 "strings"
88 "time"
99
@@ -19,6 +19,7 @@ import (
1919type Header struct {
2020 Enabled bool
2121 Name string
22+ Role string
2223}
2324
2425type Expiration struct {
@@ -32,11 +33,14 @@ type App struct {
3233 Target string
3334 Bind string
3435 Proxy bool
35- Users map [string ]string
36- Emails []string
36+ Users map [string ]string // username:password
37+ Emails []string // list of emails or @domains
38+ Roles map [string ]string // username/email:role
3739
3840 RedirectAllowlist []url.URL
3941
42+ LoginBtn bool // do not login automatically but show login button instead
43+
4044 Header Header
4145 Expiration Expiration
4246}
@@ -124,7 +128,7 @@ func (App) Init(cmd *cobra.Command) error {
124128 return err
125129 }
126130
127- cmd .PersistentFlags ().StringSlice ("app.users" , []string {}, "Users authentication using HTTP Basic Auth, with bcrypt hashes." )
131+ cmd .PersistentFlags ().StringSlice ("app.users" , []string {}, "Users authentication using HTTP Basic Auth, with bcrypt hashes, in format user:hash ." )
128132 if err := viper .BindPFlag ("app.users" , cmd .PersistentFlags ().Lookup ("app.users" )); err != nil {
129133 return err
130134 }
@@ -134,11 +138,26 @@ func (App) Init(cmd *cobra.Command) error {
134138 return err
135139 }
136140
141+ cmd .PersistentFlags ().StringSlice ("app.roles" , []string {}, "Roles for users and emails, in format key=value." )
142+ if err := viper .BindPFlag ("app.roles" , cmd .PersistentFlags ().Lookup ("app.roles" )); err != nil {
143+ return err
144+ }
145+
146+ cmd .PersistentFlags ().String ("app.roles_file" , "" , "Path to a file, where additional roles are stored, deparated by newline." )
147+ if err := viper .BindPFlag ("app.roles_file" , cmd .PersistentFlags ().Lookup ("app.roles_file" )); err != nil {
148+ return err
149+ }
150+
137151 cmd .PersistentFlags ().StringSlice ("app.redirect_allowlist" , []string {}, "Allowed redirect URLs." )
138152 if err := viper .BindPFlag ("app.redirect_allowlist" , cmd .PersistentFlags ().Lookup ("app.redirect_allowlist" )); err != nil {
139153 return err
140154 }
141155
156+ cmd .PersistentFlags ().Bool ("app.login_btn" , false , "Show login button instead of automatic login." )
157+ if err := viper .BindPFlag ("app.login_btn" , cmd .PersistentFlags ().Lookup ("app.login_btn" )); err != nil {
158+ return err
159+ }
160+
142161 //
143162 // header
144163 //
@@ -153,6 +172,11 @@ func (App) Init(cmd *cobra.Command) error {
153172 return err
154173 }
155174
175+ cmd .PersistentFlags ().String ("app.header.role" , "X-Auth-Role" , "Authentication header role." )
176+ if err := viper .BindPFlag ("app.header.role" , cmd .PersistentFlags ().Lookup ("app.header.role" )); err != nil {
177+ return err
178+ }
179+
156180 //
157181 // expiration
158182 //
@@ -183,7 +207,7 @@ func (c *App) Set() {
183207 // load emails from a file
184208 emailsFile := viper .GetString ("app.emails_file" )
185209 if emailsFile != "" {
186- emailsBytes , err := ioutil .ReadFile (emailsFile )
210+ emailsBytes , err := os .ReadFile (emailsFile )
187211 if err != nil {
188212 log .Panic ().Err (err ).Msgf ("error opening emails file" )
189213 }
@@ -198,7 +222,7 @@ func (c *App) Set() {
198222 // load users from a file
199223 usersFile := viper .GetString ("app.users_file" )
200224 if usersFile != "" {
201- usersBytes , err := ioutil .ReadFile (usersFile )
225+ usersBytes , err := os .ReadFile (usersFile )
202226 if err != nil {
203227 log .Panic ().Err (err ).Msgf ("error opening users file" )
204228 }
@@ -207,6 +231,21 @@ func (c *App) Set() {
207231 strings .Split (string (usersBytes ), "\n " )... )
208232 }
209233
234+ // get roles from config
235+ roles := viper .GetStringSlice ("app.roles" )
236+
237+ // load roles from a file
238+ rolesFile := viper .GetString ("app.roles_file" )
239+ if rolesFile != "" {
240+ rolesBytes , err := os .ReadFile (rolesFile )
241+ if err != nil {
242+ log .Panic ().Err (err ).Msgf ("error opening roles file" )
243+ }
244+
245+ roles = append (roles ,
246+ strings .Split (string (rolesBytes ), "\n " )... )
247+ }
248+
210249 // clean up emails
211250 c .Emails = []string {}
212251 for _ , email := range emails {
@@ -235,10 +274,29 @@ func (c *App) Set() {
235274 c .Users [username ] = secret
236275 }
237276
277+ // convert roles to a map
278+ c .Roles = map [string ]string {}
279+ for _ , row := range roles {
280+ row := strings .TrimSpace (row )
281+ if row == "" {
282+ continue
283+ }
284+
285+ split := strings .Split (row , "=" )
286+ if len (split ) != 2 {
287+ log .Panic ().Msgf ("error parsing role: %v" , row )
288+ }
289+
290+ user , role := strings .TrimSpace (split [0 ]), strings .TrimSpace (split [1 ])
291+ user = strings .ToLower (user )
292+ c .Roles [user ] = role
293+ }
294+
238295 log .Info ().
239296 Int ("emails" , len (c .Emails )).
240297 Int ("users" , len (c .Users )).
241- Msgf ("loaded emails and users" )
298+ Int ("roles" , len (c .Roles )).
299+ Msgf ("loaded emails, users and roles" )
242300
243301 urls := viper .GetStringSlice ("app.redirect_allowlist" )
244302 c .RedirectAllowlist = []url.URL {}
@@ -256,8 +314,11 @@ func (c *App) Set() {
256314 c .RedirectAllowlist = append (c .RedirectAllowlist , * parsed )
257315 }
258316
317+ c .LoginBtn = viper .GetBool ("app.login_btn" )
318+
259319 c .Header .Enabled = viper .GetBool ("app.header.enabled" )
260320 c .Header .Name = viper .GetString ("app.header.name" )
321+ c .Header .Role = viper .GetString ("app.header.role" )
261322
262323 c .Expiration .LoginLink = time .Duration (viper .GetInt64 ("app.expiration.link" )) * time .Second
263324 c .Expiration .Session = time .Duration (viper .GetInt64 ("app.expiration.session" )) * time .Second
0 commit comments