From 1759682aef9b66da4233c247d9b0fd863138828f Mon Sep 17 00:00:00 2001 From: Patrick Toal Date: Tue, 28 Apr 2026 15:59:50 -0400 Subject: [PATCH] Initial hyper-v demo skeleton --- .gitignore | 35 ++++ CLAUDE.md | 346 +++++++++++++++++++++++++++++++++ README.md | 61 ++++++ ansible.cfg | 24 +++ collections/requirements.yml | 21 ++ group_vars/all.yml | 15 ++ group_vars/hyperv_hosts.yml | 18 ++ group_vars/web_servers.yml | 31 +++ group_vars/windows_servers.yml | 20 ++ inventory/production/hosts.yml | 30 +++ playbooks/install-iis.yml | 43 ++++ playbooks/patch-vms.yml | 29 +++ playbooks/provision-vm.yml | 25 +++ playbooks/sync-cmdb.yml | 39 ++++ 14 files changed, 737 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 ansible.cfg create mode 100644 collections/requirements.yml create mode 100644 group_vars/all.yml create mode 100644 group_vars/hyperv_hosts.yml create mode 100644 group_vars/web_servers.yml create mode 100644 group_vars/windows_servers.yml create mode 100644 inventory/production/hosts.yml create mode 100644 playbooks/install-iis.yml create mode 100644 playbooks/patch-vms.yml create mode 100644 playbooks/provision-vm.yml create mode 100644 playbooks/sync-cmdb.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9d9d74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# Ansible +*.retry +ansible.log +*.pyc +__pycache__/ + +# Collections +collections/ansible_collections/ + +# Sensitive files +*vault* +*secret* +*password* +*.key +*.pem + +# Environment files +.env +*.env + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.bak +*.old diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f8e7fd1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,346 @@ +# Hyper-V Windows Server Automation - Project Documentation + +## Project Overview + +This project demonstrates enterprise-grade automation for the complete lifecycle of Windows Server VMs on Hyper-V using Ansible Automation Platform (AAP), implementing GitOps and Infrastructure as Code (IaC) principles. + +**Target Audience**: Enterprise IT operations teams, infrastructure engineers, platform engineers + +**Deployment Platform**: Ansible Automation Platform 2.x (formerly Ansible Tower) + +**Future Roadmap**: Event-Driven Ansible (EDA) integration for reactive automation + +## Architecture + +### Technology Stack + +- **Automation Engine**: Ansible Core 2.15+ +- **Platform**: Ansible Automation Platform 2.4+ +- **Hypervisor**: Microsoft Hyper-V (Windows Server 2019/2022) +- **Guest OS**: Windows Server 2019/2022 +- **CMDB**: ServiceNow ITSM +- **Version Control**: Git (GitOps workflow) +- **Authentication**: Active Directory / Kerberos + +### Connectivity Model + +``` +Ansible Automation Platform + ↓ (WinRM over HTTPS/Kerberos) +Windows Hyper-V Host(s) + ↓ (Hyper-V PowerShell) +Windows Server VMs + ↓ (REST API) +ServiceNow CMDB +``` + +### Core Use Cases + +1. **VM Provisioning**: Automated creation of Windows Server VMs using unattended installation (autounattend.xml) +2. **Patch Management**: Automated Windows Update deployment triggered by git commits +3. **Application Deployment**: Install and configure applications (IIS demonstration) +4. **Configuration Management**: Day-2 operations and drift remediation +5. **CMDB Synchronization**: Bidirectional sync with ServiceNow CMDB + +## Project Structure + +``` +. +├── ansible.cfg # Ansible configuration with Windows/WinRM defaults +├── collections/ +│ └── requirements.yml # Required Ansible collections +├── inventory/ +│ ├── production/ +│ │ └── hosts.yml # Production inventory +│ └── staging/ +│ └── hosts.yml # Staging inventory (future) +├── group_vars/ +│ ├── all.yml # Global variables +│ ├── hyperv_hosts.yml # Hyper-V host configuration +│ ├── windows_servers.yml # Windows Server defaults +│ └── web_servers.yml # IIS/web server configuration +├── host_vars/ # Host-specific variables (future) +├── playbooks/ +│ ├── provision-vm.yml # VM provisioning workflow +│ ├── patch-vms.yml # Windows Update automation +│ ├── install-iis.yml # IIS deployment +│ └── sync-cmdb.yml # ServiceNow CMDB sync +├── roles/ # Custom roles (future development) +│ ├── windows_baseline/ # Windows hardening & baseline config +│ ├── hyperv_vm/ # Hyper-V VM management +│ ├── iis_webapp/ # IIS application deployment +│ └── servicenow_sync/ # ServiceNow integration +├── templates/ # Jinja2 templates (future) +│ └── autounattend.xml.j2 # Windows unattended install template +└── README.md # Quick start guide +``` + +## Key Design Patterns + +### GitOps Workflow + +All infrastructure changes flow through Git: +1. Engineer creates feature branch +2. Updates inventory or group_vars to define desired state +3. Commits and creates pull request +4. AAP webhook triggers job template for validation +5. After merge, AAP webhook triggers deployment + +### Idempotency + +All playbooks must be idempotent - safe to run multiple times without side effects. Use: +- `state: present` vs `state: absent` +- Conditional tasks with `when:` +- Changed/failed handlers +- Check mode support (`--check`) + +### Credential Management + +- **Never commit secrets to Git** +- Use AAP credential types for: + - Machine credentials (WinRM) + - ServiceNow credentials + - Domain join credentials +- Use Ansible Vault for sensitive variables in development + +### Role-Based Organization + +Future development should extract common patterns into roles: +- `roles/windows_baseline/`: Base Windows configuration +- `roles/hyperv_vm/`: VM lifecycle management +- `roles/iis_webapp/`: IIS deployment patterns + +## Technical Requirements + +### Prerequisites + +1. **Ansible Automation Platform** + - AAP 2.4 or later + - Controller configured with Windows machine credentials + - Execution environment with Windows collections + +2. **Hyper-V Environment** + - Windows Server 2019/2022 with Hyper-V role + - WinRM enabled and configured + - Kerberos authentication configured + - Sufficient storage for VM images + +3. **Network Requirements** + - WinRM ports (5985/5986) open from AAP to Hyper-V hosts + - WinRM ports open from AAP to managed Windows VMs + - DNS resolution for all hosts + - Active Directory domain membership + +4. **ServiceNow** + - ServiceNow instance with CMDB + - API user credentials + - CMDB table structure defined + +### Windows Remote Management Setup + +On all Windows hosts (Hyper-V and VMs): + +```powershell +# Enable WinRM with HTTPS +winrm quickconfig -transport:https +winrm set winrm/config/service/auth '@{Kerberos="true"}' +winrm set winrm/config/service '@{AllowUnencrypted="false"}' +``` + +## Development Guidelines + +### Adding New Playbooks + +1. Create playbook in `playbooks/` directory +2. Use descriptive names: `verb-noun.yml` (e.g., `deploy-webapp.yml`) +3. Include proper documentation in header +4. Add tags for selective execution +5. Implement check mode support +6. Test in staging environment first + +### Variable Precedence + +Follow this hierarchy (least to most specific): +1. `group_vars/all.yml` - Global defaults +2. `group_vars/.yml` - Group-specific +3. `host_vars/.yml` - Host-specific +4. Playbook `vars:` - Playbook overrides +5. Extra vars (`-e`) - Runtime overrides + +### Testing Strategy + +1. **Syntax Check**: `ansible-playbook --syntax-check playbook.yml` +2. **Check Mode**: `ansible-playbook --check playbook.yml` +3. **Limit Scope**: `--limit` to test on single host first +4. **Verbose Output**: Use `-v`, `-vv`, `-vvv` for debugging +5. **Staging First**: Always test in staging before production + +### Windows Module Best Practices + +- Use `ansible.windows.*` modules (not deprecated `win_*`) +- Always handle reboots explicitly with `ansible.windows.win_reboot` +- Use `register:` to capture task output +- Check `reboot_required` in results +- Use `failed_when:` for expected error conditions + +## AAP Integration + +### Job Templates to Create + +1. **Provision VM** - `playbooks/provision-vm.yml` + - Survey for VM name, IP, CPU, RAM + - Credential: Hyper-V machine credential + - Webhook enabled for GitOps + +2. **Patch VMs** - `playbooks/patch-vms.yml` + - Limit pattern for selective patching + - Scheduled for maintenance windows + - Credential: Windows machine credential + +3. **Deploy IIS** - `playbooks/install-iis.yml` + - Limit to web_servers group + - Credential: Windows machine credential + +4. **Sync CMDB** - `playbooks/sync-cmdb.yml` + - Scheduled daily + - Credentials: Windows + ServiceNow + +### Workflow Templates (Future) + +Create workflows for complex orchestration: +- **Full VM Lifecycle**: Provision → Configure → Deploy App → Update CMDB +- **Patch & Compliance**: Patch → Verify → Update CMDB → Generate Report + +### Event-Driven Ansible (Future) + +Planned EDA integrations: +- ServiceNow incident triggers remediation playbook +- Windows Event Log monitoring triggers security response +- Hyper-V alerts trigger capacity management +- Git webhook triggers deployment pipeline + +## Common Tasks + +### Bootstrap a New VM + +```bash +# Provision VM +ansible-playbook playbooks/provision-vm.yml \ + -e vm_name=DEMO-WEB01 \ + -e vm_ip_address=192.168.1.101 + +# Configure baseline +ansible-playbook playbooks/windows-baseline.yml --limit DEMO-WEB01 + +# Deploy application +ansible-playbook playbooks/install-iis.yml --limit DEMO-WEB01 + +# Update CMDB +ansible-playbook playbooks/sync-cmdb.yml --limit DEMO-WEB01 +``` + +### Patch All Windows Servers + +```bash +ansible-playbook playbooks/patch-vms.yml --limit windows_servers +``` + +### Update Specific Group + +```bash +ansible-playbook playbooks/patch-vms.yml --limit web_servers +``` + +## Troubleshooting + +### WinRM Connection Issues + +```bash +# Test WinRM connectivity +ansible hyperv_hosts -m ansible.windows.win_ping + +# Check with verbose output +ansible hyperv_hosts -m ansible.windows.win_ping -vvv +``` + +### Common Issues + +1. **Kerberos Authentication Failure** + - Verify DNS resolution (forward and reverse) + - Check domain join status + - Verify time synchronization + - Check Kerberos ticket: `klist` + +2. **Module Not Found** + - Install collections: `ansible-galaxy collection install -r collections/requirements.yml` + - Verify in AAP execution environment + +3. **Timeout Issues** + - Increase timeout in `ansible.cfg` + - Check network connectivity + - Verify WinRM service running + +## Security Considerations + +### Credential Storage + +- Use AAP credential vault (not Ansible Vault in production) +- Rotate credentials regularly +- Use least-privilege service accounts +- Separate credentials per environment + +### Network Security + +- Use WinRM over HTTPS (port 5986) +- Enable Kerberos encryption +- Implement network segmentation +- Use jump hosts/bastion for AAP + +### Compliance + +- Enable audit logging in AAP +- Log all playbook runs +- Track changes in ServiceNow CMDB +- Implement change approval workflow + +## Future Enhancements + +### Phase 2 - Advanced Features + +- [ ] Custom execution environment with all dependencies +- [ ] Ansible Vault integration for secrets +- [ ] Enhanced autounattend.xml templating +- [ ] VM template/image management +- [ ] Backup and DR automation + +### Phase 3 - EDA Integration + +- [ ] ServiceNow incident-driven remediation +- [ ] Windows Event Log monitoring +- [ ] Hyper-V performance monitoring +- [ ] Self-healing automation + +### Phase 4 - Enterprise Scale + +- [ ] Multi-region Hyper-V clusters +- [ ] RBAC and delegation model +- [ ] Compliance scanning and remediation +- [ ] Cost tracking and optimization +- [ ] Disaster recovery automation + +## Contributing + +This is a demonstration project. When extending: + +1. Follow existing patterns and structure +2. Test thoroughly in staging +3. Document all variables in group_vars +4. Use semantic versioning for releases +5. Update this CLAUDE.md with architectural changes + +## References + +- [Ansible Windows Guide](https://docs.ansible.com/ansible/latest/os_guide/windows_usage.html) +- [Ansible Automation Platform Docs](https://access.redhat.com/documentation/en-us/red_hat_ansible_automation_platform) +- [ServiceNow ITSM Collection](https://github.com/ansible-collections/servicenow.itsm) +- [Event-Driven Ansible](https://www.ansible.com/products/event-driven-ansible) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e28ad7e --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Hyper-V Windows Server Automation + +Enterprise-grade automation for Windows Server VM lifecycle management on Hyper-V using Ansible Automation Platform, GitOps, and Infrastructure as Code practices. + +## Overview + +This project demonstrates automated Windows Server VM management including: + +- **Provisioning**: Automated VM creation using autounattend.xml +- **Configuration Management**: Day-2 operations and application deployment +- **Patch Management**: Automated Windows updates via git commits +- **CMDB Integration**: ServiceNow CMDB synchronization +- **Event-Driven Automation**: Future EDA integration + +## Quick Start + +```bash +# Install required collections +ansible-galaxy collection install -r collections/requirements.yml + +# Run VM provisioning +ansible-playbook playbooks/provision-vm.yml -e vm_name=DEMO-WEB01 + +# Patch management +ansible-playbook playbooks/patch-vms.yml --limit windows_servers + +# Install IIS demo application +ansible-playbook playbooks/install-iis.yml --limit web_servers +``` + +## Project Structure + +``` +. +├── ansible.cfg # Ansible configuration +├── inventory/ # Inventory files +│ ├── production/ +│ └── staging/ +├── playbooks/ # Playbooks by use case +│ ├── provision-vm.yml +│ ├── patch-vms.yml +│ ├── install-iis.yml +│ └── sync-cmdb.yml +├── roles/ # Custom roles +├── group_vars/ # Group variables +├── host_vars/ # Host-specific variables +└── collections/ # Ansible collections + └── requirements.yml +``` + +## Prerequisites + +- Ansible Automation Platform 2.x +- Hyper-V Server or Windows Server with Hyper-V role +- Windows Server ISO images +- ServiceNow instance (for CMDB integration) +- Active Directory domain (for authentication) + +## Documentation + +See [CLAUDE.md](CLAUDE.md) for detailed architectural documentation and development guidance. diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..c87ba5f --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,24 @@ +[defaults] +inventory = inventory/production +host_key_checking = False +retry_files_enabled = False +roles_path = roles +collections_path = collections +interpreter_python = auto_silent +timeout = 30 + +# Windows-specific settings +ansible_connection = winrm +ansible_winrm_transport = kerberos +ansible_winrm_server_cert_validation = ignore + +# Logging +log_path = ./ansible.log + +[privilege_escalation] +become = True +become_method = runas +become_user = Administrator + +[ssh_connection] +pipelining = True diff --git a/collections/requirements.yml b/collections/requirements.yml new file mode 100644 index 0000000..d65729d --- /dev/null +++ b/collections/requirements.yml @@ -0,0 +1,21 @@ +--- +collections: + # Windows management + - name: ansible.windows + version: ">=2.0.0" + + # Community Windows modules + - name: community.windows + version: ">=2.0.0" + + # General utilities + - name: ansible.builtin + version: ">=2.0.0" + + # ServiceNow integration + - name: servicenow.itsm + version: ">=2.0.0" + + # Event-Driven Ansible (future) + - name: ansible.eda + version: ">=1.0.0" diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..29cdd2d --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,15 @@ +--- +# Global variables for all hosts + +# Domain settings +domain_name: example.com +domain_netbios: EXAMPLE + +# ServiceNow CMDB integration +servicenow_instance: dev12345.service-now.com +servicenow_table: cmdb_ci_win_server + +# Tagging and metadata +project_name: hyperv-automation +environment: "{{ inventory_dir | basename }}" +managed_by: ansible diff --git a/group_vars/hyperv_hosts.yml b/group_vars/hyperv_hosts.yml new file mode 100644 index 0000000..3f056b4 --- /dev/null +++ b/group_vars/hyperv_hosts.yml @@ -0,0 +1,18 @@ +--- +# Hyper-V host configuration + +# Default VM settings +default_vm_cpu_count: 2 +default_vm_memory_gb: 4 +default_vm_disk_size_gb: 60 + +# Network settings +default_vm_switch: "Internal Switch" +default_vm_vlan: 100 + +# VM storage paths +vm_storage_path: "D:\\VMs" +iso_storage_path: "D:\\ISOs" + +# Windows Server ISO +windows_server_iso: "{{ iso_storage_path }}\\Windows_Server_2022.iso" diff --git a/group_vars/web_servers.yml b/group_vars/web_servers.yml new file mode 100644 index 0000000..326a627 --- /dev/null +++ b/group_vars/web_servers.yml @@ -0,0 +1,31 @@ +--- +# Web server configuration + +# IIS features to install +iis_features: + - Web-Server + - Web-WebServer + - Web-Common-Http + - Web-Default-Doc + - Web-Dir-Browsing + - Web-Http-Errors + - Web-Static-Content + - Web-Http-Redirect + - Web-Health + - Web-Http-Logging + - Web-Performance + - Web-Stat-Compression + - Web-Dyn-Compression + - Web-Security + - Web-Filtering + - Web-Mgmt-Tools + - Web-Mgmt-Console + +# Application pool settings +iis_app_pool_name: DefaultAppPool +iis_app_pool_identity: ApplicationPoolIdentity + +# Website settings +iis_website_name: Default Web Site +iis_website_port: 80 +iis_website_path: C:\inetpub\wwwroot diff --git a/group_vars/windows_servers.yml b/group_vars/windows_servers.yml new file mode 100644 index 0000000..9e854b8 --- /dev/null +++ b/group_vars/windows_servers.yml @@ -0,0 +1,20 @@ +--- +# Windows Server configuration + +# Windows Update settings +windows_update_categories: + - CriticalUpdates + - SecurityUpdates + - UpdateRollups + +# Common Windows features +windows_features_remove: + - Windows-Defender + +# Timezone +timezone: "Eastern Standard Time" + +# DNS servers +dns_servers: + - 192.168.1.1 + - 192.168.1.2 diff --git a/inventory/production/hosts.yml b/inventory/production/hosts.yml new file mode 100644 index 0000000..a3fb0ac --- /dev/null +++ b/inventory/production/hosts.yml @@ -0,0 +1,30 @@ +--- +all: + children: + hyperv_hosts: + hosts: + hyperv01.example.com: + ansible_host: 192.168.1.10 + + windows_servers: + children: + web_servers: + hosts: + # Provisioned VMs will be added here + # DEMO-WEB01: + # ansible_host: 192.168.1.101 + + app_servers: + hosts: + # Application servers + + db_servers: + hosts: + # Database servers + + vars: + # Windows connection settings + ansible_connection: winrm + ansible_winrm_transport: kerberos + ansible_winrm_server_cert_validation: ignore + ansible_port: 5986 diff --git a/playbooks/install-iis.yml b/playbooks/install-iis.yml new file mode 100644 index 0000000..b6e52ad --- /dev/null +++ b/playbooks/install-iis.yml @@ -0,0 +1,43 @@ +--- +- name: Install and configure IIS + hosts: web_servers + gather_facts: true + + tasks: + - name: Install IIS features + ansible.windows.win_feature: + name: "{{ iis_features }}" + state: present + register: iis_install + + - name: Reboot if required + ansible.windows.win_reboot: + reboot_timeout: 3600 + when: iis_install.reboot_required + + - name: Create demo web content + ansible.windows.win_copy: + content: | + + + + Demo IIS Site - {{ inventory_hostname }} + + +

Welcome to {{ inventory_hostname }}

+

This server was configured by Ansible Automation Platform

+

Deployment Date: {{ ansible_date_time.iso8601 }}

+ + + dest: "{{ iis_website_path }}\\index.html" + + - name: Ensure IIS service is running + ansible.windows.win_service: + name: W3SVC + state: started + start_mode: auto + + - name: Update CMDB with IIS installation + ansible.builtin.debug: + msg: "Would update ServiceNow CMDB with IIS installation" + # TODO: Implement ServiceNow CMDB update diff --git a/playbooks/patch-vms.yml b/playbooks/patch-vms.yml new file mode 100644 index 0000000..8f8075a --- /dev/null +++ b/playbooks/patch-vms.yml @@ -0,0 +1,29 @@ +--- +- name: Patch Windows Servers + hosts: windows_servers + gather_facts: true + + tasks: + - name: Search for Windows updates + ansible.windows.win_updates: + category_names: "{{ windows_update_categories }}" + state: searched + register: update_search + + - name: Display available updates + ansible.builtin.debug: + msg: "{{ update_search.found_update_count }} updates available" + + - name: Install Windows updates + ansible.windows.win_updates: + category_names: "{{ windows_update_categories }}" + state: installed + reboot: true + reboot_timeout: 3600 + when: update_search.found_update_count > 0 + register: update_result + + - name: Update CMDB with patch status + ansible.builtin.debug: + msg: "Would update ServiceNow CMDB with patch status" + # TODO: Implement ServiceNow CMDB update diff --git a/playbooks/provision-vm.yml b/playbooks/provision-vm.yml new file mode 100644 index 0000000..46eed41 --- /dev/null +++ b/playbooks/provision-vm.yml @@ -0,0 +1,25 @@ +--- +- name: Provision Windows Server VM on Hyper-V + hosts: hyperv_hosts + gather_facts: false + + vars_prompt: + - name: vm_name + prompt: "Enter VM name" + private: false + + - name: vm_ip_address + prompt: "Enter IP address for VM" + private: false + + tasks: + - name: Placeholder - Create VM + ansible.builtin.debug: + msg: "Will create VM {{ vm_name }} with IP {{ vm_ip_address }}" + + # TODO: Implement VM creation using hyper-v modules + # TODO: Generate autounattend.xml from template + # TODO: Attach autounattend.xml to VM + # TODO: Start VM and wait for provisioning + # TODO: Add VM to inventory + # TODO: Update ServiceNow CMDB diff --git a/playbooks/sync-cmdb.yml b/playbooks/sync-cmdb.yml new file mode 100644 index 0000000..2e413bf --- /dev/null +++ b/playbooks/sync-cmdb.yml @@ -0,0 +1,39 @@ +--- +- name: Synchronize VM information to ServiceNow CMDB + hosts: windows_servers + gather_facts: true + + tasks: + - name: Gather Windows facts + ansible.builtin.setup: + gather_subset: + - hardware + - network + - virtual + + - name: Prepare CMDB data + ansible.builtin.set_fact: + cmdb_data: + name: "{{ inventory_hostname }}" + ip_address: "{{ ansible_ip_addresses[0] | default('') }}" + os: "{{ ansible_os_family }}" + os_version: "{{ ansible_distribution_version }}" + cpu_count: "{{ ansible_processor_vcpus }}" + ram: "{{ ansible_memtotal_mb }}" + managed_by: "{{ managed_by }}" + environment: "{{ environment }}" + + - name: Display CMDB data + ansible.builtin.debug: + var: cmdb_data + + # TODO: Implement actual ServiceNow CMDB update using servicenow.itsm collection + # - name: Update ServiceNow CMDB + # servicenow.itsm.configuration_item: + # instance: + # host: "{{ servicenow_instance }}" + # username: "{{ servicenow_username }}" + # password: "{{ servicenow_password }}" + # state: present + # sys_class_name: "{{ servicenow_table }}" + # data: "{{ cmdb_data }}"