Skip to content
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
1 change: 1 addition & 0 deletions cmd/api/src/services/graphify/convertors.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func convertGPOData(gpo ein.GPO, converted *ConvertedData, ingestTime time.Time)
baseNodeProp := ein.ConvertObjectToNode(ein.IngestBase(gpo), ad.GPO, ingestTime)
converted.NodeProps = append(converted.NodeProps, baseNodeProp)
converted.RelProps = append(converted.RelProps, ein.ParseACEData(baseNodeProp, gpo.Aces, gpo.ObjectIdentifier, ad.GPO)...)
converted.NodeProps = append(converted.NodeProps, ein.ParseGPOData(gpo))
}

func convertOUData(ou ein.OU, converted *ConvertedData, ingestTime time.Time) {
Expand Down
2 changes: 2 additions & 0 deletions packages/csharp/graphschema/PropertyNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ public static class PropertyNames {
public static readonly string NetBIOS = "netbios";
public static readonly string AdminSDHolderProtected = "adminsdholderprotected";
public static readonly string ServicePrincipalNames = "serviceprincipalnames";
public static readonly string GPOStatusRaw = "gpostatusraw";
public static readonly string GPOStatus = "gpostatus";

}
}
16 changes: 16 additions & 0 deletions packages/cue/bh/ad/ad.cue
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,20 @@ ServicePrincipalNames: types.#StringEnum & {
representation: "serviceprincipalnames"
}

GPOStatusRaw: types.#StringEnum & {
symbol: "GPOStatusRaw"
schema: "ad"
name: "GPO Status (Raw)"
representation: "gpostatusraw"
}

GPOStatus: types.#StringEnum & {
symbol: "GPOStatus"
schema: "ad"
name: "GPO Status"
representation: "gpostatus"
}

Properties: [
AdminCount,
CASecurityCollected,
Expand Down Expand Up @@ -1158,6 +1172,8 @@ Properties: [
NetBIOS,
AdminSDHolderProtected,
ServicePrincipalNames,
GPOStatusRaw,
GPOStatus,
]

// Kinds
Expand Down
36 changes: 36 additions & 0 deletions packages/go/ein/ad.go
Original file line number Diff line number Diff line change
Expand Up @@ -1533,3 +1533,39 @@ func ParseDCRegistryData(computer Computer) IngestibleNode {
Labels: []graph.Kind{ad.Computer},
}
}

// Prettified definitions for GPOStatus
const (
PrettyGPOStatusNotExisting = "GPO Status does not exist"
PrettyGPOStatusEnabled = "Enabled"
PrettyGPOStatusUserConfigurationDisabled = "User Configuration Disabled"
PrettyGPOStatusComputerConfigurationDisabled = "Computer Configuration Disabled"
PrettyGPOStatusDisabled = "Disabled"
)

func ParseGPOData(gpo GPO) IngestibleNode {
propMap := make(map[string]any)

if status, ok := gpo.Properties[ad.GPOStatus.String()]; ok {
propMap[ad.GPOStatusRaw.String()] = strings.TrimSpace(fmt.Sprint(status))

switch propMap[ad.GPOStatusRaw.String()] {
case "0":
propMap[ad.GPOStatus.String()] = PrettyGPOStatusEnabled
case "1":
propMap[ad.GPOStatus.String()] = PrettyGPOStatusUserConfigurationDisabled
case "2":
propMap[ad.GPOStatus.String()] = PrettyGPOStatusComputerConfigurationDisabled
case "3":
propMap[ad.GPOStatus.String()] = PrettyGPOStatusDisabled
default:
propMap[ad.GPOStatus.String()] = PrettyGPOStatusNotExisting
}
}

return IngestibleNode{
ObjectID: gpo.ObjectIdentifier,
PropertyMap: propMap,
Labels: []graph.Kind{ad.GPO},
}
}
149 changes: 149 additions & 0 deletions packages/go/ein/ad_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,152 @@ func TestParseGroupMiscData(t *testing.T) {
})
}
}

func TestParseGPOData(t *testing.T) {
t.Parallel()
type args struct {
gpo ein.GPO
}
type testData struct {
name string
args args
expected ein.IngestibleNode
}

tt := []testData{
{
name: "ParseGPOData without Properties",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with GPO Enabled",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): "0"},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "0", ad.GPOStatus.String(): ein.PrettyGPOStatusEnabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with GPO UserConfigurationDisabled",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): "1"},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "1", ad.GPOStatus.String(): ein.PrettyGPOStatusUserConfigurationDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with GPO ComputerConfigurationDisabled",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): "2"},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "2", ad.GPOStatus.String(): ein.PrettyGPOStatusComputerConfigurationDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with GPO Disabled",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): "3"},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "3", ad.GPOStatus.String(): ein.PrettyGPOStatusDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with Invalid GPO Status",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): "4"},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "4", ad.GPOStatus.String(): ein.PrettyGPOStatusNotExisting},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with numeric status (int)",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): 2},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "2", ad.GPOStatus.String(): ein.PrettyGPOStatusComputerConfigurationDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with numeric status (float64)",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): float64(3)},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "3", ad.GPOStatus.String(): ein.PrettyGPOStatusDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
{
name: "ParseGPOData with whitespace-padded string",
args: args{
gpo: ein.GPO{
ObjectIdentifier: "gpoBase",
Properties: map[string]any{ad.GPOStatus.String(): " 1 "},
},
},
expected: ein.IngestibleNode{
ObjectID: "gpoBase",
PropertyMap: map[string]any{ad.GPOStatusRaw.String(): "1", ad.GPOStatus.String(): ein.PrettyGPOStatusUserConfigurationDisabled},
Labels: []graph.Kind{ad.GPO},
},
},
}

for _, testCase := range tt {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

result := ein.ParseGPOData(testCase.args.gpo)
assert.Equal(t, testCase.expected, result)
})
}
}
16 changes: 15 additions & 1 deletion packages/go/graphschema/ad/ad.go

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

6 changes: 6 additions & 0 deletions packages/javascript/bh-shared-ui/src/graphSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ export enum ActiveDirectoryKindProperties {
NetBIOS = 'netbios',
AdminSDHolderProtected = 'adminsdholderprotected',
ServicePrincipalNames = 'serviceprincipalnames',
GPOStatusRaw = 'gpostatusraw',
GPOStatus = 'gpostatus',
}
export function ActiveDirectoryKindPropertiesToDisplay(value: ActiveDirectoryKindProperties): string | undefined {
switch (value) {
Expand Down Expand Up @@ -773,6 +775,10 @@ export function ActiveDirectoryKindPropertiesToDisplay(value: ActiveDirectoryKin
return 'AdminSDHolder Protected';
case ActiveDirectoryKindProperties.ServicePrincipalNames:
return 'Service Principal Names';
case ActiveDirectoryKindProperties.GPOStatusRaw:
return 'GPO Status (Raw)';
case ActiveDirectoryKindProperties.GPOStatus:
return 'GPO Status';
default:
return undefined;
}
Expand Down