I'm building a PowerShell script that assigns new Active Directory users to groups based on attributes such as location, department, and job title. At the moment, each attribute value maps to an array of groups—for example, a department might map to its shared folder and distribution groups. The script reads a user's attributes from AD, checks the mappings, and adds the user to the matching groups.
That approach works for simple cases, but I also need to support combinations of attributes. For example, managers at a particular location may need access to a restricted resource specific to that office. The organization has more than 60 locations, with several departments and roles at each one, so hard-coding every combination in large if/else or switch statements seems difficult to maintain.
I considered using nested hashtables or keys made by concatenating attributes, but that feels fragile. I'm wondering whether the rules should be stored outside the script in JSON, CSV, or another structured format, with the PowerShell code acting as a generic rule parser. How would you model these combinations and keep the solution readable and maintainable at this scale?
4 Answers
The important distinction is between a role and the conditions that grant the role. Don’t make a separate table for every permutation if you can express a rule as a set of predicates. Store each rule as an object with conditions such as location, department, and title, plus the groups to assign when all supplied conditions match.
For example, one rule could match `Location = Chicago` and `Title = Manager`, while another matches only `Department = Finance`. A generic evaluator can treat omitted conditions as wildcards. This scales much better than concatenating attribute values into keys and makes exceptions explicit.
Whichever format you choose, include validation, logging, a preview or `-WhatIf` mode, and a way to remove groups that a user no longer qualifies for. Also be careful with broad access groups: group nesting and a clear naming convention can reduce the number of rules you need.
A practical design is to define roles separately from the script. Each role can contain the groups it grants, while a rule determines when a user qualifies for that role. The configuration might conceptually look like this:
`Roles: { Developer: [GG-Developers, GG-GitHub-Users], Manager: [GG-Managers], LocationManager: [GG-Office-Restricted] }`
Then define eligibility using fields such as `Department`, `Location`, and `Title`, for example: `Title = Manager AND Location = New York`. The script loads the JSON with `ConvertFrom-Json`, evaluates every rule against the user, combines the groups from all matching roles, removes duplicates, and applies the result.
This lets administrators update role membership and group mappings without changing the provisioning logic. It also makes it easier to test the rules and review configuration changes.
If your organization has an identity governance or role-management platform, this is a good use case for it. Define roles and eligibility rules there rather than maintaining a custom provisioning script. In environments using Entra ID, dynamic group membership can also handle attribute-based rules.
If you need to stay with PowerShell, use consistent group naming and generate the expected group name from the relevant attributes, then look it up. For example, a location-and-title group could follow a pattern such as `NewYorkCity-AssociateTechnician`. That avoids writing a separate branch for every possible combination, although it depends on being able to enforce reliable naming conventions.
For more complicated logic, represent the rules as structured data—JSON or CSV are both reasonable—and write the script to evaluate those rules. Keep the data separate from the code instead of embedding hundreds of group names in nested tables.
JSON is useful when the configuration has nested objects and several conditions; CSV is often easier for non-developers to edit. Either way, keep the file under change control and validate that every referenced group exists before making changes. The script should calculate the complete desired group set first, show the differences, and only then add or remove memberships. That prevents partial updates from leaving accounts in an unexpected state.

Related Questions
Can't Load PhpMyadmin On After Server Update
Redirect www to non-www in Apache Conf
How To Check If Your SSL Cert Is SHA 1
Windows TrackPad Gestures