forked from Velocidex/velociraptor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added user_delete() and user_create() VQL functions (Velocidex#1187)
This allows admin users to create or delete other users in the notebook.
- Loading branch information
Showing
10 changed files
with
262 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
Queries: | ||
# Should return no users | ||
- SELECT * FROM gui_users() WHERE name =~ "TestUser" | ||
|
||
# Lets create a user | ||
- SELECT user_create( | ||
user="TestUser", password="hunter2", | ||
roles=["reader", "investigator"]) FROM scope() | ||
|
||
- SELECT name, Permissions.roles FROM gui_users() WHERE name =~ "TestUser" | ||
|
||
# Now delete it | ||
- SELECT user_delete(user="TestUser") FROM scope() | ||
|
||
# Should be gone now. | ||
- SELECT * FROM gui_users() WHERE name =~ "TestUser" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
SELECT * FROM gui_users() WHERE name =~ "TestUser"[]SELECT user_create( user="TestUser", password="hunter2", roles=["reader", "investigator"]) FROM scope()[ | ||
{ | ||
"user_create(user=\"TestUser\", password=\"hunter2\", roles= [\"reader\", \"investigator\"])": "TestUser" | ||
} | ||
]SELECT name, Permissions.roles FROM gui_users() WHERE name =~ "TestUser"[ | ||
{ | ||
"name": "TestUser", | ||
"Permissions.roles": [ | ||
"reader", | ||
"investigator" | ||
] | ||
} | ||
]SELECT user_delete(user="TestUser") FROM scope()[ | ||
{ | ||
"user_delete(user=\"TestUser\")": "TestUser" | ||
} | ||
]SELECT * FROM gui_users() WHERE name =~ "TestUser"[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package users | ||
|
||
import ( | ||
"context" | ||
"crypto/rand" | ||
|
||
"github.com/Velocidex/ordereddict" | ||
"www.velocidex.com/golang/velociraptor/acls" | ||
"www.velocidex.com/golang/velociraptor/api/authenticators" | ||
"www.velocidex.com/golang/velociraptor/users" | ||
vql_subsystem "www.velocidex.com/golang/velociraptor/vql" | ||
"www.velocidex.com/golang/vfilter" | ||
"www.velocidex.com/golang/vfilter/arg_parser" | ||
) | ||
|
||
type UserCreateFunctionArgs struct { | ||
Username string `vfilter:"required,field=user,docs=The user to create or update."` | ||
Roles []string `vfilter:"required,field=roles,docs=List of roles to give the user."` | ||
Password string `vfilter:"optional,field=password,docs=A password to set for the user (If not using SSO this might be needed)."` | ||
} | ||
|
||
type UserCreateFunction struct{} | ||
|
||
func (self UserCreateFunction) Call( | ||
ctx context.Context, | ||
scope vfilter.Scope, | ||
args *ordereddict.Dict) vfilter.Any { | ||
|
||
err := vql_subsystem.CheckAccess(scope, acls.SERVER_ADMIN) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
config_obj, ok := vql_subsystem.GetServerConfig(scope) | ||
if !ok { | ||
scope.Log("Command can only run on the server") | ||
return vfilter.Null{} | ||
} | ||
|
||
arg := &UserCreateFunctionArgs{} | ||
err = arg_parser.ExtractArgsWithContext(ctx, scope, args, arg) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
// OK - Lets make the user now | ||
user_record, err := users.NewUserRecord(arg.Username) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
// Check the password if needed | ||
authenticator, err := authenticators.NewAuthenticator(config_obj) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
if authenticator.IsPasswordLess() { | ||
// Set a random password on the account to prevent login if | ||
// the authenticator is accidentally changed to a password | ||
// based one. | ||
password := make([]byte, 100) | ||
_, err = rand.Read(password) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
users.SetPassword(user_record, string(password)) | ||
|
||
} else if arg.Password == "" { | ||
// Do not accept an empty password if we are using a password | ||
// based authenticator. | ||
scope.Log("Authentication requires a password but one was not provided.") | ||
return vfilter.Null{} | ||
|
||
} else { | ||
users.SetPassword(user_record, arg.Password) | ||
} | ||
|
||
// Grant the roles to the user | ||
err = acls.GrantRoles(config_obj, arg.Username, arg.Roles) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
// Write the user record. | ||
err = users.SetUser(config_obj, user_record) | ||
if err != nil { | ||
scope.Log("user_create: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
return arg.Username | ||
} | ||
|
||
func (self UserCreateFunction) Info(scope vfilter.Scope, type_map *vfilter.TypeMap) *vfilter.FunctionInfo { | ||
return &vfilter.FunctionInfo{ | ||
Name: "user_create", | ||
Doc: "Creates a new user from the server, or updates their permissions or reset their password.", | ||
ArgType: type_map.AddType(scope, &UserCreateFunctionArgs{}), | ||
} | ||
} | ||
|
||
func init() { | ||
vql_subsystem.RegisterFunction(&UserCreateFunction{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package users | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/Velocidex/ordereddict" | ||
"www.velocidex.com/golang/velociraptor/acls" | ||
"www.velocidex.com/golang/velociraptor/datastore" | ||
"www.velocidex.com/golang/velociraptor/paths" | ||
vql_subsystem "www.velocidex.com/golang/velociraptor/vql" | ||
"www.velocidex.com/golang/vfilter" | ||
"www.velocidex.com/golang/vfilter/arg_parser" | ||
) | ||
|
||
type UserDeleteFunctionArgs struct { | ||
Username string `vfilter:"required,field=user,docs=The user to delete."` | ||
} | ||
|
||
type UserDeleteFunction struct{} | ||
|
||
func (self UserDeleteFunction) Call( | ||
ctx context.Context, | ||
scope vfilter.Scope, | ||
args *ordereddict.Dict) vfilter.Any { | ||
|
||
err := vql_subsystem.CheckAccess(scope, acls.SERVER_ADMIN) | ||
if err != nil { | ||
scope.Log("user_delete: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
config_obj, ok := vql_subsystem.GetServerConfig(scope) | ||
if !ok { | ||
scope.Log("Command can only run on the server") | ||
return vfilter.Null{} | ||
} | ||
|
||
arg := &UserDeleteFunctionArgs{} | ||
err = arg_parser.ExtractArgsWithContext(ctx, scope, args, arg) | ||
if err != nil { | ||
scope.Log("user_delete: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
db, err := datastore.GetDB(config_obj) | ||
if err != nil { | ||
scope.Log("user_delete: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
user_path_manager := paths.NewUserPathManager(arg.Username) | ||
err = db.DeleteSubject(config_obj, user_path_manager.Path()) | ||
if err != nil { | ||
scope.Log("user_delete: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
// Also remove the ACLs for the user. | ||
err = db.DeleteSubject(config_obj, user_path_manager.ACL()) | ||
if err != nil { | ||
scope.Log("user_delete: %s", err) | ||
return vfilter.Null{} | ||
} | ||
|
||
return arg.Username | ||
} | ||
|
||
func (self UserDeleteFunction) Info(scope vfilter.Scope, type_map *vfilter.TypeMap) *vfilter.FunctionInfo { | ||
return &vfilter.FunctionInfo{ | ||
Name: "user_delete", | ||
Doc: "Deletes a user from the server.", | ||
ArgType: type_map.AddType(scope, &UserDeleteFunctionArgs{}), | ||
} | ||
} | ||
|
||
func init() { | ||
vql_subsystem.RegisterFunction(&UserDeleteFunction{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package server | ||
package users | ||
|
||
import ( | ||
"context" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters