Skip to content

Commit

Permalink
Added ACL backups (Velocidex#3350)
Browse files Browse the repository at this point in the history
  • Loading branch information
scudette authored Mar 18, 2024
1 parent f557e03 commit e79ab54
Show file tree
Hide file tree
Showing 49 changed files with 396 additions and 207 deletions.
2 changes: 2 additions & 0 deletions accessors/vfs/vfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (self *TestSuite) TestVFSAccessor() {
flow_id, err := launcher.ScheduleArtifactCollection(self.Ctx, self.ConfigObj,
acl_manager, repository, &flows_proto.ArtifactCollectorArgs{
Artifacts: []string{"System.VFS.ListDirectory", "System.VFS.DownloadFile"},
Creator: utils.GetSuperuserName(self.ConfigObj),
Specs: []*flows_proto.ArtifactSpec{
{
Artifact: "System.VFS.DownloadFile",
Expand Down Expand Up @@ -167,6 +168,7 @@ func (self *TestSuite) TestVFSAccessor() {
vtesting.WaitUntil(time.Second*5, self.T(), func() bool {
flow, err := launcher.GetFlowDetails(self.Ctx, self.ConfigObj, "server", flow_id)
assert.NoError(self.T(), err)

return flow.Context.State == flows_proto.ArtifactCollectorContext_FINISHED
})

Expand Down
11 changes: 4 additions & 7 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,12 @@ func (self *ApiServer) CollectArtifact(
if err != nil {
return nil, Status(self.verbose, err)
}
principal := user_record.Name

// Internal calls from the frontend can set the creator.
if principal != org_config_obj.Client.PinnedServerName {
in.Creator = principal
}
// Ensure the request is marked with the real caller.
in.Creator = user_record.Name

acl_manager := acl_managers.NewServerACLManager(
org_config_obj, principal)
org_config_obj, in.Creator)

manager, err := services.GetRepositoryManager(org_config_obj)
if err != nil {
Expand Down Expand Up @@ -198,7 +195,7 @@ func (self *ApiServer) CollectArtifact(

// Log this event as an Audit event.
services.LogAudit(ctx,
org_config_obj, principal, "ScheduleFlow",
org_config_obj, in.Creator, "ScheduleFlow",
ordereddict.NewDict().
Set("client", in.ClientId).
Set("flow_id", flow_id).
Expand Down
7 changes: 4 additions & 3 deletions api/authenticators/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ import (
"github.com/gorilla/csrf"
acl_proto "www.velocidex.com/golang/velociraptor/acls/proto"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
utils "www.velocidex.com/golang/velociraptor/api/utils"
api_utils "www.velocidex.com/golang/velociraptor/api/utils"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
"www.velocidex.com/golang/velociraptor/constants"
"www.velocidex.com/golang/velociraptor/json"
"www.velocidex.com/golang/velociraptor/services"
"www.velocidex.com/golang/velociraptor/utils"
)

var (
Expand All @@ -111,7 +112,7 @@ func (self *CertAuthenticator) AddHandlers(mux *http.ServeMux) error {

// It is not really possible to log off when using client certs
func (self *CertAuthenticator) AddLogoff(mux *http.ServeMux) error {
mux.Handle(utils.Join(self.base, "/app/logoff.html"),
mux.Handle(api_utils.Join(self.base, "/app/logoff.html"),
IpFilter(self.config_obj,
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
Expand Down Expand Up @@ -187,7 +188,7 @@ func (self *CertAuthenticator) AuthenticateUserHandler(
// Use the super user principal to actually add the
// username so we have enough permissions.
err = users_manager.AddUserToOrg(r.Context(), services.AddNewUser,
constants.PinnedServerName, username,
utils.GetSuperuserName(self.config_obj), username,
[]string{"root"}, policy)
if err != nil {
http.Error(w,
Expand Down
59 changes: 30 additions & 29 deletions api/proxy.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/*
Velociraptor - Dig Deeper
Copyright (C) 2019-2024 Rapid7 Inc.
Velociraptor - Dig Deeper
Copyright (C) 2019-2024 Rapid7 Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package api

Expand All @@ -34,13 +34,14 @@ import (
"google.golang.org/protobuf/encoding/protojson"
"www.velocidex.com/golang/velociraptor/api/authenticators"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
utils "www.velocidex.com/golang/velociraptor/api/utils"
api_utils "www.velocidex.com/golang/velociraptor/api/utils"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
"www.velocidex.com/golang/velociraptor/constants"
crypto_utils "www.velocidex.com/golang/velociraptor/crypto/utils"
"www.velocidex.com/golang/velociraptor/grpc_client"
"www.velocidex.com/golang/velociraptor/logging"
"www.velocidex.com/golang/velociraptor/server"
"www.velocidex.com/golang/velociraptor/utils"
)

// A Mux for the reverse proxy feature.
Expand Down Expand Up @@ -140,50 +141,50 @@ func PrepareGUIMux(
return nil, err
}

base := utils.GetBasePath(config_obj)
mux.Handle(utils.Join(base, "/api/"), ipFilter(config_obj,
base := api_utils.GetBasePath(config_obj)
mux.Handle(api_utils.Join(base, "/api/"), ipFilter(config_obj,
csrfProtect(config_obj,
auther.AuthenticateUserHandler(h))))

mux.Handle(utils.Join(base, "/api/v1/DownloadTable"),
mux.Handle(api_utils.Join(base, "/api/v1/DownloadTable"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(downloadTable()))))

mux.Handle(utils.Join(base, "/api/v1/DownloadVFSFile"),
mux.Handle(api_utils.Join(base, "/api/v1/DownloadVFSFile"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(vfsFileDownloadHandler()))))

mux.Handle(utils.Join(base, "/api/v1/UploadTool"),
mux.Handle(api_utils.Join(base, "/api/v1/UploadTool"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(toolUploadHandler()))))

mux.Handle(utils.Join(base, "/api/v1/UploadFormFile"),
mux.Handle(api_utils.Join(base, "/api/v1/UploadFormFile"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(formUploadHandler()))))

// Serve prepared zip files.
mux.Handle(utils.Join(base, "/downloads/"),
mux.Handle(api_utils.Join(base, "/downloads/"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(
http.StripPrefix(base,
downloadFileStore([]string{"downloads"}))))))

// Serve notebook items
mux.Handle(utils.Join(base, "/notebooks/"),
mux.Handle(api_utils.Join(base, "/notebooks/"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(
http.StripPrefix(base,
downloadFileStore([]string{"notebooks"}))))))

// Serve files from hunt notebooks
mux.Handle(utils.Join(base, "/hunts/"),
mux.Handle(api_utils.Join(base, "/hunts/"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(
http.StripPrefix(base,
downloadFileStore([]string{"hunts"}))))))

// Serve files from client notebooks
mux.Handle(utils.Join(base, "/clients/"),
mux.Handle(api_utils.Join(base, "/clients/"),
ipFilter(config_obj, csrfProtect(config_obj,
auther.AuthenticateUserHandler(
http.StripPrefix(base,
Expand All @@ -202,14 +203,14 @@ func PrepareGUIMux(
if err != nil {
return nil, err
}
mux.Handle(utils.Join(base, "/app/index.html"),
mux.Handle(api_utils.Join(base, "/app/index.html"),
ipFilter(config_obj,
csrfProtect(config_obj, auther.AuthenticateUserHandler(h))))

// Redirect everything else to the app
mux.Handle(utils.GetBaseDirectory(config_obj),
mux.Handle(api_utils.GetBaseDirectory(config_obj),
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, utils.Join(base, "/app/index.html"), 302)
http.Redirect(w, r, api_utils.Join(base, "/app/index.html"), 302)
}))

return mux, nil
Expand Down Expand Up @@ -287,7 +288,7 @@ func GetAPIHandler(
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: CA_Pool,
ServerName: config_obj.Client.PinnedServerName,
ServerName: utils.GetSuperuserName(config_obj),
})

opts := []grpc.DialOption{
Expand All @@ -301,9 +302,9 @@ func GetAPIHandler(
return nil, err
}

base := utils.GetBasePath(config_obj)
base := api_utils.GetBasePath(config_obj)
reverse_proxy_mux := http.NewServeMux()
reverse_proxy_mux.Handle(utils.Join(base, "/api/v1/"),
reverse_proxy_mux.Handle(api_utils.Join(base, "/api/v1/"),
http.StripPrefix(base, grpc_proxy_mux))

return reverse_proxy_mux, nil
Expand Down
2 changes: 2 additions & 0 deletions artifacts/testdata/windows/github_actions.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ Datastore:
implementation: FileBaseDataStore
filestore_directory: x:\artifacts\testdata\server

defaults:
backup_period_seconds: -1

Writeback:
private_key: |
Expand Down
3 changes: 3 additions & 0 deletions artifacts/testdata/windows/test.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ Datastore:
filestore_directory: ./artifacts/testdata/server/
location: ./artifacts/testdata/server/

defaults:
backup_period_seconds: -1

Writeback:
private_key: |
-----BEGIN RSA PRIVATE KEY-----
Expand Down
40 changes: 20 additions & 20 deletions bin/config.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/*
Velociraptor - Dig Deeper
Copyright (C) 2019-2024 Rapid7 Inc.
Velociraptor - Dig Deeper
Copyright (C) 2019-2024 Rapid7 Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package main

Expand All @@ -34,13 +34,13 @@ import (
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
"www.velocidex.com/golang/velociraptor/config"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
"www.velocidex.com/golang/velociraptor/constants"
"www.velocidex.com/golang/velociraptor/crypto"
"www.velocidex.com/golang/velociraptor/crypto/utils"
crypto_utils "www.velocidex.com/golang/velociraptor/crypto/utils"
"www.velocidex.com/golang/velociraptor/json"
"www.velocidex.com/golang/velociraptor/logging"
"www.velocidex.com/golang/velociraptor/services"
"www.velocidex.com/golang/velociraptor/startup"
"www.velocidex.com/golang/velociraptor/utils"
)

var (
Expand Down Expand Up @@ -221,7 +221,7 @@ func generateNewKeys(config_obj *config_proto.Config) error {
// have a constant common name - clients will refuse to talk
// with another common name.
frontend_cert, err := crypto.GenerateServerCert(
config_obj, config_obj.Client.PinnedServerName)
config_obj, utils.GetSuperuserName(config_obj))
if err != nil {
return fmt.Errorf("Unable to create Frontend cert: %w", err)
}
Expand Down Expand Up @@ -292,7 +292,7 @@ func doRotateKeyConfig() error {

// Frontends must have a well known common name.
frontend_cert, err := crypto.GenerateServerCert(
config_obj, config_obj.Client.PinnedServerName)
config_obj, utils.GetSuperuserName(config_obj))
if err != nil {
return fmt.Errorf("Unable to create Frontend cert: %w", err)
}
Expand Down Expand Up @@ -423,7 +423,7 @@ func doDumpApiClientConfig() error {
return err
}

if *config_api_client_common_name == config_obj.Client.PinnedServerName {
if *config_api_client_common_name == utils.GetSuperuserName(config_obj) {
return errors.New("Name reserved! You may not name your " +
"api keys with this name.")
}
Expand Down Expand Up @@ -476,7 +476,7 @@ func doDumpApiClientConfig() error {

// Possibly dump out the pkcs12 key
if *config_api_client_pkcs12_output != "" {
ca_cert, err := utils.ParseX509CertFromPemStr([]byte(
ca_cert, err := crypto_utils.ParseX509CertFromPemStr([]byte(
config_obj.Client.CaCertificate))
if err != nil {
return err
Expand Down Expand Up @@ -551,8 +551,8 @@ func doDumpApiClientConfig() error {

// Make sure the user actually exists.
user_manager := services.GetUserManager()
_, err = user_manager.GetUser(ctx, constants.PinnedServerName,
*config_api_client_common_name)
_, err = user_manager.GetUser(ctx,
utils.GetSuperuserName(config_obj), *config_api_client_common_name)
if err != nil {
// Need to ensure we have a user
err := user_manager.SetUser(ctx, &api_proto.VelociraptorUser{
Expand Down
4 changes: 2 additions & 2 deletions bin/grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
jsonpatch "github.com/evanphx/json-patch/v5"
"www.velocidex.com/golang/velociraptor/acls"
acl_proto "www.velocidex.com/golang/velociraptor/acls/proto"
"www.velocidex.com/golang/velociraptor/constants"
"www.velocidex.com/golang/velociraptor/json"
logging "www.velocidex.com/golang/velociraptor/logging"
"www.velocidex.com/golang/velociraptor/services"
Expand Down Expand Up @@ -79,7 +78,8 @@ func doGrant() error {

// Check the user actually exists first
user_manager := services.GetUserManager()
_, err = user_manager.GetUser(ctx, constants.PinnedServerName, principal)
_, err = user_manager.GetUser(ctx,
utils.GetSuperuserName(config_obj), principal)
if err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions bin/orgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"fmt"

api_proto "www.velocidex.com/golang/velociraptor/api/proto"
"www.velocidex.com/golang/velociraptor/constants"
"www.velocidex.com/golang/velociraptor/json"
logging "www.velocidex.com/golang/velociraptor/logging"
"www.velocidex.com/golang/velociraptor/services"
"www.velocidex.com/golang/velociraptor/startup"
"www.velocidex.com/golang/velociraptor/utils"
)

var (
Expand Down Expand Up @@ -88,7 +88,7 @@ func doOrgUserAdd() error {

user_manager := services.GetUserManager()
record, err := user_manager.GetUserWithHashes(
ctx, constants.PinnedServerName, *orgs_user_add_user)
ctx, utils.GetSuperuserName(config_obj), *orgs_user_add_user)
if err != nil {
return err
}
Expand Down Expand Up @@ -181,7 +181,7 @@ func doOrgDelete() error {
logger.Info("Will remove org %v\n", *orgs_delete_org_id)

return org_manager.DeleteOrg(ctx,
constants.PinnedServerName, *orgs_delete_org_id)
utils.GetSuperuserName(config_obj), *orgs_delete_org_id)
}

func init() {
Expand Down
Loading

0 comments on commit e79ab54

Please sign in to comment.