Tag: PowerShell

  • How to Install Sysmon on Windows 11 (Step-by-Step Guide)

    System Monitoring Made Simple for IT Admins & Security Pros

    Sysmon (System Monitor) is part of Microsoft’s Sysinternals Suite, and it gives you deep visibility into process creation, network connections, file changes, and system activity. For threat detection, forensics, and baselining, Sysmon is one of the most powerful free tools you can deploy.

    In this guide, I’ll walk through the step-by-step process of installing Sysmon cleanly on a Windows 11 machine, loading a hardened configuration, enabling the event log, and validating that everything is working.

    This is the exact method I used on my laptop — clean, repeatable, and production-ready.


    1. Prerequisites

    Before you start:

    • Log in as a user with Local Administrator rights.
    • Open PowerShell as Administrator.

    You’ll be using a mixture of PowerShell commands and Event Viewer, so make sure you have admin elevation.


    2. Download Sysinternals Suite

    Microsoft distributes Sysmon inside the Sysinternals Suite ZIP.

    1. Download Sysinternals Suite from Microsoft’s official site.
    2. Create a clean directory:
    New-Item -ItemType Directory -Path "C:\Sysinternals" -Force
    
    1. Extract the ZIP:
    Expand-Archive "$env:USERPROFILE\Downloads\SysinternalsSuite.zip" `
      -DestinationPath "C:\Sysinternals" -Force
    
    1. Verify Sysmon64.exe exists:
    Get-ChildItem "C:\Sysinternals" -Filter Sysmon64.exe -Recurse
    

    You should see something similar to:

    Sysmon64.exe   Length: 4563248
    

    If the file is non-zero in size, it’s valid.


    3. Prepare Your Sysmon Configuration File

    Sysmon must be installed with a configuration that tells it what to monitor.
    You can use:

    • A basic config
    • A hardened config
    • The community-recommended SwiftOnSecurity config

    Here’s how to set up a config folder:

    New-Item -ItemType Directory -Path "C:\Scripts\Sysmon" -Force
    

    Copy your Sysmon config into it:

    Copy-Item "$env:USERPROFILE\Downloads\sysmonconfig-export.xml" `
      "C:\Scripts\Sysmon\sysmonconfig.xml" -Force
    

    Verify it:

    Get-ChildItem "C:\Scripts\Sysmon"
    

    You should see:

    sysmonconfig.xml   Length: (non-zero)
    

    4. Install Sysmon with the Config

    Navigate to the Sysinternals directory:

    cd "C:\Sysinternals"
    

    If Sysmon was previously installed, uninstall it first:

    .\Sysmon64.exe -u force
    

    Then install it cleanly with your XML config:

    .\Sysmon64.exe -i C:\Scripts\Sysmon\sysmonconfig.xml
    

    Expected output:

    Sysmon64 installed.
    SysmonDrv installed.
    Sysmon64 started.
    

    Check service status:

    Get-Service Sysmon64
    

    You should see:

    Running  Sysmon64
    

    5. Register the Sysmon Event Manifest

    This step ensures the Sysmon event log is visible in Event Viewer.

    .\Sysmon64.exe -m
    

    Output:

    Event manifest/format registered successfully
    

    6. Enable the Sysmon Event Log

    Check if the Sysmon log exists:

    wevtutil el | Select-String "Sysmon"
    

    You should see:

    Microsoft-Windows-Sysmon/Operational
    

    Enable the log:

    wevtutil sl "Microsoft-Windows-Sysmon/Operational" /e:true
    

    7. Validate That Sysmon Is Working

    Method A: Quick PowerShell validation

    wevtutil qe Microsoft-Windows-Sysmon/Operational /c:5 /f:text
    

    If you see any events (Event ID 1, 5, etc.), Sysmon is working.


    Method B: Event Viewer

    Open Event Viewer:

    Applications and Services Logs
      → Microsoft
          → Windows
              → Sysmon
                  → Operational
    

    You should start seeing:

    • Event ID 1 – Process Create
    • Event ID 5 – Process Terminate
    • Other IDs depending on your config

    Method C: Live test

    Run:

    Start-Process notepad.exe
    

    Then refresh Sysmon → Operational log.

    You should immediately see a new Event ID 1 logging Notepad’s process creation.

    If you see this event, Sysmon is fully operational.


    8. Optional: Create a Shortcut for Faster Access

    Desktop Shortcut

    1. Right-click Desktop → New → Shortcut
    2. Enter:
    eventvwr.msc /c:Microsoft-Windows-Sysmon/Operational
    
    1. Name it Sysmon Log

    Now you can open Sysmon in one click.

    Event Viewer Favorites

    Right-click Sysmon → OperationalAdd to Favorites.


    9. Updating the Sysmon Config Later

    If you want to modify or replace the config:

    cd C:\Sysinternals
    .\Sysmon64.exe -c C:\Scripts\Sysmon\sysmonconfig.xml
    

    You should see:

    Configuration updated.
    

    No reinstall required.


    10. Uninstall Sysmon (if needed)

    cd C:\Sysinternals
    .\Sysmon64.exe -u force
    

    This removes:

    • Sysmon64 service
    • SysmonDrv driver
    • Registry entries
    • Event manifest

    Conclusion

    Once installed, Sysmon becomes a powerful source of system telemetry for:

    • Threat hunting
    • Malware investigation
    • Lateral movement detection
    • Process monitoring
    • Incident response
    • Forensic analysis

    With a hardened config, Sysmon gives deep visibility with minimal overhead — making it an essential component of any Windows security stack.

    If you’re deploying Sysmon across multiple endpoints (like we do at work), you can automate it using Intune, GPO, or a custom PowerShell deployment package.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Advanced Exchange Online Security and Compliance: The Tools I Use Daily

    Whether it’s PowerShell, VMware, or supporting the team, I give my best because people depend on what happens behind this screen.

    Introduction

    Email is still the heart of business communication, and it’s also the easiest door for attackers to exploit.
    This is my real-world approach to securing Exchange Online: how I protect messages, enforce policies, retain critical data, and keep unwanted activity out of the environment.
    These are the tools I use every day — quiet, behind-the-scenes work that keeps an entire organization safe.


    Messaging Policies and Mail Protection

    What

    Mail flow rules control how messages enter, exit, and move inside the company.
    They prevent risky behavior, secure sensitive data, and keep communication structured.

    Why

    Without strict policies, users can accidentally leak information, forward confidential data, or bypass compliance rules.

    How

    Mail Flow Rules I Maintain

    • Prevent auto-forwarding outside the company
    • Block forwarding to personal Gmail/Yahoo
    • Restrict sensitive keywords (finance, HR, payroll)
    • Add disclaimers for external recipients
    • Enforce rules for shared mailboxes

    PowerShell Example: Show All Transport Rules

    Get-TransportRule | Select Name,State,Mode,Priority
    

    Email Aliases and Address Management

    What

    Aliases provide alternative addresses for departments, teams, or special functions.

    Why

    They simplify communication, eliminate confusion, and keep primary mailboxes private.

    How

    Add an Alias

    Set-Mailbox [email protected] -EmailAddresses @{add="[email protected]"}
    

    Litigation Hold and Retention

    What

    • Litigation Hold preserves every message
    • Retention Policies define how long data must be kept

    Why

    Legal protection.
    Compliance protection.
    And proof that no one destroyed company data intentionally.

    How

    Enable Litigation Hold

    Set-Mailbox [email protected] -LitigationHoldEnabled $true
    

    Check Hold Status

    Get-Mailbox [email protected] | Select LitigationHoldEnabled, LitigationHoldDate
    

    Retention Policies and Labels

    What

    Rules that manage email lifecycle:

    • Keep 7 years (HR, finance)
    • Keep indefinitely (executives)
    • Auto-archive after X years
    • Delete only when compliance approves

    Why

    Retention prevents chaos — too long, too short, or inconsistent retention creates legal risk.

    How

    View Retention Policies

    Get-RetentionPolicy | Select Name,RetentionId,IsDefault
    

    Message Tracing and Investigation

    What

    Tracking the path of an email from sender → filters → inbox.

    Why

    It solves:

    • Missing email
    • Routing delays
    • Spam filtering
    • Proof of delivery
    • Auto-forwarding issues

    How

    Short Trace (Last 2 Hours)

    Get-MessageTrace -RecipientAddress [email protected] -StartDate (Get-Date).AddHours(-2)
    

    Deep Trace

    Get-MessageTraceDetail -MessageTraceId <ID> -RecipientAddress [email protected]
    

    Anti-Phishing, Anti-Spam, and Safe Attachments

    What

    Policies that stop impersonation, malware, spoofing, and fraudulent links.

    Why

    Threat actors evolve daily.
    These policies must evolve with them.

    How

    What I Review

    • Spoof intelligence
    • Impersonation protection
    • Junk thresholds
    • Block/allow lists
    • Safe Links
    • Safe Attachments

    PowerShell Example

    Get-HostedContentFilterPolicy | Select Name,SpamAction,HighConfidenceSpamAction
    

    Hybrid Filtering (Proofpoint + M365)

    What

    When an organization uses Proofpoint externally and M365 internally.

    Why

    Most mail incidents happen between systems — misconfigured connectors are the #1 cause of undelivered mail.

    How

    I Manage

    • Routing tables
    • Inbound connectors
    • Outbound smart hosts
    • Quarantine overrides
    • Digest troubleshooting


    Shared Mailboxes: Tracking Activity

    What

    Audit visibility for shared mailboxes (support, sales, finance).

    Why

    Shared mailboxes often handle sensitive workflows — tracking who sent what is critical.

    How

    Who Sent Mail from Shared Mailbox

    Search-UnifiedAuditLog -StartDate (Get-Date).AddDays(-1) -Operations SendOnBehalf -UserIds [email protected]
    

    Auditing & Monitoring

    What

    My daily and weekly checks for unusual activity.

    Why

    Small changes snowball into major breaches.

    How

    Recent Permission Changes

    Search-UnifiedAuditLog -StartDate (Get-Date).AddHours(-12) -Operations Add-MailboxPermission
    

    Mailbox Size Issues & Quota Management

    What

    Mailbox storage thresholds.

    Why

    When users hit quota, they immediately lose the ability to send.

    How

    Check Size

    Get-ExoMailboxStatistics [email protected] | Select TotalItemSize,ItemCount
    

    Raise Quota

    Set-Mailbox [email protected] -ProhibitSendQuota 95GB
    

    Mailbox Delegation & Access Reviews

    What

    Review who has access to sensitive mailboxes.

    Why

    Too much access = high security risk.

    How

    Check Permissions

    Get-ExoMailboxPermission [email protected] | Where-Object { $_.User -notlike "NT AUTHORITY\SELF" }
    

    Data Loss Prevention (DLP)

    What

    Policies that prevent sensitive data (PII, financial info, SSNs, HR documents) from leaving the organization.

    Why

    Most leaks are accidental, not malicious.
    DLP prevents mistakes from becoming legal disasters.

    How

    View DLP Policies

    Get-DlpCompliancePolicy | Select Name,Mode,State
    

    Typical Rules I Maintain

    • Block sending payroll files
    • Detect credit card patterns
    • Restrict SSN transmission
    • Alert IT on violations


    Email Routing Security

    What

    Routing = the path an email takes from external → internal → outbound.

    Why

    Bad routing = lost email, spoofing risks, failed DKIM/SPF/DMARC, compromised forwarders.

    Attackers LOVE manipulating routing.

    How

    Key Areas I Maintain

    • MX records
    • SPF allow lists
    • Smart host routing
    • TLS enforcement
    • Inbound/outbound connectors
    • No open relay
    • Block unauthorized forwarding

    PowerShell: View Connectors

    Get-InboundConnector | Select Name,Enabled,SenderDomains
    Get-OutboundConnector | Select Name,Enabled,SmartHosts
    

    Conclusion

    This is my Exchange Online security toolkit — the messaging controls, retention systems, compliance protections, and routing safeguards I use every day.
    These tools protect users, leadership, legal teams, and the entire organization from silent risks that hide inside email traffic.

    Real security isn’t loud.
    It’s consistent, careful, and invisible — until the moment it saves the business.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Terraform for M365 & Azure (With Real Examples)

    Title:

    Terraform for M365 and Azure — Infrastructure-as-Code Made Simple

    Introduction

    Terraform is one of the most powerful tools for managing cloud environments because it lets you declare what you want and Azure builds it. No guessing. No clicking. No forgetting what you changed.

    Even if M365 doesn’t support Terraform natively for all workloads, you can still automate Azure AD, Conditional Access, Groups, SPNs, Networking, Key Vault, and App Registrations through the Microsoft Graph provider.

    I used IaC principles while supporting Church systems — Terraform makes environments repeatable, auditable, and consistent.


    1. Installing Terraform

    choco install terraform
    

    2. Azure Login Block

    provider "azurerm" {
      features {}
    }
    
    provider "azuread" {
    }
    

    3. Creating an Azure Resource Group

    resource "azurerm_resource_group" "rg1" {
      name     = "M365AutomationRG"
      location = "WestUS2"
    }
    

    4. Creating an Azure AD Group

    resource "azuread_group" "security_group" {
      display_name     = "M365-Automation-Admins"
      security_enabled = true
    }
    

    5. Creating an App Registration + Secret

    resource "azuread_application" "app" {
      display_name = "Terraform-Automation-App"
    }
    
    resource "azuread_service_principal" "sp" {
      application_id = azuread_application.app.application_id
    }
    
    resource "azuread_application_password" "sp_secret" {
      application_object_id = azuread_application.app.id
      display_name          = "secret1"
    }
    

    6. Conditional Access via Terraform (Yes, possible!)

    Uses the Microsoft Graph Terraform provider.

    resource "msgraph_conditional_access_policy" "block_non_us" {
      display_name = "Block Non-US IP"
      state        = "enabled"
    
      conditions {
        users {
          include_users = ["all"]
        }
        locations {
          include_locations = ["All"]
          exclude_locations = ["US"]
        }
      }
    
      grant_controls {
        operator         = "OR"
        built_in_controls = ["block"]
      }
    }
    

    7. Create an M365 Group (Unified Group)

    resource "msgraph_group" "m365_group" {
      display_name     = "Engineering Team"
      mail_nickname    = "engineering"
      security_enabled = false
      mail_enabled     = true
      group_type       = ["Unified"]
    }
    

    8. Create Azure Key Vault

    resource "azurerm_key_vault" "kv" {
      name                = "m365-keyvault-prod"
      location            = azurerm_resource_group.rg1.location
      resource_group_name = azurerm_resource_group.rg1.name
      tenant_id           = data.azuread_client_config.current.tenant_id
      sku_name            = "standard"
    }
    

    Conclusion

    Terraform is the “blueprint” of modern cloud administration.
    Clicking creates inconsistencies — IaC creates reliable, repeatable deployments.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • The Evolution of Microsoft Exchange: From 5.0 to Exchange Online (EXO)

    A Technical History Through the Tools, Upgrades, and Real-World Administration That Shaped Modern Email


    Email administration today looks nothing like it did in the mid-1990s. What began as a system of flat files and small IS databases has evolved into a globally distributed, cloud-secure service powered by modern authentication, forensic automation, and layered identity protections.

    This article covers the full evolution — from Exchange 5.0 → 5.5 → 2000 → 2003 → 2007 → 2010 → 2013 → 2016 → Hybrid → Exchange Online — through the practical tools and real operational practices that defined each era.

    It also highlights legacy repair tools (ISINTEG, ESEUTIL), the emergence of PowerShell, and modern security controls such as DKIM, DMARC, and real-time EXO policies.


    1. Exchange 5.0 — The GroupWise Era & The Limits of Early Messaging

    When Exchange 5.0 existed, Novell GroupWise was still considered the enterprise email standard. Capacity was limited and reliability required constant hands-on administration.

    Key Characteristics

    • Basic directory service
    • Small private and public folder stores
    • No Active Directory yet
    • No PowerShell
    • 16GB database ceiling
    • Frequent corruptions under heavy load

    Real Tools Used

    🔧 ISINTEG — Logical Database Repair

    Example usage:

    ISINTEG -pri -fix -test alltests
    

    🔧 ESEUTIL — Physical Database Repair

    Soft recovery:

    ESEUTIL /r E00 /l "E:\logs" /d "E:\mdbdata"
    

    Hard recovery:

    ESEUTIL /p "E:\mdbdata\priv.edb"
    

    Defrag/whitespace removal:

    ESEUTIL /d "E:\mdbdata\priv.edb"
    

    White space mattered because the database could never exceed the size limit, and defrags were essential to survive weekly growth.


    2. Exchange 5.5 — The First True Enterprise Version

    Exchange 5.5 replaced GroupWise in many organizations because it solved the two biggest weaknesses:

    Major Improvements

    • Larger database limits
    • Internet Mail Connector (IMC) matured
    • Directory replication across sites
    • Better MAPI stability
    • More predictable backups

    This was the version where large organizations first began to trust Exchange for hundreds or thousands of users.

    Database limitations still required:

    • Regular whitespace removal
    • Offline defrags
    • ISINTEG repairs

    3. Exchange 2000 / 2003 — Active Directory Arrives

    The introduction of Active Directory changed everything.

    Now Possible

    • Kerberos authentication
    • Unified Global Address List
    • Recipient policies
    • Improved SMTP stack
    • Better routing groups

    Tools of the Era

    • ESEUTIL still required
    • ISINTEG for logical repair
    • Streaming file (.STM) management
    • COM+ based transport pipeline

    Disaster recovery still required:

    • Hard repairs
    • Log replays
    • Offline maintenance windows

    4. Exchange 2007 — PowerShell Revolutionizes Email Administration

    Exchange 2007 was the turning point. This version introduced:

    Major Innovations

    • PowerShell (EMS)
    • Role-based server architecture
    • Database Availability Groups (DAGs begin later)
    • Transport rules
    • Modern SMTP pipeline

    Example PowerShell Operations

    Bulk mailbox creation

    Import-Csv users.csv | % {
      New-Mailbox -UserPrincipalName $_.UPN -Name $_.Name -Alias $_.Alias
    }
    

    Transport rule creation

    New-TransportRule -Name "Block EXE" -AttachmentExtensionMatchesWords ".exe" -RejectMessageReason "Executable blocked"
    

    Database health

    Get-MailboxDatabaseCopyStatus *
    

    PowerShell replaced ISINTEG as the primary troubleshooting interface.


    5. Exchange 2010 / 2013 — High Availability & Hybrid Era

    These versions supported:

    • DAGs with multiple copies
    • Outlook Anywhere (RPC over HTTPS)
    • Cross-forest migrations
    • Massive mailboxes (50GB+)
    • First large-scale hybrid deployments

    Database Whitespace Management

    Modern approach:

    Get-MailboxDatabase -Status | ft Name,AvailableNewMailboxSpace
    

    To reclaim all space:

    1. Create new database
    2. Move mailboxes
    3. Remove old database
    4. Mount clean database

    Multi-region examples

    • Databases per region (NA/APAC/EMEA)
    • Public folder migrations
    • CAS/Hub/MBX role separation

    6. On-Prem to Cloud Migrations — AWS WorkMail, Exchange 2010, Hybrid, EXO

    Organizations with large global footprints began migrating:

    Migration Examples

    • From AWS WorkMail → Exchange 2013 HA → EXO
    • From Exchange 2010 datacenters → Hybrid → EXO
    • From Exchange 2013 → EXO using HCW and staged cutover

    Challenges Solved by EXO

    • No more ESEUTIL
    • No more ISINTEG
    • No more DAG patching
    • No more weekend downtimes
    • Automatic redundancy
    • Modern authentication
    • Better malware scanning

    7. Exchange Online — The Modern Cloud Era

    Today, administrators rely on:

    • Exchange Online PowerShell v3
    • Graph API
    • Defender for O365
    • Purview eDiscovery
    • Modern connectors
    • DKIM / DMARC enforcement
    • Real-time spam intelligence
    • Modern auth for SMTP

    How to Rotate DKIM 2048-bit Keys

    Admin Center → Security → Email Authentication → DKIM → Rotate Keys

    Verify in PowerShell

    Get-DkimSigningConfig | fl Domain,Selector1CNAME,Selector2CNAME
    

    Keys should be:

    • 2048-bit
    • Rotated regularly
    • Protected from unauthorized access

    **8. Real-World Security Hardening in EXO

    (Including the Kill-Switch Scripts)**

    Last-generation threats require immediate defensive controls.
    These are sanitized versions of the two emergency scripts used to block impersonation attacks:


    🛑 Kill Switch Transport Rule (Blocks All External Sender Impersonation)

    New-TransportRule -Name "KILL-SWITCH" `
    -FromScope NotInOrganization `
    -SentToScope InOrganization `
    -SetHeaderName "X-Blocked" `
    -SetHeaderValue "EmergencyBlock" `
    -StopRuleProcessing $true `
    -Enabled $true `
    -Mode Enforce
    

    🛑 Block-All Impersonation Rule

    New-TransportRule -Name "BLOCK-IMPERSONATION" `
    -HeaderMatchesMessageHeader "From" `
    -HeaderMatchesPatterns ".*@yourdomain\.com" `
    -SentToScope InOrganization `
    -FromScope NotInOrganization `
    -RejectMessageReasonText "External sender attempted domain impersonation" `
    -StopRuleProcessing $true
    

    After the event is over, disable:

    Disable-TransportRule "KILL-SWITCH"
    Disable-TransportRule "BLOCK-IMPERSONATION"
    

    9. Why Exchange Online Beats Every On-Prem Version

    No More:

    • Database corruption
    • ESEUTIL repair weekends
    • ISINTEG logical rebuilds
    • Streaming file failures
    • Whitespace management
    • RPC failures
    • CAS array dependency

    Instead You Get:

    • Multi-region HA
    • Continuous patching
    • DKIM / DMARC alignment
    • Modern authentication
    • Real-time message trace
    • Defender Safe Links/Safe Attachments
    • Purview forensic tools
    • 24/7 cloud threat intelligence

    10. Summary

    This blog ties together:

    • The original on-prem tools (ISINTEG, ESEUTIL)
    • The arrival of AD
    • The PowerShell revolution
    • The hybrid era
    • The modern cloud security stack
    • DKIM rotation
    • EXO forensic investigation
    • Emergency transport rule defense

    It shows why the move from Exchange 5.0 to EXO was inevitable — every stage improved reliability, scalability, administration, and security.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Why PowerShell Still Beats Purview for Real Forensics: Speed, Depth, and No UI Limits

    Introduction

    Microsoft Purview is Microsoft’s compliance, audit, and eDiscovery platform for Microsoft 365. It provides GUI-driven tools for administrators to perform searches, create holds, review data, and respond to legal and compliance requirements.

    But here’s the reality that senior M365 engineers know:

    Purview is powerful, but it is not complete.
    It has strict limits, throttles, and boundaries designed for safety and performance — not deep forensic analysis.

    This is why serious investigations always end up in PowerShell, where engineers can bypass GUI limitations, perform deeper searches, and collect evidence with precision.


    Section 1 — What Purview Is (in plain English)

    Purview provides:

    • Content search
    • eDiscovery (Standard & Premium)
    • Litigation holds
    • Audit logs
    • Labeling and retention
    • Insider risk scanning
    • Communication compliance

    It is designed for:

    • Legal teams
    • Compliance officers
    • HR investigations
    • Corporate governance
    • High-level reporting

    And for these purposes, Purview works very well.


    Section 2 — The Hidden Limitations of Purview

    Here are the real limits engineers face:

    1. Sending & Rate Limits

    Purview actions follow the same throttling limits as Exchange Online.
    You cannot pull unlimited messages instantly.

    2. eDiscovery Query Limits

    Each Purview search query is limited to:
    10,000 characters
    This is a major limitation for complex filters.

    3. Maximum Export Sizes

    Large exports (multiple gigabytes) often fail or time out.
    This is why forensic engineers break searches into chunks.

    4. Maximum Holds Per Mailbox

    A mailbox can only have:
    25 holds total
    More than 25 affects performance, indexing, and mailbox health.

    5. External Recipient Limits

    Purview cannot override existing mailbox restrictions.

    6. Tenant-Wide Limits

    Even Premium eDiscovery has:

    • Search concurrency limits
    • Workflow throttling
    • Processing delays
    • Indexing dependency (if an item isn’t indexed, Purview can’t see it)

    7. Purview is not real-time

    It depends on indexing engines.
    Indexing delays = missing results.

    8. Purview cannot reveal everything

    For true forensics you often need:

    • Message trace logs
    • Transport logs
    • Historical mailbox snapshots
    • DeletedItems and RecoverableItems subfolders
    • Soft delete and hard delete content
    • Hidden folders
    • Unindexed items

    Purview cannot provide all of that.


    Section 3 — Why PowerShell is Superior for True Forensics

    When Microsoft engineers or financial institutions perform real investigations, they do not rely on Purview alone. They rely on PowerShell because PowerShell can do what Purview cannot.

    1. Access Every Folder (Including Hidden Ones)

    PowerShell can query:

    • Inbox
    • Sent
    • DeletedItems
    • RecoverableItems
    • Purges
    • Versions
    • Subfolders not visible in Outlook
    • Unindexed items

    Purview can’t.


    2. No GUI query limit

    There is no 10,000-character query restriction in PowerShell.

    Pattern searches can be huge, detailed, and layered.


    3. Deep Header and Message Metadata Extraction

    PowerShell can extract:

    • X-MS-Exchange-Organization-AuthAs
    • X-MS-Exchange-CrossTenant-*
    • Original client IP
    • Authentication results
    • Message submission type
    • Connector source
    • Spam confidence level (SCL)
    • Envelope sender
    • Message ID tracking

    Purview provides only summarized metadata.


    4. Instant, Real-Time Search

    PowerShell does not wait for indexing.
    You can search unindexed items directly.

    This is critical in security incidents.


    5. Mailbox Timeline Reconstruction

    With PowerShell you can reconstruct:

    • When the message was received
    • When it was moved
    • If rules redirected it
    • If a compromised mailbox forwarded it
    • If the user deleted it
    • If it was purged

    Purview cannot reconstruct movement history.


    6. PowerShell is scripting + automation

    You can automate:

    • Large case collections
    • Exports
    • Multi-mailbox searches
    • Pattern scans
    • Complex filters
    • Timeline reconstruction

    Purview cannot automate eDiscovery at the same level.


    Section 4 — When to Use Purview vs PowerShell

    Use Purview for:

    • Legal holds
    • HR requests
    • Basic content searches
    • Governance
    • Compliance reporting
    • Policy enforcement

    Use PowerShell for:

    • Security incidents
    • Ransomware investigations
    • BEC (Business Email Compromise)
    • External spoofing investigations
    • Compromised mailbox analysis
    • Hidden folder discovery
    • Deep metadata extraction
    • Multi-mailbox timeline reconstruction

    Most senior email engineers agree:

    Purview is the “legal view.”
    PowerShell is the “truth view.”


    Conclusion

    Purview is an essential tool for compliance and legal workflows — but it is not a forensic engine.
    Its GUI limits, throttles, and reliance on indexing mean that it can never replace the precision, speed, and depth of PowerShell.

    This is why real investigations — especially in financial institutions and regulated organizations — always rely on PowerShell for final answers.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Quick “Reflexes” Using PowerShell to Block Bad Actors: Emergency Transport Rules + Layer 3/7 Firewall Controls

    In modern cloud environments, threats don’t wait for meetings, approvals, or planning sessions.
    Sometimes an attack hits so fast that your only advantage is instinct, experience, and the ability to act immediately.

    Last month, I experienced exactly that — a coordinated impersonation attempt from multiple bad actors in Europe using public cloud hosting (GCP) as their relay. They created their own connectors and attempted to impersonate internal executives and accounting contacts.

    The attack bypassed standard controls because:

    • They used legitimate cloud IP ranges
    • They generated perfect SPF/DKIM passes
    • Their mail flow looked “clean” until you read the headers
    • They used crafted envelope senders + forged display names

    The only way to stop them instantly — before users were tricked — was to drop two transport rules at highest priority using PowerShell.
    These acted as “circuit breakers” until perimeter firewall rules could be deployed.

    Below is the exact PowerShell approach, redacted and rewritten for general use.


    🚨 Reflex Script #1 — Emergency “Kill Switch” Rule

    Purpose: If attackers are impersonating an internal address like [email protected], this rule blocks any external sender who uses that address in the envelope from or header from.

    # Connect to Exchange Online
    Connect-ExchangeOnline
    
    # Create emergency kill-switch rule
    New-TransportRule -Name "KILL SWITCH: Block external spoofing of noreply" `
    -FromScope External `
    -HeaderContainsMessageHeader "From" `
    -HeaderContainsWords "noreply@" `
    -SetSCL 9 `
    -StopRuleProcessing $true `
    -Priority 0
    

    What this rule does instantly:

    • Stops external senders pretending to be noreply@
    • Sets SCL=9 so the message is quarantined or rejected (depending on policy)
    • Stops evaluation of all other rules — making it hit within milliseconds

    🚨 Reflex Script #2 — Block ALL External Senders Using a Protected Address

    Attackers often rotate payloads or try other internal addresses.
    This second rule blocks all attempts — even if they change tactics.

    New-TransportRule -Name "BLOCK ALL External From Protected Address" `
    -FromScope External `
    -SenderAddressMatchesPatterns "noreply@", "billing@", "alerts@" `
    -SetSCL 9 `
    -StopRuleProcessing $true `
    -Priority 1
    

    You can modify the patterns depending on the address being abused.


    🛡️ Why This Worked Instantly

    These scripts bypass the UI delay and:

    • Apply before EOP content filters
    • Hit prior to Safe Links/Safe Attachments
    • Trigger even if messages pass SPF/DKIM/DMARC
    • Intercept mail before it reaches the user’s mailbox
    • Provide time to analyze, trace, and escalate

    This is why reflex PowerShell is critical for senior-level engineers — the GUI is too slow during live attacks.


    🔐 Permanent Fix: Layer 3 / Layer 7 Firewall Enforcement

    Once the immediate threat was stopped with PowerShell, the permanent fix required:

    Layer 3 (IP-based blocklists)

    Blocking:

    • Abused GCP IP ranges
    • Known threat actor networks
    • Anonymous compute nodes

    Layer 7 (Application-layer filtering)

    Policies included:

    • Block SMTP traffic from unknown hosts
    • Block unauthorized connector-based submissions
    • Strict URL filtering for phishing redirectors
    • Geo-blocking regions with no business presence

    Once these firewall measures were active, the PowerShell Kill Switch rules were safely disabled to avoid unnecessary mail flow impact.


    💡 Lessons Learned

    1. Bad actors are fast — you must be faster.
    2. Transport rules + PowerShell are your instant “circuit breakers.”
    3. SPF/DKIM/DMARC are not enough when attackers leverage cloud infrastructure.
    4. Layer 3 and Layer 7 controls create the “permanent seal.”
    5. Instant response + longer-term architecture = real protection.

    This is the type of real-world, battle-tested example that hiring panels want to hear.
    Not theory — lived experience.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • 🖥️ Path to Become an Infrastructure Engineer (Ivy Falls)

    From Customer Service Rep to PC Specialist, Network Engineer, System Administrator, DevSecOps, and now Infrastructure Engineer — a journey built on faith, discipline, dedication, and gratitude.

    Introduction: The Path Is the Practice

    My story didn’t begin with servers or certifications.
    It began at All Electronics Corporation in Van Nuys, California, where I worked full-time from 6:30 A.M. to 3:00 P.M., taking two Metro buses and walking a block from the station — rain or shine — from December 1990 to late 1995.

    I woke as early as 4 A.M. to catch the first bus at Western and 3rd Street in Los Angeles, sometimes heading straight to my evening shift at the Taco Bell drive-thru in Glendale.
    Those were humble, exhausting days that taught me discipline and grit — lessons that would shape every part of my career.

    At All Electronics, I became fascinated by the IC — Integrated Circuit, the heart of every desktop computer. I wanted to understand it, not just sell it.

    Back in my Koreatown apartment, I turned curiosity into calling.
    No Google. No YouTube. No AI.
    Just library books and endless nights of self-study. I intentionally crashed my computers and rebuilt them until every fix became muscle memory.

    Once confident, I started offering free repairs and computer lessons to friends, relatives, and senior citizens — setting up printers, fixing networks, and teaching email basics. Those acts of service opened the door to my first full-time IT job at the University of Southern California (USC) as a PC Specialist.

    I still remember waiting at the bus stop in the dark, dreaming of the day I wouldn’t have to ride in the rain. Years later, those same dreams became reality — not through luck, but through faith, discipline, dedication, and gratitude.
    The rides changed — from buses to a BMW, an Audi, and now a Tesla — but what never changed was the purpose: to keep moving forward while staying grounded in gratitude.


    Season of Refinement

    While working full-time at USC, I entered what I call my season of refinement.
    By day I supported campus systems and users; by night I was a full-time student at Los Angeles City College (LACC) and a weekend warrior at DeVry University, studying Management in Telecommunications.

    It was during this time that Microsoft introduced the MCSE (Microsoft Certified Systems Engineer) program.
    One of my professors at LACC encouraged me to earn it, saying, “Once you have that license, companies will chase you.”
    He was right — that MCSE became my ticket to GTE (now Verizon), my first step into enterprise-scale IT.

    My tenure at GTE was brief because Aerospace came calling with a six-figure offer just before Y2K — an opportunity too good to refuse.
    After Aerospace, I founded my own consulting firm — Ahead InfoTech (AIT) — and entered what I now call my twelve years of plenty.

    One of my earliest major clients, USC Perinatal Group, asked me to design and implement a secure LAN/WAN connecting satellite offices across major hospitals including California Hospital Medical Center, Saint Joseph of Burbank and Mission Hills, and Hollywood Presbyterian Hospital.
    We used T1 lines with CSU/DSU units and Fortinet firewalls; I supplied every workstation and server under my own AIT brand.

    Through that success I was referred to additional projects for Tarzana and San Gabriel Perinatal Groups, linked by dedicated frame-relay circuits — early-era networking at its finest.
    Momentum led to new partnerships with The Claremont Colleges and the City of West Covina, where I served as Senior Consultant handling forensic analysis and SMTP/email engineering.

    Word spread. One attorney client introduced me to an opportunity in American Samoa to help design and build a regional ISP, and later to a contract with Sanyo Philippines.
    During this period Fortinet was still new, and I became one of its early resellers.
    Refusing to rely on mass-produced systems, I built AIT servers and workstations from the ground up for every environment.
    DSL was just emerging, yet most clients still relied on dedicated T1s — real hands-on networking that demanded precision and patience.

    Those were the twelve years of plenty — projects that stretched from local hospitals to overseas data links, from LAN cables to international circuits.
    By the time AWS arrived in 2006 and Azure followed in 2010, I had already been building and managing distributed networks for years.

    When I returned to Corporate America, my first full-time role was at Payforward, where I led the On-Prem to AWS migration, designing multi-region environments across US-East (1a and 1b) and US-West, complete with VPCs, subnets, IAM policies, and full cloud security.
    That’s when I earned my AWS certifications, completing a journey that had begun with physical servers and matured in the cloud.

    Education, experience, and certification merged into one lesson:
    Discipline comes first. Validation follows.
    Degrees and credentials were never my starting line — they were the icing on the cake of years of practice, service, and faith.


    My Philosophy: One Discipline, Many Forms

    Whether in Martial Arts, IT, or Photography, mastery comes from repetition, humility, and curiosity.
    As Ansel Adams wrote:

    “When words become unclear, I shall focus with photographs. When images become inadequate, I shall be content with silence.”

    Everyone can take a photo; not everyone captures a masterpiece.
    Everyone can study tech; not everyone understands its rhythm.
    Excellence lives in awareness — the moment when curiosity meets purpose.


    The Infrastructure Engineer Path

    1️⃣ Foundations

    Learn the essentials: Windows Server, Active Directory, DNS/DHCP, GPOs, Networking (VLANs, VPNs), Linux basics, and PowerShell.
    Free Resources:

    2️⃣ Cloud Platforms

    Start with AZ-104 Azure Administrator.
    Use free tiers to lab: Azure | AWS | GCP.
    Courses:

    3️⃣ Automation & DevOps

    Learn IaC (Terraform/Bicep), Docker, Kubernetes, and CI/CD.
    Watch TechWorld with Nana.

    4️⃣ Labs & Simulators

    No hardware? Try:

    5️⃣ Portfolio

    Document every lab, build diagrams, post scripts on GitHub, and write short lessons learned.


    Final Reflection

    From bus stops to boardrooms, from fixing desktops to deploying clouds — the principles never changed: serve first, learn always, and build things that last.
    This blog will continue to evolve as technology changes — come back often and grow with it.


    🪶 Closing Note

    I share this story not to boast, but to inspire those still discovering their own path in technology.
    Everything here is told from personal experience and memory; if a date or detail differs from official records, it’s unintentional.
    I’m grateful for mentors like my LACC professor, who once told me to look up a name not yet famous — Bill Gates — and earn my MCSE + I.
    He was right: that single decision opened countless doors.

    I don’t claim to know everything; I simply kept learning, serving, and sharing.
    My living witnesses are my son, my younger brother, and friends who once worked with me and now thrive in IT.
    After all these years, I’m still standing — doing what I love most: helping people through Information Technology.


    ⚖️ Legal Disclaimer

    All events and company names mentioned are described from personal recollection for educational and inspirational purposes only. Any factual inaccuracies are unintentional. Opinions expressed are my own and do not represent any past or current employer.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Exchange Online: Mailbox Used/Quota/Available (Redacted)

    Excerpt

    Exchange Online sometimes reports mailbox sizes with “Unlimited” wrappers that break simple math. Today I built a one-liner-friendly PowerShell snippet that returns Used GB, Quota GB, and Available GB—even when EXO wraps values in Unlimited<T>.

    Intro

    I needed the available mailbox size for [mailbox]@[domain] without exposing tenant internals. The usual TotalItemSize parsing failed because EXO returned Unlimited<ByteQuantifiedSize>. Here’s the redacted approach that works reliably and falls back cleanly.

    Notes from {Speaker}

    • Context: Exchange Online + PowerShell; target was [mailbox]@[domain].
    • Constraint: TotalItemSize and ProhibitSendQuota show Unlimited wrappers or localized strings.
    • Goal: Get UsedGB / QuotaGB / AvailableGB with no tenant secrets.

    Perspective (direct quotes)

    “If it’s Unlimited<T>, ask for .Value—and always guard with IsUnlimited.”
    “When objects don’t expose bytes, regex the (123,456 bytes) pattern as a fallback.”

    Practice (today, not someday)

    Use this redacted snippet. It works with Get-EXO* and falls back to classic cmdlets:

    # EXO connection (redacted UPN)
    Connect-ExchangeOnline -UserPrincipalName [me] -ShowBanner:$false
    
    $upn = '[mailbox]@[domain]'   # e.g., [email protected]
    
    try {
      $stat = Get-EXOMailboxStatistics -Identity $upn -ErrorAction Stop
      $mbx  = Get-EXOMailbox           -Identity $upn -PropertySets Quota -ErrorAction Stop
    
      $usedBytes = if ($stat.TotalItemSize.PSObject.Properties.Name -contains 'Value') {
        [int64]$stat.TotalItemSize.Value.ToBytes()
      } else {
        [int64](([regex]::Match($stat.TotalItemSize.ToString(), '\(([\d,]+)\sbytes\)')).Groups[1].Value -replace ',','')
      }
    
      $quotaBytes = if ($mbx.ProhibitSendQuota -and `
                        ($mbx.ProhibitSendQuota.PSObject.Properties.Name -contains 'IsUnlimited') -and `
                        -not $mbx.ProhibitSendQuota.IsUnlimited) {
        [int64]$mbx.ProhibitSendQuota.Value.ToBytes()
      } elseif ($mbx.ProhibitSendQuota.ToString() -notmatch 'Unlimited') {
        [int64](([regex]::Match($mbx.ProhibitSendQuota.ToString(), '\(([\d,]+)\sbytes\)')).Groups[1].Value -replace ',','')
      } else { $null }
    }
    catch {
      $stat = Get-MailboxStatistics -Identity $upn
      $mbx  = Get-Mailbox           -Identity $upn
      $usedBytes  = [int64](([regex]::Match($stat.TotalItemSize.ToString(), '\(([\d,]+)\sbytes\)')).Groups[1].Value -replace ',','')
      $quotaBytes = if ($mbx.ProhibitSendQuota.ToString() -match 'Unlimited') { $null }
                    else { [int64](([regex]::Match($mbx.ProhibitSendQuota.ToString(), '\(([\d,]+)\sbytes\)')).Groups[1].Value -replace ',','') }
    }
    
    $usedGB  = [math]::Round($usedBytes/1GB, 2)
    $quotaGB = if ($quotaBytes) { [math]::Round($quotaBytes/1GB, 2) } else { $null }
    $availGB = if ($quotaBytes) { [math]::Round(($quotaBytes-$usedBytes)/1GB, 2) } else { $null }
    
    [pscustomobject]@{
      Mailbox            = $upn
      UsedGB             = $usedGB
      QuotaGB            = $quotaGB
      AvailableGB        = $availGB
      StorageLimitStatus = $stat.StorageLimitStatus
    }
    

    Final Reflection

    EXO’s objects are powerful but quirky. Guarding for IsUnlimited, using .Value.ToBytes(), and keeping a regex fallback turns a flaky one-off into a repeatable tool.

    Pocket I’m Keeping

    Parse what’s there, not what you expect.” When APIs return wrapped or localized strings, a small fallback (regex for (#### bytes)) saves the day.

    What I Hear Now (direct quotes)

    “Measure in bytes, report in GB.”
    “Handle Unlimited first, then do math.”
    “One clean object out—every time.”

    Link to the Script

    Microsoft Exchange Online PowerShell (Get-EXOMailbox, Get-Mailbox) — official docs

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Beat the 99% Wall: Upgrade Windows 10 → 11 the Easy Offline Way (Do This Before Oct 5, 2025)

    When the upgrade sits at 99%… don’t panic. Go offline and run the ISO upgrade the smart way

    Windows 10 reaches end of life on Oct 5, 2025. After that, it won’t get security updates. If you stay on Win10, your machine is a sitting duck for malware and attackers. Don’t procrastinate.

    If Windows Update keeps failing—or hangs forever at 99%—use this clean, offline upgrade that skips the flaky “checking for updates” step.


    1) First, confirm your PC is Windows 11–ready

    Use Microsoft’s official checker:
    https://support.microsoft.com/en-us/windows/check-if-a-device-meets-windows-11-system-requirements-after-changing-device-hardware-f3bc0aeb-6884-41a1-ab57-88258df6812b

    Important: The most common blockers are the CPU and motherboard (TPM 2.0, UEFI/Secure Boot). If your device doesn’t meet Windows 11 requirements, it’s unsupported after Oct 5, 2025. Treat that Windows 10 PC as unsafe for internet use—either upgrade/replace the hardware, reassign it to offline tasks, or retire it.


    2) Prep (5–10 minutes)

    • Unplug non-essential USB devices (drives, printers, docks).
    • Ensure ≥30 GB free on C:.
    • Suspend BitLocker (if enabled): Control Panel → BitLocker → Suspend.
    • Temporarily disable third-party AV/VPN.
    • Clean Boot: msconfigServicesHide Microsoft servicesDisable all; Startup → disable everything.

    3) Reset Windows Update & appraiser caches (PowerShell)

    Open PowerShell as Administrator and run:

    net stop wuauserv
    net stop bits
    net stop cryptsvc
    
    ren "C:\Windows\SoftwareDistribution" SoftwareDistribution.old
    ren "C:\Windows\System32\catroot2" catroot2.old
    
    rd /s /q "C:\$WINDOWS.~BT"
    rd /s /q "C:\$WINDOWS.~WS"
    rd /s /q "C:\Windows\Panther"
    md "C:\Windows\Panther"
    
    net start cryptsvc
    net start bits
    net start wuauserv
    

    Then heal the image:

    DISM /Online /Cleanup-Image /RestoreHealth
    sfc /scannow
    

    4) Run the upgrade offline from ISO (no update checks)

    1. Download the official Windows 11 ISO (same edition/language/arch) from Microsoft.
    2. Right-click the ISO → Mount → note the drive letter (e.g., E:).
    3. Disconnect the network (unplug Ethernet / disable Wi-Fi).
    4. In elevated PowerShell, launch Setup with Dynamic Update disabled:
    Start-Process -FilePath 'E:\setup.exe' -ArgumentList '/auto upgrade /dynamicupdate disable /copylogs C:\$UpgradeLogs' -Verb RunAs -Wait
    

    (Optional quick blocker scan without upgrading):

    Start-Process -FilePath 'E:\setup.exe' -ArgumentList '/compat scanonly /dynamicupdate disable' -Verb RunAs -Wait
    

    5) If it still stalls

    • Drivers (most common):
      • Storage: Device Manager → Storage controllers → switch to Microsoft Standard controller (Update driver → Let me pick).
      • Display: use Microsoft Basic Display Adapter temporarily.
      • Remove extra language packs, old VPN clients, and heavy OEM utilities.
    • BIOS/Chipset: update from your PC maker’s support page.
    • Rerun the offline setup command.

    6) Pinpoint the exact blocker (2 minutes)

    If it fails again, run Microsoft SetupDiag and read the summary:

    mkdir C:\SetupDiag; cd C:\SetupDiag
    .\SetupDiag.exe /Output:C:\SetupDiag\SetupDiagResults.log
    
    • Codes like 0xC1900101-0x… usually name a driver (oem*.inf)—remove/roll it back and retry.
    • Dynamic-Update/Appraiser errors → repeat Step 3 and ensure you’re truly offline with /dynamicupdate disable.

    7) After success

    • Re-enable BitLocker, AV/VPN, and normal startup apps.
    • Reconnect the network and run Windows Update to pull fresh drivers and features.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Cloning a VM with PowerShell and VMware PowerCLI


    Intro

    When you need to quickly spin up a test or lab machine, cloning an existing VM can save hours compared to building from scratch. VMware PowerCLI brings the full power of vSphere management into PowerShell. Here’s a simple walkthrough.


    Step 1 — Install VMware PowerCLI

    Open PowerShell as administrator and run:

    Install-Module -Name VMware.PowerCLI -Scope CurrentUser
    Import-Module VMware.PowerCLI
    

    This installs the official VMware module and loads it into your session.


    Step 2 — Connect to vCenter

    You’ll need credentials for your vCenter server.

    Connect-VIServer -Server <vcenter-server.domain> -User <username> -Password '<password>'
    

    Step 3 — Clone an Existing VM

    Pick the source VM, target VM names, host, and datastore. Example:

    # Define source VM
    $sourceVM = "Base-Win10-VM"
    
    # Clone to new VM
    New-VM -Name "Test-VM01" -VM $sourceVM `
           -VMHost (Get-VMHost -Name <target-host>) `
           -Datastore (Get-Datastore -Name <datastore-name>) `
           -Location (Get-Folder -Name "VMs")
    
    • -VM points to the existing machine you’re cloning.
    • -VMHost pins the new VM to a specific ESXi host.
    • -Datastore chooses where to store the VM’s disks.
    • -Location defines the vCenter folder for organization.

    Step 4 — Power On the New VM

    Start-VM -VM "Test-VM01"
    

    Final Reflection

    PowerCLI makes cloning fast, repeatable, and scriptable. Instead of clicking through vSphere UI screens, you can prepare test VMs with a single command.


    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Marked in Time — Fixing a “Sender not allowed” DL (redacted)

    Excerpt
    Our all-hands list rejected internal senders after we allowed two external addresses. Here’s what happened, how to fix it cleanly in Exchange Online, and a PowerShell snippet you can reuse.


    Intro
    Two days ago, I could email everyone@[redacted].com just fine. Today, my message bounced: “this group only accepts messages from people in its organization or on its allowed senders list.” We’d recently added two partner addresses (s@[partner].com, j@[partner].com) so they could email the DL. That change flipped the DL into strict allow-list mode—blocking even internal senders who weren’t explicitly listed. Here’s the minimal, durable fix.


    Straight line (what happened)
    • Symptom: NDR when sending to everyone@[redacted].com from an internal account.
    • State check showed:
    – RequireSenderAuthenticationEnabled: False
    – AcceptMessagesOnlyFromSendersOrMembers: {} (and earlier, it contained only the two partner GUIDs).
    • Root cause: Delivery management was saved in “only these senders” mode; membership/ownership doesn’t matter in that state.
    • Goal: Let all internal, authenticated users send; allow only specific externals; block the rest.


    Fix (clean model)

    1. Let internal, authenticated users send to the DL (no hard allow-list on the group).
    2. Enforce external restrictions with a transport rule that allows only the partner exceptions.

    Commands (PowerShell — Exchange Online)

    Connect

    Connect-ExchangeOnline -ShowBanner:$false
    

    Allow internal, authenticated senders (clear hard allow-list)

    Set-DistributionGroup everyone@[redacted].com `
      -AcceptMessagesOnlyFromSendersOrMembers $null `
      -RequireSenderAuthenticationEnabled:$true
    

    Create the external block rule with an allow-list

    # remove if an older copy exists (safe if none)
    Get-TransportRule "Block external to Everyone (except allow-list)" -ErrorAction SilentlyContinue |
      Remove-TransportRule -Confirm:$false
    
    New-TransportRule "Block external to Everyone (except allow-list)" `
      -FromScope NotInOrganization `
      -AnyOfToHeader "everyone@[redacted].com" `
      -ExceptIfFrom "s@[partner].com","j@[partner].com" `
      -RejectMessageReasonText "External senders are not allowed for this list."
    

    Verify

    Get-DistributionGroup everyone@[redacted].com |
      fl PrimarySmtpAddress,RequireSenderAuthenticationEnabled,AcceptMessagesOnlyFromSendersOrMembers
    
    Get-TransportRule "Block external to Everyone (except allow-list)" |
      fl Name,State,FromScope,AnyOfToHeader,ExceptIfFrom
    

    Update the allow-list later

    # add another partner
    Set-TransportRule "Block external to Everyone (except allow-list)" `
      -ExceptIfFrom @{Add="newuser@[partner].com"}
    
    # remove a partner
    Set-TransportRule "Block external to Everyone (except allow-list)" `
      -ExceptIfFrom @{Remove="j@[partner].com"}
    

    Smoke tests
    • Internal sender → everyone@[redacted].com: delivers.
    • External sender (not on list): NDR with “External senders are not allowed…”
    • Allowed partner (s@[partner].com or j@[partner].com): delivers.


    Why not leave the DL in allow-list mode?
    Because it’s brittle. Every internal sender must be explicitly added, which guarantees future bounces and admin toil. Using RequireSenderAuthenticationEnabled for internal mail + a transport rule for externals gives you clarity and control.


    Final reflection
    Small toggles can have outsized effects. DL delivery settings look simple, but one checkbox can silently change who’s “allowed.” The durable pattern is: authenticate inside, whitelist outside, and verify with a quick trace.


    Pocket I’m keeping
    • Always snapshot DL settings before/after a change.
    • Prefer transport rules for external policy; don’t hard-gate internals via allow-lists.
    • Add a ready-to-run “add/remove external exception” snippet to the runbook.


    What I hear now
    Clarity beats cleverness. Make the rule obvious enough that the next admin can read it and know exactly who can send and why.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Ops Note — Picking the best vSAN host with one PowerCLI check

    Excerpt
    Quick, repeatable way to see CPU/RAM/vSAN headroom across hosts and choose where to place the next VM. Today it pointed us to vsan2.


    Intro
    Before cloning a new Windows VM, I ran a fast PowerCLI sweep across three vSAN hosts to compare free CPU, free memory, and vSAN free space. All three had identical vSAN capacity; vsan2 had the most free RAM, so that’s the landing spot.


    Straight line (what I did)
    • Pulled CPU and memory usage per host (MHz/MB) and calculated free.
    • Queried each host’s vSAN datastore(s) and summed free/total GB.
    • Printed a compact table to compare vsan1/2/3 at a glance.
    • Chose the host with the highest Mem_Free_GB (tie-break on vSAN free).


    Command (copy/paste)

    # Hosts to check (redacted)
    $hosts = 'vsan1.example.local','vsan2.example.local','vsan3.example.local'
    
    $report = foreach ($h in $hosts) {
      try {
        $vmh    = Get-VMHost -Name $h -ErrorAction Stop
        $cpuTot = $vmh.CpuTotalMhz;  $cpuUse = $vmh.CpuUsageMhz
        $memTot = $vmh.MemoryTotalMB; $memUse = $vmh.MemoryUsageMB
    
        $vsan      = $vmh | Get-Datastore | Where-Object { $_.Type -eq 'vsan' }
        $dsCapGB   = ($vsan | Measure-Object CapacityGB  -Sum).Sum
        $dsFreeGB  = ($vsan | Measure-Object FreeSpaceGB -Sum).Sum
        $dsFreePct = if ($dsCapGB) { [math]::Round(100*($dsFreeGB/$dsCapGB),2) } else { 0 }
    
        [pscustomobject]@{
          Host          = $vmh.Name
          CPU_Free_GHz  = [math]::Round(($cpuTot-$cpuUse)/1000,2)
          CPU_Total_GHz = [math]::Round($cpuTot/1000,2)
          CPU_Free_pct  = if ($cpuTot) { [math]::Round(100*(($cpuTot-$cpuUse)/$cpuTot),2) } else { 0 }
          Mem_Free_GB   = [math]::Round(($memTot-$memUse)/1024,2)
          Mem_Total_GB  = [math]::Round($memTot/1024,2)
          Mem_Free_pct  = if ($memTot) { [math]::Round(100*(($memTot-$memUse)/$memTot),2) } else { 0 }
          vSAN_Free_GB  = [math]::Round($dsFreeGB,2)
          vSAN_Total_GB = [math]::Round($dsCapGB,2)
          vSAN_Free_pct = $dsFreePct
        }
      } catch {
        [pscustomobject]@{ Host=$h; CPU_Free_GHz='n/a'; CPU_Total_GHz='n/a'; CPU_Free_pct='n/a';
          Mem_Free_GB='n/a'; Mem_Total_GB='n/a'; Mem_Free_pct='n/a';
          vSAN_Free_GB='n/a'; vSAN_Total_GB='n/a'; vSAN_Free_pct='n/a' }
      }
    }
    
    $report | Format-Table -AutoSize
    
    # Optional: pick best host by RAM, then vSAN GB
    $best = $report | Where-Object { $_.Mem_Free_GB -is [double] } |
            Sort-Object Mem_Free_GB, vSAN_Free_GB -Descending | Select-Object -First 1
    "Suggested placement: $($best.Host) (Mem free: $($best.Mem_Free_GB) GB, vSAN free: $($best.vSAN_Free_GB) GB)"
    

    Result today
    • vsan2 showed the most free RAM, with CPU headroom similar across all three and identical vSAN free space.
    • Suggested placement: vsan2.


    Pocket I’m keeping
    • Check host headroom before every clone—30 seconds now saves hours later.
    • Prefer RAM headroom for Windows VDI/worker VMs; CPU is usually similar across nodes.
    • Keep a one-liner that prints the table and the suggested host.


    What I hear now
    Clone to vsan2, power up, then let DRS/vMotion rebalance after the build window. Repeat this check whenever adding workloads or after maintenance.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Fixing “Sender not allowed” to an internal group (Exchange Online) — a quick forensic + runbook


    POST BODY

    When a partner emailed our all-hands list, they got an NDR:
    “the group only accepts messages from people in its organization or on its allowed senders list… sender not allowed.”

    We’d solved this once before and didn’t capture the steps. This time we did.


    Forensic summary (redacted)

    • group: all@[corp-redacted].com
    • external sender: firstname.lastname@[partner-redacted].com
    • symptom: NDR “sender not allowed”
    • root causes:
      1. the group required authenticated (internal) senders only, and
      2. the external wasn’t on the group’s allowed-senders list
    • gotcha we hit: New-MailContact failed with ProxyAddressExists — an existing MailUser already owned the external SMTP, so we reused it instead of creating a new contact

    Straight line (what fixed it)

    1. identify group by SMTP and check whether it’s a DL or a Microsoft 365 Group
    2. locate the external as an existing MailContact/MailUser (include soft-deleted objects)
    3. add that object to the group’s AcceptMessagesOnlyFromSendersOrMembers list
    4. allow the group to accept external senders (keeps the allow-list in effect)
    5. test and confirm with Message trace

    Reusable runbook (PowerShell, redacted)

    # 0) Connect
    Connect-ExchangeOnline
    
    # 1) Variables (edit these)
    $GroupSmtp = "all@[corp-redacted].com"
    $ExternalAddresses = @("firstname.lastname@[partner-redacted].com")
    
    # 2) Resolve the group (works for DL or M365 Group)
    $grp = Get-EXORecipient -Filter "PrimarySmtpAddress -eq '$GroupSmtp'"
    $grp | fl Name,RecipientTypeDetails,PrimarySmtpAddress,Identity,ExternalDirectoryObjectId
    
    # 3) Ensure each external exists as a recipient we can allow (MailContact/MailUser).
    #    If already present (or soft-deleted), reuse it.
    $recips = @()
    foreach ($addr in $ExternalAddresses) {
      $r = Get-EXORecipient -ResultSize Unlimited -IncludeSoftDeletedRecipients `
           -Filter "PrimarySmtpAddress -eq '$addr'"
      if (-not $r) {
        try { New-MailContact -Name $addr -ExternalEmailAddress $addr | Out-Null
              $r = Get-EXORecipient -Filter "PrimarySmtpAddress -eq '$addr'" }
        catch { Write-Host "Contact already exists somewhere: $addr" }
      }
      $recips += $r
    }
    $recips | ft Name,RecipientTypeDetails,PrimarySmtpAddress -AutoSize
    
    # 4) Add externals to allow-list AND allow external senders
    if ($grp.RecipientTypeDetails -eq "GroupMailbox") {
      # Microsoft 365 Group (Unified Group)
      foreach ($r in $recips) {
        Set-UnifiedGroup -Identity $grp.ExternalDirectoryObjectId `
          -AcceptMessagesOnlyFromSendersOrMembers @{Add=$r.Identity}
      }
      Set-UnifiedGroup -Identity $grp.ExternalDirectoryObjectId -AllowExternalSenders:$true
      Get-UnifiedGroup -Identity $grp.ExternalDirectoryObjectId |
        fl DisplayName,PrimarySmtpAddress,AllowExternalSenders,AcceptMessagesOnlyFromSendersOrMembers
    } else {
      # Distribution Group / Mail-enabled Security Group
      foreach ($r in $recips) {
        Set-DistributionGroup -Identity $grp.Identity `
          -AcceptMessagesOnlyFromSendersOrMembers @{Add=$r.Identity}
      }
      Set-DistributionGroup -Identity $grp.Identity -RequireSenderAuthenticationEnabled:$false
      Get-DistributionGroup -Identity $grp.Identity |
        fl DisplayName,PrimarySmtpAddress,RequireSenderAuthenticationEnabled,AcceptMessagesOnlyFromSendersOrMembers
    }
    
    # 5) Message trace (adjust window)
    Get-MessageTrace -SenderAddress $ExternalAddresses[0] -RecipientAddress $GroupSmtp `
      -StartDate (Get-Date).AddHours(-2) -EndDate (Get-Date) |
      ft Received,Status,RecipientAddress,MessageId
    

    Common pitfalls we saw (and how we handled them)

    • ProxyAddressExists on New-MailContact → an existing MailUser/Contact already holds that SMTP; reuse it (or permanently remove the soft-deleted recipient first).
    • group can’t be found by display name → target by SMTP with Get-EXORecipient -Filter "PrimarySmtpAddress -eq '...'".
    • delivery still blocked after allow-list → the DL still required authenticated senders; set RequireSenderAuthenticationEnabled:$false (DL) or AllowExternalSenders:$true (M365 Group).

    Click-path (EAC, if you don’t want PowerShell)

    • Recipients → Contacts → add/find the partner’s contact
    • Recipients → Groups → open the group → Delivery management → “Accept messages from” → add the contact
    • For DLs: turn off “Require sender authentication”
    • For M365 Groups: enable “Allow external senders”

    Prevention / hygiene

    • keep an “Authorized External Senders — all” mail-enabled security group; allow that group on the DL/M365 Group, then just add/remove partner contacts over time
    • document the NDR verbatim and the message trace ID when you close an incident

    Redaction note

    All addresses and names are redacted. Replace with your real SMTPs when running the script.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • 🌥️ The Cloud Above Us

    PIMCO (Newport Beach HQ, CA) 🌍 — Global financial services supporting regions in NA, EMEA, APAC.
    Church (Riverton Office Building, UT) ⛪ — Worldwide infrastructure with 200k employees and over 80k missionaries.
    Monster Energy (Corona HQ, CA) ⚡ — Global enterprise IT operations across NA, EMEA, APAC.
    City National Bank (Downtown LA, CA) 🏙️ — U.S. banking systems at scale.

    A journey across scales: national (CNB), global (PIMCO & Monster Energy), and worldwide (The Church).


    Every IT career tells a story, and mine has moved through three different scales of impact:

    Company-Level Foundations → At PayForward, I migrated an entire OnPrem environment into AWS. That meant setting up VPCs, building HA Exchange clusters with load balancers, and proving the power of cloud for a fast-moving startup.

    Regional / Global Scale → At Monster Energy and PIMCO, the work stretched across North America, EMEA, and APAC. The systems never slept. VMware clusters and M365 tenants had to function as one, even though users were scattered across time zones and continents.

    Worldwide Reach → At the Church, the scale expanded beyond regions. Over 200,000 employees and over 80,000 missionaries, connected by systems that had to reach every corner of the globe, demanded both technical precision and spiritual responsibility.

    This journey shows that the “cloud above us” isn’t just AWS, Azure, or GCP — it’s the ability to design, secure, and sustain systems at every possible scale.

    A colleague once told me: “Automate, or eliminate.” In IT, that isn’t just a clever saying — it’s survival. At the scale of hundreds or even thousands of VMs, EC2 instances, or mailboxes, doing things manually is not just unrealistic — it’s risky. What automation can finish in under 10 minutes might take days or weeks by hand, and even then would be prone to errors.

    That’s why Python, PowerShell, Bash, and automation frameworks became part of my daily toolkit. Not to flaunt, but because without automation, no single engineer could handle the demands of environments as large as PIMCO, Monster Energy, or the Church.


    Snippet 1: AWS (My PayForward Days)

    import boto3
    
    # Connect to AWS S3
    s3 = boto3.client('s3')
    
    # List buckets
    buckets = s3.list_buckets()
    print("Your AWS buckets:")
    for bucket in buckets['Buckets']:
        print(f"  {bucket['Name']}")
    

    From racks of servers to a few lines of Python—that’s the power of AWS.

    Snippet 2: PowerShell + Azure (My Church Years, CNB)

    Connect-AzAccount
    Get-AzResourceGroup | Select ResourceGroupName, Location
    

    One line, and you can see every Azure resource group spread across the world. A task that once required data center visits and clipboards is now just a command away.

    Snippet 3: PHP + GCP (Expanding Horizons)

    use Google\Cloud\Storage\StorageClient;
    
    $storage = new StorageClient([
        'keyFilePath' => 'my-service-account.json'
    ]);
    
    $buckets = $storage->buckets();
    
    foreach ($buckets as $bucket) {
        echo $bucket->name() . PHP_EOL;
    }
    

    Snippet 4: VMware + M365 (Monster Energy, PIMCO, and Beyond)

    # Connect to vCenter and list VMs across data centers
    Connect-VIServer -Server vcenter.global.company.com -User admin -Password pass
    Get-VM | Select Name, PowerState, VMHost, Folder
    
    # Quick check of licensed users in M365 (global tenants)
    Connect-MgGraph -Scopes "User.Read.All"
    Get-MgUser -All -Property DisplayName, UserPrincipalName, UsageLocation |
        Group-Object UsageLocation |
        Select Name, Count
    

    One script, and suddenly you’re seeing footprints of users spread across the globe — NA, EMEA, APAC, or even worldwide. That’s the reality of modern IT infrastructure.


    The “cloud above us” is both a literal technology — AWS, Azure, and GCP that I’ve worked across — and a metaphor. It represents resilience, scalability, and unseen support. Just as automation carries workloads we could never handle by hand, life has storms we cannot carry alone.

    From startups making their first move to the cloud, to global financial institutions, to worldwide organizations with hundreds of thousands of users, the lesson is the same: we are not meant to fight every battle manually.

    We are given tools, teammates, and even unseen strength from above to keep moving forward. The same way a script can manage thousands of servers or accounts without error, trust and preparation help us navigate the storms of life with less fear.

    ☁️ Above every storm, there’s always a cloud carrying potential. And above that cloud, always light waiting to break through.

    Before my cloud journey, I also spent nine years in forensic IT supporting law enforcement — a grounding reminder that technology isn’t only about systems and scale, but about accountability and truth.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Secure Automation with PowerShell SecretManagement: Simplifying Credential Management for IT Pros

    Introduction:
    In enterprise environments, automation is only as secure as the credentials it uses. Hardcoding passwords into scripts is a security disaster waiting to happen. Enter PowerShell SecretManagement — a cross-platform module that allows IT professionals to store, retrieve, and manage credentials securely while keeping scripts clean, compliant, and automation-ready.

    Description & Guide:

    1. What is SecretManagement?
      The SecretManagement module provides a unified way to work with secrets across different vaults like Windows Credential Manager, Azure Key Vault, KeePass, or HashiCorp Vault — without locking you into a single storage provider.
    2. Installing the Modules
    Install-Module Microsoft.PowerShell.SecretManagement
    Install-Module Microsoft.PowerShell.SecretStore
    

    3. Registering a Vault
    For a local secure store:

    Register-SecretVault -Name LocalVault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
    

    4. Adding a Secret

    Set-Secret -Name MySQLAdmin -Secret (Get-Credential)
    

    5. Retrieving a Secret in Scripts

    $cred = Get-Secret -Name MySQLAdmin -AsCredential
    Invoke-Sqlcmd -ServerInstance "SQL01" -Username $cred.UserName -Password $cred.GetNetworkCredential().Password
    

    6. Why This Matters

    • Eliminates plaintext passwords in scripts
    • Centralizes secret management for easier updates
    • Works seamlessly with CI/CD pipelines and scheduled tasks

    Conclusion:
    Security and automation don’t have to be enemies. With PowerShell SecretManagement, you can protect sensitive credentials without sacrificing automation speed or flexibility. For IT pros managing hybrid environments, this module is a must-have in your PowerShell toolbox.

    If you’d like to go beyond this post and see what Microsoft officially recommends, here are my go-to resources:

    Microsoft Docs – SecretManagement Overview

    Microsoft Docs – SecretStore vault extension

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Migrating Azure AD Scripts to Microsoft Graph PowerShell: A Practical Guide for IT Administrators

    Introduction
    The AzureAD PowerShell module has served IT administrators for years, but it’s now officially deprecated in favor of the Microsoft Graph PowerShell SDK. While the change may feel like another “cloud shuffle,” migrating your scripts is not just a compliance move — it’s your ticket to a more powerful, secure, and future-proof automation toolkit. In this post, I’ll walk you through the essentials of converting your Azure AD scripts to Microsoft Graph, with clear side-by-side examples.

    Why Migrate?

    • Future Support: Microsoft Graph is actively developed; AzureAD is on life support.
    • Unified Endpoint: Graph covers Azure AD, Intune, Exchange Online, Teams, and more in one API.
    • Security: Better authentication methods, including secure app registrations and least-privilege scopes.

    Step 1 – Install Microsoft Graph PowerShell

    # Install the module
    Install-Module Microsoft.Graph -Scope CurrentUser
    
    # Update if already installed
    Update-Module Microsoft.Graph
    
    # Connect with interactive sign-in
    Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"
    
    # Confirm connection
    Get-MgContext
    

    Step 2 – Side-by-Side Script Conversion

    Example: Get all Azure AD users
    AzureAD Module:

    Connect-AzureAD
    Get-AzureADUser -All $true
    

    Microsoft Graph:

    Connect-MgGraph -Scopes "User.Read.All"
    Get-MgUser -All
    

    Example: Get members of a group
    AzureAD Module:

    $groupId = (Get-AzureADGroup -SearchString "Sales Team").ObjectId
    Get-AzureADGroupMember -ObjectId $groupId
    

    Microsoft Graph:

    $groupId = (Get-MgGroup -Filter "displayName eq 'Sales Team'").Id
    Get-MgGroupMember -GroupId $groupId
    

    Example: Create a new group
    AzureAD Module:

    New-AzureADGroup -DisplayName "Project A Team" -MailEnabled $false -SecurityEnabled $true -MailNickname "ProjectATeam"
    

    Microsoft Graph:

    New-MgGroup -DisplayName "Project A Team" `
        -MailEnabled:$false `
        -SecurityEnabled `
        -MailNickname "ProjectATeam"
    

    Step 3 – Updating Authentication
    With Microsoft Graph, you can fine-tune permissions at sign-in instead of granting broad directory access:

    Connect-MgGraph -Scopes "User.ReadWrite.All", "Group.ReadWrite.All"
    

    Only request the scopes you actually need — this aligns with least privilege best practices.

    Step 4 – Testing and Verification
    Before replacing scripts in production, run them in a test tenant or a non-production environment. Compare outputs from AzureAD and Graph to ensure parity.

    Conclusion
    Migrating from AzureAD to Microsoft Graph PowerShell is more than just a rewrite — it’s a forward-looking investment. Once you adapt, you’ll unlock richer APIs, cross-service automation, and security benefits that AzureAD simply can’t match. My advice? Start small: pick one script, convert it, and test until you’re confident. Once you see the gains, the rest will follow naturally.

    For official guidance and best practices from Microsoft, check out these resources:

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • Fixing Disabled Azure AD Accounts: PowerShell vs Portal

    Minutes before boarding at Salt Lake City International Airport, I received an urgent text about a disabled Azure AD account. I opened my laptop, tethered to my phone’s hotspot, connected to Cisco VPN, and got to work—resolving the issue securely without relying on public Wi-Fi

    Introduction:
    Last Friday, just as I was getting ready to board my flight to JFK from the Salt Lake City airport, I received a message from an end user:

    “I think I’m blocked. I can’t access Outlook, Teams, or OneDrive.”

    Time was limited, and I was already seated at the gate with my laptop ready. Instead of panicking, I tethered through my phone’s personal hotspot and launched Cisco AnyConnect VPN. I deliberately avoided the airport’s public Wi-Fi to reduce the risk of a security breach.

    Once I authenticated and connected securely, I logged into Azure. I discovered that the user’s account in portal.azure.com was disabled. Fortunately, there are two ways to quickly resolve this kind of issue:

    ✅ Method 1: PowerShell (Quickest & Most Efficient)

    If you have the AzureAD or Microsoft Graph PowerShell module installed and proper permissions, this method is the fastest.

    Step-by-step using Microsoft Graph PowerShell:

    # Connect to Microsoft Graph
    Connect-MgGraph -Scopes "User.ReadWrite.All"
    
    # Re-enable the disabled account
    Update-MgUser -UserId [email protected] -AccountEnabled $true
    

    Note: Replace [email protected] with the actual UPN or Object ID of the affected user.

    Advantages:

    • Fast (under 30 seconds)
    • No GUI needed
    • Can be scripted for multiple accounts

    🧭 Method 2: Azure Portal (GUI Approach)

    If you’re not ready to run PowerShell or don’t have the module available, the Azure Portal offers a visual way to fix it.

    Steps:

    1. Go to https://portal.azure.com
    2. Navigate to Azure Active Directory
    3. Click on Users
    4. Search for the affected user
    5. Click the Edit button at the top
    6. Set Account Enabled to Yes
    7. Click Save

    Advantages:

    • Good for admins who prefer a visual interface
    • Easier to audit changes
    • Helpful for one-off account fixes

    🧠 Final Thoughts

    Both approaches—PowerShell and the Azure portal—get the job done. However, for IT professionals constantly on the move, PowerShell is king. It’s fast, efficient, and doesn’t rely on a graphical interface.

    That said, having the flexibility to switch between GUI and scripting tools is essential. Some situations demand precision and speed; others might call for a visual confirmation or audit trail.

    In the end, what matters most is being prepared. Whether you’re at your desk or at an airport gate, the ability to jump in and resolve an issue on the fly is what defines a reliable IT Engineer.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • How to Bypass Spam Filtering for Internal Senders Using PowerShell

    Intro:
    When internal emails from trusted coworkers suddenly stop showing up in your focused inbox or fail to trigger your Outlook rules, it’s easy to miss critical messages. In my case, one sender was previously blocked due to a spoofing incident, and although removed from the block list, her messages were still bypassing my folder rules—buried in the inbox. Message Trace confirmed the emails were delivered, but not filtered correctly. Here’s how I resolved the issue using PowerShell.

    🔍 Problem Recap:

    Despite the sender being trusted and allowed, her emails:

    • Skipped my Outlook inbox rules
    • Did not show up in Focused Inbox or designated folders
    • Were confirmed delivered via Message Trace
    • Were previously on the Blocked Sender List, but later removed

    The Exchange Admin Center (EAC) didn’t offer the flexibility I needed to create an accurate spam bypass rule. So I switched to PowerShell.

    🛠️ Solution: Create a Transport Rule via PowerShell

    Instead of struggling with the limited dropdowns in the modern Exchange portal, I used the New-TransportRule cmdlet to create a spam filter bypass rule in just a few lines.

    Here’s how:

    Connect-ExchangeOnline -UserPrincipalName [email protected]
    
    New-TransportRule -Name "Bypass Spam Filtering from Trusted Senders" `
      -From '[email protected]','[email protected]' `
      -SetSCL -1
    

    What it does:

    • Matches emails from the listed senders
    • Sets SCL (Spam Confidence Level) to -1, meaning “do not treat as spam”
    • Ensures messages bypass all anti-spam filters and go straight to your inbox

    ⚡ Why Use PowerShell?

    The new Exchange Admin Center UI (EAC) lacks direct options to set SCL or bypass spam filtering with precision. PowerShell:

    • Provides full control
    • Is faster and more reliable
    • Allows batch configuration
    • Gives access to legacy controls like -SetSCL

    🔐 Notes:

    • Email addresses in the example are redacted for privacy
    • Make sure you have the Exchange Online PowerShell v3 module installed
    • You can verify the rule with:
    Get-TransportRule "Bypass Spam Filtering from Trusted Senders" | Format-List Name, From, SetSCL
    

    Conclusion:
    PowerShell remains the most powerful tool in any IT administrator’s arsenal—especially when the GUI can’t keep up. If you ever run into stubborn mail delivery or spam issues, consider creating targeted transport rules using PowerShell. It’s fast, clean, and gets the job done without frustration.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

  • From IIS Logs to Iron Discipline: How My Son and I Share the Same Grit in Fitness and IT

    Introduction

    Confidence is earned — often forged in quiet moments when no one’s watching. Often, it’s forged in quiet moments when no one’s watching.
    Whether I’m at a blank PowerShell console or gripping a loaded barbell, the principle is the same: discipline, consistency, no shortcuts.


    I’ve Always Been an ABC Person

    I’ve always lived by three words: Always Be Curious.

    That curiosity pulled me into IT. I lacked credentials, but I had grit and a drive to learn.
    I’ve never believed in shortcuts — not in spiritual growth, troubleshooting IIS, or transforming your body.
    Temporary fixes cover symptoms — but they rarely solve the root cause.

    You don’t fix problems with assumptions, Google, and a quick prayer. You fix them with logs, tools, and patience.
    That’s what I’ve learned — the hard way — through years of trial, error, and persistence.


    Why I Don’t Believe in Band-Aid Fixes

    Quick fixes fade fast. They treat symptoms, not root problems.
    Take IIS, for example — a broken SSL binding or 503 error might vanish temporarily, but it usually comes back with greater risk.

    That’s why I value discipline over speed. Precision over panic.

    It’s the same principle my son applies as he preps for his first fitness competition. He doesn’t rely on shortcuts or crash diets. And definitely no “quick fixes” to look lean. Just clean eating, consistent training, and unwavering focus — day in and day out.

    Watching him chase excellence reminds me of my early days — hungry, overlooked, and determined to make noise through results, not volume.

    I didn’t wait for permission—I made my own path.
    I spoke up when others stayed silent, dove into neglected technologies…, and taught myself to harden and scale IIS in real-world, high-pressure environments.
    I wasn’t the loudest voice in the room, but I became the go-to problem solver—delivering solutions that worked the first time.


    Triple D: Discipline. Dedication. Determination.

    Tonight’s fuel: Baked Atlantic salmon with lemon, garlic, and power greens — topped with walnuts and 42g of clean protein. Discipline doesn’t stop at the keyboard — it continues at the dinner table.

    Confidence isn’t found. It’s forged — through repetition, patience, and precision. Knowledge doesn’t come overnight. Much like getting fit, it takes what I call the Triple D:
    Discipline. Dedication. Determination.

    Tonight’s early dinner? Fresh Atlantic salmon baked with lemon, garlic, and a bed of power greens. To boost nutrients, I topped it with walnuts and washed it down with 42g of Fairlife protein. I eat twice a day — every bite calculated, nutrient-packed, and designed for peak performance..

    As for training, I’m in the zone six days a week — no shortcuts. Mostly bodyweight: push-ups, sit-ups, glute bridges, crab walks, planks, and shadow boxing. I train with intensity — until the burn says I’m done..

    That’s how I’ve kept my edge for decades — by showing up, sweating, and sticking to the plan.

    You train your body the way you train your mind. Log files are your feedback loop. Errors are your instructors. Study. Adapt. Try again.

    That mindset shapes how I approach IT and life.


    Bruce Lee Said It Best

    “If you always put limits on everything you do — physical or anything else — it will spread into your work and into your life. There are no limits. There are only plateaus, and you must not stay there, you must go beyond them.” — Bruce Lee

    I carry that with me daily. In both IT and fitness, mastery is a moving target — the moment you think you’ve arrived, growth demands a new challenge.


    My Son’s Grit, My Quiet Pride

    24 days out from competition.

    “Starvation is at its highest for me… it feels like I’m crawling my way to survive all day long. This is the toughest sport I’ve ever experienced.”

    Those are the words my son texted me as he prepares for his upcoming debut at TheFitExpo in Anaheim on August 2, 2025.

    His commitment to clean eating, intense workouts, and honest prep — no shortcuts — mirrors the way I built my IT career: with sweat equity.

    He used to dominate dance stages as a four-time All-Male hip-hop champion with West Covina High School. After college, he became a CNA and now works as a gym personal trainer — turning his passion for fitness into purpose. He’s carrying the torch of discipline — and I couldn’t be prouder.


    From IIS to Iron: A Shared DNA

    Take IIS — often dismissed as legacy tech, yet it powers critical internal systems beneath the buzzwords. But the reality is, it still powers critical internal applications..

    When it breaks — when HTTP 500 errors fill your logs — assumptions won’t fix it.
    First, trace the issue. Dig through the logs. Slow down. Understand the root cause — then take action.

    That’s the same mental muscle my son flexes in the gym.
    He logs his intake. Monitors results. Makes adjustments.

    We train differently — I with bodyweight and discipline, he with prep meals and physique goals.
    The goals differ — but the grit is the same.


    Here’s a script I wrote to search the most recent IIS log file for errors — the same kind of tool I use to avoid assumptions and find the real issue:

    🧰 PowerShell Script: Digging Through IIS Logs

    # Find the latest IIS log and search for error codes
    $LogPath = "C:\inetpub\logs\LogFiles\W3SVC1"
    $LatestLog = Get-ChildItem -Path $LogPath -Filter *.log | Sort-Object LastWriteTime -Descending | Select-Object -First 1
    Select-String -Path $LatestLog.FullName -Pattern " 500 " | Select-Object LineNumber, Line
    

    If it’s worth fixing, it’s worth fixing the right way.


    Conclusion: Carry On

    This week’s Church hymn, “Carry On,” stirred something quiet in me —
    It reminded me that sometimes, the holiest thing we can do is simply hold our ground.
    It reminded me:



    It reminded me:

    “Firm as the mountains around us,
    Stalwart and brave we stand…”

    We don’t walk this path alone.
    Others cleared the way — now it’s our turn to keep going.

    This isn’t about spotlighting effort.
    It’s for the ones working in silence.
    In server rooms. In waiting rooms. In small spaces where no one claps.

    The message doesn’t seek attention — it invites action: carry on.

    © 2012–2025 Jet Mariano. All rights reserved.
    For usage terms, please see the Legal Disclaimer.

error: Content is protected !!