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

LDAP Property Processor Refactor and Testing #96

Conversation

definitelynotagoblin
Copy link
Collaborator

@definitelynotagoblin definitelynotagoblin commented Jan 17, 2024

Description

Refactoring LDAPPropertyProcessor to provide constraints and prepare for more granular testing.
Note that this expands upon the changes made for ESC6.

Motivation and Context

The goal is to prepare LDAP Property Processor for growth and continued development.

How Has This Been Tested?

Project unit tests insofar, with plans to expand testing.

Screenshots (if appropriate):

Types of changes

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • Documentation updates are needed, and have been made accordingly.
  • I have added and/or updated tests to cover my changes.
  • All new and existing tests passed.
  • My changes include a database migration.

@definitelynotagoblin definitelynotagoblin marked this pull request as draft January 17, 2024 16:16
@@ -393,6 +393,14 @@ public static Label GetLabel(this SearchResultEntry entry)
return objectType;
}

public static void AddRange<T, U>(this Dictionary<T, U> me, IEnumerable<KeyValuePair<T, U>> keyValuePairs)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I should rename to AddMany?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caveat: not a c# expert

I tend to agree that AddRange is a little unintuitive about what this function is doing. Some additional ideas off the top of my head:

  • AddEntries
  • Assign
  • AddToDict

That said, whatever you end up calling it, it's probably a good idea to document the API so folks can rely on their intellisense to figure out what it does.

@@ -148,45 +106,84 @@ public async Task<UserProperties> ReadUserProperties(ISearchResultEntry entry)
{
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the top-level ReadUserProperties and ReadComputerProperties methods especially I'm trying to pull a lot of the "how" out and make these methods more compositional.

@@ -589,6 +489,167 @@ public async Task<ComputerProperties> ReadComputerProperties(ISearchResultEntry

return props;
}

public static Dictionary<string, object> GetProperties(string ldapProperty, ISearchResultEntry entry)
{
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal here is single-truth LDAP property mapping. It provides a dictionary of sorts of our available properties (the "how", see above) and tries to enforce that properties get added to props through our "vetted" source.

/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static string GetPropertyName(string ldapProperty)
{
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not certain this will live here or that it should take this form as a method instead of a static class providing static properties, but this provides a glossary of LDAP properties and our own internal names for them.

props.Add(PropertyMap.GetUacPropertyName(UacFlags.TrustedForDelegation), allFlags[UacFlags.TrustedForDelegation]);
props.Add(PropertyMap.GetUacPropertyName(UacFlags.DontExpirePassword), allFlags[UacFlags.DontExpirePassword]);
// Note that we flip the flag for Account Disable ("enabled" by resolved name)
props.Add(PropertyMap.GetUacPropertyName(UacFlags.AccountDisable), !allFlags[UacFlags.AccountDisable]);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property breaks the mold and devalues the benefits of the new pattern a bit because it's an inverse of the LDAP property. I'm not super jazzed that this new pattern doesn't so gracefully address this so if you have any ideas or concerns here please let me know.

case LDAPProperties.ServicePrincipalNames:
var spn = entry.GetArrayProperty(LDAPProperties.ServicePrincipalNames);
props.Add(PropertyMap.GetPropertyName(ldapProperty), spn);
props.Add("hasspn", spn.Length > 0);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like creating a precedent here for wild-west property names (that aren't vetted through PropertyMap) from the get out of a refactor, but I have no better solutions for this many-to-one property map at the moment.
Because we're still vetting through our single-truth mapping method I'm inclined to let it slide, but I might be the only one.

props.AddRange(GetProperties(LDAPProperties.OperatingSystem, entry));

var sidHistory = ReadSidHistory(entry);
props.Add(PropertyMap.GetPropertyName(LDAPProperties.SIDHistory), sidHistory.History.ToArray());
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SidHistory breaks the new design a little because it provides dual functionality that can't be split without duplicating efforts (see ReadSidHistory below), and so we map the property value here instead of within GetProperties as the others. Not sure how I want to resolve this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned this up a bit.

@definitelynotagoblin definitelynotagoblin marked this pull request as ready for review January 18, 2024 23:04
@definitelynotagoblin definitelynotagoblin changed the title Draft: LDAP Property Processor Refactor LDAP Property Processor Refactor and Testing Jan 19, 2024

// [Fact]
// public void LDAPPropertyProcessor_ReadAllowedToActPrincipals_ReturnsPopulatedList()
// {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be a limitation of platform, need to test further, but failed to produce mocks for ActiveDirectorySecurityDescriptor for this test. Will remove before merging if this can't be resolved.

@github-actions github-actions bot locked and limited conversation to collaborators Sep 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants