diff --git a/cmd/admin/auth.go b/cmd/admin/auth.go index fbeedc19..ca05d4fe 100644 --- a/cmd/admin/auth.go +++ b/cmd/admin/auth.go @@ -4,6 +4,7 @@ import ( "context" "log" "net/http" + "strings" "github.com/jmpsec/osctrl/pkg/settings" ) @@ -104,8 +105,55 @@ func handlerAuthCheck(h http.Handler) http.Handler { samlMiddleware.RequireAccount(h).ServeHTTP(w, r) } case settings.AuthHeaders: - // Access always granted - h.ServeHTTP(w, r) + username := r.Header.Get(headersConfig.TrustedPrefix + headersConfig.UserName) + email := r.Header.Get(headersConfig.TrustedPrefix + headersConfig.Email) + groups := strings.Split(r.Header.Get(headersConfig.TrustedPrefix+headersConfig.Groups), ",") + fullname := r.Header.Get(headersConfig.TrustedPrefix + headersConfig.DisplayName) + + // A username is required to use this system + if username == "" { + http.Redirect(w, r, forbiddenPath, http.StatusBadRequest) + return + } + + s := make(contextValue) + s["user"] = username + + for _, group := range groups { + if group == headersConfig.AdminGroup { + s["level"] = adminLevel + // We can break because there is no greater permission level + break + } else if group == headersConfig.UserGroup { + s["level"] = userLevel + // We can't break because we might still find a higher permission level + } + } + + // This user didn't present a group that has permission to use the service + if _, ok := s["level"]; !ok { + http.Redirect(w, r, forbiddenPath, http.StatusForbidden) + return + } + + newUser, err := adminUsers.New(username, "", email, fullname, (s["level"] == adminLevel)) + if err != nil { + log.Printf("Error with new user %s: %v", username, err) + http.Redirect(w, r, forbiddenPath, http.StatusFound) + return + } + + if err := adminUsers.Create(newUser); err != nil { + log.Printf("Error creating user %s: %v", username, err) + http.Redirect(w, r, forbiddenPath, http.StatusFound) + return + } + // _, session := sessionsmgr.CheckAuth(r) + // s["csrftoken"] = session.Values["csrftoken"].(string) + ctx := context.WithValue(r.Context(), contextKey("session"), s) + + // Access granted + h.ServeHTTP(w, r.WithContext(ctx)) } }) } diff --git a/cmd/admin/headers.go b/cmd/admin/headers.go new file mode 100644 index 00000000..de6f116d --- /dev/null +++ b/cmd/admin/headers.go @@ -0,0 +1,30 @@ +package main + +import ( + "log" + + "github.com/jmpsec/osctrl/pkg/settings" + "github.com/jmpsec/osctrl/pkg/types" + "github.com/spf13/viper" +) + +// Function to load the configuration file +func loadHeaders(file string) (types.JSONConfigurationHeaders, error) { + var cfg types.JSONConfigurationHeaders + log.Printf("Loading %s", file) + // Load file and read config + viper.SetConfigFile(file) + err := viper.ReadInConfig() + if err != nil { + return cfg, err + } + // Header values + headersRaw := viper.Sub(settings.AuthHeaders) + err = headersRaw.Unmarshal(&cfg) + if err != nil { + return cfg, err + } + + // No errors! + return cfg, nil +} diff --git a/cmd/admin/main.go b/cmd/admin/main.go index ffec8e55..48272a77 100644 --- a/cmd/admin/main.go +++ b/cmd/admin/main.go @@ -50,6 +50,8 @@ const ( dbConfigurationFile string = "config/db.json" // Default SAML configuration file samlConfigurationFile string = "config/saml.json" + // Default Headers configuration file + headersConfigurationFile string = "config/headers.json" // osquery version to display tables osqueryTablesVersion string = "4.0.1" // JSON file with osquery tables data @@ -87,6 +89,7 @@ var ( configFlag *string dbFlag *string samlFlag *string + headersFlag *string ) // SAML variables @@ -96,13 +99,20 @@ var ( samlData samlThings ) -// Valid values for auth and logging in configuration +// Headers variables +var ( + headersConfig types.JSONConfigurationHeaders +) + +// Valid values for auth in configuration var validAuth = map[string]bool{ settings.AuthDB: true, settings.AuthSAML: true, settings.AuthHeaders: true, settings.AuthJSON: true, } + +// Valid values for logging in configuration var validLogging = map[string]bool{ settings.LoggingDB: true, settings.LoggingSplunk: true, @@ -146,6 +156,7 @@ func init() { configFlag = flag.String("c", configurationFile, "Service configuration JSON file to use.") dbFlag = flag.String("D", dbConfigurationFile, "DB configuration JSON file to use.") samlFlag = flag.String("S", samlConfigurationFile, "SAML configuration JSON file to use.") + headersFlag = flag.String("H", headersConfigurationFile, "Headers configuration JSON file to use.") // Parse all flags flag.Parse() if *versionFlag { @@ -158,17 +169,29 @@ func init() { if err != nil { log.Fatalf("Error loading %s - %s", *configFlag, err) } + + // Load osquery tables JSON + osqueryTables, err = loadOsqueryTables(osqueryTablesFile) + if err != nil { + log.Fatalf("Error loading osquery tables %s", err) + } + // Load configuration for SAML if enabled if adminConfig.Auth == settings.AuthSAML { samlConfig, err = loadSAML(*samlFlag) if err != nil { log.Fatalf("Error loading %s - %s", *samlFlag, err) } + return } - // Load osquery tables JSON - osqueryTables, err = loadOsqueryTables(osqueryTablesFile) - if err != nil { - log.Fatalf("Error loading osquery tables %s", err) + + // Load configuration for Headers if enabled + if adminConfig.Auth == settings.AuthHeaders { + headersConfig, err = loadHeaders(*headersFlag) + if err != nil { + log.Fatalf("Error loading %s - %s", *headersFlag, err) + } + return } } diff --git a/pkg/types/types.go b/pkg/types/types.go index e42f0e84..33136cbf 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -20,3 +20,17 @@ type JSONConfigurationService struct { Auth string `json:"auth"` Logging string `json:"logging"` } + +// JSONConfigurationHeaders to keep all SAML details for auth +type JSONConfigurationHeaders struct { + TrustedPrefix string `json:"trustedPrefix"` + AdminGroup string `json:"adminGroup"` + UserGroup string `json:"userGroup"` + Email string `json:"email"` + UserName string `json:"userName"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + DisplayName string `json:"displayName"` + DistinguishedName string `json:"distinguishedName"` + Groups string `json:"groups"` +}