Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into populate-audit-log-fi…
Browse files Browse the repository at this point in the history
…elds
  • Loading branch information
superlinkx committed Jan 31, 2024
2 parents af01314 + d52d17b commit 9ff9831
Show file tree
Hide file tree
Showing 36 changed files with 1,131 additions and 144 deletions.
27 changes: 27 additions & 0 deletions cmd/api/src/analysis/ad/adcs_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,33 @@ func TestADCSESC10a(t *testing.T) {
}
return nil
})

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if results, err := ops.FetchRelationships(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.ADCSESC10a)
})); err != nil {
t.Fatalf("error fetching esc9a edges in integration test; %v", err)
} else {
assert.Equal(t, 1, len(results))
edge := results[0]

if edgeComp, err := ad2.GetEdgeCompositionPath(context.Background(), db, edge); err != nil {
t.Fatalf("error getting edge composition for esc9: %v", err)
} else {
nodes := edgeComp.AllNodes().Slice()
assert.Contains(t, nodes, harness.ESC10aHarnessECA.Group1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.User1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.Domain1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.NTAuthStore1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.RootCA1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.DC1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.EnterpriseCA1)
assert.Contains(t, nodes, harness.ESC10aHarnessECA.CertTemplate1)
}
}

return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
Expand Down
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 {
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",
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 @@ -237,7 +237,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 @@ -270,7 +270,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 @@ -303,7 +303,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 @@ -336,7 +336,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 @@ -372,7 +372,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

0 comments on commit 9ff9831

Please sign in to comment.