Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New role "Power User" #343

Merged
merged 8 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/api/src/api/v2/apiclient/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ func (s Client) UserRemoveRole(userID uuid.UUID, roleID int32) error {
func (s Client) GetPermission(id int32) (model.Permission, error) {
var permission model.Permission

if response, err := s.Request(http.MethodGet, fmt.Sprintf("api/v2/auth/permissions/%d", id), nil, nil); err != nil {
if response, err := s.Request(http.MethodGet, fmt.Sprintf("api/v2/permissions/%d", id), nil, nil); err != nil {
return permission, err
} else {
defer response.Body.Close()
Expand All @@ -380,7 +380,7 @@ func (s Client) GetPermission(id int32) (model.Permission, error) {
func (s Client) ListPermissions() (v2.ListPermissionsResponse, error) {
var permissions v2.ListPermissionsResponse

if response, err := s.Request(http.MethodGet, "api/v2/auth/permissions", nil, nil); err != nil {
if response, err := s.Request(http.MethodGet, "api/v2/permissions", nil, nil); err != nil {
mistahj67 marked this conversation as resolved.
Show resolved Hide resolved
return permissions, err
} else {
defer response.Body.Close()
Expand Down
43 changes: 43 additions & 0 deletions cmd/api/src/api/v2/apiclient/savedqueries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package apiclient

import (
"github.com/specterops/bloodhound/src/api"
v2 "github.com/specterops/bloodhound/src/api/v2"
"github.com/specterops/bloodhound/src/model"
"net/http"
)

func (s Client) ListSavedQueries() (model.SavedQueries, error) {
var queries model.SavedQueries
if response, err := s.Request(http.MethodGet, "api/v2/saved-queries", nil, nil); err != nil {
return queries, err
} else {
defer response.Body.Close()

if api.IsErrorResponse(response) {
return queries, ReadAPIError(response)
}

return queries, api.ReadAPIV2ResponsePayload(&queries, response)
}
}

func (s Client) CreateSavedQuery() (model.SavedQuery, error) {
var query model.SavedQuery
payload := v2.CreateSavedQueryRequest{
Query: "Match(q:Question {life: 1, universe: 1, everything: 1}) return q",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣

Name: "AnswerToLifeUniverseEverything",
}

if response, err := s.Request(http.MethodPost, "api/v2/saved-queries", nil, payload); err != nil {
return query, err
} else {
defer response.Body.Close()

if api.IsErrorResponse(response) {
return query, ReadAPIError(response)
}

return query, api.ReadAPIV2ResponsePayload(&query, response)
}
}
10 changes: 5 additions & 5 deletions cmd/api/src/api/v2/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func TestManagementResource_ListPermissions_SortingError(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

endpoint := "/api/v2/auth/permissions"
endpoint := "/api/v2/permissions"
mockDB := dbmocks.NewMockDatabase(mockCtrl)

config, err := config.NewDefaultConfiguration()
Expand Down Expand Up @@ -273,7 +273,7 @@ func TestManagementResource_ListPermissions_InvalidFilterPredicate(t *testing.T)
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

endpoint := "/api/v2/auth/permissions"
endpoint := "/api/v2/permissions"
mockDB := dbmocks.NewMockDatabase(mockCtrl)

config, err := config.NewDefaultConfiguration()
Expand Down Expand Up @@ -306,7 +306,7 @@ func TestManagementResource_ListPermissions_PredicateMismatchWithColumn(t *testi
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

endpoint := "/api/v2/auth/permissions"
endpoint := "/api/v2/permissions"
mockDB := dbmocks.NewMockDatabase(mockCtrl)

config, err := config.NewDefaultConfiguration()
Expand Down Expand Up @@ -339,7 +339,7 @@ func TestManagementResource_ListPermissions_DBError(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

endpoint := "/api/v2/auth/permissions"
endpoint := "/api/v2/permissions"
mockDB := dbmocks.NewMockDatabase(mockCtrl)
mockDB.EXPECT().GetAllPermissions("authority desc, name", model.SQLFilter{SQLString: "name = ?", Params: []any{"foo"}}).Return(model.Permissions{}, fmt.Errorf("foo"))

Expand Down Expand Up @@ -375,7 +375,7 @@ func TestManagementResource_ListPermissions(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

endpoint := "/api/v2/auth/permissions"
endpoint := "/api/v2/permissions"

perm1 := model.Permission{
Authority: "a",
Expand Down
10 changes: 5 additions & 5 deletions cmd/api/src/api/v2/cypher_search_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ import (

func Test_CypherSearch(t *testing.T) {
var (
harness = harnesses.NewIntegrationTestHarness(fixtures.BHApiClientFixture)
harness = harnesses.NewIntegrationTestHarness(fixtures.BHAdminApiClientFixture)
)

lab.Pack(harness, fixtures.BasicComputerFixture)

lab.NewSpec(t, harness).Run(
lab.TestCase("errors on empty input", func(assert *require.Assertions, harness *lab.Harness) {
apiClient, ok := lab.Unpack(harness, fixtures.BHApiClientFixture)
apiClient, ok := lab.Unpack(harness, fixtures.BHAdminApiClientFixture)
assert.True(ok)

_, err := apiClient.CypherSearch(v2.CypherSearch{})
assert.ErrorContains(err, frontend.ErrInvalidInput.Error())
}),
lab.TestCase("errors on syntax mistake", func(assert *require.Assertions, harness *lab.Harness) {
apiClient, ok := lab.Unpack(harness, fixtures.BHApiClientFixture)
apiClient, ok := lab.Unpack(harness, fixtures.BHAdminApiClientFixture)
assert.True(ok)

_, err := apiClient.CypherSearch(v2.CypherSearch{
Expand All @@ -56,7 +56,7 @@ func Test_CypherSearch(t *testing.T) {
assert.ErrorContains(err, "extraneous input")
}),
lab.TestCase("errors on queries that are not supported", func(assert *require.Assertions, harness *lab.Harness) {
apiClient, ok := lab.Unpack(harness, fixtures.BHApiClientFixture)
apiClient, ok := lab.Unpack(harness, fixtures.BHAdminApiClientFixture)
assert.True(ok)

queryWithUpdateClause := "match (b) where b.name = 'test' remove b.prop return b"
Expand All @@ -66,7 +66,7 @@ func Test_CypherSearch(t *testing.T) {
assert.ErrorContains(err, frontend.ErrUpdateClauseNotSupported.Error())
}),
lab.TestCase("succesfully runs cypher query", func(assert *require.Assertions, harness *lab.Harness) {
apiClient, ok := lab.Unpack(harness, fixtures.BHApiClientFixture)
apiClient, ok := lab.Unpack(harness, fixtures.BHAdminApiClientFixture)
assert.True(ok)

graphResponse, err := apiClient.CypherSearch(v2.CypherSearch{
Expand Down
74 changes: 36 additions & 38 deletions cmd/api/src/auth/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,81 +21,79 @@ import (
)

type PermissionSet struct {
GraphDBRead model.Permission
GraphDBWrite model.Permission

AppReadApplicationConfiguration model.Permission
AppWriteApplicationConfiguration model.Permission

CollectionManageJobs model.Permission

ClientsManage model.Permission
ClientsTasking model.Permission
APsGenerateReport model.Permission
APsManageAPs model.Permission

AuthAcceptEULA model.Permission
AuthCreateToken model.Permission
AuthManageApplicationConfigurations model.Permission
AuthManageProviders model.Permission
AuthManageSelf model.Permission
AuthAcceptEULA model.Permission
AuthManageUsers model.Permission
AuthManageProviders model.Permission
AuthManageApplicationConfigurations model.Permission

APsGenerateReport model.Permission
APsManageAPs model.Permission
ClientsManage model.Permission
ClientsRead model.Permission
ClientsTasking model.Permission

CollectionManageJobs model.Permission

GraphDBRead model.Permission
GraphDBWrite model.Permission

SavedQueriesRead model.Permission
SavedQueriesWrite model.Permission

ClientsRead model.Permission
}

func (s PermissionSet) All() model.Permissions {
return model.Permissions{
s.GraphDBWrite,
s.GraphDBRead,
s.AppReadApplicationConfiguration,
s.AppWriteApplicationConfiguration,
s.CollectionManageJobs,
s.ClientsManage,
s.ClientsTasking,
s.APsGenerateReport,
s.APsManageAPs,
s.AuthCreateToken,
s.AuthManageUsers,
s.AuthManageApplicationConfigurations,
s.AuthManageProviders,
s.AuthManageSelf,
s.AuthManageApplicationConfigurations,
s.APsGenerateReport,
s.APsManageAPs,
s.AuthManageUsers,
s.ClientsManage,
s.ClientsRead,
s.ClientsTasking,
s.CollectionManageJobs,
s.GraphDBRead,
s.GraphDBWrite,
s.SavedQueriesRead,
s.SavedQueriesWrite,
s.ClientsRead,
}
}

func Permissions() PermissionSet {
return PermissionSet{
GraphDBRead: model.NewPermission("graphdb", "Read"),
GraphDBWrite: model.NewPermission("graphdb", "Write"),

AppReadApplicationConfiguration: model.NewPermission("app", "ReadAppConfig"),
AppWriteApplicationConfiguration: model.NewPermission("app", "WriteAppConfig"),

CollectionManageJobs: model.NewPermission("collection", "ManageJobs"),

ClientsManage: model.NewPermission("clients", "Manage"),
ClientsTasking: model.NewPermission("clients", "Tasking"),
APsGenerateReport: model.NewPermission("risks", "GenerateReport"),
APsManageAPs: model.NewPermission("risks", "ManageRisks"),

AuthCreateToken: model.NewPermission("auth", "CreateToken"),
AuthManageSelf: model.NewPermission("auth", "ManageSelf"),
AuthAcceptEULA: model.NewPermission("auth", "AcceptEULA"),
AuthCreateToken: model.NewPermission("auth", "CreateToken"),
AuthManageApplicationConfigurations: model.NewPermission("auth", "ManageAppConfig"),
AuthManageProviders: model.NewPermission("auth", "ManageProviders"),
AuthManageSelf: model.NewPermission("auth", "ManageSelf"),
AuthManageUsers: model.NewPermission("auth", "ManageUsers"),
AuthManageApplicationConfigurations: model.NewPermission("auth", "ManageAppConfig"),

APsGenerateReport: model.NewPermission("risks", "GenerateReport"),
APsManageAPs: model.NewPermission("risks", "ManageRisks"),
ClientsManage: model.NewPermission("clients", "Manage"),
ClientsRead: model.NewPermission("clients", "Read"),
ClientsTasking: model.NewPermission("clients", "Tasking"),

CollectionManageJobs: model.NewPermission("collection", "ManageJobs"),

GraphDBRead: model.NewPermission("graphdb", "Read"),
GraphDBWrite: model.NewPermission("graphdb", "Write"),

SavedQueriesRead: model.NewPermission("saved_queries", "Read"),
SavedQueriesWrite: model.NewPermission("saved_queries", "Write"),

ClientsRead: model.NewPermission("clients", "Read"),
}
}
35 changes: 28 additions & 7 deletions cmd/api/src/auth/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
RoleUploadOnly = "Upload-Only"
RoleReadOnly = "Read-Only"
RoleUser = "User"
RolePowerUser = "Power User"
RoleAdministrator = "Administrator"
)

Expand Down Expand Up @@ -70,32 +71,52 @@ func Roles() map[string]RoleTemplate {
Name: RoleReadOnly,
Description: "Used for integrations",
Permissions: model.Permissions{
permissions.GraphDBRead,
permissions.AuthManageSelf,
permissions.APsGenerateReport,
permissions.AppReadApplicationConfiguration,
permissions.APsGenerateReport,
permissions.AuthManageSelf,
permissions.GraphDBRead,
},
},
RoleUploadOnly: {
Name: RoleUploadOnly,
Description: "Used for data collection clients, can post data but cannot read data",
Permissions: model.Permissions{
permissions.GraphDBWrite,
permissions.ClientsTasking,
permissions.GraphDBWrite,
},
},
RoleUser: {
Name: RoleUser,
Description: "Can read data, modify asset group memberships",
Permissions: model.Permissions{
permissions.GraphDBRead,
permissions.AppReadApplicationConfiguration,
permissions.APsGenerateReport,
permissions.AuthCreateToken,
permissions.AuthManageSelf,
permissions.APsGenerateReport,
permissions.AppReadApplicationConfiguration,
permissions.ClientsRead,
permissions.GraphDBRead,
permissions.SavedQueriesRead,
permissions.SavedQueriesWrite,
},
},
RolePowerUser: {
Name: RolePowerUser,
Description: "Can upload data, manage clients, and perform any action a User can",
Permissions: model.Permissions{
permissions.AppReadApplicationConfiguration,
permissions.AppWriteApplicationConfiguration,
permissions.APsGenerateReport,
permissions.APsManageAPs,
permissions.AuthCreateToken,
permissions.AuthManageSelf,
permissions.ClientsManage,
permissions.ClientsRead,
permissions.ClientsTasking,
permissions.CollectionManageJobs,
permissions.GraphDBWrite,
permissions.GraphDBRead,
permissions.SavedQueriesRead,
permissions.SavedQueriesWrite,
},
},
RoleAdministrator: {
Expand Down
Loading
Loading