Hello. In the previous lesson, you turned identity data into Boolean facts with comparisons, membership checks, and logical operators. For example, a script can now determine whether an account is enabled, whether a department is eligible, and whether a user already has a group.
This lesson turns those facts into controlled processing decisions. You will use if, elseif, and else to choose one appropriate path for an identity record, then use switch when one categorical value determines the path. The focus is deliberately on making a decision and recording it, not yet changing a directory account or group.
Conditional execution: only run the code that fits the condition
An if statement evaluates the condition inside parentheses. If that condition is $true, PowerShell runs the statement block inside braces.
if ($true) {
Write-Output "This block runs."
}
The braces are required in PowerShell, even if the block contains only one command.
A realistic access-processing decision begins with named facts. Consider this in-memory identity record:
$user = @{
UserPrincipalName = "jordan.lee@contoso.com"
AccountState = "Enabled"
Department = "Finance"
ManagerApproved = $true
Groups = @(
"Employees"
"MFA-Required"
)
}
Using the operators from the previous lesson, calculate facts before deciding what to do:
$eligibleDepartments = @(
"Finance"
"Accounting"
)
$isEnabled = $user["AccountState"] -eq "Enabled"
$isExplicitlyBlocked =
$user["AccountState"] -in @(
"Disabled"
"Suspended"
"Terminated"
)
$isEligibleDepartment =
$user["Department"] -in $eligibleDepartments
$hasManagerApproval =
$user["ManagerApproved"] -eq $true
$alreadyInFinanceGroup =
"Finance-Analyst" -in $user["Groups"]
Notice the separation of concerns:
- The first set of statements evaluates the record.
- A conditional statement chooses a processing decision.
- A later script, after further safety checks, could perform a state-changing action.
That separation makes IAM logic easier to review. An auditor or teammate can examine whether the decision rule is right without having to untangle it from a command that changes group membership.
PowerShell 7 Tutorials for Beginners #6 : If, ElseIf, Else (Conditional Statements)
Watch “PowerShell 7 Tutorials for Beginners #6: If, ElseIf, Else (Conditional Statements)” from JackedProgrammer for a visual walkthrough of the basic branching syntax. The file example is different from IAM processing, but the control-flow behavior is the same.
Start with basic if to see the condition, parentheses, and braces in action. Then watch if and else, focusing on how else handles the false case without attempting the command that would fail. Finish with elseif order; pay attention to the fact that PowerShell evaluates branches from top to bottom and executes only the first matching branch.
if, elseif, and else: a prioritized decision policy
An if statement is useful for a single yes-or-no gate:
if ($isEnabled) {
Write-Output "The account may proceed to later checks."
}
But IAM decisions commonly have several possible outcomes. Use an if/elseif/else chain when:
- the conditions test different facts;
- the order represents a policy priority;
- exactly one outcome should be selected.
The general structure is:
if (first-condition) {
# Highest-priority path
}
elseif (second-condition) {
# Used only when the first condition was false
}
else {
# Fallback when every earlier condition was false
}
elseif is written as one word. Once one branch evaluates to $true and runs, PowerShell skips the rest of that chain.
Build a conservative access decision
Suppose the policy for the Finance-Analyst group is:
- Required data must be present.
- Disabled, suspended, and terminated accounts must not be provisioned.
- Accounts in unknown states require review.
- Only eligible departments may receive this access.
- Manager approval is required.
- An existing membership needs no change.
- Only then is the account eligible for later provisioning.
Here is a decision block implementing that policy:
$missingRequiredData = (
($null -eq $user["AccountState"]) -or
($null -eq $user["Department"]) -or
($null -eq $user["ManagerApproved"]) -or
($null -eq $user["Groups"])
)
if ($missingRequiredData) {
$decision = "ManualReview"
$reason = "Required identity attributes are missing."
}
elseif ($isExplicitlyBlocked) {
$decision = "DoNotProvision"
$reason = "The account is disabled, suspended, or terminated."
}
elseif (-not $isEnabled) {
$decision = "ManualReview"
$reason = "The account state is not recognized as enabled."
}
elseif (-not $isEligibleDepartment) {
$decision = "ManualReview"
$reason = "Department is not eligible for Finance-Analyst access."
}
elseif (-not $hasManagerApproval) {
$decision = "ManualReview"
$reason = "Required manager approval is absent."
}
elseif ($alreadyInFinanceGroup) {
$decision = "NoChange"
$reason = "The user is already a member of Finance-Analyst."
}
else {
$decision = "EligibleForProvisioning"
$reason = "All baseline eligibility checks passed."
}
The values in this example are policy-specific. A real organization may have HR eligibility data, a ticket approval ID, separation-of-duties rules, or different lifecycle states. The programming principle stays the same: make the priority order explicit and select a safe outcome.
You can then emit a structured result for logging, review, or later pipeline processing:
$result = @{
UserPrincipalName = $user["UserPrincipalName"]
Decision = $decision
Reason = $reason
}
$result
$result is still a live hash table object. PowerShell may display it as text in the console, but the value flowing through a pipeline remains structured data rather than a directory change.
Why branch order matters
In an elseif chain, conditions are not merely a list. They are a priority order.
| Record state | First applicable branch | Result |
|---|---|---|
ManagerApproved is missing and account is disabled | $missingRequiredData | ManualReview |
Account is Suspended, even with approval | $isExplicitlyBlocked | DoNotProvision |
Account is Pending rather than Enabled | -not $isEnabled | ManualReview |
| Enabled Sales employee with approval | -not $isEligibleDepartment | ManualReview |
| Enabled Finance employee already in the target group | $alreadyInFinanceGroup | NoChange |
| Enabled, approved Finance employee without the group | else | EligibleForProvisioning |
Putting data validation first prevents a malformed record from being silently classified as a normal access request. Placing an explicit block before eligibility checks prevents an account in a blocked state from being treated as provisionable merely because other attributes look correct.
A common error is to write several independent if statements:
if ($isEnabled) {
$decision = "EligibleForProvisioning"
}
if ($alreadyInFinanceGroup) {
$decision = "NoChange"
}
Both blocks can run. That may be intentional for independent reporting, but it is usually wrong for a single access decision. An if/elseif/else chain makes the “one record, one decision” intent visible.
Another unsafe pattern is an else branch that automatically grants access:
# Avoid this pattern
else {
Add-GroupMember -Group "Finance-Analyst" -Member $user["UserPrincipalName"]
}
An else means only that prior conditions were false. It does not independently prove that the request is authorized. In this lesson, the else is safe because the preceding branches deliberately cover missing data, blocked accounts, unknown states, eligibility, approval, and existing membership.
When switch expresses the policy more clearly
Use switch when one expression, usually one categorical field, determines the processing path. Lifecycle event type is a natural IAM example:
$eventType = "Mover"
An if chain would work:
if ($eventType -eq "Joiner") {
$queue = "ProvisioningQueue"
}
elseif ($eventType -eq "Mover") {
$queue = "AccessRecalculationQueue"
}
elseif ($eventType -eq "Leaver") {
$queue = "DeprovisioningQueue"
}
else {
$queue = "ManualReviewQueue"
}
But this is a set of comparisons against the same value. switch makes that structure more direct:
$queue = switch ($eventType) {
"Joiner" {
"ProvisioningQueue"
break
}
"Mover" {
"AccessRecalculationQueue"
break
}
"Leaver" {
"DeprovisioningQueue"
break
}
default {
"ManualReviewQueue"
break
}
}
The switch expression is $eventType. Each quoted value is a case to compare against it. The default block plays the same role as else: it handles an event that did not match any listed case.
The strings emitted by the matching block become the value assigned to $queue. No external operation has happened; the script has simply routed the record to an appropriate next stage.
Why use break in a PowerShell switch?
A crucial PowerShell detail is that switch can execute every matching case. This matters when you accidentally repeat a case, use wildcards, use regular expressions, or write condition script blocks that overlap.
For access-processing decisions, one event should normally produce one route. Put break at the end of each case to exit the switch after the intended match.
PowerShell 7 Tutorials for Beginners #7 : Switch (Conditional Statements)
Watch “PowerShell 7 Tutorials for Beginners #7: Switch (Conditional Statements)” from JackedProgrammer to see an if/elseif chain translated into a switch and to observe the effect of omitting break.
Watch basic switch for the syntax of matching values and using default. Then view why break matters. Continue with condition cases and multiple matches; focus on $_, which represents the current value being tested, and on why overlapping cases can produce more than one result without break.
Choose the right construct
| Situation | Prefer | Reason |
|---|---|---|
| Decide whether all required access conditions hold | if | The decision combines several Boolean facts. |
| Handle several prioritized outcomes from different conditions | if / elseif / else | The order is part of the policy. |
Route a record based on one known category, such as Joiner, Mover, or Leaver | switch | The code reads as a map from category to handling path. |
| Compare risk-score thresholds or multiple attributes | if / elseif | Numerical ranges and mixed conditions are generally clearer. |
By default, PowerShell switch comparisons are case-insensitive, and PowerShell converts values to strings for its basic matching behavior. That is another reason to use simple categorical strings, such as lifecycle event names, for basic switch statements. For typed numeric conditions, such as “risk score greater than or equal to 80,” an if statement is usually more explicit.
Keep conditional code reviewable
As IAM automation grows, conditional logic can become a source of hidden risk. A few habits keep it understandable:
- Name facts before branching. Prefer
$hasManagerApprovalto a long repeated expression inside several branches. - Validate before deciding. Missing values should usually be reviewed rather than treated as ordinary eligibility failures.
- Put hard stops early. Disabled or terminated accounts should not reach provisioning logic.
- Use a meaningful fallback.
ManualReviewis often safer than an implicit grant for unknown states or events. - Record both the decision and the reason. A label such as
NoChangeis useful; an explanation is better for debugging and audit evidence. - Keep action separate from classification. A later step can apply an approved decision, with safeguards such as dry-run support and postcondition checks.
Avoid using = inside a condition. It assigns a value rather than comparing one:
# Wrong: assignment, not comparison
if ($user["AccountState"] = "Enabled") {
# ...
}
Use -eq for the comparison:
if ($user["AccountState"] -eq "Enabled") {
# ...
}
Key takeaways
ifruns its brace-delimited block only when its condition is true.elseifadds prioritized alternatives; PowerShell runs the first matching branch and skips the rest of that chain.elseis a fallback, not proof that access should be granted. Use a conservative outcome for unexpected conditions.- Build named Boolean facts first, then use them in a readable decision policy.
- Use
switchwhen one categorical value determines the handling path. - In PowerShell, use
breakin aswitchwhen one matching case should determine one outcome. - Conditional logic should classify and document an identity record before a later script performs a state-changing action.
Next, you will apply these decision patterns to multiple identity records using foreach loops and pipeline-based enumeration.
Can't find a good explanation? Sign up and we'll make it for you
Sign up