diff --git a/cmd/api/src/analysis/ad/adcs_integration_test.go b/cmd/api/src/analysis/ad/adcs_integration_test.go
index 16dcb6fc4..fb828d9ea 100644
--- a/cmd/api/src/analysis/ad/adcs_integration_test.go
+++ b/cmd/api/src/analysis/ad/adcs_integration_test.go
@@ -21,8 +21,8 @@ package ad_test
import (
"context"
-
"github.com/specterops/bloodhound/analysis"
+ "github.com/specterops/bloodhound/analysis/impact"
"github.com/specterops/bloodhound/graphschema"
ad2 "github.com/specterops/bloodhound/analysis/ad"
@@ -709,7 +709,6 @@ func TestADCSESC6a(t *testing.T) {
})
}
}
-
}
operation.Done()
@@ -957,3 +956,264 @@ func TestADCSESC6a(t *testing.T) {
})
})
}
+
+func FetchADCSPrereqs(db graph.Database) (impact.PathAggregator, []*graph.Node, []*graph.Node, []*graph.Node, ad2.ADCSCache, error) {
+ if expansions, err := ad2.ExpandAllRDPLocalGroups(context.Background(), db); err != nil {
+ return nil, nil, nil, nil, ad2.ADCSCache{}, err
+ } else if eca, err := ad2.FetchNodesByKind(context.Background(), db, ad.EnterpriseCA); err != nil {
+ return nil, nil, nil, nil, ad2.ADCSCache{}, err
+ } else if certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate); err != nil {
+ return nil, nil, nil, nil, ad2.ADCSCache{}, err
+ } else if domains, err := ad2.FetchNodesByKind(context.Background(), db, ad.Domain); err != nil {
+ return nil, nil, nil, nil, ad2.ADCSCache{}, err
+ } else {
+ cache := ad2.NewADCSCache()
+ cache.BuildCache(context.Background(), db, eca, certTemplates)
+ return expansions, eca, certTemplates, domains, cache, nil
+ }
+}
+
+func TestADCSESC10a(t *testing.T) {
+ testContext := integration.NewGraphTestContext(t, graphschema.DefaultGraphSchema())
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.ESC10aPrincipalHarness.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC10a")
+
+ groupExpansions, enterpriseCertAuthorities, _, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ for _, domain := range domains {
+ innerDomain := domain
+
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
+ innerEnterpriseCA := enterpriseCA
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := ad2.PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ } else {
+ return nil
+ }
+
+ return nil
+ })
+ }
+ }
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.ADCSESC10a)
+ })); err != nil {
+ t.Fatalf("error fetching esc10a edges in integration test; %v", err)
+ } else {
+ require.Equal(t, 6, len(results))
+
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.Group1))
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.Group2))
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.Group3))
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.Group4))
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.Group5))
+ require.True(t, results.Contains(harness.ESC10aPrincipalHarness.User2))
+
+ }
+ return nil
+ })
+ })
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.ESC10aHarness1.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC10a")
+
+ groupExpansions, enterpriseCertAuthorities, _, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ for _, domain := range domains {
+ innerDomain := domain
+
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
+ innerEnterpriseCA := enterpriseCA
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := ad2.PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ } else {
+ return nil
+ }
+
+ return nil
+ })
+ }
+ }
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.ADCSESC10a)
+ })); err != nil {
+ t.Fatalf("error fetching esc10a edges in integration test; %v", err)
+ } else {
+ require.Equal(t, 3, len(results))
+
+ require.True(t, results.Contains(harness.ESC10aHarness1.Group1))
+ require.True(t, results.Contains(harness.ESC10aHarness1.Group2))
+ require.True(t, results.Contains(harness.ESC10aHarness1.Group3))
+
+ }
+ return nil
+ })
+ })
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.ESC10aHarness2.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC10a")
+
+ groupExpansions, enterpriseCertAuthorities, _, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ for _, domain := range domains {
+ innerDomain := domain
+
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
+ innerEnterpriseCA := enterpriseCA
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := ad2.PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ } else {
+ return nil
+ }
+
+ return nil
+ })
+ }
+ }
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.ADCSESC10a)
+ })); err != nil {
+ t.Fatalf("error fetching esc10a edges in integration test; %v", err)
+ } else {
+ require.Equal(t, 4, len(results))
+
+ require.True(t, results.Contains(harness.ESC10aHarness2.Group6))
+ require.True(t, results.Contains(harness.ESC10aHarness2.Group5))
+ require.True(t, results.Contains(harness.ESC10aHarness2.Computer5))
+ require.True(t, results.Contains(harness.ESC10aHarness2.User5))
+
+ }
+ return nil
+ })
+ })
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.ESC10aHarnessECA.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC10a")
+
+ groupExpansions, enterpriseCertAuthorities, _, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ for _, domain := range domains {
+ innerDomain := domain
+
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
+ innerEnterpriseCA := enterpriseCA
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := ad2.PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ } else {
+ return nil
+ }
+
+ return nil
+ })
+ }
+ }
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.ADCSESC10a)
+ })); err != nil {
+ t.Fatalf("error fetching esc10a edges in integration test; %v", err)
+ } else {
+ require.Equal(t, 1, len(results))
+
+ require.True(t, results.Contains(harness.ESC10aHarnessECA.Group1))
+
+ }
+ return nil
+ })
+ })
+
+ testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
+ harness.ESC10aHarnessVictim.Setup(testContext)
+ return nil
+ }, func(harness integration.HarnessDetails, db graph.Database) {
+ operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - ESC10a")
+
+ groupExpansions, enterpriseCertAuthorities, _, domains, cache, err := FetchADCSPrereqs(db)
+ require.Nil(t, err)
+
+ for _, domain := range domains {
+ innerDomain := domain
+
+ for _, enterpriseCA := range enterpriseCertAuthorities {
+ if cache.DoesCAChainProperlyToDomain(enterpriseCA, innerDomain) {
+ innerEnterpriseCA := enterpriseCA
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := ad2.PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ t.Logf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ } else {
+ return nil
+ }
+
+ return nil
+ })
+ }
+ }
+ }
+ err = operation.Done()
+ require.Nil(t, err)
+
+ db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
+ if results, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.Kind(query.Relationship(), ad.ADCSESC10a)
+ })); err != nil {
+ t.Fatalf("error fetching esc10a edges in integration test; %v", err)
+ } else {
+ require.Equal(t, 2, len(results))
+
+ require.True(t, results.Contains(harness.ESC10aHarnessVictim.Group1))
+ require.True(t, results.Contains(harness.ESC10aHarnessVictim.Group2))
+
+ }
+ return nil
+ })
+ })
+}
diff --git a/cmd/api/src/test/integration/graph.go b/cmd/api/src/test/integration/graph.go
index a56fbd8e6..ea39683a9 100644
--- a/cmd/api/src/test/integration/graph.go
+++ b/cmd/api/src/test/integration/graph.go
@@ -431,6 +431,7 @@ func (s *GraphTestContext) NewActiveDirectoryCertTemplate(name, domainSID string
ad.SubjectAltRequireSPN: data.SubjectAltRequireSPN,
ad.SubjectAltRequireDNS: data.SubjectAltRequireDNS,
ad.SubjectAltRequireDomainDNS: data.SubjectAltRequireDomainDNS,
+ ad.SubjectAltRequireEmail: data.SubjectAltRequireEmail,
}), ad.Entity, ad.CertTemplate)
}
@@ -442,6 +443,7 @@ type CertTemplateData struct {
SubjectAltRequireSPN bool
SubjectAltRequireDNS bool
SubjectAltRequireDomainDNS bool
+ SubjectAltRequireEmail bool
NoSecurityExtension bool
SchemaVersion float64
AuthorizedSignatures float64
diff --git a/cmd/api/src/test/integration/harnesses.go b/cmd/api/src/test/integration/harnesses.go
index b9d582047..4bbfba80a 100644
--- a/cmd/api/src/test/integration/harnesses.go
+++ b/cmd/api/src/test/integration/harnesses.go
@@ -2156,6 +2156,650 @@ func (s *ESC6aHarnessTemplate2) Setup(c *GraphTestContext) {
setupHarnessFromArrowsJson(c, "esc6a-template2")
}
+type ESC10aPrincipalHarness struct {
+ Domain *graph.Node
+ NTAuthStore *graph.Node
+ RootCA *graph.Node
+ EnterpriseCA *graph.Node
+ DC *graph.Node
+ CertTemplate *graph.Node
+ User1 *graph.Node
+ Group1 *graph.Node
+ Group2 *graph.Node
+ Group6 *graph.Node
+ Group3 *graph.Node
+ Group4 *graph.Node
+ Group5 *graph.Node
+ User2 *graph.Node
+ Group0 *graph.Node
+}
+
+func (s *ESC10aPrincipalHarness) Setup(graphTestContext *GraphTestContext) {
+ domainSid := RandomDomainSID()
+ s.Domain = graphTestContext.NewActiveDirectoryDomain("Domain", domainSid, false, true)
+ s.NTAuthStore = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore", domainSid)
+ s.RootCA = graphTestContext.NewActiveDirectoryRootCA("RootCA", domainSid)
+ s.EnterpriseCA = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA", domainSid)
+ s.DC = graphTestContext.NewActiveDirectoryComputer("DC", domainSid)
+ s.CertTemplate = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.User1 = graphTestContext.NewActiveDirectoryUser("User1", domainSid)
+ s.Group1 = graphTestContext.NewActiveDirectoryGroup("Group1", domainSid)
+ s.Group2 = graphTestContext.NewActiveDirectoryGroup("Group2", domainSid)
+ s.Group6 = graphTestContext.NewActiveDirectoryGroup("Group6", domainSid)
+ s.Group3 = graphTestContext.NewActiveDirectoryGroup("Group3", domainSid)
+ s.Group4 = graphTestContext.NewActiveDirectoryGroup("Group4", domainSid)
+ s.Group5 = graphTestContext.NewActiveDirectoryGroup("Group5", domainSid)
+ s.User2 = graphTestContext.NewActiveDirectoryUser("User2", domainSid)
+ s.Group0 = graphTestContext.NewActiveDirectoryGroup("Group0", domainSid)
+ graphTestContext.NewRelationship(s.RootCA, s.Domain, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.RootCA, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.NTAuthStore, s.Domain, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.NTAuthStore, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.DC, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.DC, s.Domain, ad.DCFor)
+ graphTestContext.NewRelationship(s.CertTemplate, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.Group1, s.User1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group2, s.User1, ad.GenericWrite)
+ graphTestContext.NewRelationship(s.Group6, s.User1, ad.AllExtendedRights)
+ graphTestContext.NewRelationship(s.Group3, s.User1, ad.WriteDACL)
+ graphTestContext.NewRelationship(s.Group4, s.User1, ad.WriteOwner)
+ graphTestContext.NewRelationship(s.Group5, s.User1, ad.WriteOwner)
+ graphTestContext.NewRelationship(s.User2, s.User2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.User1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Group0, s.CertTemplate, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group0, s.EnterpriseCA, ad.Enroll)
+}
+
+type ESC10aHarness1 struct {
+ CertTemplate1 *graph.Node
+ CertTemplate2 *graph.Node
+ CertTemplate3 *graph.Node
+ CertTemplate4 *graph.Node
+ CertTemplate5 *graph.Node
+ CertTemplate6 *graph.Node
+ CertTemplate7 *graph.Node
+ DC *graph.Node
+ Domain *graph.Node
+ EnterpriseCA *graph.Node
+ Group0 *graph.Node
+ Group1 *graph.Node
+ Group2 *graph.Node
+ Group3 *graph.Node
+ Group4 *graph.Node
+ Group5 *graph.Node
+ Group6 *graph.Node
+ Group7 *graph.Node
+ NTAuthStore *graph.Node
+ RootCA *graph.Node
+ User1 *graph.Node
+ User2 *graph.Node
+ User3 *graph.Node
+ User4 *graph.Node
+ User5 *graph.Node
+ User6 *graph.Node
+ User7 *graph.Node
+}
+
+func (s *ESC10aHarness1) Setup(graphTestContext *GraphTestContext) {
+ domainSid := RandomDomainSID()
+ s.CertTemplate1 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate1", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 2,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate2 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate2", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: true,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate3 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate3", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: true,
+ SubjectAltRequireUPN: false,
+ })
+ s.CertTemplate4 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate4", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: true,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate5 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate5", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: false,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate6 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate6", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 1,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 2,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate7 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate7", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: false,
+ })
+ s.DC = graphTestContext.NewActiveDirectoryComputer("DC", domainSid)
+ s.Domain = graphTestContext.NewActiveDirectoryDomain("Domain", domainSid, false, true)
+ s.EnterpriseCA = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA", domainSid)
+ s.Group0 = graphTestContext.NewActiveDirectoryGroup("Group0", domainSid)
+ s.Group1 = graphTestContext.NewActiveDirectoryGroup("Group1", domainSid)
+ s.Group2 = graphTestContext.NewActiveDirectoryGroup("Group2", domainSid)
+ s.Group3 = graphTestContext.NewActiveDirectoryGroup("Group3", domainSid)
+ s.Group4 = graphTestContext.NewActiveDirectoryGroup("Group4", domainSid)
+ s.Group5 = graphTestContext.NewActiveDirectoryGroup("Group5", domainSid)
+ s.Group6 = graphTestContext.NewActiveDirectoryGroup("Group6", domainSid)
+ s.Group7 = graphTestContext.NewActiveDirectoryGroup("Group7", domainSid)
+ s.NTAuthStore = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore", domainSid)
+ s.RootCA = graphTestContext.NewActiveDirectoryRootCA("RootCA", domainSid)
+ s.User1 = graphTestContext.NewActiveDirectoryUser("User1", domainSid)
+ s.User2 = graphTestContext.NewActiveDirectoryUser("User2", domainSid)
+ s.User3 = graphTestContext.NewActiveDirectoryUser("User3", domainSid)
+ s.User4 = graphTestContext.NewActiveDirectoryUser("User4", domainSid)
+ s.User5 = graphTestContext.NewActiveDirectoryUser("User5", domainSid)
+ s.User6 = graphTestContext.NewActiveDirectoryUser("User6", domainSid)
+ s.User7 = graphTestContext.NewActiveDirectoryUser("User7", domainSid)
+ graphTestContext.NewRelationship(s.CertTemplate2, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.RootCA, s.Domain, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.RootCA, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.NTAuthStore, s.Domain, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.NTAuthStore, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.DC, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.DC, s.Domain, ad.DCFor)
+ graphTestContext.NewRelationship(s.User3, s.CertTemplate3, ad.Enroll)
+ graphTestContext.NewRelationship(s.CertTemplate3, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.CertTemplate4, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.User4, s.CertTemplate4, ad.Enroll)
+ graphTestContext.NewRelationship(s.User2, s.CertTemplate2, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group0, s.EnterpriseCA, ad.Enroll)
+ graphTestContext.NewRelationship(s.User2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User3, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User4, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.CertTemplate5, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.User5, s.CertTemplate5, ad.Enroll)
+ graphTestContext.NewRelationship(s.User5, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User6, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User6, s.CertTemplate6, ad.Enroll)
+ graphTestContext.NewRelationship(s.CertTemplate6, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.CertTemplate1, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.User1, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.User1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.CertTemplate7, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.User7, s.CertTemplate7, ad.Enroll)
+ graphTestContext.NewRelationship(s.User7, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Group7, s.User7, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group6, s.User6, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group5, s.User5, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group4, s.User4, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group3, s.User3, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group2, s.User2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group1, s.User1, ad.GenericAll)
+}
+
+type ESC10aHarness2 struct {
+ CertTemplate1 *graph.Node
+ CertTemplate2 *graph.Node
+ CertTemplate3 *graph.Node
+ Computer1 *graph.Node
+ Computer2 *graph.Node
+ Computer3 *graph.Node
+ Computer4 *graph.Node
+ Computer5 *graph.Node
+ Computer6 *graph.Node
+ DC *graph.Node
+ Domain *graph.Node
+ EnterpriseCA *graph.Node
+ Group0 *graph.Node
+ Group1 *graph.Node
+ Group2 *graph.Node
+ Group3 *graph.Node
+ Group4 *graph.Node
+ Group5 *graph.Node
+ Group6 *graph.Node
+ NTAuthStore *graph.Node
+ RootCA *graph.Node
+ User1 *graph.Node
+ User2 *graph.Node
+ User3 *graph.Node
+ User4 *graph.Node
+ User5 *graph.Node
+ User6 *graph.Node
+}
+
+func (s *ESC10aHarness2) Setup(graphTestContext *GraphTestContext) {
+ domainSid := RandomDomainSID()
+ s.CertTemplate1 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate1", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 2,
+ SubjectAltRequireDNS: false,
+ SubjectAltRequireDomainDNS: false,
+ SubjectAltRequireEmail: true,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate2 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate2", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 2,
+ SubjectAltRequireDNS: true,
+ SubjectAltRequireDomainDNS: false,
+ SubjectAltRequireEmail: true,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate3 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate3", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 2,
+ SubjectAltRequireDNS: false,
+ SubjectAltRequireDomainDNS: true,
+ SubjectAltRequireEmail: true,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.Computer1 = graphTestContext.NewActiveDirectoryComputer("Computer1", domainSid)
+ s.Computer2 = graphTestContext.NewActiveDirectoryComputer("Computer2", domainSid)
+ s.Computer3 = graphTestContext.NewActiveDirectoryComputer("Computer3", domainSid)
+ s.Computer4 = graphTestContext.NewActiveDirectoryComputer("Computer4", domainSid)
+ s.Computer5 = graphTestContext.NewActiveDirectoryComputer("Computer5", domainSid)
+ s.Computer6 = graphTestContext.NewActiveDirectoryComputer("Computer6", domainSid)
+ s.DC = graphTestContext.NewActiveDirectoryComputer("DC", domainSid)
+ s.Domain = graphTestContext.NewActiveDirectoryDomain("Domain", domainSid, false, true)
+ s.EnterpriseCA = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA", domainSid)
+ s.Group0 = graphTestContext.NewActiveDirectoryGroup("Group0", domainSid)
+ s.Group1 = graphTestContext.NewActiveDirectoryGroup("Group1", domainSid)
+ s.Group2 = graphTestContext.NewActiveDirectoryGroup("Group2", domainSid)
+ s.Group3 = graphTestContext.NewActiveDirectoryGroup("Group3", domainSid)
+ s.Group4 = graphTestContext.NewActiveDirectoryGroup("Group4", domainSid)
+ s.Group5 = graphTestContext.NewActiveDirectoryGroup("Group5", domainSid)
+ s.Group6 = graphTestContext.NewActiveDirectoryGroup("Group6", domainSid)
+ s.NTAuthStore = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore", domainSid)
+ s.RootCA = graphTestContext.NewActiveDirectoryRootCA("RootCA", domainSid)
+ s.User1 = graphTestContext.NewActiveDirectoryUser("User1", domainSid)
+ s.User2 = graphTestContext.NewActiveDirectoryUser("User2", domainSid)
+ s.User3 = graphTestContext.NewActiveDirectoryUser("User3", domainSid)
+ s.User4 = graphTestContext.NewActiveDirectoryUser("User4", domainSid)
+ s.User5 = graphTestContext.NewActiveDirectoryUser("User5", domainSid)
+ s.User6 = graphTestContext.NewActiveDirectoryUser("User6", domainSid)
+ graphTestContext.NewRelationship(s.RootCA, s.Domain, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.RootCA, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.NTAuthStore, s.Domain, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.NTAuthStore, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.DC, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.DC, s.Domain, ad.DCFor)
+ graphTestContext.NewRelationship(s.Group0, s.EnterpriseCA, ad.Enroll)
+ graphTestContext.NewRelationship(s.CertTemplate1, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.Group1, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.CertTemplate2, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.CertTemplate3, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.Computer1, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.Computer1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User1, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.User1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Group2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Computer2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User2, s.CertTemplate2, ad.Enroll)
+ graphTestContext.NewRelationship(s.Computer2, s.CertTemplate2, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group2, s.CertTemplate2, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group3, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Computer3, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User3, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.Group3, s.CertTemplate3, ad.Enroll)
+ graphTestContext.NewRelationship(s.Computer3, s.CertTemplate3, ad.Enroll)
+ graphTestContext.NewRelationship(s.User3, s.CertTemplate3, ad.Enroll)
+ graphTestContext.NewRelationship(s.User6, s.User3, ad.GenericAll)
+ graphTestContext.NewRelationship(s.User5, s.Computer3, ad.GenericAll)
+ graphTestContext.NewRelationship(s.User4, s.Group3, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Computer6, s.User2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Computer5, s.Computer2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Computer4, s.Group2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group6, s.User1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group5, s.Computer1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group4, s.Group1, ad.GenericAll)
+}
+
+type ESC10aHarnessECA struct {
+ CertTemplate1 *graph.Node
+ CertTemplate2 *graph.Node
+ CertTemplate3 *graph.Node
+ CertTemplate4 *graph.Node
+ CertTemplate5 *graph.Node
+ DC1 *graph.Node
+ DC2 *graph.Node
+ DC3 *graph.Node
+ DC4 *graph.Node
+ DC5 *graph.Node
+ Domain1 *graph.Node
+ Domain2 *graph.Node
+ Domain3 *graph.Node
+ Domain4 *graph.Node
+ Domain5 *graph.Node
+ EnterpriseCA1 *graph.Node
+ EnterpriseCA2 *graph.Node
+ EnterpriseCA3 *graph.Node
+ EnterpriseCA4 *graph.Node
+ EnterpriseCA5 *graph.Node
+ Group1 *graph.Node
+ Group2 *graph.Node
+ Group3 *graph.Node
+ Group4 *graph.Node
+ Group5 *graph.Node
+ NTAuthStore1 *graph.Node
+ NTAuthStore2 *graph.Node
+ NTAuthStore3 *graph.Node
+ NTAuthStore4 *graph.Node
+ NTAuthStore5 *graph.Node
+ RootCA1 *graph.Node
+ RootCA2 *graph.Node
+ RootCA3 *graph.Node
+ RootCA4 *graph.Node
+ RootCA5 *graph.Node
+ User1 *graph.Node
+ User2 *graph.Node
+ User3 *graph.Node
+ User4 *graph.Node
+ User5 *graph.Node
+}
+
+func (s *ESC10aHarnessECA) Setup(graphTestContext *GraphTestContext) {
+ domainSid1 := RandomDomainSID()
+ domainSid2 := RandomDomainSID()
+ domainSid3 := RandomDomainSID()
+ domainSid4 := RandomDomainSID()
+ domainSid5 := RandomDomainSID()
+ s.CertTemplate1 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate1", domainSid1, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate2 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate2", domainSid2, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate3 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate3", domainSid3, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate4 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate4", domainSid4, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.CertTemplate5 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate5", domainSid5, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.DC1 = graphTestContext.NewActiveDirectoryComputer("DC1", domainSid1)
+ s.DC2 = graphTestContext.NewActiveDirectoryComputer("DC2", domainSid2)
+ s.DC3 = graphTestContext.NewActiveDirectoryComputer("DC3", domainSid3)
+ s.DC4 = graphTestContext.NewActiveDirectoryComputer("DC4", domainSid4)
+ s.DC5 = graphTestContext.NewActiveDirectoryComputer("DC5", domainSid5)
+ s.Domain1 = graphTestContext.NewActiveDirectoryDomain("Domain1", domainSid1, false, true)
+ s.Domain2 = graphTestContext.NewActiveDirectoryDomain("Domain2", domainSid2, false, true)
+ s.Domain3 = graphTestContext.NewActiveDirectoryDomain("Domain3", domainSid3, false, true)
+ s.Domain4 = graphTestContext.NewActiveDirectoryDomain("Domain4", domainSid4, false, true)
+ s.Domain5 = graphTestContext.NewActiveDirectoryDomain("Domain5", domainSid5, false, true)
+ s.EnterpriseCA1 = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA1", domainSid1)
+ s.EnterpriseCA2 = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA2", domainSid2)
+ s.EnterpriseCA3 = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA3", domainSid3)
+ s.EnterpriseCA4 = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA4", domainSid4)
+ s.EnterpriseCA5 = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA5", domainSid5)
+ s.Group1 = graphTestContext.NewActiveDirectoryGroup("Group1", domainSid1)
+ s.Group2 = graphTestContext.NewActiveDirectoryGroup("Group2", domainSid2)
+ s.Group3 = graphTestContext.NewActiveDirectoryGroup("Group3", domainSid3)
+ s.Group4 = graphTestContext.NewActiveDirectoryGroup("Group4", domainSid4)
+ s.Group5 = graphTestContext.NewActiveDirectoryGroup("Group5", domainSid5)
+ s.NTAuthStore1 = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore1", domainSid1)
+ s.NTAuthStore2 = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore2", domainSid2)
+ s.NTAuthStore3 = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore3", domainSid3)
+ s.NTAuthStore4 = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore4", domainSid4)
+ s.NTAuthStore5 = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore5", domainSid5)
+ s.RootCA1 = graphTestContext.NewActiveDirectoryRootCA("RootCA1", domainSid1)
+ s.RootCA2 = graphTestContext.NewActiveDirectoryRootCA("RootCA2", domainSid2)
+ s.RootCA3 = graphTestContext.NewActiveDirectoryRootCA("RootCA3", domainSid3)
+ s.RootCA4 = graphTestContext.NewActiveDirectoryRootCA("RootCA4", domainSid4)
+ s.RootCA5 = graphTestContext.NewActiveDirectoryRootCA("RootCA5", domainSid5)
+ s.User1 = graphTestContext.NewActiveDirectoryUser("User1", domainSid1)
+ s.User2 = graphTestContext.NewActiveDirectoryUser("User2", domainSid2)
+ s.User3 = graphTestContext.NewActiveDirectoryUser("User3", domainSid3)
+ s.User4 = graphTestContext.NewActiveDirectoryUser("User4", domainSid4)
+ s.User5 = graphTestContext.NewActiveDirectoryUser("User5", domainSid5)
+ graphTestContext.NewRelationship(s.RootCA1, s.Domain1, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.NTAuthStore1, s.Domain1, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.DC1, s.Domain1, ad.DCFor)
+ graphTestContext.NewRelationship(s.CertTemplate1, s.EnterpriseCA1, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.EnterpriseCA1, s.RootCA1, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.EnterpriseCA1, s.NTAuthStore1, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.User1, s.EnterpriseCA1, ad.Enroll)
+ graphTestContext.NewRelationship(s.EnterpriseCA1, s.DC1, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.User1, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.RootCA2, s.Domain2, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.NTAuthStore2, s.Domain2, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.DC2, s.Domain2, ad.DCFor)
+ graphTestContext.NewRelationship(s.CertTemplate2, s.EnterpriseCA2, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.EnterpriseCA2, s.RootCA2, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.EnterpriseCA2, s.NTAuthStore2, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.User2, s.EnterpriseCA2, ad.Enroll)
+ graphTestContext.NewRelationship(s.User2, s.CertTemplate2, ad.Enroll)
+ graphTestContext.NewRelationship(s.RootCA3, s.Domain3, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.NTAuthStore3, s.Domain3, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.DC3, s.Domain3, ad.DCFor)
+ graphTestContext.NewRelationship(s.CertTemplate3, s.EnterpriseCA3, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.EnterpriseCA3, s.RootCA3, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.User3, s.EnterpriseCA3, ad.Enroll)
+ graphTestContext.NewRelationship(s.EnterpriseCA3, s.DC3, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.User3, s.CertTemplate3, ad.Enroll)
+ graphTestContext.NewRelationship(s.RootCA4, s.Domain4, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.NTAuthStore4, s.Domain4, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.DC4, s.Domain4, ad.DCFor)
+ graphTestContext.NewRelationship(s.CertTemplate4, s.EnterpriseCA4, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.EnterpriseCA4, s.NTAuthStore4, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.User4, s.EnterpriseCA4, ad.Enroll)
+ graphTestContext.NewRelationship(s.EnterpriseCA4, s.DC4, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.User4, s.CertTemplate4, ad.Enroll)
+ graphTestContext.NewRelationship(s.RootCA5, s.Domain5, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.NTAuthStore5, s.Domain5, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.DC5, s.Domain5, ad.DCFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA5, s.RootCA5, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.EnterpriseCA5, s.NTAuthStore5, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.User5, s.EnterpriseCA5, ad.Enroll)
+ graphTestContext.NewRelationship(s.EnterpriseCA5, s.DC5, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.User5, s.CertTemplate5, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group1, s.User1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group2, s.User2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group5, s.User5, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group4, s.User4, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group3, s.User3, ad.GenericAll)
+}
+
+type ESC10aHarnessVictim struct {
+ CertTemplate1 *graph.Node
+ DC *graph.Node
+ Domain *graph.Node
+ EnterpriseCA *graph.Node
+ Group0 *graph.Node
+ Group1 *graph.Node
+ Group2 *graph.Node
+ Group3 *graph.Node
+ Group4 *graph.Node
+ NTAuthStore *graph.Node
+ RootCA *graph.Node
+ User1 *graph.Node
+ User2 *graph.Node
+ User3 *graph.Node
+ User4 *graph.Node
+}
+
+func (s *ESC10aHarnessVictim) Setup(graphTestContext *GraphTestContext) {
+ domainSid := RandomDomainSID()
+ s.CertTemplate1 = graphTestContext.NewActiveDirectoryCertTemplate("CertTemplate1", domainSid, CertTemplateData{
+ ApplicationPolicies: []string{},
+ AuthenticationEnabled: true,
+ AuthorizedSignatures: 0,
+ EKUS: []string{},
+ EnrolleeSuppliesSubject: false,
+ NoSecurityExtension: false,
+ RequiresManagerApproval: false,
+ SchemaVersion: 1,
+ SubjectAltRequireEmail: false,
+ SubjectAltRequireSPN: false,
+ SubjectAltRequireUPN: true,
+ })
+ s.DC = graphTestContext.NewActiveDirectoryComputer("DC", domainSid)
+ s.Domain = graphTestContext.NewActiveDirectoryDomain("Domain", domainSid, false, true)
+ s.EnterpriseCA = graphTestContext.NewActiveDirectoryEnterpriseCA("EnterpriseCA", domainSid)
+ s.Group0 = graphTestContext.NewActiveDirectoryGroup("Group0", domainSid)
+ s.Group1 = graphTestContext.NewActiveDirectoryGroup("Group1", domainSid)
+ s.Group2 = graphTestContext.NewActiveDirectoryGroup("Group2", domainSid)
+ s.Group3 = graphTestContext.NewActiveDirectoryGroup("Group3", domainSid)
+ s.Group4 = graphTestContext.NewActiveDirectoryGroup("Group4", domainSid)
+ s.NTAuthStore = graphTestContext.NewActiveDirectoryNTAuthStore("NTAuthStore", domainSid)
+ s.RootCA = graphTestContext.NewActiveDirectoryRootCA("RootCA", domainSid)
+ s.User1 = graphTestContext.NewActiveDirectoryUser("User1", domainSid)
+ s.User2 = graphTestContext.NewActiveDirectoryUser("User2", domainSid)
+ s.User3 = graphTestContext.NewActiveDirectoryUser("User3", domainSid)
+ s.User4 = graphTestContext.NewActiveDirectoryUser("User4", domainSid)
+ graphTestContext.NewRelationship(s.RootCA, s.Domain, ad.RootCAFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.RootCA, ad.IssuedSignedBy)
+ graphTestContext.NewRelationship(s.NTAuthStore, s.Domain, ad.NTAuthStoreFor)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.NTAuthStore, ad.TrustedForNTAuth)
+ graphTestContext.NewRelationship(s.EnterpriseCA, s.DC, ad.CanAbuseUPNCertMapping)
+ graphTestContext.NewRelationship(s.DC, s.Domain, ad.DCFor)
+ graphTestContext.NewRelationship(s.Group0, s.EnterpriseCA, ad.Enroll)
+ graphTestContext.NewRelationship(s.CertTemplate1, s.EnterpriseCA, ad.PublishedTo)
+ graphTestContext.NewRelationship(s.User1, s.CertTemplate1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.User1, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User2, s.CertTemplate1, ad.AllExtendedRights)
+ graphTestContext.NewRelationship(s.User2, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User3, s.CertTemplate1, ad.GenericWrite)
+ graphTestContext.NewRelationship(s.User3, s.Group0, ad.MemberOf)
+ graphTestContext.NewRelationship(s.User4, s.CertTemplate1, ad.Enroll)
+ graphTestContext.NewRelationship(s.Group1, s.User1, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group2, s.User2, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group3, s.User3, ad.GenericAll)
+ graphTestContext.NewRelationship(s.Group4, s.User4, ad.GenericAll)
+}
+
type ShortcutHarness struct {
Group1 *graph.Node
Group2 *graph.Node
@@ -2255,4 +2899,9 @@ type HarnessDetails struct {
ESC6aHarnessTemplate1 ESC6aHarnessTemplate1
ESC6aHarnessTemplate2 ESC6aHarnessTemplate2
ESC9AHarness ESC9AHarness
+ ESC10aPrincipalHarness ESC10aPrincipalHarness
+ ESC10aHarness1 ESC10aHarness1
+ ESC10aHarness2 ESC10aHarness2
+ ESC10aHarnessECA ESC10aHarnessECA
+ ESC10aHarnessVictim ESC10aHarnessVictim
}
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharness1.json b/cmd/api/src/test/integration/harnesses/esc10aharness1.json
new file mode 100644
index 000000000..60c77c896
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharness1.json
@@ -0,0 +1,807 @@
+{
+ "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": 1166.2401531581963,
+ "y": 1669.717944661677
+ },
+ "caption": "Domain",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n1",
+ "position": {
+ "x": 1763.8169426399654,
+ "y": 1545.8922712261758
+ },
+ "caption": "NTAuthStore",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 1763.8169426399654,
+ "y": 1669.7179446616767
+ },
+ "caption": "RootCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 2343.4991450315265,
+ "y": 1270.461309154399
+ },
+ "caption": "EnterpriseCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 313.8361415302825
+ },
+ "caption": "CertTemplate2",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True",
+ "NoSecurityExtension": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n5",
+ "position": {
+ "x": 1763.8169426399654,
+ "y": 1420.0681651505495
+ },
+ "caption": "DC",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 698.5658018046843,
+ "y": 973.4264953559922
+ },
+ "caption": "User4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "border-color": "#000000",
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 445.75421229542417
+ },
+ "caption": "CertTemplate3",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "False",
+ "SubjectAltRequireSPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n8",
+ "position": {
+ "x": 542.6743513535134,
+ "y": 973.4264953559922
+ },
+ "caption": "User3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "border-color": "#000000",
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n9",
+ "position": {
+ "x": 386.7829009023419,
+ "y": 973.4264953559922
+ },
+ "caption": "User2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n10",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 577.6722830605653
+ },
+ "caption": "CertTemplate4",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "True",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "caption-position": "inside",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n11",
+ "position": {
+ "x": 1166.2401531581963,
+ "y": 1270.461309154399
+ },
+ "caption": "Group0",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n12",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 709.5903538257065
+ },
+ "caption": "CertTemplate5",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "False",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n13",
+ "position": {
+ "x": 854.4572522558553,
+ "y": 973.4264953559922
+ },
+ "caption": "User5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n14",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 841.5084245908482
+ },
+ "caption": "CertTemplate6",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "2",
+ "SubjectAltRequireUPN": "True",
+ "AuthorizedSignatures": "1"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n15",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 181.91807076514067
+ },
+ "caption": "CertTemplate1",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "2",
+ "SubjectAltRequireUPN": "True",
+ "AuthorizedSignatures": "0"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n16",
+ "position": {
+ "x": 1010.348702707026,
+ "y": 973.4264953559904
+ },
+ "caption": "User6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n17",
+ "position": {
+ "x": 230.89145045117098,
+ "y": 973.4264953559922
+ },
+ "caption": "User1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n18",
+ "position": {
+ "x": 1979.2258547112808,
+ "y": 973.4264953559904
+ },
+ "caption": "CertTemplate7",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "False"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n19",
+ "position": {
+ "x": 1166.2401531581963,
+ "y": 973.4264953559904
+ },
+ "caption": "User7",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n23",
+ "position": {
+ "x": 1166.2401531581959,
+ "y": 49.99999999999923
+ },
+ "caption": "Group7",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n24",
+ "position": {
+ "x": 1010.348702707025,
+ "y": 49.99999999999923
+ },
+ "caption": "Group6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n25",
+ "position": {
+ "x": 854.4572522558542,
+ "y": 49.99999999999923
+ },
+ "caption": "Group5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n26",
+ "position": {
+ "x": 698.5658018046829,
+ "y": 49.99999999999923
+ },
+ "caption": "Group4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n27",
+ "position": {
+ "x": 542.6743513535134,
+ "y": 1420.0681651505477
+ },
+ "caption": "Group3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n28",
+ "position": {
+ "x": 386.7829009023419,
+ "y": 1545.892271226174
+ },
+ "caption": "Group2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n29",
+ "position": {
+ "x": 230.89145045117098,
+ "y": 1669.7179446616767
+ },
+ "caption": "Group1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#000000"
+ }
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n4",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n1",
+ "fromId": "n2",
+ "toId": "n0",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n2",
+ "fromId": "n3",
+ "toId": "n2",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n3",
+ "fromId": "n1",
+ "toId": "n0",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n4",
+ "fromId": "n3",
+ "toId": "n1",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n5",
+ "fromId": "n3",
+ "toId": "n5",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n6",
+ "fromId": "n5",
+ "toId": "n0",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n7",
+ "fromId": "n8",
+ "toId": "n7",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n8",
+ "fromId": "n7",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n9",
+ "fromId": "n10",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n10",
+ "fromId": "n6",
+ "toId": "n10",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n11",
+ "fromId": "n9",
+ "toId": "n4",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n12",
+ "fromId": "n11",
+ "toId": "n3",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n13",
+ "fromId": "n9",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n14",
+ "fromId": "n8",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n15",
+ "fromId": "n6",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n16",
+ "fromId": "n12",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n17",
+ "fromId": "n13",
+ "toId": "n12",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n18",
+ "fromId": "n13",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n19",
+ "fromId": "n16",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n20",
+ "fromId": "n16",
+ "toId": "n14",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n21",
+ "fromId": "n14",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n22",
+ "fromId": "n15",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n23",
+ "fromId": "n17",
+ "toId": "n15",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n24",
+ "fromId": "n17",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n25",
+ "fromId": "n18",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n26",
+ "fromId": "n19",
+ "toId": "n18",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n27",
+ "fromId": "n19",
+ "toId": "n11",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n32",
+ "fromId": "n23",
+ "toId": "n19",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n33",
+ "fromId": "n24",
+ "toId": "n16",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n34",
+ "fromId": "n25",
+ "toId": "n13",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n35",
+ "fromId": "n26",
+ "toId": "n6",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n36",
+ "fromId": "n27",
+ "toId": "n8",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n37",
+ "fromId": "n28",
+ "toId": "n9",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n38",
+ "fromId": "n29",
+ "toId": "n17",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n39",
+ "fromId": "n27",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n40",
+ "fromId": "n28",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n41",
+ "fromId": "n29",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharness1.svg b/cmd/api/src/test/integration/harnesses/esc10aharness1.svg
new file mode 100644
index 000000000..b2f3b82ef
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharness1.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharness2.json b/cmd/api/src/test/integration/harnesses/esc10aharness2.json
new file mode 100644
index 000000000..062fb24db
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharness2.json
@@ -0,0 +1,797 @@
+{
+ "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": "n1",
+ "position": {
+ "x": 129,
+ "y": 1327.41620651926
+ },
+ "caption": "Domain",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 1664.8135268077572,
+ "y": 1118.6584948427476
+ },
+ "caption": "NTAuthStore",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 1734.0761748485493,
+ "y": 1226.5718804439516
+ },
+ "caption": "RootCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 2089.3408145645117,
+ "y": 922.3660942769798
+ },
+ "caption": "EnterpriseCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n5",
+ "position": {
+ "x": 1855.4850232261435,
+ "y": 1327.41620651926
+ },
+ "caption": "DC",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 1324.7762805968055,
+ "y": 922.3660942769798
+ },
+ "caption": "Group0",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 1855.4850232261435,
+ "y": 649.2340527998417
+ },
+ "caption": "CertTemplate1",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "2",
+ "AuthorizedSignatures": "0",
+ "SubjectAltRequireEmail": "True",
+ "SubjectAltRequireUPN": "True",
+ "SubjectAltRequireDNS": "False",
+ "SubjectAltRequireDomainDNS": "False"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n8",
+ "position": {
+ "x": 973.639047876434,
+ "y": 727.2392440430749
+ },
+ "caption": "Group1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n9",
+ "position": {
+ "x": 1855.4850232261435,
+ "y": 366.352007001999
+ },
+ "caption": "CertTemplate2",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "2",
+ "AuthorizedSignatures": "0",
+ "SubjectAltRequireEmail": "True",
+ "SubjectAltRequireUPN": "True",
+ "SubjectAltRequireDNS": "True",
+ "SubjectAltRequireDomainDNS": "False"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n10",
+ "position": {
+ "x": 1855.4850232261435,
+ "y": 74.00519124323318
+ },
+ "caption": "CertTemplate3",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "2",
+ "AuthorizedSignatures": "0",
+ "SubjectAltRequireEmail": "True",
+ "SubjectAltRequireUPN": "True",
+ "SubjectAltRequireDNS": "False",
+ "SubjectAltRequireDomainDNS": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n11",
+ "position": {
+ "x": 883.4172386161655,
+ "y": 649.2340527998417
+ },
+ "caption": "Computer1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b"
+ }
+ },
+ {
+ "id": "n12",
+ "position": {
+ "x": 973.639047876434,
+ "y": 571.2288615566085
+ },
+ "caption": "User1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n13",
+ "position": {
+ "x": 973.639047876434,
+ "y": 444.3571982452322
+ },
+ "caption": "Group2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n14",
+ "position": {
+ "x": 883.4172386161655,
+ "y": 366.352007001999
+ },
+ "caption": "Computer2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b"
+ }
+ },
+ {
+ "id": "n15",
+ "position": {
+ "x": 973.639047876434,
+ "y": 288.3468157587656
+ },
+ "caption": "User2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n16",
+ "position": {
+ "x": 973.639047876434,
+ "y": 152.01038248646637
+ },
+ "caption": "Group3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n17",
+ "position": {
+ "x": 883.4172386161655,
+ "y": 74.00519124323318
+ },
+ "caption": "Computer3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b"
+ }
+ },
+ {
+ "id": "n18",
+ "position": {
+ "x": 973.639047876434,
+ "y": -4
+ },
+ "caption": "User3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n19",
+ "position": {
+ "x": 695.1130959232657,
+ "y": 727.2392440430749
+ },
+ "caption": "Group4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n20",
+ "position": {
+ "x": 619.2141547864899,
+ "y": 649.2340527998417
+ },
+ "caption": "Group5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n21",
+ "position": {
+ "x": 541.4379963358472,
+ "y": 571.2288615566085
+ },
+ "caption": "Group6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcc400"
+ }
+ },
+ {
+ "id": "n22",
+ "position": {
+ "x": 498.952275954523,
+ "y": 444.3571982452322
+ },
+ "caption": "Computer4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n23",
+ "position": {
+ "x": 419.9345466228922,
+ "y": 366.352007001999
+ },
+ "caption": "Computer5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b"
+ }
+ },
+ {
+ "id": "n24",
+ "position": {
+ "x": 343.33133116590204,
+ "y": 288.3468157587656
+ },
+ "caption": "Computer6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n25",
+ "position": {
+ "x": 282.15189381679534,
+ "y": 152.01038248646637
+ },
+ "caption": "User4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n26",
+ "position": {
+ "x": 206.68013167102274,
+ "y": 74.00519124323318
+ },
+ "caption": "User5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n27",
+ "position": {
+ "x": 129,
+ "y": -4
+ },
+ "caption": "User6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#73d8ff"
+ }
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n3",
+ "toId": "n1",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n1",
+ "fromId": "n4",
+ "toId": "n3",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n2",
+ "fromId": "n2",
+ "toId": "n1",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n3",
+ "fromId": "n4",
+ "toId": "n2",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n4",
+ "fromId": "n4",
+ "toId": "n5",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n5",
+ "fromId": "n5",
+ "toId": "n1",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n6",
+ "fromId": "n6",
+ "toId": "n4",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n7",
+ "fromId": "n7",
+ "toId": "n4",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n8",
+ "fromId": "n8",
+ "toId": "n7",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n9",
+ "fromId": "n8",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n10",
+ "fromId": "n9",
+ "toId": "n4",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n11",
+ "fromId": "n10",
+ "toId": "n4",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n12",
+ "fromId": "n11",
+ "toId": "n7",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n13",
+ "fromId": "n11",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n14",
+ "fromId": "n12",
+ "toId": "n7",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n15",
+ "fromId": "n12",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n16",
+ "fromId": "n13",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n17",
+ "fromId": "n14",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n18",
+ "fromId": "n15",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n19",
+ "fromId": "n15",
+ "toId": "n9",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n20",
+ "fromId": "n14",
+ "toId": "n9",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n21",
+ "fromId": "n13",
+ "toId": "n9",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n22",
+ "fromId": "n16",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n23",
+ "fromId": "n17",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n24",
+ "fromId": "n18",
+ "toId": "n6",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n25",
+ "fromId": "n16",
+ "toId": "n10",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n26",
+ "fromId": "n17",
+ "toId": "n10",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n27",
+ "fromId": "n18",
+ "toId": "n10",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n28",
+ "fromId": "n27",
+ "toId": "n18",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n29",
+ "fromId": "n26",
+ "toId": "n17",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n30",
+ "fromId": "n25",
+ "toId": "n16",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n31",
+ "fromId": "n24",
+ "toId": "n15",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n32",
+ "fromId": "n23",
+ "toId": "n14",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n33",
+ "fromId": "n22",
+ "toId": "n13",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n34",
+ "fromId": "n21",
+ "toId": "n12",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n35",
+ "fromId": "n20",
+ "toId": "n11",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n36",
+ "fromId": "n19",
+ "toId": "n8",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n37",
+ "fromId": "n26",
+ "toId": "n1",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n39",
+ "fromId": "n23",
+ "toId": "n1",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n41",
+ "fromId": "n21",
+ "toId": "n1",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n42",
+ "fromId": "n20",
+ "toId": "n1",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharness2.svg b/cmd/api/src/test/integration/harnesses/esc10aharness2.svg
new file mode 100644
index 000000000..2db2d6938
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharness2.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharnesseca.json b/cmd/api/src/test/integration/harnesses/esc10aharnesseca.json
new file mode 100644
index 000000000..6e3db8ed6
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharnesseca.json
@@ -0,0 +1,1078 @@
+{
+ "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": 1838.2521199214677,
+ "y": 2555.736538757399
+ },
+ "caption": "Domain1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n1",
+ "position": {
+ "x": 1442.701427932503,
+ "y": 2273.231824786215
+ },
+ "caption": "NTAuthStore1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 1442.701427932503,
+ "y": 2428.987863580507
+ },
+ "caption": "RootCA1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 446.2054422641352,
+ "y": 2273.231824786215
+ },
+ "caption": "CertTemplate1",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 1442.701427932503,
+ "y": 2117.4757859919237
+ },
+ "caption": "DC1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n5",
+ "position": {
+ "x": 956.6260599607343,
+ "y": 2273.231824786215
+ },
+ "caption": "EnterpriseCA1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 75.00000000000023,
+ "y": 2555.736538757399
+ },
+ "caption": "User1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 1838.2521199214673,
+ "y": 2038.867592259418
+ },
+ "caption": "Domain2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n8",
+ "position": {
+ "x": 1442.7014279325028,
+ "y": 1756.3628782882338
+ },
+ "caption": "NTAuthStore2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n9",
+ "position": {
+ "x": 1442.7014279325028,
+ "y": 1912.118917082525
+ },
+ "caption": "RootCA2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n10",
+ "position": {
+ "x": 446.20544226413443,
+ "y": 1756.3628782882338
+ },
+ "caption": "CertTemplate2",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n11",
+ "position": {
+ "x": 1442.7014279325028,
+ "y": 1600.6068394939425
+ },
+ "caption": "DC2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n12",
+ "position": {
+ "x": 956.6260599607343,
+ "y": 1756.3628782882338
+ },
+ "caption": "EnterpriseCA2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n13",
+ "position": {
+ "x": 75.00000000000034,
+ "y": 2038.867592259418
+ },
+ "caption": "User2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n14",
+ "position": {
+ "x": 1838.2521199214673,
+ "y": 1521.9986457614368
+ },
+ "caption": "Domain3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n15",
+ "position": {
+ "x": 1442.7014279325022,
+ "y": 1239.4939317902526
+ },
+ "caption": "NTAuthStore3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n16",
+ "position": {
+ "x": 1442.7014279325022,
+ "y": 1395.249970584544
+ },
+ "caption": "RootCA3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n17",
+ "position": {
+ "x": 446.20544226413415,
+ "y": 1239.4939317902526
+ },
+ "caption": "CertTemplate3",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n18",
+ "position": {
+ "x": 1442.7014279325022,
+ "y": 1083.7378929959623
+ },
+ "caption": "DC3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n19",
+ "position": {
+ "x": 956.6260599607343,
+ "y": 1239.4939317902526
+ },
+ "caption": "EnterpriseCA3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n20",
+ "position": {
+ "x": 75,
+ "y": 1521.9986457614368
+ },
+ "caption": "User3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n21",
+ "position": {
+ "x": 1838.2521199214677,
+ "y": 1005.1296992634557
+ },
+ "caption": "Domain4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n22",
+ "position": {
+ "x": 1442.7014279325026,
+ "y": 722.6249852922715
+ },
+ "caption": "NTAuthStore4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n23",
+ "position": {
+ "x": 1442.7014279325026,
+ "y": 878.3810240865628
+ },
+ "caption": "RootCA4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n24",
+ "position": {
+ "x": 446.2054422641343,
+ "y": 722.6249852922715
+ },
+ "caption": "CertTemplate4",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n25",
+ "position": {
+ "x": 1442.7014279325026,
+ "y": 566.8689464979814
+ },
+ "caption": "DC4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n26",
+ "position": {
+ "x": 956.6260599607343,
+ "y": 722.6249852922715
+ },
+ "caption": "EnterpriseCA4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n27",
+ "position": {
+ "x": 75.00000000000023,
+ "y": 1005.1296992634557
+ },
+ "caption": "User4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n28",
+ "position": {
+ "x": 1838.2521199214682,
+ "y": 488.26075276547454
+ },
+ "caption": "Domain5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n29",
+ "position": {
+ "x": 1442.7014279325024,
+ "y": 205.75603879429036
+ },
+ "caption": "NTAuthStore5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n30",
+ "position": {
+ "x": 1442.7014279325024,
+ "y": 361.51207758858163
+ },
+ "caption": "RootCA5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n31",
+ "position": {
+ "x": 446.2054422641345,
+ "y": 205.75603879429036
+ },
+ "caption": "CertTemplate5",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff"
+ }
+ },
+ {
+ "id": "n32",
+ "position": {
+ "x": 1442.7014279325024,
+ "y": 50
+ },
+ "caption": "DC5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n33",
+ "position": {
+ "x": 956.6260599607343,
+ "y": 205.75603879429036
+ },
+ "caption": "EnterpriseCA5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n34",
+ "position": {
+ "x": 75.00000000000034,
+ "y": 488.26075276547454
+ },
+ "caption": "User5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n35",
+ "position": {
+ "x": -194.9337573355329,
+ "y": 2761.1687609848414
+ },
+ "caption": "Group1",
+ "style": {
+ "node-color": "#fcdc00"
+ },
+ "labels": [],
+ "properties": {}
+ },
+ {
+ "id": "n36",
+ "position": {
+ "x": -194.9337573355329,
+ "y": 2244.299814486861
+ },
+ "caption": "Group2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n37",
+ "position": {
+ "x": -194.9337573355329,
+ "y": 1727.430867988881
+ },
+ "caption": "Group3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n38",
+ "position": {
+ "x": -194.9337573355329,
+ "y": 1210.5619214909007
+ },
+ "caption": "Group4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n39",
+ "position": {
+ "x": -194.9337573355329,
+ "y": 693.6929749929204
+ },
+ "caption": "Group5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n2",
+ "toId": "n0",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n1",
+ "fromId": "n1",
+ "toId": "n0",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n2",
+ "fromId": "n4",
+ "toId": "n0",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n3",
+ "fromId": "n3",
+ "toId": "n5",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n4",
+ "fromId": "n5",
+ "toId": "n2",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n5",
+ "fromId": "n5",
+ "toId": "n1",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n6",
+ "fromId": "n6",
+ "toId": "n5",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n7",
+ "fromId": "n5",
+ "toId": "n4",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n8",
+ "fromId": "n6",
+ "toId": "n3",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n9",
+ "fromId": "n9",
+ "toId": "n7",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n10",
+ "fromId": "n8",
+ "toId": "n7",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n11",
+ "fromId": "n11",
+ "toId": "n7",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n12",
+ "fromId": "n10",
+ "toId": "n12",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n13",
+ "fromId": "n12",
+ "toId": "n9",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n14",
+ "fromId": "n12",
+ "toId": "n8",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n15",
+ "fromId": "n13",
+ "toId": "n12",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n16",
+ "fromId": "n13",
+ "toId": "n10",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n17",
+ "fromId": "n16",
+ "toId": "n14",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n18",
+ "fromId": "n15",
+ "toId": "n14",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n19",
+ "fromId": "n18",
+ "toId": "n14",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n20",
+ "fromId": "n17",
+ "toId": "n19",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n21",
+ "fromId": "n19",
+ "toId": "n16",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n22",
+ "fromId": "n20",
+ "toId": "n19",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n23",
+ "fromId": "n19",
+ "toId": "n18",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n24",
+ "fromId": "n20",
+ "toId": "n17",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n25",
+ "fromId": "n23",
+ "toId": "n21",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n26",
+ "fromId": "n22",
+ "toId": "n21",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n27",
+ "fromId": "n25",
+ "toId": "n21",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n28",
+ "fromId": "n24",
+ "toId": "n26",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n29",
+ "fromId": "n26",
+ "toId": "n22",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n30",
+ "fromId": "n27",
+ "toId": "n26",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n31",
+ "fromId": "n26",
+ "toId": "n25",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n32",
+ "fromId": "n27",
+ "toId": "n24",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n33",
+ "fromId": "n30",
+ "toId": "n28",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n34",
+ "fromId": "n29",
+ "toId": "n28",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n35",
+ "fromId": "n32",
+ "toId": "n28",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n36",
+ "fromId": "n33",
+ "toId": "n30",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n37",
+ "fromId": "n33",
+ "toId": "n29",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n38",
+ "fromId": "n34",
+ "toId": "n33",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n39",
+ "fromId": "n33",
+ "toId": "n32",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n40",
+ "fromId": "n34",
+ "toId": "n31",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n41",
+ "type": "GenericAll",
+ "style": {},
+ "properties": {},
+ "fromId": "n35",
+ "toId": "n6"
+ },
+ {
+ "id": "n42",
+ "type": "ADCSESC10a",
+ "style": {},
+ "properties": {},
+ "fromId": "n35",
+ "toId": "n0"
+ },
+ {
+ "id": "n43",
+ "type": "GenericAll",
+ "style": {},
+ "properties": {},
+ "fromId": "n36",
+ "toId": "n13"
+ },
+ {
+ "id": "n44",
+ "type": "GenericAll",
+ "style": {},
+ "properties": {},
+ "fromId": "n39",
+ "toId": "n34"
+ },
+ {
+ "id": "n45",
+ "type": "GenericAll",
+ "style": {},
+ "properties": {},
+ "fromId": "n38",
+ "toId": "n27"
+ },
+ {
+ "id": "n46",
+ "type": "GenericAll",
+ "style": {},
+ "properties": {},
+ "fromId": "n37",
+ "toId": "n20"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharnesseca.svg b/cmd/api/src/test/integration/harnesses/esc10aharnesseca.svg
new file mode 100644
index 000000000..5a9511fda
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharnesseca.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.json b/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.json
new file mode 100644
index 000000000..2865cd0be
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.json
@@ -0,0 +1,452 @@
+{
+ "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": 337.04748861166024,
+ "y": 50
+ },
+ "caption": "Domain",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n1",
+ "position": {
+ "x": 2497.3664674686984,
+ "y": 410.62726890336444
+ },
+ "caption": "NTAuthStore",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 2381.5025296927042,
+ "y": 212.5597044346638
+ },
+ "caption": "RootCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 2215.339273936165,
+ "y": 1016.8790026674126
+ },
+ "caption": "EnterpriseCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 2215.339273936165,
+ "y": 50
+ },
+ "caption": "DC",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n5",
+ "position": {
+ "x": 531.0993047358514,
+ "y": 1016.8790026674126
+ },
+ "caption": "Group0",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 1987.2171233355546,
+ "y": 529.3782522542996
+ },
+ "caption": "CertTemplate1",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 1041.8790026674124,
+ "y": 312.04748861166024
+ },
+ "caption": "User1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n8",
+ "position": {
+ "x": 1041.8790026674124,
+ "y": 456.9346643734199
+ },
+ "caption": "User2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n9",
+ "position": {
+ "x": 1041.8790026674124,
+ "y": 601.8218401351795
+ },
+ "caption": "User3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n10",
+ "position": {
+ "x": 1041.8790026674124,
+ "y": 746.7090158969393
+ },
+ "caption": "User4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#000000"
+ }
+ },
+ {
+ "id": "n11",
+ "position": {
+ "x": 75,
+ "y": 312.04748861166024
+ },
+ "caption": "Group1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n12",
+ "position": {
+ "x": 158.45112686904184,
+ "y": 456.9346643734199
+ },
+ "caption": "Group2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n13",
+ "position": {
+ "x": 246.0320350312874,
+ "y": 601.8218401351795
+ },
+ "caption": "Group3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n14",
+ "position": {
+ "x": 337.04748861166024,
+ "y": 746.7090158969393
+ },
+ "caption": "Group4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n2",
+ "toId": "n0",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n1",
+ "fromId": "n3",
+ "toId": "n2",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n2",
+ "fromId": "n1",
+ "toId": "n0",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n3",
+ "fromId": "n3",
+ "toId": "n1",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n4",
+ "fromId": "n3",
+ "toId": "n4",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n5",
+ "fromId": "n4",
+ "toId": "n0",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n6",
+ "fromId": "n5",
+ "toId": "n3",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n7",
+ "fromId": "n6",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n8",
+ "fromId": "n7",
+ "toId": "n6",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n9",
+ "fromId": "n7",
+ "toId": "n5",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n10",
+ "type": "AllExtendedRights",
+ "style": {},
+ "properties": {},
+ "fromId": "n8",
+ "toId": "n6"
+ },
+ {
+ "id": "n11",
+ "fromId": "n8",
+ "toId": "n5",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n12",
+ "fromId": "n9",
+ "toId": "n6",
+ "type": "GenericWrite",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n13",
+ "fromId": "n9",
+ "toId": "n5",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n14",
+ "fromId": "n10",
+ "toId": "n6",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n15",
+ "fromId": "n11",
+ "toId": "n7",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n16",
+ "fromId": "n11",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n17",
+ "fromId": "n12",
+ "toId": "n8",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n18",
+ "fromId": "n12",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n19",
+ "fromId": "n13",
+ "toId": "n9",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n20",
+ "fromId": "n14",
+ "toId": "n10",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.svg b/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.svg
new file mode 100644
index 000000000..18146eadf
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aharnessvictim.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.json b/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.json
new file mode 100644
index 000000000..c0c4bd7f8
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.json
@@ -0,0 +1,474 @@
+{
+ "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": 24.6412667909101,
+ "y": 1790.9164380862208
+ },
+ "caption": "Domain",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#68ccca"
+ }
+ },
+ {
+ "id": "n1",
+ "position": {
+ "x": 915.5043544911281,
+ "y": 1554.763441047
+ },
+ "caption": "NTAuthStore",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n2",
+ "position": {
+ "x": 915.5043544911281,
+ "y": 1672.8399395666104
+ },
+ "caption": "RootCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#653294",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n3",
+ "position": {
+ "x": 1729.453404980963,
+ "y": 1396.5299845769014
+ },
+ "caption": "EnterpriseCA",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#194d33",
+ "caption-color": "#ffffff"
+ }
+ },
+ {
+ "id": "n4",
+ "position": {
+ "x": 915.5043544911281,
+ "y": 1790.9164380862208
+ },
+ "caption": "DC",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#f44e3b",
+ "caption-position": "inside",
+ "property-alignment": "colon",
+ "property-position": "outside"
+ }
+ },
+ {
+ "id": "n6",
+ "position": {
+ "x": 1729.453404980963,
+ "y": 1082.4385788188413
+ },
+ "caption": "CertTemplate",
+ "labels": [],
+ "properties": {
+ "AuthenticationEnabled": "True",
+ "RequireManagerApproval": "False",
+ "SchemaVersion": "1",
+ "SubjectAltRequireUPN": "True"
+ },
+ "style": {
+ "node-color": "#fda1ff",
+ "outside-position": "left",
+ "node-margin": 50
+ }
+ },
+ {
+ "id": "n7",
+ "position": {
+ "x": 915.5043544911281,
+ "y": 1082.4385788188413
+ },
+ "caption": "User1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n11",
+ "position": {
+ "x": 24.6412667909101,
+ "y": 842.2531080094587
+ },
+ "caption": "Group1",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n12",
+ "position": {
+ "x": 97.83319758088052,
+ "y": 977.4451369153232
+ },
+ "caption": "Group2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n14",
+ "position": {
+ "x": 432.58749843883385,
+ "y": 1449.4515969240565
+ },
+ "caption": "Group6",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00",
+ "border-color": "#73d8ff"
+ }
+ },
+ {
+ "id": "n15",
+ "position": {
+ "x": 180.7937059276843,
+ "y": 1105.4077644506815
+ },
+ "caption": "Group3",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n16",
+ "position": {
+ "x": 259.9130584079944,
+ "y": 1235.2263846542628
+ },
+ "caption": "Group4",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n17",
+ "position": {
+ "x": 345.4214516200178,
+ "y": 1344.891677696618
+ },
+ "caption": "Group5",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ },
+ {
+ "id": "n18",
+ "position": {
+ "x": 915.504354491128,
+ "y": 1396.5299845769018
+ },
+ "caption": "User2",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#a4dd00"
+ }
+ },
+ {
+ "id": "n19",
+ "position": {
+ "x": 1311.4447947779927,
+ "y": 1235.2263846542628
+ },
+ "caption": "Group0",
+ "labels": [],
+ "properties": {},
+ "style": {
+ "node-color": "#fcdc00"
+ }
+ }
+ ],
+ "relationships": [
+ {
+ "id": "n0",
+ "fromId": "n2",
+ "toId": "n0",
+ "type": "RootCAFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n1",
+ "fromId": "n3",
+ "toId": "n2",
+ "type": "IssuedSignedBy",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n2",
+ "fromId": "n1",
+ "toId": "n0",
+ "type": "NTAuthStoreFor",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n3",
+ "fromId": "n3",
+ "toId": "n1",
+ "type": "TrustedForNTAuth",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n4",
+ "fromId": "n3",
+ "toId": "n4",
+ "type": "CanAbuseUPNCertMapping",
+ "properties": {},
+ "style": {
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n5",
+ "fromId": "n4",
+ "toId": "n0",
+ "type": "DCFor",
+ "properties": {},
+ "style": {
+ "type-color": "#000000",
+ "arrow-color": "#000000"
+ }
+ },
+ {
+ "id": "n7",
+ "fromId": "n6",
+ "toId": "n3",
+ "type": "PublishedTo",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n17",
+ "fromId": "n11",
+ "toId": "n7",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n18",
+ "fromId": "n11",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n20",
+ "fromId": "n12",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n21",
+ "fromId": "n12",
+ "toId": "n7",
+ "type": "GenericWrite",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n22",
+ "fromId": "n14",
+ "toId": "n7",
+ "type": "AllExtendedRights",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n23",
+ "fromId": "n15",
+ "toId": "n7",
+ "type": "WriteDacl",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n24",
+ "fromId": "n15",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n25",
+ "fromId": "n16",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n26",
+ "fromId": "n16",
+ "toId": "n7",
+ "type": "WriteOwner",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n27",
+ "fromId": "n17",
+ "toId": "n0",
+ "type": "ADCSESC10a",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n28",
+ "fromId": "n17",
+ "toId": "n7",
+ "type": "WriteOwner",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n38",
+ "fromId": "n18",
+ "toId": "n18",
+ "type": "GenericAll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n39",
+ "type": "ADCSESC10a",
+ "style": {},
+ "properties": {},
+ "fromId": "n18",
+ "toId": "n0"
+ },
+ {
+ "id": "n40",
+ "fromId": "n7",
+ "toId": "n19",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n41",
+ "fromId": "n18",
+ "toId": "n19",
+ "type": "MemberOf",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n42",
+ "fromId": "n19",
+ "toId": "n6",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ },
+ {
+ "id": "n43",
+ "fromId": "n19",
+ "toId": "n3",
+ "type": "Enroll",
+ "properties": {},
+ "style": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.svg b/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.svg
new file mode 100644
index 000000000..2e5387ed1
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/esc10aprincipalharness.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/cmd/api/src/test/integration/harnesses/harnessgen.py b/cmd/api/src/test/integration/harnesses/harnessgen.py
new file mode 100644
index 000000000..9b0167ee9
--- /dev/null
+++ b/cmd/api/src/test/integration/harnesses/harnessgen.py
@@ -0,0 +1,183 @@
+import json
+import sys
+
+with open(sys.argv[1], 'r') as f:
+ j = json.load(f)
+
+nodes = {}
+relationships = []
+
+
+class BaseNode:
+ def __init__(self, name: str):
+ self.name = name
+
+
+class UserNode(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryUser("{self.name}", domainSid)'
+
+
+class GroupNode(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryGroup("{self.name}", domainSid)'
+
+
+class ComputerNode(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryComputer("{self.name}", domainSid)'
+
+
+class OUNode(BaseNode):
+ def __init__(self, name: str, blocksInheritance: bool = False):
+ super().__init__(name)
+ self.blocksInheritance = blocksInheritance
+
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryOU("{self.name}", domainSid, {json.dumps(self.blocksInheritance)})'
+
+
+class DomainNode(BaseNode):
+ def __init__(self, name: str, blocksInheritance: bool = False):
+ super().__init__(name)
+ self.blocksInheritance = blocksInheritance
+
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryDomain("{self.name}", domainSid, {json.dumps(self.blocksInheritance)}, true)'
+
+
+class NTAuthStore(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryNTAuthStore("{self.name}", domainSid)'
+
+
+class RootCA(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryRootCA("{self.name}", domainSid)'
+
+
+class EnterpriseCA(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.NewActiveDirectoryEnterpriseCA("{self.name}", domainSid)'
+
+
+class CertTemplateData:
+ def __init__(self) -> None:
+ self.RequiresManagerApproval = False
+ self.AuthenticationEnabled = False
+ self.EnrolleeSuppliesSubject = False
+ self.SubjectAltRequireUPN = False
+ self.SubjectAltRequireSPN = False
+ self.NoSecurityExtension = False
+ self.SchemaVersion = 1
+ self.AuthorizedSignatures = 0
+ self.EKUS = []
+ self.ApplicationPolicies = []
+ self.SubjectAltRequireEmail = False
+
+ def toJSON(self):
+ return json.dumps(self, default=lambda o: o.__dict__,
+ sort_keys=True, indent=4)
+
+
+def create_certtemplate_data(j):
+ data = CertTemplateData()
+ properties = j['properties']
+ for key in properties:
+ v = properties[key]
+ k = key
+ if k == 'RequireManagerApproval':
+ k = 'RequiresManagerApproval'
+ if v == 'True':
+ data.__dict__[k] = True
+ elif v == 'False':
+ data.__dict__[k] = False
+ else:
+ try:
+ i = int(v)
+ data.__dict__[k] = i
+ except:
+ data.__dict__[k] = v
+
+ return data
+
+
+class CertTemplate(BaseNode):
+ def __init__(self, name: str, data: CertTemplateData):
+ super().__init__(name)
+ self.data = data
+
+ def create_creation_statement(self):
+ d = self.data.toJSON()
+ d = d.replace(']', '}')
+ d = d.replace('[', '[]string{')
+ d = d.replace('"', '')
+ d = d[:-2] + "," + d[-2:]
+ b = f's.{self.name} = graphTestContext.NewActiveDirectoryCertTemplate("{self.name}", domainSid, CertTemplateData{d})'
+
+ return b
+
+
+class UnknownNode(BaseNode):
+ def create_creation_statement(self):
+ return f's.{self.name} = graphTestContext.REPLACEME("{self.name}", domainSid)'
+
+
+class Relationship:
+ def __init__(self, fromID: str, toID: str, type: str) -> None:
+ self.fromID = fromID
+ self.toID = toID
+ self.type = type
+
+ def create_statement(self):
+ return f'graphTestContext.NewRelationship(s.{nodes[self.fromID].name}, s.{nodes[self.toID].name}, ad.{self.type})'
+
+
+for node in j['nodes']:
+ name = node['caption']
+ id = node['id']
+ if 'User' in name:
+ nodes[id] = UserNode(name)
+ elif 'Group' in name:
+ nodes[id] = GroupNode(name)
+ elif 'Computer' in name:
+ nodes[id] = ComputerNode(name)
+ elif 'OU' in name:
+ nodes[id] = OUNode(name)
+ elif 'NTAuthStore' in name:
+ nodes[id] = NTAuthStore(name)
+ elif 'RootCA' in name:
+ nodes[id] = RootCA(name)
+ elif 'Domain' in name:
+ nodes[id] = DomainNode(name)
+ elif 'EnterpriseCA' in name or 'ECA' in name:
+ nodes[id] = EnterpriseCA(name)
+ elif 'CertTemplate' in name:
+ d = create_certtemplate_data(node)
+ nodes[id] = CertTemplate(name, d)
+ else:
+ print(f'Could not determine type for {name}')
+ nodes[id] = UnknownNode(name)
+
+for rel in j['relationships']:
+ relationships.append(Relationship(rel['fromId'], rel['toId'], rel['type']))
+
+harnessName = input("Name this harness: ")
+structDef = f"type {harnessName} struct {{\n"
+setupFunc = f"func (s *{harnessName}) Setup(graphTestContext *GraphTestContext) {{\n domainSid := RandomDomainSID()\n"
+
+for k in {k: v for k, v in sorted(nodes.items(), key=lambda item: item[1].name)}:
+ structDef += f'{nodes[k].name} *graph.Node\n'
+ setupFunc += nodes[k].create_creation_statement() + "\n"
+
+structDef += "}"
+
+for r in relationships:
+ setupFunc += r.create_statement() + "\n"
+
+setupFunc += "}"
+
+print()
+print(structDef)
+print()
+print(setupFunc)
diff --git a/packages/cue/bh/ad/ad.cue b/packages/cue/bh/ad/ad.cue
index 5b7677751..7db18c148 100644
--- a/packages/cue/bh/ad/ad.cue
+++ b/packages/cue/bh/ad/ad.cue
@@ -1011,6 +1011,16 @@ ADCSESC9b: types.#Kind & {
schema: "active_directory"
}
+ADCSESC10a: types.#Kind & {
+ symbol: "ADCSESC10a"
+ schema: "active_directory"
+}
+
+ADCSESC10b: types.#Kind & {
+ symbol: "ADCSESC10b"
+ schema: "active_directory"
+}
+
// Relationship Kinds
RelationshipKinds: [
Owns,
@@ -1076,6 +1086,8 @@ RelationshipKinds: [
ADCSESC7,
ADCSESC9a,
ADCSESC9b,
+ ADCSESC10a,
+ ADCSESC10b
]
// ACL Relationships
@@ -1149,5 +1161,7 @@ PathfindingRelationships: [
ADCSESC7,
ADCSESC9a,
ADCSESC9b,
+ ADCSESC10a,
+ ADCSESC10b,
DCFor
]
diff --git a/packages/go/analysis/ad/adcs.go b/packages/go/analysis/ad/adcs.go
index eb64a1537..66689084c 100644
--- a/packages/go/analysis/ad/adcs.go
+++ b/packages/go/analysis/ad/adcs.go
@@ -487,6 +487,14 @@ func PostADCS(ctx context.Context, db graph.Database, groupExpansions impact.Pat
return nil
})
+
+ operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error {
+ if err := PostADCSESC10a(ctx, tx, outC, groupExpansions, innerEnterpriseCA, innerDomain, cache); err != nil {
+ log.Errorf("failed post processing for %s: %v", ad.ADCSESC10a.String(), err)
+ }
+
+ return nil
+ })
}
}
diff --git a/packages/go/analysis/ad/esc10.go b/packages/go/analysis/ad/esc10.go
new file mode 100644
index 000000000..233ff24a9
--- /dev/null
+++ b/packages/go/analysis/ad/esc10.go
@@ -0,0 +1,150 @@
+// Copyright 2024 Specter Ops, Inc.
+//
+// Licensed under the Apache License, Version 2.0
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+package ad
+
+import (
+ "context"
+ "errors"
+ "github.com/specterops/bloodhound/analysis"
+ "github.com/specterops/bloodhound/analysis/impact"
+ "github.com/specterops/bloodhound/dawgs/cardinality"
+ "github.com/specterops/bloodhound/dawgs/graph"
+ "github.com/specterops/bloodhound/dawgs/ops"
+ "github.com/specterops/bloodhound/dawgs/query"
+ "github.com/specterops/bloodhound/dawgs/util/channels"
+ "github.com/specterops/bloodhound/graphschema/ad"
+ "github.com/specterops/bloodhound/log"
+)
+
+func PostADCSESC10a(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob, groupExpansions impact.PathAggregator, eca, domain *graph.Node, cache ADCSCache) error {
+ results := cardinality.NewBitmap32()
+
+ if canAbuseUPNRels, err := FetchCanAbuseUPNCertMappingRels(tx, eca); err != nil {
+ if graph.IsErrNotFound(err) {
+ return nil
+ }
+
+ return err
+ } else if len(canAbuseUPNRels) == 0 {
+ return nil
+ } else if publishedCertTemplates, ok := cache.PublishedTemplateCache[eca.ID]; !ok {
+ return nil
+ } else {
+ for _, template := range publishedCertTemplates {
+ if valid, err := isCertTemplateValidForESC10a(template); err != nil {
+ if !errors.Is(err, graph.ErrPropertyNotFound) {
+ log.Errorf("Error checking cert template validity for template %d: %v", template.ID, err)
+ } else {
+ log.Debugf("Error checking cert template validity for template %d: %v", template.ID, err)
+ }
+ } else if !valid {
+ continue
+ } else if certTemplateControllers, ok := cache.CertTemplateControllers[template.ID]; !ok {
+ log.Debugf("Failed to retrieve controllers for cert template %d from cache", template.ID)
+ continue
+ } else if ecaControllers, ok := cache.EnterpriseCAEnrollers[eca.ID]; !ok {
+ log.Debugf("Failed to retrieve controllers for enterprise ca %d from cache", eca.ID)
+ continue
+ } else {
+ //Expand controllers for the eca + template completely because we don't do group shortcutting here
+ var (
+ victimBitmap = expandNodeSliceToBitmapWithoutGroups(certTemplateControllers, groupExpansions)
+ ecaBitmap = expandNodeSliceToBitmapWithoutGroups(ecaControllers, groupExpansions)
+ )
+ victimBitmap.And(ecaBitmap)
+ //Use our id list to filter down to users
+ if userNodes, err := ops.FetchNodeSet(tx.Nodes().Filterf(func() graph.Criteria {
+ return query.And(
+ query.KindIn(query.Node(), ad.User),
+ query.InIDs(query.NodeID(), cardinality.DuplexToGraphIDs(victimBitmap)...),
+ )
+ })); err != nil && !graph.IsErrNotFound(err) {
+ log.Warnf("Error getting user nodes for esc10a attacker nodes: %v", err)
+ continue
+ } else if len(userNodes) > 0 {
+ if subjRequireDns, err := template.Properties.Get(ad.SubjectAltRequireDNS.String()).Bool(); err != nil {
+ log.Debugf("Failed to retrieve subjectAltRequireDNS for template %d: %v", template.ID, err)
+ victimBitmap.Xor(cardinality.NodeSetToDuplex(userNodes))
+ } else if subjRequireDomainDns, err := template.Properties.Get(ad.SubjectAltRequireDomainDNS.String()).Bool(); err != nil {
+ log.Debugf("Failed to retrieve subjectAltRequireDomainDNS for template %d: %v", template.ID, err)
+ victimBitmap.Xor(cardinality.NodeSetToDuplex(userNodes))
+ } else if subjRequireDns || subjRequireDomainDns {
+ //If either of these properties is true, we need to remove all these users from our victims list
+ victimBitmap.Xor(cardinality.NodeSetToDuplex(userNodes))
+ }
+ }
+
+ if attackers, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.And(
+ query.KindIn(query.Start(), ad.Group, ad.User, ad.Computer),
+ query.KindIn(query.Relationship(), ad.GenericAll, ad.GenericWrite, ad.Owns, ad.WriteOwner, ad.WriteDACL),
+ query.InIDs(query.EndID(), cardinality.DuplexToGraphIDs(victimBitmap)...),
+ )
+ })); err != nil {
+ log.Warnf("Error getting start nodes for esc10a attacker nodes: %v", err)
+ continue
+ } else {
+ results.Or(cardinality.NodeSetToDuplex(attackers))
+ }
+ }
+ }
+
+ results.Each(func(value uint32) (bool, error) {
+ if !channels.Submit(ctx, outC, analysis.CreatePostRelationshipJob{
+ FromID: graph.ID(value),
+ ToID: domain.ID,
+ Kind: ad.ADCSESC10a,
+ }) {
+ return false, nil
+ } else {
+ return true, nil
+ }
+ })
+
+ return nil
+ }
+}
+
+func isCertTemplateValidForESC10a(ct *graph.Node) (bool, error) {
+ if reqManagerApproval, err := ct.Properties.Get(ad.RequiresManagerApproval.String()).Bool(); err != nil {
+ return false, err
+ } else if reqManagerApproval {
+ return false, nil
+ } else if authenticationEnabled, err := ct.Properties.Get(ad.AuthenticationEnabled.String()).Bool(); err != nil {
+ return false, err
+ } else if !authenticationEnabled {
+ return false, nil
+ } else if enrolleeSuppliesSubject, err := ct.Properties.Get(ad.EnrolleeSuppliesSubject.String()).Bool(); err != nil {
+ return false, err
+ } else if enrolleeSuppliesSubject {
+ return false, nil
+ } else if schemaVersion, err := ct.Properties.Get(ad.SchemaVersion.String()).Float64(); err != nil {
+ return false, err
+ } else if authorizedSignatures, err := ct.Properties.Get(ad.AuthorizedSignatures.String()).Float64(); err != nil {
+ return false, err
+ } else if schemaVersion > 1 && authorizedSignatures > 0 {
+ return false, nil
+ } else if subjectAltRequireUPN, err := ct.Properties.Get(ad.SubjectAltRequireUPN.String()).Bool(); err != nil {
+ return false, err
+ } else if subjectAltRequireSPN, err := ct.Properties.Get(ad.SubjectAltRequireSPN.String()).Bool(); err != nil {
+ return false, err
+ } else if subjectAltRequireSPN || subjectAltRequireUPN {
+ return true, nil
+ } else {
+ return false, nil
+ }
+}
diff --git a/packages/go/analysis/ad/esc6.go b/packages/go/analysis/ad/esc6.go
index 1df859d79..fcf00ade3 100644
--- a/packages/go/analysis/ad/esc6.go
+++ b/packages/go/analysis/ad/esc6.go
@@ -26,6 +26,7 @@ import (
"github.com/specterops/bloodhound/dawgs/util/channels"
"github.com/specterops/bloodhound/errors"
"github.com/specterops/bloodhound/graphschema/ad"
+ "github.com/specterops/bloodhound/log"
)
func PostCanAbuseUPNCertMapping(operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob], enterpriseCertAuthorities []*graph.Node) error {
@@ -49,7 +50,7 @@ func PostCanAbuseUPNCertMapping(operation analysis.StatTrackedOperation[analysis
} else {
for _, dcForNode := range dcForNodes {
if cmmrProperty, err := dcForNode.Properties.Get(ad.CertificateMappingMethodsRaw.String()).Int(); err != nil {
- collector.Collect(fmt.Errorf("error in PostCanAbuseUPNCertMapping: unable to fetch %v property for node ID %v: %v", ad.StrongCertificateBindingEnforcementRaw.String(), dcForNode.ID, err))
+ log.Warnf("error in PostCanAbuseUPNCertMapping: unable to fetch %v property for node ID %v: %v", ad.StrongCertificateBindingEnforcementRaw.String(), dcForNode.ID, err)
continue
} else if cmmrProperty&0x04 == 0x04 {
if !channels.Submit(ctx, outC, analysis.CreatePostRelationshipJob{
@@ -91,7 +92,7 @@ func PostCanAbuseWeakCertBinding(operation analysis.StatTrackedOperation[analysi
} else {
for _, dcForNode := range dcForNodes {
if strongCertBindingEnforcement, err := dcForNode.Properties.Get(ad.StrongCertificateBindingEnforcementRaw.String()).Int(); err != nil {
- collector.Collect(fmt.Errorf("error in PostCanAbuseWeakCertBinding: unable to fetch %v property for node ID %v: %v", ad.StrongCertificateBindingEnforcementRaw.String(), dcForNode.ID, err))
+ log.Warnf("error in PostCanAbuseWeakCertBinding: unable to fetch %v property for node ID %v: %v", ad.StrongCertificateBindingEnforcementRaw.String(), dcForNode.ID, err)
continue
} else if strongCertBindingEnforcement == 0 || strongCertBindingEnforcement == 1 {
if !channels.Submit(ctx, outC, analysis.CreatePostRelationshipJob{
diff --git a/packages/go/analysis/ad/post.go b/packages/go/analysis/ad/post.go
index 40a32db13..d25b48f69 100644
--- a/packages/go/analysis/ad/post.go
+++ b/packages/go/analysis/ad/post.go
@@ -55,6 +55,9 @@ func PostProcessedRelationships() []graph.Kind {
ad.ADCSESC5,
ad.ADCSESC6a,
ad.ADCSESC7,
+ ad.ADCSESC10a,
+ ad.ADCSESC10b,
+ ad.ADCSESC9a,
ad.EnrollOnBehalfOf,
}
}
diff --git a/packages/go/analysis/ad/queries.go b/packages/go/analysis/ad/queries.go
index 7c3dc6bbf..ad6a6dc74 100644
--- a/packages/go/analysis/ad/queries.go
+++ b/packages/go/analysis/ad/queries.go
@@ -1439,6 +1439,20 @@ func FetchCanAbuseWeakCertBindingRels(tx graph.Transaction, node *graph.Node) ([
}
}
+func FetchCanAbuseUPNCertMappingRels(tx graph.Transaction, node *graph.Node) ([]*graph.Relationship, error) {
+ if rels, err := ops.FetchRelationships(tx.Relationships().Filterf(func() graph.Criteria {
+ return query.And(
+ query.Equals(query.StartID(), node.ID),
+ query.Kind(query.Relationship(), ad.CanAbuseUPNCertMapping),
+ query.Kind(query.End(), ad.Entity),
+ )
+ })); err != nil {
+ return nil, err
+ } else {
+ return rels, nil
+ }
+}
+
func FetchEnterpriseCAsCertChainPathToDomain(tx graph.Transaction, enterpriseCA, domain *graph.Node) (graph.PathSet, error) {
return ops.TraversePaths(tx, ops.TraversalPlan{
Root: enterpriseCA,
diff --git a/packages/go/graphschema/ad/ad.go b/packages/go/graphschema/ad/ad.go
index 1d02df59b..5877ce472 100644
--- a/packages/go/graphschema/ad/ad.go
+++ b/packages/go/graphschema/ad/ad.go
@@ -103,6 +103,8 @@ var (
ADCSESC7 = graph.StringKind("ADCSESC7")
ADCSESC9a = graph.StringKind("ADCSESC9a")
ADCSESC9b = graph.StringKind("ADCSESC9b")
+ ADCSESC10a = graph.StringKind("ADCSESC10a")
+ ADCSESC10b = graph.StringKind("ADCSESC10b")
)
type Property string
@@ -640,13 +642,13 @@ func Nodes() []graph.Kind {
return []graph.Kind{Entity, User, Computer, Group, GPO, OU, Container, Domain, LocalGroup, LocalUser, AIACA, RootCA, EnterpriseCA, NTAuthStore, CertTemplate}
}
func Relationships() []graph.Kind {
- return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, GetChanges, GetChangesAll, GetChangesInFilteredSet, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, LocalToComputer, MemberOfLocalGroup, RemoteInteractiveLogonPrivilege, SyncLAPSPassword, WriteAccountRestrictions, RootCAFor, DCFor, PublishedTo, ManageCertificates, ManageCA, DelegatedEnrollmentAgent, Enroll, HostsCAService, WritePKIEnrollmentFlag, WritePKINameFlag, NTAuthStoreFor, TrustedForNTAuth, EnterpriseCAFor, CanAbuseUPNCertMapping, CanAbuseWeakCertBinding, IssuedSignedBy, GoldenCert, EnrollOnBehalfOf, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6a, ADCSESC7, ADCSESC9a, ADCSESC9b}
+ return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, GetChanges, GetChangesAll, GetChangesInFilteredSet, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, LocalToComputer, MemberOfLocalGroup, RemoteInteractiveLogonPrivilege, SyncLAPSPassword, WriteAccountRestrictions, RootCAFor, DCFor, PublishedTo, ManageCertificates, ManageCA, DelegatedEnrollmentAgent, Enroll, HostsCAService, WritePKIEnrollmentFlag, WritePKINameFlag, NTAuthStoreFor, TrustedForNTAuth, EnterpriseCAFor, CanAbuseUPNCertMapping, CanAbuseWeakCertBinding, IssuedSignedBy, GoldenCert, EnrollOnBehalfOf, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6a, ADCSESC7, ADCSESC9a, ADCSESC9b, ADCSESC10a, ADCSESC10b}
}
func ACLRelationships() []graph.Kind {
return []graph.Kind{AllExtendedRights, ForceChangePassword, AddMember, AddAllowedToAct, GenericAll, WriteDACL, WriteOwner, GenericWrite, ReadLAPSPassword, ReadGMSAPassword, Owns, AddSelf, WriteSPN, AddKeyCredentialLink, GetChanges, GetChangesAll, GetChangesInFilteredSet, WriteAccountRestrictions, SyncLAPSPassword, DCSync, ManageCertificates, ManageCA, Enroll, WritePKIEnrollmentFlag, WritePKINameFlag}
}
func PathfindingRelationships() []graph.Kind {
- return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, SyncLAPSPassword, WriteAccountRestrictions, GoldenCert, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6a, ADCSESC7, ADCSESC9a, ADCSESC9b, DCFor}
+ return []graph.Kind{Owns, GenericAll, GenericWrite, WriteOwner, WriteDACL, MemberOf, ForceChangePassword, AllExtendedRights, AddMember, HasSession, Contains, GPLink, AllowedToDelegate, TrustedBy, AllowedToAct, AdminTo, CanPSRemote, CanRDP, ExecuteDCOM, HasSIDHistory, AddSelf, DCSync, ReadLAPSPassword, ReadGMSAPassword, DumpSMSAPassword, SQLAdmin, AddAllowedToAct, WriteSPN, AddKeyCredentialLink, SyncLAPSPassword, WriteAccountRestrictions, GoldenCert, ADCSESC1, ADCSESC3, ADCSESC4, ADCSESC5, ADCSESC6a, ADCSESC7, ADCSESC9a, ADCSESC9b, ADCSESC10a, ADCSESC10b, DCFor}
}
func IsACLKind(s graph.Kind) bool {
for _, acl := range ACLRelationships() {
diff --git a/packages/javascript/bh-shared-ui/src/graphSchema.ts b/packages/javascript/bh-shared-ui/src/graphSchema.ts
index 3759576a6..f475267d9 100644
--- a/packages/javascript/bh-shared-ui/src/graphSchema.ts
+++ b/packages/javascript/bh-shared-ui/src/graphSchema.ts
@@ -131,6 +131,8 @@ export enum ActiveDirectoryRelationshipKind {
ADCSESC7 = 'ADCSESC7',
ADCSESC9a = 'ADCSESC9a',
ADCSESC9b = 'ADCSESC9b',
+ ADCSESC10a = 'ADCSESC10a',
+ ADCSESC10b = 'ADCSESC10b',
}
export function ActiveDirectoryRelationshipKindToDisplay(value: ActiveDirectoryRelationshipKind): string | undefined {
switch (value) {
@@ -260,6 +262,10 @@ export function ActiveDirectoryRelationshipKindToDisplay(value: ActiveDirectoryR
return 'ADCSESC9a';
case ActiveDirectoryRelationshipKind.ADCSESC9b:
return 'ADCSESC9b';
+ case ActiveDirectoryRelationshipKind.ADCSESC10a:
+ return 'ADCSESC10a';
+ case ActiveDirectoryRelationshipKind.ADCSESC10b:
+ return 'ADCSESC10b';
default:
return undefined;
}
@@ -528,6 +534,8 @@ export function ActiveDirectoryPathfindingEdges(): ActiveDirectoryRelationshipKi
ActiveDirectoryRelationshipKind.ADCSESC7,
ActiveDirectoryRelationshipKind.ADCSESC9a,
ActiveDirectoryRelationshipKind.ADCSESC9b,
+ ActiveDirectoryRelationshipKind.ADCSESC10a,
+ ActiveDirectoryRelationshipKind.ADCSESC10b,
ActiveDirectoryRelationshipKind.DCFor,
];
}