Tag: PowerShell

  • 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.

  • IT Climb With Purpose: Rising Through Faith, Grit, and Growth – Jet Mariano

    —Climbing With Purpose in IT, Life, and Light

    They say when you see a man on top of the mountain, he didn’t fall there.

    He planned the climb, stumbled on jagged trails, and kept going even when the sky turned gray.

    This post isn’t just about photography, or starting a new role, or PowerShell scripts.
    It’s about finding your footing again when life shakes your routine—whether you’re debugging a script, chasing stars at 2AM, or collecting a laptop that brings back a hundred memories.

    You’ll find stories about IT challenges, career shifts, Milky Way photography, emotional storms—and most of all, how to rise above the blues when everything feels heavy.

    Carrying the gear, chasing the stars—because purpose isn’t found at the summit, it’s carried every step.

    ⛰️ New Job, New Mountain

    They say starting a new job is like standing at the foot of a mountain.
    The view is exciting—but the climb? Uncertain.

    No one really tells you what it feels like to start over.
    You’re learning people, process, and pace all at once.
    Even if you’re an expert, you’re blind on day one.
    And if you’re in IT, like me, the terrain can feel like a minefield.

    Pros:

    • A fresh start
    • The chance to sharpen or add new skills
    • A clean slate to prove your value again

    Cons:

    • Culture shock
    • Pressure to perform quickly
    • Emotional whiplash, especially when you’re still letting go of the last place

    I’ve lived this cycle more than ten times—moving from job to job, project to project.
    From my first IT gig where I got fired after just a few days (yes, really), to roles in telecom, manufacturing, finance, education, government, and now infrastructure engineering—every restart brought unexpected lessons.

    That early firing? It broke me. But it built me too.
    It taught me to expect the unknowns.
    It made this scripture real to me:

    “For of him unto whom much is given much is required.” – Luke 12:48

    And that’s what they don’t tell you:
    Starting a job doesn’t just mean you’re on probation—
    it means you’re learning the language, the culture, the personalities, and the systems.
    Sometimes you’re expected to run before you even learn where the shoes are.

    So how do I handle it?

    Soft skills.
    Empathy.
    Active listening.
    And above all, humility.

    The technical side is always tough, but people are the real challenge.
    Knowing how to adapt, how to read the room, and when to ask versus when to figure it out—those are the survival tools.

    “If ye are prepared ye shall not fear.” – D&C 38:30
    That verse? It’s more than a motto.
    It’s how I show up—every first day, every new login, every fresh deployment.

    I’ve seen people not make it past the 90-day mark.
    Sometimes they didn’t fit.
    Sometimes the job was the problem.
    Sometimes—let’s be honest—they oversold their résumé, got lucky at the interview, and then the real work revealed the truth.

    Others just get carried by the blues—barely holding it together until their tank runs empty.

    That’s why preparation matters.
    You don’t go to war without gear.
    You don’t climb a mountain without checking your boots.
    And you don’t start a new role without anchoring your mindset.


    Finally, land where you love.
    A job shouldn’t just pay the bills — it should fuel your purpose.
    When you love what you do, it’s a win-win:
    You rise, and so does the company.

    But if you’re stuck in a rut just to make ends meet…
    eventually, it drains more than your energy —
    it drains your spirit.

    So don’t just look for a job.
    Climb toward work that gives you life.

    A glimpse of the heavens through earthly shadows—chasing the Milky Way isn’t just about light, it’s about learning to see in the dark.

    🌌 Chasing the Milky Way

    There’s something sacred about standing in the desert with the Milky Way overhead.

    I’ve chased it from Joshua Tree in California to Grand Canyon in Arizona, Monument Valley in Utah, and Moab—and every time, I feel the same awe.

    My process is disciplined and deliberate. I survey the area in daylight, using the PhotoPills app to map the galactic core. Then I visualize my composition, mark the safest route from the car, and prep all my gear.

    • Primary lens: Nikon 14-24mm f/2.8G
    • Backup: Nikon 24mm f/1.4G
    • Tripod, remote shutter, red LED headlamp
    • Pre-focus and manual mode to avoid lens hunting
    • ISO, shutter speed, aperture—all dialed in

    Everything is anticipated—just like in IT. One missed step, and the whole shot—or system—can fail. Just seeing the Milky Way with your own eyes is breathtaking—but to compose it meaningfully, that takes skill.

    A great Milky Way shot is not just about stars—
    it’s about how you prepare in the dark.

    🛠 When PowerShell Becomes Armor

    It’s Monday morning. Your inbox is full. A user can’t log in, the SQL service is down, and your boss wants answers.

    If you’re not ready, it feels like going to war without armor.

    That’s where PowerShell becomes your weapon.

    Let’s say you’re troubleshooting remote system uptime across 50 servers. Instead of logging in one by one:

    powershellCopyEdit$servers = Get-Content .\ServerList.txt
    $results = foreach ($server in $servers) {
        Try {
            $uptime = (Get-CimInstance -ComputerName $server -ClassName win32_operatingsystem).LastBootUpTime
            [PSCustomObject]@{
                Server = $server
                LastBoot = $uptime
            }
        } Catch {
            [PSCustomObject]@{
                Server = $server
                LastBoot = "Unreachable"
            }
        }
    }
    $results | Format-Table -AutoSize
    📊 Real-time uptime scan across multiple servers using PowerShell – one script, instant clarity.
    
    
    
    
    

    In just 10 seconds, you’ve got eyes on the entire server fleet. Who’s up. Who’s down. Who’s silent. The sharp tech doesn’t panic—he pinpoints, isolates, and executes. Fast. Focused. Fix deployed.

    PowerShell isn’t just a tool—it’s your recon drone.

    Like photographing the Milky Way, the best troubleshooting happens when everything is ready before chaos begins.

    🎈 Rise Above the Blues

    You’re not a machine.
    You weren’t built to be immune to fear, fatigue, or failure.

    Unlike AI, we can’t predict everything. Life throws us emotional landmines—doubt, loneliness, weariness, fear and grief. And sometimes, it hits out of nowhere. A memory. A song. A walk past an empty office.

    But here’s what I’ve learned:

    You don’t need to erase the blues—
    you rise above them.

    Just like launching a balloon skyward, it takes intention:

    • You eat clean even when you feel messy.
    • You work out even when your spirit is sore.
    • You create even when motivation lags.
    • And yes, you kneel—asking God for strength.

    Whether you’re debugging a failed script, standing under a galaxy of stars, or simply trying to make it through a quiet night…

    💪 The Endurance Factor

    Endurance isn’t just for the gym — it’s a mindset I carry into every part of my life. Whether I’m hammering out code at 2AM or waiting patiently for the perfect light in photography, the principle is the same: lasting through the grind matters more than talent alone. Battle rope training reminds me that breakthroughs come after fatigue — in the gym, in IT, and behind the lens. Those who endure, evolve. Those who push past comfort zones, create lasting impact.

    Each battle rope rep runs 180 seconds — just like a boxing round. I push through up to 6 rounds, simulating the intensity of a 12-round fight. It’s not just training — it’s conditioning for IT, for life, for the moments when quitting is easier. Endurance is the quiet strength behind every breakthrough.

    🎯 Precision Under Pressure: Shooting, Striking, and Showing Up

    Whether I’m at the range or on the mat, the ritual is the same:
    Prepare. Focus. Repeat.

    When I train with my pistols, I practice daily with dummy rounds—loading, unloading, chamber checks, slide control. I break them down, clean them, reassemble them blindfolded—until every movement is instinctive.

    It’s the same with MMA and air punching drills. My body is conditioned not just for strength, but discipline. Every strike, every stance, is deliberate. I don’t train to show off—I train to be ready.

    You see, when it’s Monday morning and something breaks at work—your system is down, a PowerShell script fails, a teammate’s counting on you—that’s your moment. That’s your live fire.

    You don’t rise to the occasion.
    You fall back on your training.

    Whether I’m troubleshooting a crashed server, hiking a steep trail for that perfect Milky Way shot, or helping someone start their climb—discipline is the thread. I’ve learned that showing up prepared is half the victory.

    Just like the range:

    • No second chances if you’re not ready.
    • Precision comes from practice.
    • And calm comes from confidence.

    🏁 Conclusion

    There are mountains I’ve climbed—in IT, in life, and in silence.

    From my early days as a PC Support Specialist at USC, through roles in telecom (Verizon), manufacturing (Alcoa), local government (City of West Covina), law firms, education (The Claremont Colleges), our Worldwide Church, regional banking (City National Bank), fintech (Payforward), retail (Monster Energy), global finance (PIMCO), and now as an Infrastructure Engineer in Utahnone of those summits came easy.

    Even when I chase the stars with my camera, it’s the climb that makes the view meaningful.

    So to anyone out there starting over, picking up the pieces, or doubting their path:

    You don’t fall on a mountaintop.
    You climb it.
    And you keep climbing.
    Even when you’re tired.
    Especially when you’re tired.

    —Jet Mariano

    © 2012–2025 Jet Mariano. All rights reserved.

    For usage terms, please see the Legal Disclaimer.

error: Content is protected !!