Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PowerShell Environment

A modular, cross-platform PowerShell environment with a declarative Azure Bastion routing engine. Direct port of bash_environment — same commands, same config file, pick your shell.

Shell Parity

Command Bash PowerShell Description
bastion Show help and list VMs
bastion <alias> Background tunnel
bastion <alias> ssh Interactive SSH session
list_vms List configured VMs
list_connections Show active tunnels
cleanup_tunnels Tear down connections
connect-vm Escape hatch wrapper
start<alias> Start VM (auto-generated)
stop<alias> Stop VM (auto-generated)

Both shells read the same .bastion_topology.conf file — configure once, use from either shell.

Repository Structure

profile.ps1                  # Entry point — sources profile.d/* in order
profile.d/
  15-ssh_agent.ps1           # Cross-platform SSH agent management
  20-editor.ps1              # PSReadLine vi-mode, editor config
  30-history.ps1             # History settings
  30-azure_routing.ps1       # Core Azure Bastion routing engine (~500 lines)
.bastion_profiles/           # Escape hatch scripts for edge-case topologies
scripts/                     # Standalone utilities

Installation

Option 1: Source from existing profile

Add this line to your $PROFILE:

. ~/git/pwsh_environment/profile.ps1

To find your profile location:

$PROFILE
# Usually: C:\Users\<you>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Option 2: Symlink (PowerShell 7+ on Windows as Admin)

New-Item -ItemType SymbolicLink -Path $PROFILE -Target ~/git/pwsh_environment/profile.ps1 -Force

Option 3: Copy modules individually

# Create profile.d if it doesn't exist
$profileDir = Join-Path (Split-Path $PROFILE) "profile.d"
New-Item -ItemType Directory -Path $profileDir -Force

# Copy modules
Copy-Item ~/git/pwsh_environment/profile.d/*.ps1 $profileDir/

# Add loader to profile
Add-Content $PROFILE @'

# Load modules from profile.d
$profileDir = Join-Path (Split-Path $PROFILE) "profile.d"
if (Test-Path $profileDir) {
    Get-ChildItem -Path $profileDir -Filter "*.ps1" | Sort-Object Name | ForEach-Object {
        . $_.FullName
    }
}
'@

Configuration

Uses the same .bastion_topology.conf as the bash version. Copy and configure:

Copy-Item ~/git/bash_environment/.bastion_topology.conf.example ~/.bastion_topology.conf
notepad ~/.bastion_topology.conf

Topology File Format

# alias|azure_name|resource_group|subscription|port|type|autostart|auth_type
BASTION_VMS=(
    "api0|vm-api-dev-01|rg-project-dev|Sub_Dev|12022|flat|true|azureuser"
    "jbox|vm-jumpbox-01|rg-sandbox|Sub_Sandbox|10022|tiered|false|entra"
    "secvdi|vm-secure-vdi-01|rg-secure|Sub_Secure|20000|flat-entra|false|entra"
)

# Dynamic properties
declare -A VM_PROPS
VM_PROPS["jbox_az_tunnels"]="2022:10.0.1.5:22 13389:10.0.1.6:3389"
VM_PROPS["global_default_bastion"]="bst-default-region-01"

Usage

# Show help and all configured VMs
bastion

# Establish a background tunnel (sets up port forwards)
bastion api0

# Drop into an interactive SSH session
bastion api0 ssh

# List all configured VMs and their routing settings
list_vms

# Show active connections and forwarded ports
list_connections

# Tear down tunnels
cleanup_tunnels api0    # Specific alias
cleanup_tunnels all     # Everything

# Override SSH username for a single connection
$env:BASTION_USER = "root"; bastion api0 ssh

# Start/stop VMs directly (auto-generated functions)
startapi0
stopapi0

Supported Topologies

1. Flat (flat)

Standard Azure Bastion tunnel directly to target VM.

  • Backgrounds az network bastion tunnel
  • Supports dynamic port forwarding via VM_PROPS[<alias>_az_tunnels]

2. Flat-Entra (flat-entra)

Azure Bastion with Entra ID (AAD) authentication.

  • Uses az network bastion ssh --auth-type AAD
  • Note: Dynamic port forwards (-L) not supported in interactive mode

3. Tiered (tiered)

Multi-hop routing via jumpbox with nested port forwarding.

  • az ssh vm --ip <jumpbox> with -L forwarding
  • Supports nested plink/ssh tunnels via VM_PROPS[<alias>_plink_tunnels]

Escape Hatches

For VMs that don't fit standard topologies (JIT access, VPN, reverse shells), create a profile script:

# ~/.bastion_profiles/<vm-alias>.ps1

function Connect-VMProfile {
    param([string]$Mode = "")
    
    # Custom connection logic here
    Write-Host "Requesting JIT access..."
    # az security jit-policy initiate ...
    
    Start-Sleep -Seconds 30
    bastion -VM "my-vm" -Mode $Mode
}

The connect-vm command will automatically use this instead of the standard engine.

Key Differences from Bash Version

Feature Bash PowerShell
Background processes & (disown) Start-Job
Associative arrays declare -A @{} hashtables
Process detection ps -ef | grep Get-Process + CIM
Port checking netstat | egrep netstat + Select-String
Escape hatch function connect() Connect-VMProfile

Prerequisites

  • PowerShell 7+ (recommended) or Windows PowerShell 5.1
  • Azure CLI (az) installed and authenticated
  • OpenSSH client (built into Windows 10+)
  • For tiered topology: PuTTY (plink.exe) optional

Cross-Platform Notes

This environment works on:

  • Windows — Native PowerShell, uses Windows OpenSSH Agent service
  • Linux/macOS — PowerShell Core, uses ssh-agent process management
  • WSL — Either bash_environment or pwsh_environment

Related

License

Private repository. Internal use only.

About

powershell environment

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages