Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: EnrollOnBehalfOf logic issue #1002

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 71 additions & 14 deletions cmd/api/src/analysis/ad/adcs_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,63 +447,75 @@ func TestTrustedForNTAuth(t *testing.T) {
func TestEnrollOnBehalfOf(t *testing.T) {
testContext := integration.NewGraphTestContext(t, graphschema.DefaultGraphSchema())
testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.EnrollOnBehalfOfHarnessOne.Setup(testContext)
harness.EnrollOnBehalfOfHarness1.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
v1Templates := make([]*graph.Node, 0)
v2Templates := make([]*graph.Node, 0)

for _, template := range certTemplates {
if version, err := template.Properties.Get(ad.SchemaVersion.String()).Float64(); err != nil {
continue
} else if version == 1 {
v1Templates = append(v1Templates, template)
} else if version >= 2 {
continue
v2Templates = append(v2Templates, template)
}
}

require.Nil(t, err)

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates)
results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates, harness.EnrollOnBehalfOfHarness1.Domain1)
require.Nil(t, err)

require.Len(t, results, 3)

require.Contains(t, results, analysis.CreatePostRelationshipJob{
FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate11.ID,
ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate11.ID,
ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})

require.Contains(t, results, analysis.CreatePostRelationshipJob{
FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate13.ID,
ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate13.ID,
ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})

require.Contains(t, results, analysis.CreatePostRelationshipJob{
FromID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
ToID: harness.EnrollOnBehalfOfHarnessOne.CertTemplate12.ID,
FromID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
ToID: harness.EnrollOnBehalfOfHarness1.CertTemplate12.ID,
Kind: ad.EnrollOnBehalfOf,
})

return nil
})

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates, harness.EnrollOnBehalfOfHarness1.Domain1)
require.Nil(t, err)

require.Len(t, results, 0)

return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.EnrollOnBehalfOfHarnessTwo.Setup(testContext)
harness.EnrollOnBehalfOfHarness2.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
certTemplates, err := ad2.FetchNodesByKind(context.Background(), db, ad.CertTemplate)
v1Templates := make([]*graph.Node, 0)
v2Templates := make([]*graph.Node, 0)

for _, template := range certTemplates {
if version, err := template.Properties.Get(ad.SchemaVersion.String()).Float64(); err != nil {
continue
} else if version == 1 {
continue
v1Templates = append(v1Templates, template)
} else if version >= 2 {
v2Templates = append(v2Templates, template)
}
Expand All @@ -512,15 +524,60 @@ func TestEnrollOnBehalfOf(t *testing.T) {
require.Nil(t, err)

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates)
results, err := ad2.EnrollOnBehalfOfVersionOne(tx, v1Templates, certTemplates, harness.EnrollOnBehalfOfHarness2.Domain2)
require.Nil(t, err)

require.Len(t, results, 0)
return nil
})

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
results, err := ad2.EnrollOnBehalfOfVersionTwo(tx, v2Templates, certTemplates, harness.EnrollOnBehalfOfHarness2.Domain2)
require.Nil(t, err)

require.Len(t, results, 1)
require.Contains(t, results, analysis.CreatePostRelationshipJob{
FromID: harness.EnrollOnBehalfOfHarnessTwo.CertTemplate21.ID,
ToID: harness.EnrollOnBehalfOfHarnessTwo.CertTemplate23.ID,
FromID: harness.EnrollOnBehalfOfHarness2.CertTemplate21.ID,
ToID: harness.EnrollOnBehalfOfHarness2.CertTemplate23.ID,
Kind: ad.EnrollOnBehalfOf,
})
return nil
})
})

testContext.DatabaseTestWithSetup(func(harness *integration.HarnessDetails) error {
harness.EnrollOnBehalfOfHarness3.Setup(testContext)
return nil
}, func(harness integration.HarnessDetails, db graph.Database) {
operation := analysis.NewPostRelationshipOperation(context.Background(), db, "ADCS Post Process Test - EnrollOnBehalfOf 3")

_, enterpriseCertAuthorities, certTemplates, domains, cache, err := FetchADCSPrereqs(db)
require.Nil(t, err)

if err := ad2.PostEnrollOnBehalfOf(domains, enterpriseCertAuthorities, certTemplates, cache, operation); err != nil {
t.Logf("failed post processing for %s: %v", ad.EnrollOnBehalfOf.String(), err)
}
err = operation.Done()
require.Nil(t, err)

db.ReadTransaction(context.Background(), func(tx graph.Transaction) error {
if startNodes, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.EnrollOnBehalfOf)
})); err != nil {
t.Fatalf("error fetching EnrollOnBehalfOf edges in integration test; %v", err)
} else if endNodes, err := ops.FetchStartNodes(tx.Relationships().Filterf(func() graph.Criteria {
return query.Kind(query.Relationship(), ad.EnrollOnBehalfOf)
})); err != nil {
t.Fatalf("error fetching EnrollOnBehalfOf edges in integration test; %v", err)
} else {
require.Len(t, startNodes, 2)
require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate11))
require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))

require.Len(t, endNodes, 2)
require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))
require.True(t, startNodes.Contains(harness.EnrollOnBehalfOfHarness3.CertTemplate12))
}

return nil
})
Expand Down
99 changes: 77 additions & 22 deletions cmd/api/src/test/integration/harnesses.go
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,7 @@ func (s *ADCSESC1HarnessAuthUsers) Setup(graphTestContext *GraphTestContext) {
graphTestContext.UpdateNode(s.AuthUsers)
}

type EnrollOnBehalfOfHarnessTwo struct {
type EnrollOnBehalfOfHarness2 struct {
Domain2 *graph.Node
AuthStore2 *graph.Node
RootCA2 *graph.Node
Expand All @@ -1604,10 +1604,9 @@ type EnrollOnBehalfOfHarnessTwo struct {
CertTemplate22 *graph.Node
CertTemplate23 *graph.Node
CertTemplate24 *graph.Node
CertTemplate25 *graph.Node
}

func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
func (s *EnrollOnBehalfOfHarness2) Setup(gt *GraphTestContext) {
certRequestAgentEKU := make([]string, 0)
certRequestAgentEKU = append(certRequestAgentEKU, adAnalysis.EkuCertRequestAgent)
emptyAppPolicies := make([]string, 0)
Expand All @@ -1623,7 +1622,7 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 1,
SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: certRequestAgentEKU,
ApplicationPolicies: emptyAppPolicies,
Expand All @@ -1635,7 +1634,7 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 1,
SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: []string{adAnalysis.EkuCertRequestAgent, adAnalysis.EkuAnyPurpose},
ApplicationPolicies: emptyAppPolicies,
Expand Down Expand Up @@ -1664,18 +1663,6 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
EffectiveEKUs: emptyAppPolicies,
ApplicationPolicies: emptyAppPolicies,
})
s.CertTemplate25 = gt.NewActiveDirectoryCertTemplate("certtemplate2-5", sid, CertTemplateData{
RequiresManagerApproval: false,
AuthenticationEnabled: false,
EnrolleeSuppliesSubject: false,
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 1,
AuthorizedSignatures: 1,
EffectiveEKUs: emptyAppPolicies,
ApplicationPolicies: emptyAppPolicies,
})

gt.NewRelationship(s.AuthStore2, s.Domain2, ad.NTAuthStoreFor)
gt.NewRelationship(s.RootCA2, s.Domain2, ad.RootCAFor)
Expand All @@ -1685,10 +1672,9 @@ func (s *EnrollOnBehalfOfHarnessTwo) Setup(gt *GraphTestContext) {
gt.NewRelationship(s.CertTemplate22, s.EnterpriseCA2, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate23, s.EnterpriseCA2, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate24, s.EnterpriseCA2, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate25, s.EnterpriseCA2, ad.PublishedTo)
}

type EnrollOnBehalfOfHarnessOne struct {
type EnrollOnBehalfOfHarness1 struct {
Domain1 *graph.Node
AuthStore1 *graph.Node
RootCA1 *graph.Node
Expand All @@ -1698,7 +1684,7 @@ type EnrollOnBehalfOfHarnessOne struct {
CertTemplate13 *graph.Node
}

func (s *EnrollOnBehalfOfHarnessOne) Setup(gt *GraphTestContext) {
func (s *EnrollOnBehalfOfHarness1) Setup(gt *GraphTestContext) {
sid := RandomDomainSID()
anyPurposeEkus := make([]string, 0)
anyPurposeEkus = append(anyPurposeEkus, adAnalysis.EkuAnyPurpose)
Expand Down Expand Up @@ -1753,6 +1739,74 @@ func (s *EnrollOnBehalfOfHarnessOne) Setup(gt *GraphTestContext) {
gt.NewRelationship(s.CertTemplate13, s.EnterpriseCA1, ad.PublishedTo)
}

type EnrollOnBehalfOfHarness3 struct {
Domain1 *graph.Node
AuthStore1 *graph.Node
RootCA1 *graph.Node
EnterpriseCA1 *graph.Node
EnterpriseCA2 *graph.Node
CertTemplate11 *graph.Node
CertTemplate12 *graph.Node
CertTemplate13 *graph.Node
}

func (s *EnrollOnBehalfOfHarness3) Setup(gt *GraphTestContext) {
sid := RandomDomainSID()
anyPurposeEkus := make([]string, 0)
anyPurposeEkus = append(anyPurposeEkus, adAnalysis.EkuAnyPurpose)
emptyAppPolicies := make([]string, 0)
s.Domain1 = gt.NewActiveDirectoryDomain("domain1", sid, false, true)
s.AuthStore1 = gt.NewActiveDirectoryNTAuthStore("authstore1", sid)
s.RootCA1 = gt.NewActiveDirectoryRootCA("rca1", sid)
s.EnterpriseCA1 = gt.NewActiveDirectoryEnterpriseCA("eca1", sid)
s.EnterpriseCA2 = gt.NewActiveDirectoryEnterpriseCA("eca2", sid)
s.CertTemplate11 = gt.NewActiveDirectoryCertTemplate("certtemplate1-1", sid, CertTemplateData{
RequiresManagerApproval: false,
AuthenticationEnabled: false,
EnrolleeSuppliesSubject: false,
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: anyPurposeEkus,
ApplicationPolicies: emptyAppPolicies,
})
s.CertTemplate12 = gt.NewActiveDirectoryCertTemplate("certtemplate1-2", sid, CertTemplateData{
RequiresManagerApproval: false,
AuthenticationEnabled: false,
EnrolleeSuppliesSubject: false,
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 1,
AuthorizedSignatures: 0,
EffectiveEKUs: anyPurposeEkus,
ApplicationPolicies: emptyAppPolicies,
})
s.CertTemplate13 = gt.NewActiveDirectoryCertTemplate("certtemplate1-3", sid, CertTemplateData{
RequiresManagerApproval: false,
AuthenticationEnabled: false,
EnrolleeSuppliesSubject: false,
SubjectAltRequireUPN: false,
SubjectAltRequireSPN: false,
NoSecurityExtension: false,
SchemaVersion: 2,
AuthorizedSignatures: 0,
EffectiveEKUs: anyPurposeEkus,
ApplicationPolicies: emptyAppPolicies,
})

gt.NewRelationship(s.AuthStore1, s.Domain1, ad.NTAuthStoreFor)
gt.NewRelationship(s.RootCA1, s.Domain1, ad.RootCAFor)
gt.NewRelationship(s.EnterpriseCA1, s.AuthStore1, ad.TrustedForNTAuth)
gt.NewRelationship(s.EnterpriseCA1, s.RootCA1, ad.EnterpriseCAFor)
gt.NewRelationship(s.EnterpriseCA2, s.RootCA1, ad.EnterpriseCAFor)
gt.NewRelationship(s.CertTemplate11, s.EnterpriseCA1, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate12, s.EnterpriseCA1, ad.PublishedTo)
gt.NewRelationship(s.CertTemplate13, s.EnterpriseCA2, ad.PublishedTo)
}

type ADCSGoldenCertHarness struct {
NTAuthStore1 *graph.Node
RootCA1 *graph.Node
Expand Down Expand Up @@ -8437,8 +8491,9 @@ type HarnessDetails struct {
ShortcutHarnessEveryone2 ShortcutHarnessEveryone2
ADCSESC1Harness ADCSESC1Harness
ADCSESC1HarnessAuthUsers ADCSESC1HarnessAuthUsers
EnrollOnBehalfOfHarnessOne EnrollOnBehalfOfHarnessOne
EnrollOnBehalfOfHarnessTwo EnrollOnBehalfOfHarnessTwo
EnrollOnBehalfOfHarness1 EnrollOnBehalfOfHarness1
EnrollOnBehalfOfHarness2 EnrollOnBehalfOfHarness2
EnrollOnBehalfOfHarness3 EnrollOnBehalfOfHarness3
ADCSGoldenCertHarness ADCSGoldenCertHarness
IssuedSignedByHarness IssuedSignedByHarness
EnterpriseCAForHarness EnterpriseCAForHarness
Expand Down
Loading
Loading