diff --git a/cmd/api/src/analysis/ad/adcs_integration_test.go b/cmd/api/src/analysis/ad/adcs_integration_test.go
index 39e9bd9213..5a85fe3ed2 100644
--- a/cmd/api/src/analysis/ad/adcs_integration_test.go
+++ b/cmd/api/src/analysis/ad/adcs_integration_test.go
@@ -447,63 +447,75 @@ func TestTrustedForNTAuth(t *testing.T) {
func TestEnrollOnBehalfOf(t *testing.T) {
testContext := integration.NewGraphTestContext(t, graphschema.DefaultGraphSchema())
testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
- harness.EnrollOnBehalfOfHarnessOne.Setup(testContext)
+ harness.EnrollOnBehalfOfHarness1.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
v1Templates := make([]*graph.Node, 0)
+ v2Templates := make([]*graph.Node, 0)
+
for _, template := range certTemplates {
if version, err := template.Properties.Get(ad.SchemaVersion.String()).Float64(); err != nil {
continue
} else if version == 1 {
v1Templates = append(v1Templates, template)
} else if version >= 2 {
- continue
+ v2Templates = append(v2Templates, template)
}
}
require.Nil(t, err)
db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
- results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates)
+ results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates, harness.EnrollOnBehalfOfHarness1.Domain1)
require.Nil(t, err)
require.Len(t, results, 3)
require.Contains(t, results, analysis.CreatePostRelationshipJob{
- FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate11.ID,
- ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
+ FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate11.ID,
+ ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})
require.Contains(t, results, analysis.CreatePostRelationshipJob{
- FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate13.ID,
- ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
+ FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate13.ID,
+ ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})
require.Contains(t, results, analysis.CreatePostRelationshipJob{
- FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
- ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
+ FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
+ ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})
return nil
})
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates, harness.EnrollOnBehalfOfHarness1.Domain1)
+ require.Nil(t, err)
+
+ require.Len(t, results, 0)
+
+ return nil
+ })
})
testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
- harness.EnrollOnBehalfOfHarnessTwo.Setup(testContext)
+ harness.EnrollOnBehalfOfHarness2.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
+ v1Templates := make([]*graph.Node, 0)
v2Templates := make([]*graph.Node, 0)
for _, template := range certTemplates {
if version, err := template.Properties.Get(ad.SchemaVersion.String()).Float64(); err != nil {
continue
} else if version == 1 {
- continue
+ v1Templates = append(v1Templates, template)
} else if version >= 2 {
v2Templates = append(v2Templates, template)
}
@@ -512,15 +524,60 @@ func TestEnrollOnBehalfOf(t *testing.T) {
require.Nil(t, err)
db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
- results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates)
+ results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates, harness.EnrollOnBehalfOfHarness2.Domain2)
+ require.Nil(t, err)
+
+ require.Len(t, results, 0)
+ return nil
+ })
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates, harness.EnrollOnBehalfOfHarness2.Domain2)
require.Nil(t, err)
require.Len(t, results, 1)
require.Contains(t, results, analysis.CreatePostRelationshipJob{
- FromID: harness.EnrollOnBehalfOfHarnessTwo.CertTemplate21.ID,
- ToID: harness.EnrollOnBehalfOfHarnessTwo.CertTemplate23.ID,
+ FromID: harness.EnrollOnBehalfOfHarness2.CertTemplate21.ID,
+ ToID: harness.EnrollOnBehalfOfHarness2.CertTemplate23.ID,
Kind: ad.EnrollOnBehalfOf,
})
+ return nil
+ })
+ })
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.EnrollOnBehalfOfHarness3.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - EnrollOnBehalfOf 3")
+
+ _, enterpriseCertAuthorities, certTemplates, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ if err := ad2.PostEnrollOnBehalfOf(domains, enterpriseCertAuthorities, certTemplates, cache, operation); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.EnrollOnBehalfOf.String(), err)
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if startNodes, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.EnrollOnBehalfOf)
+ })); err != nil {
+ t.Fatalf("error fetching EnrollOnBehalfOf edges in integration test; %v", err)
+ } else if endNodes, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.EnrollOnBehalfOf)
+ })); err != nil {
+ t.Fatalf("error fetching EnrollOnBehalfOf edges in integration test; %v", err)
+ } else {
+ require.Len(t, startNodes, 2)
+ require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate11))
+ require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))
+
+ require.Len(t, endNodes, 2)
+ require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))
+ require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))
+ }
return nil
})
diff --git a/cmd/api/src/test/integration/harnesses.go b/cmd/api/src/test/integration/harnesses.go
index 637aebc7c0..dede7f384a 100644
--- a/cmd/api/src/test/integration/harnesses.go
+++ b/cmd/api/src/test/integration/harnesses.go
@@ -1595,7 +1595,7 @@ func (s *ADCSESC1HarnessAuthUsers) Setup(graphTestContext *GraphTestContext) {
graphTestContext.UpdateNode(s.AuthUsers)
}
-type EnrollOnBehalfOfHarnessTwo struct {
+type EnrollOnBehalfOfHarness2 struct {
Domain2 *graph.Node
AuthStore2 *graph.Node
RootCA2 *graph.Node
@@ -1604,10 +1604,9 @@ type EnrollOnBehalfOfHarnessTwo struct {
CertTemplate22 *graph.Node
CertTemplate23 *graph.Node
CertTemplate24 *graph.Node
- CertTemplate25 *graph.Node
}
-func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
+func (s *EnrollOnBehalfOfHarness2) Setup(gt *GraphTestContext) {
certRequestAgentEKU := make([]string, 0)
certRequestAgentEKU = append(certRequestAgentEKU, adAnalysis.EkuCertRequestAgent)
emptyAppPolicies := make([]string, 0)
@@ -1623,7 +1622,7 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
- SchemaVersion: 1,
+ SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: certRequestAgentEKU,
ApplicationPolicies: emptyAppPolicies,
@@ -1635,7 +1634,7 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
- SchemaVersion: 1,
+ SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: []string{adAnalysis.EkuCertRequestAgent, adAnalysis.EkuAnyPurpose},
ApplicationPolicies: emptyAppPolicies,
@@ -1664,18 +1663,6 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
EffectiveEKUs: emptyAppPolicies,
ApplicationPolicies: emptyAppPolicies,
})
- s.CertTemplate25 = gt.NewActiveDirectoryCertTemplate("certtemplate2-5", sid, CertTemplateData{
- RequiresManagerApproval: false,
- AuthenticationEnabled: false,
- EnrolleeSuppliesSubject: false,
- SubjectAltRequireUPN: false,
- SubjectAltRequireSPN: false,
- NoSecurityExtension: false,
- SchemaVersion: 1,
- AuthorizedSignatures: 1,
- EffectiveEKUs: emptyAppPolicies,
- ApplicationPolicies: emptyAppPolicies,
- })
gt.NewRelationship(s.AuthStore2, s.Domain2, ad.NTAuthStoreFor)
gt.NewRelationship(s.RootCA2, s.Domain2, ad.RootCAFor)
@@ -1685,10 +1672,9 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
gt.NewRelationship(s.CertTemplate22, s.EnterpriseCA2, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate23, s.EnterpriseCA2, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate24, s.EnterpriseCA2, ad.PublishedTo)
- gt.NewRelationship(s.CertTemplate25, s.EnterpriseCA2, ad.PublishedTo)
}
-type EnrollOnBehalfOfHarnessOne struct {
+type EnrollOnBehalfOfHarness1 struct {
Domain1 *graph.Node
AuthStore1 *graph.Node
RootCA1 *graph.Node
@@ -1698,7 +1684,7 @@ type EnrollOnBehalfOfHarnessOne struct {
CertTemplate13 *graph.Node
}
-func (s *EnrollOnBehalfOfHarnessOne) Setup(gt *GraphTestContext) {
+func (s *EnrollOnBehalfOfHarness1) Setup(gt *GraphTestContext) {
sid := RandomDomainSID()
anyPurposeEkus := make([]string, 0)
anyPurposeEkus = append(anyPurposeEkus, adAnalysis.EkuAnyPurpose)
@@ -1753,6 +1739,74 @@ func (s *EnrollOnBehalfOfHarnessOne) Setup(gt *GraphTestContext) {
gt.NewRelationship(s.CertTemplate13, s.EnterpriseCA1, ad.PublishedTo)
}
+type EnrollOnBehalfOfHarness3 struct {
+ Domain1 *graph.Node
+ AuthStore1 *graph.Node
+ RootCA1 *graph.Node
+ EnterpriseCA1 *graph.Node
+ EnterpriseCA2 *graph.Node
+ CertTemplate11 *graph.Node
+ CertTemplate12 *graph.Node
+ CertTemplate13 *graph.Node
+}
+
+func (s *EnrollOnBehalfOfHarness3) Setup(gt *GraphTestContext) {
+ sid := RandomDomainSID()
+ anyPurposeEkus := make([]string, 0)
+ anyPurposeEkus = append(anyPurposeEkus, adAnalysis.EkuAnyPurpose)
+ emptyAppPolicies := make([]string, 0)
+ s.Domain1 = gt.NewActiveDirectoryDomain("domain1", sid, false, true)
+ s.AuthStore1 = gt.NewActiveDirectoryNTAuthStore("authstore1", sid)
+ s.RootCA1 = gt.NewActiveDirectoryRootCA("rca1", sid)
+ s.EnterpriseCA1 = gt.NewActiveDirectoryEnterpriseCA("eca1", sid)
+ s.EnterpriseCA2 = gt.NewActiveDirectoryEnterpriseCA("eca2", sid)
+ s.CertTemplate11 = gt.NewActiveDirectoryCertTemplate("certtemplate1-1", sid, CertTemplateData{
+ RequiresManagerApproval: false,
+ AuthenticationEnabled: false,
+ EnrolleeSuppliesSubject: false,
+ SubjectAltRequireUPN: false,
+ SubjectAltRequireSPN: false,
+ NoSecurityExtension: false,
+ SchemaVersion: 2,
+ AuthorizedSignatures: 0,
+ EffectiveEKUs: anyPurposeEkus,
+ ApplicationPolicies: emptyAppPolicies,
+ })
+ s.CertTemplate12 = gt.NewActiveDirectoryCertTemplate("certtemplate1-2", sid, CertTemplateData{
+ RequiresManagerApproval: false,
+ AuthenticationEnabled: false,
+ EnrolleeSuppliesSubject: false,
+ SubjectAltRequireUPN: false,
+ SubjectAltRequireSPN: false,
+ NoSecurityExtension: false,
+ SchemaVersion: 1,
+ AuthorizedSignatures: 0,
+ EffectiveEKUs: anyPurposeEkus,
+ ApplicationPolicies: emptyAppPolicies,
+ })
+ s.CertTemplate13 = gt.NewActiveDirectoryCertTemplate("certtemplate1-3", sid, CertTemplateData{
+ RequiresManagerApproval: false,
+ AuthenticationEnabled: false,
+ EnrolleeSuppliesSubject: false,
+ SubjectAltRequireUPN: false,
+ SubjectAltRequireSPN: false,
+ NoSecurityExtension: false,
+ SchemaVersion: 2,
+ AuthorizedSignatures: 0,
+ EffectiveEKUs: anyPurposeEkus,
+ ApplicationPolicies: emptyAppPolicies,
+ })
+
+ gt.NewRelationship(s.AuthStore1, s.Domain1, ad.NTAuthStoreFor)
+ gt.NewRelationship(s.RootCA1, s.Domain1, ad.RootCAFor)
+ gt.NewRelationship(s.EnterpriseCA1, s.AuthStore1, ad.TrustedForNTAuth)
+ gt.NewRelationship(s.EnterpriseCA1, s.RootCA1, ad.EnterpriseCAFor)
+ gt.NewRelationship(s.EnterpriseCA2, s.RootCA1, ad.EnterpriseCAFor)
+ gt.NewRelationship(s.CertTemplate11, s.EnterpriseCA1, ad.PublishedTo)
+ gt.NewRelationship(s.CertTemplate12, s.EnterpriseCA1, ad.PublishedTo)
+ gt.NewRelationship(s.CertTemplate13, s.EnterpriseCA2, ad.PublishedTo)
+}
+
type ADCSGoldenCertHarness struct {
NTAuthStore1 *graph.Node
RootCA1 *graph.Node
@@ -8437,8 +8491,9 @@ type HarnessDetails struct {
ShortcutHarnessEveryone2 ShortcutHarnessEveryone2
ADCSESC1Harness ADCSESC1Harness
ADCSESC1HarnessAuthUsers ADCSESC1HarnessAuthUsers
- EnrollOnBehalfOfHarnessOne EnrollOnBehalfOfHarnessOne
- EnrollOnBehalfOfHarnessTwo EnrollOnBehalfOfHarnessTwo
+ EnrollOnBehalfOfHarness1 EnrollOnBehalfOfHarness1
+ EnrollOnBehalfOfHarness2 EnrollOnBehalfOfHarness2
+ EnrollOnBehalfOfHarness3 EnrollOnBehalfOfHarness3
ADCSGoldenCertHarness ADCSGoldenCertHarness
IssuedSignedByHarness IssuedSignedByHarness
EnterpriseCAForHarness EnterpriseCAForHarness
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.json b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.json
index cc51045b70..9232e6f121 100644
--- a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.json
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.json
@@ -54,10 +54,10 @@
},
"nodes": [
{
- "id": "n1",
+ "id": "n0",
"position": {
- "x": 729.9551990267428,
- "y": -4
+ "x": 675.9551990267428,
+ "y": 50
},
"caption": "Domain1",
"labels": [],
@@ -67,10 +67,10 @@
}
},
{
- "id": "n2",
+ "id": "n1",
"position": {
- "x": 129,
- "y": 273.97628342478527
+ "x": 75,
+ "y": 327.97628342478527
},
"caption": "CertTemplate1-1",
"labels": [],
@@ -83,10 +83,10 @@
}
},
{
- "id": "n3",
+ "id": "n2",
"position": {
- "x": 487.6313891898351,
- "y": -4
+ "x": 433.6313891898351,
+ "y": 50
},
"caption": "NTAuthStore1",
"labels": [],
@@ -96,10 +96,10 @@
}
},
{
- "id": "n4",
+ "id": "n3",
"position": {
- "x": 487.6313891898351,
- "y": 273.97628342478527
+ "x": 433.6313891898351,
+ "y": 327.97628342478527
},
"caption": "EnterpriseCA1",
"labels": [],
@@ -109,10 +109,10 @@
}
},
{
- "id": "n5",
+ "id": "n4",
"position": {
- "x": 230.03558347937087,
- "y": 551.9525668495705
+ "x": 176.03558347937087,
+ "y": 605.9525668495705
},
"caption": "CertTemplate1-2",
"labels": [],
@@ -125,10 +125,10 @@
}
},
{
- "id": "n6",
+ "id": "n5",
"position": {
- "x": 508.01086036954564,
- "y": 551.2045130499298
+ "x": 454.01086036954564,
+ "y": 605.2045130499298
},
"caption": "CertTemplate1-3",
"labels": [],
@@ -141,10 +141,10 @@
}
},
{
- "id": "n7",
+ "id": "n6",
"position": {
- "x": 729.9551990267428,
- "y": 273.97628342478527
+ "x": 675.9551990267428,
+ "y": 327.97628342478527
},
"caption": "RootCA1",
"labels": [],
@@ -157,64 +157,64 @@
"relationships": [
{
"id": "n0",
- "fromId": "n3",
- "toId": "n1",
+ "fromId": "n2",
+ "toId": "n0",
"type": "NTAuthStoreFor",
"properties": {},
"style": {}
},
{
"id": "n1",
- "fromId": "n4",
- "toId": "n3",
+ "fromId": "n3",
+ "toId": "n2",
"type": "TrustedForNTAuth",
"properties": {},
"style": {}
},
{
"id": "n2",
- "fromId": "n2",
- "toId": "n4",
+ "fromId": "n1",
+ "toId": "n3",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
"id": "n3",
- "fromId": "n5",
- "toId": "n4",
+ "fromId": "n4",
+ "toId": "n3",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
"id": "n4",
- "fromId": "n6",
- "toId": "n4",
+ "fromId": "n5",
+ "toId": "n3",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
"id": "n5",
- "fromId": "n7",
- "toId": "n1",
+ "fromId": "n6",
+ "toId": "n0",
"type": "RootCAFor",
"properties": {},
"style": {}
},
{
"id": "n6",
- "fromId": "n4",
- "toId": "n7",
+ "fromId": "n3",
+ "toId": "n6",
"type": "EnterpriseCAFor",
"properties": {},
"style": {}
},
{
"id": "n7",
- "fromId": "n2",
- "toId": "n5",
+ "fromId": "n1",
+ "toId": "n4",
"type": "EnrollOnBehalfOf",
"properties": {},
"style": {
@@ -223,13 +223,23 @@
},
{
"id": "n8",
- "fromId": "n6",
- "toId": "n5",
+ "fromId": "n5",
+ "toId": "n4",
"type": "EnrollOnBehalfOf",
"properties": {},
"style": {
"arrow-color": "#68ccca"
}
+ },
+ {
+ "id": "n9",
+ "type": "EnrollOnBehalfOf",
+ "style": {
+ "arrow-color": "#68ccca"
+ },
+ "properties": {},
+ "fromId": "n4",
+ "toId": "n4"
}
]
}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.svg b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.svg
index a86d80d2f0..6fcfa6838d 100644
--- a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.svg
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-1.svg
@@ -1,18 +1 @@
-
-
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.json b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.json
index ee3e2a4b43..607f78cbef 100644
--- a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.json
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.json
@@ -1,10 +1,63 @@
{
+ "style": {
+ "font-family": "sans-serif",
+ "background-color": "#ffffff",
+ "background-image": "",
+ "background-size": "100%",
+ "node-color": "#ffffff",
+ "border-width": 4,
+ "border-color": "#000000",
+ "radius": 50,
+ "node-padding": 5,
+ "node-margin": 2,
+ "outside-position": "auto",
+ "node-icon-image": "",
+ "node-background-image": "",
+ "icon-position": "inside",
+ "icon-size": 64,
+ "caption-position": "inside",
+ "caption-max-width": 200,
+ "caption-color": "#000000",
+ "caption-font-size": 50,
+ "caption-font-weight": "normal",
+ "label-position": "inside",
+ "label-display": "pill",
+ "label-color": "#000000",
+ "label-background-color": "#ffffff",
+ "label-border-color": "#000000",
+ "label-border-width": 4,
+ "label-font-size": 40,
+ "label-padding": 5,
+ "label-margin": 4,
+ "directionality": "directed",
+ "detail-position": "inline",
+ "detail-orientation": "parallel",
+ "arrow-width": 5,
+ "arrow-color": "#000000",
+ "margin-start": 5,
+ "margin-end": 5,
+ "margin-peer": 20,
+ "attachment-start": "normal",
+ "attachment-end": "normal",
+ "relationship-icon-image": "",
+ "type-color": "#000000",
+ "type-background-color": "#ffffff",
+ "type-border-color": "#000000",
+ "type-border-width": 0,
+ "type-font-size": 16,
+ "type-padding": 5,
+ "property-position": "outside",
+ "property-alignment": "colon",
+ "property-color": "#000000",
+ "property-font-size": 16,
+ "property-font-weight": "normal"
+ },
"nodes": [
{
"id": "n0",
"position": {
- "x": -569.1685177598522,
- "y": -1021.0927494329366
+ "x": 657.3454879680903,
+ "y": 50
},
"caption": "Domain2",
"labels": [],
@@ -14,10 +67,10 @@
}
},
{
- "id": "n2",
+ "id": "n1",
"position": {
- "x": -811.4923275967599,
- "y": -1021.0927494329366
+ "x": 415.0216781311826,
+ "y": 50
},
"caption": "NTAuthStore2",
"labels": [],
@@ -27,10 +80,10 @@
}
},
{
- "id": "n5",
+ "id": "n2",
"position": {
- "x": -811.4923275967599,
- "y": -743.1164660081513
+ "x": 415.0216781311826,
+ "y": 327.97628342478527
},
"caption": "EnterpriseCA2",
"labels": [],
@@ -40,10 +93,10 @@
}
},
{
- "id": "n13",
+ "id": "n3",
"position": {
- "x": -569.1685177598522,
- "y": -743.1164660081513
+ "x": 657.3454879680903,
+ "y": 327.97628342478527
},
"caption": "RootCA2",
"labels": [],
@@ -53,40 +106,42 @@
}
},
{
- "id": "n14",
+ "id": "n4",
"position": {
- "x": -1151.5140057279425,
- "y": -743.1164660081513
+ "x": 75,
+ "y": 327.97628342478527
},
"caption": "CertTemplate2-1",
"labels": [],
"properties": {
- "effectiveekus": "[\"1.3.6.1.4.1.311.20.2.1\"]"
+ "effectiveekus": "[\"1.3.6.1.4.1.311.20.2.1\"]",
+ "schemaversion": "2"
},
"style": {
"node-color": "#fda1ff"
}
},
{
- "id": "n15",
+ "id": "n5",
"position": {
- "x": -1151.5140057279425,
- "y": -546.8048586088046
+ "x": 75,
+ "y": 524.287890824132
},
"caption": "CertTemplate2-2",
"labels": [],
"properties": {
- "effectiveekus": "[\"1.3.6.1.4.1.311.20.2.1\", \"2.5.29.37.0\"]"
+ "effectiveekus": "[\"1.3.6.1.4.1.311.20.2.1\", \"2.5.29.37.0\"]",
+ "schemaversion": "2"
},
"style": {
"node-color": "#fda1ff"
}
},
{
- "id": "n16",
+ "id": "n6",
"position": {
- "x": -981.5031666623508,
- "y": -448.6490549091318
+ "x": 245.01083906559165,
+ "y": 622.4436945238048
},
"caption": "CertTemplate2-3",
"labels": [],
@@ -101,10 +156,10 @@
}
},
{
- "id": "n17",
+ "id": "n7",
"position": {
- "x": -695.4923275967599,
- "y": -448.6490549091318
+ "x": 531.0216781311826,
+ "y": 622.4436945238048
},
"caption": "CertTemplate2-4",
"labels": [],
@@ -117,29 +172,12 @@
"style": {
"node-color": "#fda1ff"
}
- },
- {
- "id": "n18",
- "position": {
- "x": -517.02491649774,
- "y": -448.6490549091315
- },
- "caption": "CertTemplate2-5",
- "labels": [],
- "properties": {
- "effectiveekus": "[]",
- "schemaversion": "1",
- "subjectaltrequiresupn": "true"
- },
- "style": {
- "node-color": "#fda1ff"
- }
}
],
"relationships": [
{
"id": "n0",
- "fromId": "n2",
+ "fromId": "n1",
"toId": "n0",
"type": "NTAuthStoreFor",
"properties": {},
@@ -147,141 +185,69 @@
},
{
"id": "n1",
- "fromId": "n5",
- "toId": "n2",
+ "fromId": "n2",
+ "toId": "n1",
"type": "TrustedForNTAuth",
"properties": {},
"style": {}
},
{
- "id": "n9",
- "fromId": "n13",
+ "id": "n2",
+ "fromId": "n3",
"toId": "n0",
"type": "RootCAFor",
"properties": {},
"style": {}
},
{
- "id": "n10",
- "fromId": "n5",
- "toId": "n13",
+ "id": "n3",
+ "fromId": "n2",
+ "toId": "n3",
"type": "EnterpriseCAFor",
"properties": {},
"style": {}
},
{
- "id": "n11",
- "fromId": "n14",
- "toId": "n5",
- "type": "PublishedTo",
- "properties": {},
- "style": {}
- },
- {
- "id": "n12",
- "fromId": "n15",
- "toId": "n5",
+ "id": "n4",
+ "fromId": "n4",
+ "toId": "n2",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
- "id": "n13",
- "fromId": "n16",
- "toId": "n5",
+ "id": "n5",
+ "fromId": "n5",
+ "toId": "n2",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
- "id": "n14",
- "fromId": "n17",
- "toId": "n5",
+ "id": "n6",
+ "fromId": "n6",
+ "toId": "n2",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
- "id": "n15",
- "type": "EnrollOnBehalfOf",
- "style": {
- "arrow-color": "#a4dd00"
- },
- "properties": {},
- "toId": "n16",
- "fromId": "n14"
- },
- {
- "id": "n16",
- "fromId": "n18",
- "toId": "n5",
+ "id": "n7",
+ "fromId": "n7",
+ "toId": "n2",
"type": "PublishedTo",
"properties": {},
"style": {}
},
{
- "id": "n17",
- "fromId": "n18",
- "toId": "n18",
+ "id": "n8",
+ "fromId": "n4",
+ "toId": "n6",
"type": "EnrollOnBehalfOf",
"properties": {},
"style": {
- "type-color": "#4d4d4d",
"arrow-color": "#a4dd00"
}
}
- ],
- "style": {
- "font-family": "sans-serif",
- "background-color": "#ffffff",
- "background-image": "",
- "background-size": "100%",
- "node-color": "#ffffff",
- "border-width": 4,
- "border-color": "#000000",
- "radius": 50,
- "node-padding": 5,
- "node-margin": 2,
- "outside-position": "auto",
- "node-icon-image": "",
- "node-background-image": "",
- "icon-position": "inside",
- "icon-size": 64,
- "caption-position": "inside",
- "caption-max-width": 200,
- "caption-color": "#000000",
- "caption-font-size": 50,
- "caption-font-weight": "normal",
- "label-position": "inside",
- "label-display": "pill",
- "label-color": "#000000",
- "label-background-color": "#ffffff",
- "label-border-color": "#000000",
- "label-border-width": 4,
- "label-font-size": 40,
- "label-padding": 5,
- "label-margin": 4,
- "directionality": "directed",
- "detail-position": "inline",
- "detail-orientation": "parallel",
- "arrow-width": 5,
- "arrow-color": "#000000",
- "margin-start": 5,
- "margin-end": 5,
- "margin-peer": 20,
- "attachment-start": "normal",
- "attachment-end": "normal",
- "relationship-icon-image": "",
- "type-color": "#000000",
- "type-background-color": "#ffffff",
- "type-border-color": "#000000",
- "type-border-width": 0,
- "type-font-size": 16,
- "type-padding": 5,
- "property-position": "outside",
- "property-alignment": "colon",
- "property-color": "#000000",
- "property-font-size": 16,
- "property-font-weight": "normal"
- }
+ ]
}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.svg b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.svg
index dd203c5b22..d8d8ec0fcb 100644
--- a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.svg
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-2.svg
@@ -1,18 +1 @@
-
-
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.json b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.json
new file mode 100644
index 0000000000..e0537e9ec6
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.json
@@ -0,0 +1,256 @@
+{
+ "style": {
+ "font-family": "sans-serif",
+ "background-color": "#ffffff",
+ "background-image": "",
+ "background-size": "100%",
+ "node-color": "#ffffff",
+ "border-width": 4,
+ "border-color": "#000000",
+ "radius": 50,
+ "node-padding": 5,
+ "node-margin": 2,
+ "outside-position": "auto",
+ "node-icon-image": "",
+ "node-background-image": "",
+ "icon-position": "inside",
+ "icon-size": 64,
+ "caption-position": "inside",
+ "caption-max-width": 200,
+ "caption-color": "#000000",
+ "caption-font-size": 50,
+ "caption-font-weight": "normal",
+ "label-position": "inside",
+ "label-display": "pill",
+ "label-color": "#000000",
+ "label-background-color": "#ffffff",
+ "label-border-color": "#000000",
+ "label-border-width": 4,
+ "label-font-size": 40,
+ "label-padding": 5,
+ "label-margin": 4,
+ "directionality": "directed",
+ "detail-position": "inline",
+ "detail-orientation": "parallel",
+ "arrow-width": 5,
+ "arrow-color": "#000000",
+ "margin-start": 5,
+ "margin-end": 5,
+ "margin-peer": 20,
+ "attachment-start": "normal",
+ "attachment-end": "normal",
+ "relationship-icon-image": "",
+ "type-color": "#000000",
+ "type-background-color": "#ffffff",
+ "type-border-color": "#000000",
+ "type-border-width": 0,
+ "type-font-size": 16,
+ "type-padding": 5,
+ "property-position": "outside",
+ "property-alignment": "colon",
+ "property-color": "#000000",
+ "property-font-size": 16,
+ "property-font-weight": "normal"
+ },
+ "nodes": [
+ {
+ "id": "n0",
+ "position": {
+ "x": 675.9551990267428,
+ "y": 50
+ },
+ "caption": "Domain1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n1",
+ "position": {
+ "x": -44.95912785436991,
+ "y": 327.97628342478527
+ },
+ "caption": "CertTemplate1-1",
+ "labels": [],
+ "properties": {
+ "schemaversion": "2",
+ "effectiveekus": "[\"2.5.29.37.0\"]"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 433.6313891898351,
+ "y": 50
+ },
+ "caption": "NTAuthStore1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#7b64ff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 433.6313891898351,
+ "y": 327.97628342478527
+ },
+ "caption": "EnterpriseCA1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#b0bc00"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 194.3361306677326,
+ "y": 557.3609078601627
+ },
+ "caption": "CertTemplate1-2",
+ "labels": [],
+ "properties": {
+ "schemaversion": "1",
+ "effectiveekus": "[\"2.5.29.37.0\"]"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n5",
+ "position": {
+ "x": 433.6313891898351,
+ "y": 796.6561663822652
+ },
+ "caption": "CertTemplate1-3",
+ "labels": [],
+ "properties": {
+ "schemaversion": "2",
+ "effectiveekus": "[\"2.5.29.37.0\"]"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 675.9551990267428,
+ "y": 327.97628342478527
+ },
+ "caption": "RootCA1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#e27300"
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 433.6313891898351,
+ "y": 500.5114025285298
+ },
+ "caption": "EnterpriseCA2",
+ "style": {
+ "node-color": "#b0bc00"
+ },
+ "labels": [],
+ "properties": {}
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n2",
+ "toId": "n0",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n1",
+ "fromId": "n3",
+ "toId": "n2",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n2",
+ "fromId": "n1",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n3",
+ "fromId": "n4",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n5",
+ "fromId": "n6",
+ "toId": "n0",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n6",
+ "fromId": "n3",
+ "toId": "n6",
+ "type": "EnterpriseCAFor",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n7",
+ "fromId": "n1",
+ "toId": "n4",
+ "type": "EnrollOnBehalfOf",
+ "properties": {},
+ "style": {
+ "arrow-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n12",
+ "type": "PublishedTo",
+ "fromId": "n5",
+ "toId": "n7",
+ "style": {},
+ "properties": {}
+ },
+ {
+ "id": "n13",
+ "type": "EnterpriseCAFor",
+ "fromId": "n7",
+ "toId": "n6",
+ "style": {},
+ "properties": {}
+ },
+ {
+ "id": "n14",
+ "type": "EnrollOnBehalfOf",
+ "style": {
+ "arrow-color": "#68ccca"
+ },
+ "properties": {},
+ "fromId": "n4",
+ "toId": "n4"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.svg b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.svg
new file mode 100644
index 0000000000..d7192c6074
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/enrollonbehalfof-3.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/go/analysis/ad/adcs.go b/packages/go/analysis/ad/adcs.go
index 537b0b0770..ac1f9a76cb 100644
--- a/packages/go/analysis/ad/adcs.go
+++ b/packages/go/analysis/ad/adcs.go
@@ -47,30 +47,33 @@ func PostADCS(ctx context.Context, db graph.Database, groupExpansions impact.Pat
return &analysis.AtomicPostProcessingStats{}, fmt.Errorf("failed fetching domain nodes: %w", err)
} else if step1Stats, err := postADCSPreProcessStep1(ctx, db, enterpriseCertAuthorities, rootCertAuthorities, aiaCertAuthorities, certTemplates); err != nil {
return &analysis.AtomicPostProcessingStats{}, fmt.Errorf("failed adcs pre-processing step 1: %w", err)
- } else if step2Stats, err := postADCSPreProcessStep2(ctx, db, certTemplates); err != nil {
- return &analysis.AtomicPostProcessingStats{}, fmt.Errorf("failed adcs pre-processing step 2: %w", err)
} else {
- operation := analysis.NewPostRelationshipOperation(ctx, db, "ADCS Post Processing")
-
- operation.Stats.Merge(step1Stats)
- operation.Stats.Merge(step2Stats)
-
var cache = NewADCSCache()
cache.BuildCache(ctx, db, enterpriseCertAuthorities, certTemplates, domains)
- for _, domain := range domains {
- innerDomain := domain
+ if step2Stats, err := postADCSPreProcessStep2(ctx, db, domains, enterpriseCertAuthorities, certTemplates, cache); err != nil {
+ return &analysis.AtomicPostProcessingStats{}, fmt.Errorf("failed adcs pre-processing step 2: %w", err)
+ } else {
+
+ operation := analysis.NewPostRelationshipOperation(ctx, db, "ADCS Post Processing")
+
+ operation.Stats.Merge(step1Stats)
+ operation.Stats.Merge(step2Stats)
- for _, enterpriseCA := range enterpriseCertAuthorities {
- innerEnterpriseCA := enterpriseCA
+ for _, domain := range domains {
+ innerDomain := domain
- if cache.DoesCAChainProperlyToDomain(innerEnterpriseCA, innerDomain) {
- processEnterpriseCAWithValidCertChainToDomain(innerEnterpriseCA, innerDomain, groupExpansions, cache, operation)
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ innerEnterpriseCA := enterpriseCA
+
+ if cache.DoesCAChainProperlyToDomain(innerEnterpriseCA, innerDomain) {
+ processEnterpriseCAWithValidCertChainToDomain(innerEnterpriseCA, innerDomain, groupExpansions, cache, operation)
+ }
}
}
- }
+ return &operation.Stats, operation.Done()
- return &operation.Stats, operation.Done()
+ }
}
}
@@ -97,10 +100,10 @@ func postADCSPreProcessStep1(ctx context.Context, db graph.Database, enterpriseC
}
// postADCSPreProcessStep2 Processes the edges that are dependent on those processed in postADCSPreProcessStep1
-func postADCSPreProcessStep2(ctx context.Context, db graph.Database, certTemplates []*graph.Node) (*analysis.AtomicPostProcessingStats, error) {
+func postADCSPreProcessStep2(ctx context.Context, db graph.Database, domains, enterpriseCertAuthorities, certTemplates []*graph.Node, cache ADCSCache) (*analysis.AtomicPostProcessingStats, error) {
operation := analysis.NewPostRelationshipOperation(ctx, db, "ADCS Post Processing Step 2")
- if err := PostEnrollOnBehalfOf(certTemplates, operation); err != nil {
+ if err := PostEnrollOnBehalfOf(domains, enterpriseCertAuthorities, certTemplates, cache, operation); err != nil {
operation.Done()
return &analysis.AtomicPostProcessingStats{}, fmt.Errorf("failed post processing for %s: %w", ad.EnrollOnBehalfOf.String(), err)
} else {
diff --git a/packages/go/analysis/ad/esc3.go b/packages/go/analysis/ad/esc3.go
index 2406e0081b..28abe1fcec 100644
--- a/packages/go/analysis/ad/esc3.go
+++ b/packages/go/analysis/ad/esc3.go
@@ -142,60 +142,71 @@ func PostADCSESC3(ctx context.Context, tx graph.Transaction, outC chan<- analysi
return nil
}
-func PostEnrollOnBehalfOf(certTemplates []*graph.Node, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) error {
+func PostEnrollOnBehalfOf(domains, enterpriseCertAuthorities, certTemplates []*graph.Node, cache ADCSCache, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) error {
versionOneTemplates := make([]*graph.Node, 0)
versionTwoTemplates := make([]*graph.Node, 0)
-
for _, node := range certTemplates {
if version, err := node.Properties.Get(ad.SchemaVersion.String()).Float64(); errors.Is(err, graph.ErrPropertyNotFound) {
log.Warnf("Did not get schema version for cert template %d: %v", node.ID, err)
} else if err != nil {
log.Errorf("Error getting schema version for cert template %d: %v", node.ID, err)
+ } else if version == 1 {
+ versionOneTemplates = append(versionOneTemplates, node)
+ } else if version >= 2 {
+ versionTwoTemplates = append(versionTwoTemplates, node)
} else {
- if version == 1 {
- versionOneTemplates = append(versionOneTemplates, node)
- } else if version >= 2 {
- versionTwoTemplates = append(versionTwoTemplates, node)
- } else {
- log.Warnf("Got cert template %d with an invalid version %d", node.ID, version)
- }
+ log.Warnf("Got cert template %d with an invalid version %d", node.ID, version)
}
}
- operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
- if results, err := EnrollOnBehalfOfVersionTwo(tx, versionTwoTemplates, certTemplates); err != nil {
- return err
- } else {
- for _, result := range results {
- if !channels.Submit(ctx, outC, result) {
- return nil
- }
- }
+ for _, domain := range domains {
+ innerDomain := domain
- return nil
- }
- })
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ innerEnterpriseCA := enterpriseCA
- operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
- if results, err := EnrollOnBehalfOfVersionOne(tx, versionOneTemplates, certTemplates); err != nil {
- return err
- } else {
- for _, result := range results {
- if !channels.Submit(ctx, outC, result) {
+ if cache.DoesCAChainProperlyToDomain(innerEnterpriseCA, innerDomain) {
+ if publishedCertTemplates := cache.GetPublishedTemplateCache(enterpriseCA.ID); len(publishedCertTemplates) == 0 {
return nil
+ } else {
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if results, err := EnrollOnBehalfOfVersionTwo(tx, versionTwoTemplates, publishedCertTemplates, innerDomain); err != nil {
+ return err
+ } else {
+ for _, result := range results {
+ if !channels.Submit(ctx, outC, result) {
+ return nil
+ }
+ }
+
+ return nil
+ }
+ })
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if results, err := EnrollOnBehalfOfVersionOne(tx, versionOneTemplates, publishedCertTemplates, innerDomain); err != nil {
+ return err
+ } else {
+ for _, result := range results {
+ if !channels.Submit(ctx, outC, result) {
+ return nil
+ }
+ }
+
+ return nil
+ }
+ })
}
}
-
- return nil
}
- })
+ }
return nil
}
-func EnrollOnBehalfOfVersionTwo(tx graph.Transaction, versionTwoCertTemplates, allCertTemplates []*graph.Node) ([]analysis.CreatePostRelationshipJob, error) {
+func EnrollOnBehalfOfVersionTwo(tx graph.Transaction, versionTwoCertTemplates, publishedTemplates []*graph.Node, domainNode *graph.Node) ([]analysis.CreatePostRelationshipJob, error) {
results := make([]analysis.CreatePostRelationshipJob, 0)
- for _, certTemplateOne := range allCertTemplates {
+ for _, certTemplateOne := range publishedTemplates {
if hasBadEku, err := certTemplateHasEku(certTemplateOne, EkuAnyPurpose); errors.Is(err, graph.ErrPropertyNotFound) {
log.Warnf("Did not get EffectiveEKUs for cert template %d: %v", certTemplateOne.ID, err)
} else if err != nil {
@@ -208,12 +219,6 @@ func EnrollOnBehalfOfVersionTwo(tx graph.Transaction, versionTwoCertTemplates, a
log.Errorf("Error getting EffectiveEKUs for cert template %d: %v", certTemplateOne.ID, err)
} else if !hasEku {
continue
- } else if domainNode, err := getDomainForCertTemplate(tx, certTemplateOne); err != nil {
- log.Errorf("Error getting domain node for cert template %d: %v", certTemplateOne.ID, err)
- } else if isLinked, err := DoesCertTemplateLinkToDomain(tx, certTemplateOne, domainNode); err != nil {
- log.Errorf("Error fetching paths from cert template %d to domain: %v", certTemplateOne.ID, err)
- } else if !isLinked {
- continue
} else {
for _, certTemplateTwo := range versionTwoCertTemplates {
if certTemplateOne.ID == certTemplateTwo.ID {
@@ -260,10 +265,10 @@ func certTemplateHasEku(certTemplate *graph.Node, targetEkus ...string) (bool, e
}
}
-func EnrollOnBehalfOfVersionOne(tx graph.Transaction, versionOneCertTemplates []*graph.Node, allCertTemplates []*graph.Node) ([]analysis.CreatePostRelationshipJob, error) {
+func EnrollOnBehalfOfVersionOne(tx graph.Transaction, versionOneCertTemplates []*graph.Node, publishedTemplates []*graph.Node, domainNode *graph.Node) ([]analysis.CreatePostRelationshipJob, error) {
results := make([]analysis.CreatePostRelationshipJob, 0)
- for _, certTemplateOne := range allCertTemplates {
+ for _, certTemplateOne := range publishedTemplates {
//prefilter as much as we can first
if hasEku, err := certTemplateHasEkuOrAll(certTemplateOne, EkuCertRequestAgent, EkuAnyPurpose); errors.Is(err, graph.ErrPropertyNotFound) {
log.Warnf("Error checking ekus for certtemplate %d: %v", certTemplateOne.ID, err)
@@ -271,12 +276,6 @@ func EnrollOnBehalfOfVersionOne(tx graph.Transaction, versionOneCertTemplates []
log.Errorf("Error checking ekus for certtemplate %d: %v", certTemplateOne.ID, err)
} else if !hasEku {
continue
- } else if domainNode, err := getDomainForCertTemplate(tx, certTemplateOne); err != nil {
- log.Errorf("Error getting domain node for certtemplate %d: %v", certTemplateOne.ID, err)
- } else if hasPath, err := DoesCertTemplateLinkToDomain(tx, certTemplateOne, domainNode); err != nil {
- log.Errorf("Error fetching paths from certtemplate %d to domain: %v", certTemplateOne.ID, err)
- } else if !hasPath {
- continue
} else {
for _, certTemplateTwo := range versionOneCertTemplates {
if hasPath, err := DoesCertTemplateLinkToDomain(tx, certTemplateTwo, domainNode); err != nil {
@@ -359,19 +358,9 @@ func certTemplateHasEkuOrAll(certTemplate *graph.Node, targetEkus ...string) (bo
}
}
-func getDomainForCertTemplate(tx graph.Transaction, certTemplate *graph.Node) (*graph.Node, error) {
- if domainSid, err := certTemplate.Properties.Get(ad.DomainSID.String()).String(); err != nil {
- return &graph.Node{}, err
- } else if domainNode, err := analysis.FetchNodeByObjectID(tx, domainSid); err != nil {
- return &graph.Node{}, err
- } else {
- return domainNode, nil
- }
-}
-
func GetADCSESC3EdgeComposition(ctx context.Context, db graph.Database, edge *graph.Relationship) (graph.PathSet, error) {
/*
- MATCH p1 = (x)-[:MemberOf*0..]->()-[:GenericAll|Enroll|AllExtendedRights]->(ct1:CertTemplate)-[:PublishedTo]->(eca1:EnterpriseCA)
+ MATCH p1 = (x)-[:MemberOf*0..]->()-[:GenericAll|Enroll|AllExtendedRights]->(ct1:CertTemplate)-[:PublishedTo]->(eca1:EnterpriseCA)-[:TrustedForNTAuth]->(:NTAuthStore)-[:NTAuthStoreFor]->(d)
WHERE x.objectid = "S-1-5-21-83094068-830424655-2031507174-500"
AND d.objectid = "S-1-5-21-83094068-830424655-2031507174"
AND ct1.requiresmanagerapproval = false
@@ -483,7 +472,7 @@ func GetADCSESC3EdgeComposition(ctx context.Context, db graph.Database, edge *gr
for _, n := range startNodes.Slice() {
if err := traversalInst.BreadthFirst(ctx, traversal.Plan{
Root: n,
- Driver: ADCSESC3Path1Pattern(enterpriseCANodes).Do(func(terminal *graph.PathSegment) error {
+ Driver: ADCSESC3Path1Pattern(edge.EndID, enterpriseCANodes).Do(func(terminal *graph.PathSegment) error {
certTemplateNode := terminal.Search(func(nextSegment *graph.PathSegment) bool {
return nextSegment.Node.Kinds.ContainsOneOf(ad.CertTemplate)
})
@@ -673,7 +662,7 @@ func GetADCSESC3EdgeComposition(ctx context.Context, db graph.Database, edge *gr
return paths, nil
}
-func ADCSESC3Path1Pattern(enterpriseCAs cardinality.Duplex[uint64]) traversal.PatternContinuation {
+func ADCSESC3Path1Pattern(domainId graph.ID, enterpriseCAs cardinality.Duplex[uint64]) traversal.PatternContinuation {
return traversal.NewPattern().OutboundWithDepth(0, 0, query.And(
query.Kind(query.Relationship(), ad.MemberOf),
query.Kind(query.End(), ad.Group),
@@ -696,6 +685,14 @@ func ADCSESC3Path1Pattern(enterpriseCAs cardinality.Duplex[uint64]) traversal.Pa
query.KindIn(query.Relationship(), ad.PublishedTo),
query.InIDs(query.End(), graph.DuplexToGraphIDs(enterpriseCAs)...),
query.Kind(query.End(), ad.EnterpriseCA),
+ )).
+ Outbound(query.And(
+ query.KindIn(query.Relationship(), ad.TrustedForNTAuth),
+ query.Kind(query.End(), ad.NTAuthStore),
+ )).
+ Outbound(query.And(
+ query.KindIn(query.Relationship(), ad.NTAuthStoreFor),
+ query.Equals(query.EndID(), domainId),
))
}