Initial work on auth
This commit is contained in:
parent
c072e16cc4
commit
5a151859d7
|
|
@ -8,6 +8,7 @@ message ActionButton {
|
|||
string id = 1;
|
||||
string title = 2;
|
||||
string icon = 3;
|
||||
bool canExec = 4;
|
||||
}
|
||||
|
||||
message GetButtonsResponse {
|
||||
|
|
@ -34,6 +35,8 @@ message LogEntry {
|
|||
string stderr = 4;
|
||||
bool timedOut = 5;
|
||||
int32 exitCode = 6;
|
||||
string user = 7;
|
||||
string userClass = 8;
|
||||
}
|
||||
|
||||
message GetLogsResponse {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
package acl
|
||||
|
||||
import (
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"context"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string;
|
||||
}
|
||||
|
||||
func IsAllowedExec(cfg *config.Config, user *User, action *config.ActionButton) bool {
|
||||
canExec := cfg.DefaultPermissions.Exec
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": canExec,
|
||||
}).Debug("isAllowedExec Permission Default")
|
||||
|
||||
for _, permissionEntry := range action.Permissions {
|
||||
if isUserInGroup(user, permissionEntry.Usergroup) {
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": permissionEntry.Exec,
|
||||
}).Debug("isAllowedExec Permission Entry")
|
||||
|
||||
canExec = permissionEntry.Exec
|
||||
}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanExec": canExec,
|
||||
}).Debug("isAllowedExec Final Result")
|
||||
|
||||
return canExec;
|
||||
}
|
||||
|
||||
func IsAllowedView(cfg *config.Config, user *User, action *config.ActionButton) bool {
|
||||
canView := cfg.DefaultPermissions.View
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": canView,
|
||||
}).Debug("isAllowedView Permission Default")
|
||||
|
||||
for idx, permissionEntry := range action.Permissions {
|
||||
if isUserInGroup(user, permissionEntry.Usergroup) {
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": permissionEntry.View,
|
||||
"Index": idx,
|
||||
}).Debug("isAllowedView Permission Entry")
|
||||
|
||||
canView = permissionEntry.View
|
||||
}
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"User": user.Username,
|
||||
"Action": action.Title,
|
||||
"CanView": canView,
|
||||
}).Debug("isAllowedView Final Result")
|
||||
|
||||
return canView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
func isUserInGroup(user *User, usergroup string) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
func UserFromContext(ctx context.Context) *User {
|
||||
return &User {
|
||||
Username: "Guest",
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ type ActionButton struct {
|
|||
Shell string
|
||||
CSS map[string]string `mapstructure:"omitempty"`
|
||||
Timeout int
|
||||
Permissions []PermissionsEntry
|
||||
}
|
||||
|
||||
// Entity represents a "thing" that can have multiple actions associated with it.
|
||||
|
|
@ -21,6 +22,22 @@ type Entity struct {
|
|||
CSS map[string]string
|
||||
}
|
||||
|
||||
type PermissionsEntry struct {
|
||||
Usergroup string
|
||||
View bool
|
||||
Exec bool
|
||||
}
|
||||
|
||||
type DefaultPermissions struct {
|
||||
View bool
|
||||
Exec bool
|
||||
}
|
||||
|
||||
type UserGroup struct {
|
||||
Name string
|
||||
Members []string
|
||||
}
|
||||
|
||||
// Config is the global config used through the whole app.
|
||||
type Config struct {
|
||||
UseSingleHTTPFrontend bool
|
||||
|
|
@ -34,6 +51,8 @@ type Config struct {
|
|||
ActionButtons []ActionButton `mapstructure:"actions"`
|
||||
Entities []Entity `mapstructure:"omitempty"`
|
||||
CheckForUpdates bool
|
||||
Usergroups []UserGroup
|
||||
DefaultPermissions DefaultPermissions
|
||||
}
|
||||
|
||||
// DefaultConfig gets a new Config structure with sensible default values.
|
||||
|
|
@ -46,6 +65,8 @@ func DefaultConfig() *Config {
|
|||
config.ListenAddressWebUI = "localhost:1340"
|
||||
config.LogLevel = "INFO"
|
||||
config.CheckForUpdates = true
|
||||
config.DefaultPermissions.Exec = true
|
||||
config.DefaultPermissions.View = true
|
||||
|
||||
return &config
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
pb "github.com/jamesread/OliveTin/gen/grpc"
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
|
||||
"context"
|
||||
"errors"
|
||||
|
|
@ -26,21 +27,11 @@ type Executor struct {
|
|||
}
|
||||
|
||||
// ExecAction executes an action.
|
||||
func (e *Executor) ExecAction(cfg *config.Config, action string) *pb.StartActionResponse {
|
||||
func (e *Executor) ExecAction(cfg *config.Config, user *acl.User, actualAction *config.ActionButton) *pb.StartActionResponse {
|
||||
log.WithFields(log.Fields{
|
||||
"actionName": action,
|
||||
"actionName": actualAction.Title,
|
||||
}).Infof("StartAction")
|
||||
|
||||
actualAction, err := findAction(cfg, action)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error finding action %s, %s", err, action)
|
||||
|
||||
return &pb.StartActionResponse{
|
||||
LogEntry: nil,
|
||||
}
|
||||
}
|
||||
|
||||
res := execAction(cfg, actualAction)
|
||||
|
||||
e.Logs = append(e.Logs, *res);
|
||||
|
|
@ -103,7 +94,7 @@ func sanitizeAction(action *config.ActionButton) {
|
|||
}
|
||||
}
|
||||
|
||||
func findAction(cfg *config.Config, actionTitle string) (*config.ActionButton, error) {
|
||||
func FindAction(cfg *config.Config, actionTitle string) (*config.ActionButton, error) {
|
||||
for _, action := range cfg.ActionButtons {
|
||||
if action.Title == actionTitle {
|
||||
sanitizeAction(&action)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
config "github.com/jamesread/OliveTin/internal/config"
|
||||
executor "github.com/jamesread/OliveTin/internal/executor"
|
||||
acl "github.com/jamesread/OliveTin/internal/acl"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -23,23 +24,52 @@ type oliveTinAPI struct {
|
|||
}
|
||||
|
||||
func (api *oliveTinAPI) StartAction(ctx ctx.Context, req *pb.StartActionRequest) (*pb.StartActionResponse, error) {
|
||||
return ex.ExecAction(cfg, req.ActionName), nil
|
||||
actualAction, err := executor.FindAction(cfg, req.ActionName)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error finding action %s, %s", err, req.ActionName)
|
||||
|
||||
return &pb.StartActionResponse{
|
||||
LogEntry: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
user := acl.UserFromContext(ctx)
|
||||
|
||||
if !acl.IsAllowedExec(cfg, user, actualAction) {
|
||||
return &pb.StartActionResponse{
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
return ex.ExecAction(cfg, acl.UserFromContext(ctx), actualAction), nil
|
||||
}
|
||||
|
||||
func (api *oliveTinAPI) GetButtons(ctx ctx.Context, req *pb.GetButtonsRequest) (*pb.GetButtonsResponse, error) {
|
||||
res := &pb.GetButtonsResponse{}
|
||||
|
||||
user := acl.UserFromContext(ctx)
|
||||
|
||||
for _, action := range cfg.ActionButtons {
|
||||
if !acl.IsAllowedView(cfg, user, &action) {
|
||||
continue
|
||||
}
|
||||
|
||||
btn := pb.ActionButton{
|
||||
Id: fmt.Sprintf("%x", md5.Sum([]byte(action.Title))),
|
||||
Title: action.Title,
|
||||
Icon: lookupHTMLIcon(action.Icon),
|
||||
CanExec: acl.IsAllowedExec(cfg, user, &action),
|
||||
}
|
||||
|
||||
res.Actions = append(res.Actions, &btn)
|
||||
}
|
||||
|
||||
log.Infof("getButtons: %v", res)
|
||||
if len(res.Actions) == 0 {
|
||||
log.Warn("Zero actions found - check that you have some actions defined, with a view permission")
|
||||
}
|
||||
|
||||
log.Debugf("getButtons: %v", res)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue