Skip to content

VMWare Setup [Sec480]

ConnorEast edited this page May 1, 2026 · 2 revisions

SYS/SEC 480 - Environment Overview

This page documents the virtualization and DevSecOps environment built over the course of the semester. The environment was constructed on bare-metal hardware running VMware ESXi 8, managed through vCenter, and progressively automated using PowerCLI (via a custom PowerShell module) and Ansible.


Physical Layer

I had been assigned a dedicated physical server in which I needed to wipe before installing ESXi 8.x directly on the bare metal. The server was accessible via an iKVM console and configured with a static management IP. A virtual switch called 480-WAN was created on the hypervisor to connect virtual machines to the lab network (10.0.17.0/24).


vCenter Server

VMware vCenter Server Appliance (VCSA) 8.0 was deployed as a VM on the ESXi host. vCenter is VMware's centralized management platform for virtualized infrastructure. Where ESXi manages a single physical host, vCenter provides a single pane of glass to manage multiple ESXi hosts, their VMs, datastores, networking, and permissions from one interface.

What vCenter Enabled in this Environment

Centralized VM management: All virtual machines across the environment could be created, configured, started, stopped, and monitored from a single web UI or API endpoint rather than connecting to the ESXi host directly each time.

Datacenter and inventory organization: A datacenter object (480-yourname) was created inside vCenter to logically group the ESXi host and all of its VMs, folders, datastores, and networks into one organized hierarchy.

PowerCLI target: Every PowerCLI command in the 480-utils module connects to vCenter (at vcenter.east.local) rather than directly to ESXi. All automation — cloning, network configuration, IP retrieval, hardware spec changes — is issued through vCenter's API, which then orchestrates the underlying ESXi host.

SSO and identity integration: vCenter was joined to a self created Active Directory domain, allowing domain administrators to log into vCenter using their AD credentials. The domain's Domain Admins group was granted vCenter Administrator rights, enabling role-based access control tied to the existing identity infrastructure.

Snapshot and clone foundation: vCenter's API exposes snapshot management and linked clone creation, which are the core operations used by 480-utils throughout the semester. PowerCLI's New-VM -LinkedClone and Get-Snapshot cmdlets operate through the vCenter API.


Core Infrastructure Network (480-WAN / 10.0.17.0/24)

The core management network hosted the foundational services of the environment. All infrastructure VMs started here before the Blue network was segmented out.

VyOS Firewall (480-fw) — 10.0.17.2

A VyOS router/firewall served as the default gateway for the 480-WAN network and provided NAT for internet access. VyOS was also used as the base image for all firewall VMs in the environment. A "Base" snapshot was taken of a clean VyOS install and all subsequent firewalls were deployed as linked clones from it.

Windows Server 2019 Domain Controller (dc1) — 10.0.17.4

A fully sysprepped Windows Server 2019 base image was created, snapshotted, and then used to stand up dc1. Active Directory Domain Services, DNS, and DHCP were all configured remotely via PowerShell over SSH from the xubuntu-wan management box. The domain (yourname.local) hosted all users, groups, DNS records, and DHCP scopes for the core network. A named domain administrator account was created and used for all subsequent domain-joined operations including vCenter SSO.

DNS records were created for vcenter, 480-fw, xubuntu-wan, and dc1. DHCP was configured with a scope of 10.0.17.101–150.

vCenter Server Appliance — 10.0.17.3

Deployed as a VM on the ESXi host and joined to the yourname.local domain. See the vCenter section above for detail on its role.

Xubuntu Management Workstation (xubuntu-wan) — 10.0.17.100

The primary management machine from which all automation was authored and executed. PowerShell, PowerCLI, VSCode, Git, and Ansible were all installed here. This machine served as the Ansible control node for every playbook run in the environment.


Base VM Library

Before any automation could deploy VMs rapidly, a library of clean base images was established. Base VM were prepared with had VMware Tools installed and were snapshotted at a clean state with the snapshot named "Base". New VMs were then deployed as either linked clones (sharing the base disk, low storage overhead) or full clones (independent copies) from these snapshots.

Three base images were maintained: a Windows Server 2019 base (sysprepped, no MAC address, no mounted ISO), a VyOS base (clean router config), and an Ubuntu Server base (minimal install with VMware Tools). A Rocky Linux 9 Minimal base was added later for the Blue network.

The early standalone scripts (mk-winsrv.sh, mk-vyos.sh, mk-ubusrv.sh) demonstrated the raw PowerCLI pattern for full cloning: create a temporary linked clone from the Base snapshot, clone that into a full independent VM, take a new Base snapshot on the result, then delete the temporary linked clone. This pattern was later generalized inside 480-utils.


480-utils PowerShell Module

The core automation tool built over the course of the semester. 480Utils.psm1 wraps VMware PowerCLI into documented, reusable functions. A companion config file (480.json) stores environment-specific values — the vCenter address, ESXi host IP, datastore name, and default snapshot name.

Configuration and Connection

Get-480Config reads 480.json and returns a PowerShell object. All other functions call this first to load environment values. Connect-480VIServer connects to vCenter using the loaded config, checks if a session is already active to avoid duplicates, and suppresses certificate warnings for lab use.

VM Selection

Select-VM lists all VMs in vCenter (optionally filtered to a named folder) and prompts the user to pick one by number. It is used as an interactive fallback in any function where a VM name is not passed directly as a parameter.

Cloning

New-LinkedClone creates a linked clone of a VM from a named snapshot. It prompts for clone name, ESXi host, and datastore if not provided, defaulting to config values. It checks for duplicate VM names before proceeding. New-FullClone produces an independent copy by creating a temporary linked clone, cloning that into a new standalone VM, snapshotting it at "Base", and then deleting the temporary clone with -DeletePermanently so no orphaned disk files are left on the datastore.

Power Management

Invoke-StartVM and Invoke-ShutdownVM start or gracefully shut down a VM by name, warning if the VM is already in the target state. Shutdown uses Stop-VMGuest (VMware Tools graceful shutdown) rather than a hard power-off.

Networking

Create-Network creates a new vSwitch and port group on the ESXi host, checking for existing objects first so the function is safe to re-run. Set-VMNetwork sets a VM's network adapter to a specified port group, listing all adapters so the correct index can be targeted.

IP and Hardware

Get-VMIPAddress retrieves the IPv4 address of a running VM via VMware Tools guest info. A -WaitForIP switch polls on a configurable timeout, useful immediately after boot. It falls back to scanning all NICs if the primary guest IP field reports an IPv6 address. Set-VMSpec changes CPU count, RAM, and disk size. The VM must be powered off; the function offers to shut it down gracefully first. Disk shrinking is explicitly blocked.

Windows Guest IP Configuration

Set-WindowsIP sets a static IP on a Windows VM by running netsh commands through PowerCLI's Invoke-VMScript. This requires only VMware Tools — no SSH or WinRM. The guest password is accepted as a SecureString and the plain-text value is extracted only at call time using System.Net.NetworkCredential, never written to disk or logged.


Blue Network Segment (10.0.5.0/24)

A second isolated network was created to simulate a segmented user and services environment. A new vSwitch and port group were created on the ESXi host via 480-utils. A dedicated VyOS firewall (fw-blue1) was deployed as a linked clone of the VyOS base and connected between the 480-WAN uplink and the Blue LAN. A static route was added to the core 480-fw firewall so traffic from 480-WAN destined for 10.0.5.0/24 was routed to fw-blue1.

fw-blue1 — 10.0.5.2

The Blue network gateway, configured entirely via Ansible. The VyOS configuration was templated in Jinja2 (config.boot.j2) with variables for interface IPs, hostname, gateway, name server, NAT, and the login password hash. The password was prompted at playbook runtime, hashed to SHA-512 via Ansible's password_hash filter, and injected into the template — the plaintext never touched the config file or the repository. After writing the config, the playbook bounced the router with a backgrounded sleep 5 && shutdown -r now to preserve SSH session continuity. A follow-up playbook used the vyos_config Ansible module to configure a DHCP server on fw-blue1 with pool range 10.0.5.75–10.0.5.125.

Rocky Linux Servers (rocky-1, rocky-2, rocky-3) — 10.0.5.10, 10.0.5.11, 10.0.5.12

Three Rocky Linux 9 Minimal linked clones deployed via 480-utils that initially received DHCP addresses. An Ansible playbook post-provisioned each: adding the deployer user's SSH public key, creating a passwordless sudo drop-in, setting the hostname, and converting the DHCP assignment to a static IP using nmcli.

Ubuntu Servers (ubuntu-1, ubuntu-2) — 10.0.5.30, 10.0.5.31

Two Ubuntu Server linked clones, post-provisioned with the same structure as Rocky. Static IP configuration used a Jinja2-templated netplan YAML written to /etc/netplan/ followed by netplan apply.

Windows Domain Controller (dc-blue1) — 10.0.5.5

A Windows Server 2019 linked clone deployed to the Blue LAN. Its static IP was set using Set-WindowsIP from 480-utils via Invoke-VMScript, requiring no network access to the VM beforehand. Active Directory was then deployed entirely via Ansible: the playbook set the local Administrator password, renamed the host (with reboot), installed AD DS and DNS features, created the new forest for BLUE1.LOCAL, waited for DNS services to initialize, added a DNS forwarder, and built the OU structure (Accounts, Groups, Servers, Workstations under the BLUE1 container). No passwords were stored in the playbook or inventory — all were prompted at runtime using vars_prompt with private: yes.


SIEM — Velociraptor (blue-siem) — 10.0.5.5

Velociraptor is an open-source Digital Forensics and Incident Response (DFIR) platform used as the environment's SIEM. It was chosen for its lightweight footprint, built-in artifact collection capabilities, and ability to run fully self-hosted without a vendor account or license wall.

The server was deployed to a Rocky Linux VM on the Blue LAN via Ansible. The playbook handled the full installation without manual steps: installing prerequisites and firewalld, opening ports 8000 (agent frontend) and 8889 (GUI), setting SELinux to permissive, downloading the musl-linked Velociraptor binary from GitHub, generating a self-signed server config, patching the config to bind to the correct server IP, writing and enabling a systemd service unit, creating the admin user via expect to handle the interactive password prompt, and fetching the resulting client config to the Ansible controller for use by the agent playbook.

A separate agent playbook installed the Velociraptor client on target Blue LAN hosts. It selected the correct binary for the OS family (glibc for Ubuntu, musl for Rocky), deployed the client config, wrote a systemd service unit, and verified the agent was running and connecting by examining journalctl output. The GUI was accessible at https://10.0.5.5:8889 and agents communicated outbound to https://10.0.5.5:8000.


Skills Developed

Skill Description
VMware ESXi and vCenter Administration Installing ESXi on bare metal, managing datastores, virtual switches, port groups, VMs, and snapshots through the vSphere web UI and API. Understanding the relationship between the ESXi hypervisor and vCenter as its management and automation layer.
PowerShell and PowerCLI Writing modular, reusable PowerShell organized into a .psm1 module with a JSON-driven config. Using PowerCLI cmdlets to drive VM lifecycle operations, network configuration, hardware spec changes, and guest OS scripting through VMware Tools.
Windows Server Administration Sysprepping Windows Server 2019, configuring Active Directory Domain Services, DNS, and DHCP entirely from the command line over SSH. Forest and domain creation, OU structure design, and domain user management.
Ansible Automation Writing idempotent playbooks for Linux and Windows targets. Using modules including vyos_config, win_domain, ansible.builtin.hostname, ansible.posix.authorized_key, and ansible.builtin.systemd. Templating configuration files with Jinja2. Handling secrets safely with vars_prompt and the password_hash filter.
Linux Server Administration Post-provisioning Rocky Linux and Ubuntu servers: user management, sudoers configuration, SSH key-based authentication, and static IP assignment via nmcli and netplan.
Network Segmentation and Routing Designing a multi-segment virtual network, configuring VyOS as a NAT gateway and DHCP server, adding inter-network static routes, and connecting DNS forwarding between segments.
DFIR Tooling Deploying Velociraptor as a self-hosted SIEM/DFIR platform, generating and distributing agent configs, and verifying telemetry flow from endpoints to the server through Ansible.
DevSecOps Practices Source-controlling all scripts, playbooks, and templates in Git. Keeping secrets out of repositories. Using SecureString for credential handling in PowerShell and vars_prompt in Ansible. Documenting environment builds in a tech journal alongside the code that produced them.