Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
29da793
environment added to opengraphschema service + principal kinds - lots…
kpowderly Jan 6, 2026
a7f351e
did an overhaul of everything after talking with Cody and pulled a co…
kpowderly Jan 7, 2026
bc97cb0
cleanup
kpowderly Jan 7, 2026
bce213b
transactions that hopefully satisfy both databases
kpowderly Jan 7, 2026
479fb18
Merge remote-tracking branch 'origin/main' into BED-6852-environment
kpowderly Jan 7, 2026
89998ee
just prepare
kpowderly Jan 7, 2026
6ded4e3
abandoned the transactor
kpowderly Jan 7, 2026
6c08285
abandoned the transactor
kpowderly Jan 7, 2026
4ae5dfb
entry pointed corrected so transactions can live on the interface aga…
kpowderly Jan 8, 2026
a3d9422
some cleanup
kpowderly Jan 8, 2026
5987407
feat(graphschema): Add Environment principal kinds BED-7076
cweidenkeller Dec 29, 2025
e76b52d
pretty decent sized refactor to move from service layer to database l…
kpowderly Jan 9, 2026
75b6804
Merge remote-tracking branch 'origin/BED-7076' into BED-6852-environment
kpowderly Jan 9, 2026
38186be
pulled in Conrad's changes
kpowderly Jan 9, 2026
ab74bf1
code rabbit comments
kpowderly Jan 9, 2026
d63427f
updated to add integration flag
kpowderly Jan 9, 2026
bad51d2
missed an arg
kpowderly Jan 9, 2026
6e4ba47
peer review changes
kpowderly Jan 9, 2026
f94cb7c
Merge remote-tracking branch 'origin/main' into BED-6852-environment
kpowderly Jan 9, 2026
535fcb7
majority of logic for findings and remediation but still working on t…
kpowderly Jan 13, 2026
3c5f688
Merge remote-tracking branch 'origin/main' into BED-6852-environment
kpowderly Jan 13, 2026
85b9407
merge conflicts
kpowderly Jan 13, 2026
be02063
updated to be in line with other PR
kpowderly Jan 13, 2026
094d52a
just prepare
kpowderly Jan 13, 2026
be0c964
just prepare
kpowderly Jan 13, 2026
712d776
tests
kpowderly Jan 13, 2026
c2758be
just prepare
kpowderly Jan 14, 2026
86560a5
updated error message
kpowderly Jan 14, 2026
434fb40
Merge remote-tracking branch 'origin/main' into BED-6852-environment
kpowderly Jan 14, 2026
2b08c97
Merge remote-tracking branch 'origin/main' into BED-6853
kpowderly Jan 14, 2026
c75a03b
just prepare
kpowderly Jan 14, 2026
a6b04d8
integration flag added
kpowderly Jan 14, 2026
84cbd17
just prepare
kpowderly Jan 14, 2026
6d12e75
Merge remote-tracking branch 'origin/main' into BED-6853
kpowderly Jan 14, 2026
b476226
addressing code rabbit comments
kpowderly Jan 14, 2026
51e44b5
main changes
kpowderly Jan 14, 2026
1cab880
peer review changes
kpowderly Jan 15, 2026
b9cbb50
Merge remote-tracking branch 'origin/main' into BED-6852-environment
kpowderly Jan 15, 2026
471fc4e
peer review changes - more naming
kpowderly Jan 15, 2026
1de71fc
migration update
kpowderly Jan 15, 2026
a2427b6
migration update
kpowderly Jan 15, 2026
fe8076b
Merge remote-tracking branch 'origin/main' into BED-6853
kpowderly Jan 16, 2026
ce73f7f
Merge remote-tracking branch 'origin/BED-6852-environment' into BED-6853
kpowderly Jan 16, 2026
38456ce
getting 6853 in line with peer review comments from 6852
kpowderly Jan 16, 2026
f5ed3a2
Merge remote-tracking branch 'origin/main' into BED-6853
kpowderly Jan 16, 2026
c576593
updated per 6852 peer review
kpowderly Jan 16, 2026
cd60110
mocks
kpowderly Jan 16, 2026
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
17 changes: 17 additions & 0 deletions cmd/api/src/api/v2/opengraphschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type OpenGraphSchemaService interface {

type GraphSchemaExtension struct {
Environments []Environment `json:"environments"`
Findings []Finding `json:"findings"`
}

type Environment struct {
Expand All @@ -39,6 +40,22 @@ type Environment struct {
PrincipalKinds []string `json:"principalKinds"`
}

type Finding struct {
Name string `json:"name"`
DisplayName string `json:"displayName"`
SourceKind string `json:"sourceKind"`
RelationshipKind string `json:"relationshipKind"`
EnvironmentKind string `json:"environmentKind"`
Remediation Remediation `json:"remediation"`
}

type Remediation struct {
ShortDescription string `json:"shortDescription"`
LongDescription string `json:"longDescription"`
ShortRemediation string `json:"shortRemediation"`
LongRemediation string `json:"longRemediation"`
}

// TODO: Implement this - skeleton endpoint to simply test the handler.
func (s Resources) OpenGraphSchemaIngest(response http.ResponseWriter, request *http.Request) {
var (
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ type Configuration struct {
EnableAPILogging bool `json:"enable_api_logging"`
EnableCypherMutations bool `json:"enable_cypher_mutations"`
DisableAnalysis bool `json:"disable_analysis"`
DisableAPIKeys bool `json:"disable_api_keys"`
DisableAPIKeys bool `json:"disable_api_keys"`
DisableCypherComplexityLimit bool `json:"disable_cypher_complexity_limit"`
DisableIngest bool `json:"disable_ingest"`
DisableMigrations bool `json:"disable_migrations"`
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/src/config/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func NewDefaultConfiguration() (Configuration, error) {
EnableStartupWaitPeriod: true,
EnableAPILogging: true,
DisableAnalysis: false,
DisableAPIKeys: false,
DisableAPIKeys: false,
DisableCypherComplexityLimit: false,
DisableIngest: false,
DisableMigrations: false,
Expand Down
21 changes: 21 additions & 0 deletions cmd/api/src/database/graphschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type OpenGraphSchema interface {

CreateSchemaRelationshipFinding(ctx context.Context, extensionId int32, relationshipKindId int32, environmentId int32, name string, displayName string) (model.SchemaRelationshipFinding, error)
GetSchemaRelationshipFindingById(ctx context.Context, findingId int32) (model.SchemaRelationshipFinding, error)
GetSchemaRelationshipFindingByName(ctx context.Context, name string) (model.SchemaRelationshipFinding, error)
DeleteSchemaRelationshipFinding(ctx context.Context, findingId int32) error

CreateRemediation(ctx context.Context, findingId int32, shortDescription string, longDescription string, shortRemediation string, longRemediation string) (model.Remediation, error)
Expand Down Expand Up @@ -677,6 +678,23 @@ func (s *BloodhoundDB) GetSchemaRelationshipFindingById(ctx context.Context, fin
return finding, nil
}

// GetSchemaRelationshipFindingByName - retrieves a schema relationship finding by finding name.
func (s *BloodhoundDB) GetSchemaRelationshipFindingByName(ctx context.Context, name string) (model.SchemaRelationshipFinding, error) {
var finding model.SchemaRelationshipFinding

if result := s.db.WithContext(ctx).Raw(fmt.Sprintf(`
SELECT id, schema_extension_id, relationship_kind_id, environment_id, name, display_name, created_at
FROM %s WHERE name = ?`,
finding.TableName()),
name).Scan(&finding); result.Error != nil {
return model.SchemaRelationshipFinding{}, CheckError(result)
} else if result.RowsAffected == 0 {
return model.SchemaRelationshipFinding{}, ErrNotFound
}

return finding, nil
}

// DeleteSchemaRelationshipFinding - deletes a schema relationship finding by id.
func (s *BloodhoundDB) DeleteSchemaRelationshipFinding(ctx context.Context, findingId int32) error {
var finding model.SchemaRelationshipFinding
Expand Down Expand Up @@ -793,6 +811,9 @@ func (s *BloodhoundDB) CreatePrincipalKind(ctx context.Context, environmentId in
VALUES (?, ?, NOW())
RETURNING environment_id, principal_kind, created_at`,
environmentId, principalKind).Scan(&envPrincipalKind); result.Error != nil {
if strings.Contains(result.Error.Error(), DuplicateKeyValueErrorString) {
return model.SchemaEnvironmentPrincipalKind{}, result.Error
}
return model.SchemaEnvironmentPrincipalKind{}, CheckError(result)
}

Expand Down
15 changes: 15 additions & 0 deletions cmd/api/src/database/mocks/db.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions cmd/api/src/database/upsert_schema_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (s *BloodhoundDB) UpsertSchemaEnvironmentWithPrincipalKinds(ctx context.Con
SchemaExtensionId: schemaExtensionId,
}

envKind, err := s.validateAndTranslateEnvironmentKind(ctx, environmentKind)
envKindID, err := s.validateAndTranslateEnvironmentKind(ctx, environmentKind)
if err != nil {
return err
}
Expand All @@ -46,7 +46,7 @@ func (s *BloodhoundDB) UpsertSchemaEnvironmentWithPrincipalKinds(ctx context.Con
return err
}

environment.EnvironmentKindId = int32(envKind.ID)
environment.EnvironmentKindId = envKindID
environment.SourceKindId = sourceKindID

envID, err := s.replaceSchemaEnvironment(ctx, environment)
Expand All @@ -62,13 +62,13 @@ func (s *BloodhoundDB) UpsertSchemaEnvironmentWithPrincipalKinds(ctx context.Con
}

// validateAndTranslateEnvironmentKind validates that the environment kind exists in the kinds table.
func (s *BloodhoundDB) validateAndTranslateEnvironmentKind(ctx context.Context, environmentKindName string) (model.Kind, error) {
func (s *BloodhoundDB) validateAndTranslateEnvironmentKind(ctx context.Context, environmentKindName string) (int32, error) {
if envKind, err := s.GetKindByName(ctx, environmentKindName); err != nil && !errors.Is(err, ErrNotFound) {
return model.Kind{}, fmt.Errorf("error retrieving environment kind '%s': %w", environmentKindName, err)
return 0, fmt.Errorf("error retrieving environment kind '%s': %w", environmentKindName, err)
} else if errors.Is(err, ErrNotFound) {
return model.Kind{}, fmt.Errorf("environment kind '%s' not found", environmentKindName)
return 0, fmt.Errorf("environment kind '%s' not found", environmentKindName)
} else {
return envKind, nil
return envKind.ID, nil
}
}

Expand Down
28 changes: 27 additions & 1 deletion cmd/api/src/database/upsert_schema_extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,40 @@ type EnvironmentInput struct {
PrincipalKinds []string
}

func (s *BloodhoundDB) UpsertGraphSchemaExtension(ctx context.Context, extensionID int32, environments []EnvironmentInput) error {
type FindingInput struct {
Name string
DisplayName string
RelationshipKindName string
EnvironmentKindName string
SourceKindName string
RemediationInput RemediationInput
}

type RemediationInput struct {
ShortDescription string
LongDescription string
ShortRemediation string
LongRemediation string
}

func (s *BloodhoundDB) UpsertGraphSchemaExtension(ctx context.Context, extensionID int32, environments []EnvironmentInput, findings []FindingInput) error {
return s.Transaction(ctx, func(tx *BloodhoundDB) error {
for _, env := range environments {
if err := tx.UpsertSchemaEnvironmentWithPrincipalKinds(ctx, extensionID, env.EnvironmentKindName, env.SourceKindName, env.PrincipalKinds); err != nil {
return fmt.Errorf("failed to upsert environment with principal kinds: %w", err)
}
}

for _, finding := range findings {
if schemaFinding, err := tx.UpsertFinding(ctx, extensionID, finding.SourceKindName, finding.RelationshipKindName, finding.EnvironmentKindName, finding.Name, finding.DisplayName); err != nil {
return fmt.Errorf("failed to upsert finding: %w", err)
} else {
if err := tx.UpsertRemediation(ctx, schemaFinding.ID, finding.RemediationInput.ShortDescription, finding.RemediationInput.LongDescription, finding.RemediationInput.ShortRemediation, finding.RemediationInput.LongRemediation); err != nil {
return fmt.Errorf("failed to upsert remediation: %w", err)
}
}
}

return nil
})
}
Loading