commit f8eba4f09ac22a2351e2e317d27943e396e8fed7 Author: nikola Date: Tue May 19 14:53:37 2026 +0200 feat: initial commit diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..17498e1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,14 @@ +# Project Rules - Wazuh Proxmox IaC + +## Scope +Build and operate Terraform-based deployment for one Wazuh VM on local Proxmox. + +## Source of Truth +- `sources/iac-test/` is the baseline for single-VM provisioning. +- `sources/multi-vm-iac/` is reference-only for future scale-out patterns. + +## Working Rules +- Do not commit secrets, token files, `.terraform/`, or `terraform.tfstate*`. +- Keep variables explicit in `terraform.tfvars.example`. +- Prefer one-step reproducible flow: `init -> plan -> apply -> verify`. + diff --git a/docs/PLAN.md b/docs/PLAN.md new file mode 100644 index 0000000..0b9a34e --- /dev/null +++ b/docs/PLAN.md @@ -0,0 +1,48 @@ +# Wazuh on Proxmox - Plan + +## Goal +Provision one VM on local Proxmox using Terraform and install Wazuh all-in-one +automatically. + +## Current Assets +- Ready single-VM Proxmox Terraform baseline in `sources/iac-test/main.tf`. +- Ready multi-VM reference in `sources/multi-vm-iac/main.tf`. +- Known working Proxmox params from existing code: + - endpoint `https://10.0.50.110:8006/` + - node `rbmk2` + - template VM ID `169` + - bridge `vmbr0` + - cloud-init user `devops` + +## Selected Base +Use `iac-test` as base because target is one VM for Wazuh. + +## Work Plan +1. Create clean Terraform project structure from single-VM base: + - `main.tf`, `variables.tf`, `outputs.tf`, `versions.tf` + - `terraform.tfvars.example` +2. Parameterize all environment-specific values: + - Proxmox endpoint/token file path/node/template/datastore/bridge + - VM name, CPU, RAM, disk, IP, gateway, SSH key, SSH port +3. Add cloud-init/user-data provisioning for Wazuh: + - OS packages and prerequisites + - run `wazuh-install.sh -a` + - ensure services are enabled and started +4. Add post-deploy validation outputs: + - VM IP + - dashboard URL + - quick health commands +5. Add runbook (`README.md`) with exact operator commands: + - `terraform init` + - `terraform plan -var-file=...` + - `terraform apply -var-file=...` + - access + agent enrollment steps +6. Optional hardening pass: + - split Wazuh install from VM creation (null_resource/ansible) + - add destroy safeguards and tags + +## Open Inputs Needed Before Apply +- Final static IP for Wazuh VM in LAN. +- Whether to keep default Wazuh ports (443, 1514, 1515) exposed as-is. +- Template `169` confirmation (cloud-init enabled and qemu-guest-agent present). + diff --git a/docs/RUNBOOK_WAZUH_RBMK.md b/docs/RUNBOOK_WAZUH_RBMK.md new file mode 100644 index 0000000..ab1d0a4 --- /dev/null +++ b/docs/RUNBOOK_WAZUH_RBMK.md @@ -0,0 +1,201 @@ +# Wazuh Lab Runbook (RBMK2, VMID/IP reuse) + +## Scope +- Rebuild VM `104` on `rbmk2` +- Keep IP `10.1.50.125/24` +- Use Ubuntu 22.04 template `9000` +- Install Wazuh all-in-one + +## 1) Create Ubuntu template on RBMK2 +Run on: `root@rbmk2` + +```bash +qm status 9000 || true +wget -O /var/lib/vz/template/iso/jammy-server-cloudimg-amd64.img https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img +qm create 9000 --name ubuntu2204-template-rbmk2 --memory 4096 --cores 2 --net0 virtio,bridge=vmbr0,firewall=1 +qm importdisk 9000 /var/lib/vz/template/iso/jammy-server-cloudimg-amd64.img local-lvm +qm set 9000 --scsihw virtio-scsi-single --scsi0 local-lvm:vm-9000-disk-0 +qm set 9000 --ide2 local-lvm:cloudinit +qm set 9000 --boot order=scsi0 +qm set 9000 --agent enabled=1 +qm template 9000 +qm resize 9000 scsi0 60G +qm config 9000 | egrep '^(name|template|ostype|agent|boot|scsihw|scsi0|ide2|net0):' +``` + +Expected: +- `template: 1` +- `ide2: ...cloudinit` +- `scsi0 ... size=60G` + +## 2) Prepare Terraform +Run on: local laptop +Path: `/home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform` + +```bash +cd /home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform +mkdir -p .secrets +cp terraform.tfvars.example terraform.tfvars +nano terraform.tfvars +nano .secrets/api_token +chmod 600 .secrets/api_token +terraform init +terraform fmt -recursive +terraform validate +terraform plan -out tfplan +``` + +Set in `terraform.tfvars`: +- `proxmox_template_vm_id = 9000` +- `vm_id = 104` +- `vm_ipv4_cidr = "10.1.50.125/24"` +- `vm_ssh_public_key = ""` + +Expected: +- `Success! The configuration is valid.` +- plan shows `+ create` for `vm_id = 104` + +## 3) Replace old VM 104 +Run on: `root@rbmk2` + +```bash +qm stop 104 || true +qm destroy 104 --purge 1 --destroy-unreferenced-disks 1 +``` + +Expected: +- old test VM removed + +## 4) Apply Terraform +Run on: local laptop +Path: `/home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform` + +```bash +terraform apply tfplan +terraform output +``` + +Expected: +- `Apply complete!` +- outputs include: + - `ssh devops@10.1.50.125 -p42315` + - `https://10.1.50.125` + +## 5) Fix guest agent if apply waits +Symptom: +- long `Still creating...` +- on rbmk2: `qm agent 104 ping` => `QEMU guest agent is not running` + +Run on: VM `10.1.50.125` (ssh `-p22` or `-p42315`) + +```bash +sudo apt-get update +sudo apt-get install -y qemu-guest-agent +sudo systemctl start qemu-guest-agent +sudo systemctl status qemu-guest-agent --no-pager +``` + +Verify on `rbmk2`: + +```bash +qm agent 104 ping +``` + +Expected: +- agent running; apply completes + +## 6) Apply company SSH baseline +Run on: local laptop +Path: `/home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform` + +```bash +chmod +x scripts/company-bootstrap-ubuntu.sh scripts/install-wazuh-aio.sh scripts/verify-wazuh.sh +scp -P22 scripts/company-bootstrap-ubuntu.sh devops@10.1.50.125:/tmp/ +ssh devops@10.1.50.125 -p22 "sudo bash /tmp/company-bootstrap-ubuntu.sh devops 42315 \"$(cat ~/.ssh/id_ed25519.pub)\"" +ssh devops@10.1.50.125 -p42315 "sudo sshd -T | egrep '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication)'" +``` + +Expected: +- `port 42315` +- `permitrootlogin no` +- `passwordauthentication no` +- `pubkeyauthentication yes` + +## 7) Install Wazuh +Run on: local laptop +Path: `/home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform` + +```bash +scp -P42315 scripts/install-wazuh-aio.sh devops@10.1.50.125:/tmp/ +ssh devops@10.1.50.125 -p42315 "sudo bash /tmp/install-wazuh-aio.sh" +./scripts/verify-wazuh.sh 10.1.50.125 +ssh devops@10.1.50.125 -p42315 "sudo systemctl status wazuh-indexer wazuh-manager wazuh-dashboard filebeat --no-pager" +``` + +Expected: +- Installer summary with dashboard URL and admin password +- `verify-wazuh.sh` checks pass +- all 4 services `active (running)` + +## Common issues and fixes +1. `can't clone to non-shared storage 'local-lvm'` +- Cause: cross-node clone to non-shared storage. +- Fix: create template directly on `rbmk2`. + +2. `unable to find configuration file for VM 129 on node 'rbmk2'` +- Cause: source VM exists on another node. +- Fix: run actions on the correct source node or avoid cross-node clone. + +3. SSH host key changed warning +- Fix: +```bash +ssh-keygen -f ~/.ssh/known_hosts -R '[10.1.50.125]:42315' +``` + +4. `QEMU guest agent is not running` +- Fix: install/start `qemu-guest-agent` inside VM, then retry/check. + +5. Thin pool warnings during import/resize +- Cause: local-lvm oversubscription warning. +- Fix: monitor storage free space before new clones and log growth. + +## Post-install hardening checklist (Wazuh lab) +Run on: VM `10.1.50.125` (`ssh devops@10.1.50.125 -p42315`) + +1. Rotate default admin password +- In dashboard: `https://10.1.50.125` -> change `admin` password immediately. + +2. Restrict API exposure (if not needed externally) +```bash +sudo ss -tulpen | egrep '(:443|:1514|:1515|:55000)' +``` +- confirm only required ports are listening. + +3. Enable host firewall baseline +```bash +sudo apt-get install -y ufw +sudo ufw default deny incoming +sudo ufw default allow outgoing +sudo ufw allow 42315/tcp +sudo ufw allow 443/tcp +sudo ufw allow 1514/tcp +sudo ufw allow 1515/tcp +sudo ufw allow 55000/tcp +sudo ufw --force enable +sudo ufw status verbose +``` +- keep only Wazuh + SSH management ports open. + +4. Verify services are enabled and healthy +```bash +sudo systemctl is-active wazuh-indexer wazuh-manager wazuh-dashboard filebeat +sudo systemctl is-enabled wazuh-indexer wazuh-manager wazuh-dashboard filebeat +``` +- all should be active/enabled. + +5. Backup install artifacts and credentials file +```bash +sudo ls -l /root/wazuh-install-files.tar /var/log/wazuh-install.log +``` +- copy to a secure internal vault/location. + diff --git a/sources/iac-test/.terraform.lock.hcl b/sources/iac-test/.terraform.lock.hcl new file mode 100644 index 0000000..d81c0d3 --- /dev/null +++ b/sources/iac-test/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/bpg/proxmox" { + version = "0.68.0" + constraints = "0.68.0" + hashes = [ + "h1:4Q+bUZoRz7o2ij/oPS3SsAy1D2CDdIMasegk+ll7oho=", + "zh:012f3fce033a7921335576edba0f2d2dad7dcaec2e5ed3b68ced692845131656", + "zh:1853ddbaef049b14e738bf8531a2c8e45d9ac409676a7f7f997d40ae794db783", + "zh:2a284f49f95bfe022f8b5bfed6ae56df5577f590ff26ae12322767f23e3b6c50", + "zh:491a7d5a3cf47fc3016213ca047fcf20288200901f5c0195314c32925fcd36c0", + "zh:4a198ab0b40b02a35955156d9a195c76a22f92d4078195ce94316b793d0d58d4", + "zh:63f0e62c5805b48893f9a106ed11e628f1a3bc3d34360a2bb31a88cfcc2051dd", + "zh:64cdc6a3bdd56e2285a2d65a17d87ee284fcdbbe69246baed4aeaf465a955007", + "zh:6721eaaa4998795c0caed3225aa2bc8ff796a6de86114431194b9770f98e2600", + "zh:79ef8a813d1b3d5ef69f2a00a3160fde9ca65c541db42c998c69db6dea66558f", + "zh:96aa2d4a6cdac17dcccbb76a1ef0afc15052c3f13fa3bb0f3f44b385272405d4", + "zh:9e1e18b04f228d671e1653294828021e672dab6635a309e72b2da4ba3b9f07e9", + "zh:a91b69c6df914f8f0504d0f0d25af6a870b79befe6ae11d39a1bd8b879871084", + "zh:bc618ee4f85b8c5db0e1494d207d2a6170ca08dad5ce9844866550a94dd56bea", + "zh:ea85f7e5dbbe768e2e15e0cafacee1c94e319d04c1835db1984a6ce79674c8e4", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + ] +} diff --git a/sources/iac-test/main.tf b/sources/iac-test/main.tf new file mode 100644 index 0000000..1ad822e --- /dev/null +++ b/sources/iac-test/main.tf @@ -0,0 +1,61 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.68.0" + } + } +} + +provider "proxmox" { + endpoint = "https://10.0.50.110:8006/" + insecure = true + api_token = trimspace(file("${path.module}/.secrets/api_token")) +} + +resource "proxmox_virtual_environment_vm" "testvm" { + name = "terraform-testvm-1" + node_name = "rbmk2" + + clone { + vm_id = 169 + full = true + datastore_id = "local-lvm" + } + + cpu { + sockets = 1 + cores = 2 + } + + memory { + dedicated = 8192 + } + + network_device { + model = "virtio" + bridge = "vmbr0" + } + + initialization { + datastore_id = "local-lvm" + + user_account { + username = "devops" + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyVe1ZhUCVs9imt0UmcCIXRAHpoSKFQ7IH/ekEXohZG dzoni-wolkabout" + ] + } + + ip_config { + ipv4 { + address = "10.1.50.125/24" + gateway = "10.1.50.1" + } + } + } + + agent { + enabled = true + } +} diff --git a/sources/multi-vm-iac/.terraform.lock.hcl b/sources/multi-vm-iac/.terraform.lock.hcl new file mode 100644 index 0000000..d81c0d3 --- /dev/null +++ b/sources/multi-vm-iac/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/bpg/proxmox" { + version = "0.68.0" + constraints = "0.68.0" + hashes = [ + "h1:4Q+bUZoRz7o2ij/oPS3SsAy1D2CDdIMasegk+ll7oho=", + "zh:012f3fce033a7921335576edba0f2d2dad7dcaec2e5ed3b68ced692845131656", + "zh:1853ddbaef049b14e738bf8531a2c8e45d9ac409676a7f7f997d40ae794db783", + "zh:2a284f49f95bfe022f8b5bfed6ae56df5577f590ff26ae12322767f23e3b6c50", + "zh:491a7d5a3cf47fc3016213ca047fcf20288200901f5c0195314c32925fcd36c0", + "zh:4a198ab0b40b02a35955156d9a195c76a22f92d4078195ce94316b793d0d58d4", + "zh:63f0e62c5805b48893f9a106ed11e628f1a3bc3d34360a2bb31a88cfcc2051dd", + "zh:64cdc6a3bdd56e2285a2d65a17d87ee284fcdbbe69246baed4aeaf465a955007", + "zh:6721eaaa4998795c0caed3225aa2bc8ff796a6de86114431194b9770f98e2600", + "zh:79ef8a813d1b3d5ef69f2a00a3160fde9ca65c541db42c998c69db6dea66558f", + "zh:96aa2d4a6cdac17dcccbb76a1ef0afc15052c3f13fa3bb0f3f44b385272405d4", + "zh:9e1e18b04f228d671e1653294828021e672dab6635a309e72b2da4ba3b9f07e9", + "zh:a91b69c6df914f8f0504d0f0d25af6a870b79befe6ae11d39a1bd8b879871084", + "zh:bc618ee4f85b8c5db0e1494d207d2a6170ca08dad5ce9844866550a94dd56bea", + "zh:ea85f7e5dbbe768e2e15e0cafacee1c94e319d04c1835db1984a6ce79674c8e4", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + ] +} diff --git a/sources/multi-vm-iac/README.md b/sources/multi-vm-iac/README.md new file mode 100644 index 0000000..17c8640 --- /dev/null +++ b/sources/multi-vm-iac/README.md @@ -0,0 +1,33 @@ +# Multi VM Terraform setup + +## Priprema okruženja +- `cd ~/multi-vm-iac` +- `rm -rf .terraform terraform.tfstate*` # osveži backend da ne deli state sa starim projektom +- `terraform init -reconfigure` + +## Konfiguracija IP adresa +- `cat <<'EOF' > terraform.tfvars` + ``` + vm_addresses = { + alpha = "10.1.50.XXX/24" + bravo = "10.1.50.YYY/24" + charlie = "10.1.50.ZZZ/24" + delta = "10.1.50.WWW/24" + } + ``` + `EOF` +- Izmeni XXX/YYY/ZZZ/WWW u slobodne adrese pre `apply`. + +## Startovanje pojedinačnih VM-ova +- `terraform plan -target=proxmox_virtual_environment_vm.vm_alpha` +- `terraform apply -target=proxmox_virtual_environment_vm.vm_alpha` +- Ponovi za `vm_bravo`, `vm_charlie`, `vm_delta` po potrebi. + +## Provera i gašenje +- `terraform state list` # pregled aktivnih resursa u ovom projektu +- `terraform destroy -target=proxmox_virtual_environment_vm.vm_alpha` # gasi samo jednu mašinu +- `terraform destroy` # gasi sve instance iz ovog foldera kada završiš + +## Dodatno +- Ako budeš delio state, pređi na remote backend (S3 + DynamoDB lock, Terraform Cloud…) pre proizvodnog korišćenja. +- Za promenu gateway-a koristi varijablu `vm_gateway` u `terraform.tfvars`. diff --git a/sources/multi-vm-iac/main.tf b/sources/multi-vm-iac/main.tf new file mode 100644 index 0000000..98d6a27 --- /dev/null +++ b/sources/multi-vm-iac/main.tf @@ -0,0 +1,218 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.68.0" + } + } +} + +provider "proxmox" { + endpoint = "https://10.0.50.110:8006/" + insecure = true + api_token = trimspace(file("${path.module}/.secrets/api_token")) +} + +variable "vm_gateway" { + type = string + description = "Default gateway for all virtual machines." + default = "10.1.50.1" +} + +variable "vm_addresses" { + type = object({ + alpha = string + bravo = string + charlie = string + delta = string + }) + description = "CIDR formatted IPv4 addresses for each virtual machine (e.g. 10.1.50.130/24)." +} + +resource "proxmox_virtual_environment_vm" "vm_alpha" { + name = "terraform-multi-vm-alpha" + node_name = "rbmk2" + + clone { + vm_id = 169 + full = true + datastore_id = "local-lvm" + } + + cpu { + sockets = 1 + cores = 2 + } + + memory { + dedicated = 4096 + } + + network_device { + model = "virtio" + bridge = "vmbr0" + } + + initialization { + datastore_id = "local-lvm" + + user_account { + username = "devops" + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyVe1ZhUCVs9imt0UmcCIXRAHpoSKFQ7IH/ekEXohZG dzoni-wolkabout" + ] + } + + ip_config { + ipv4 { + address = var.vm_addresses.alpha + gateway = var.vm_gateway + } + } + } + + agent { + enabled = true + } +} + +resource "proxmox_virtual_environment_vm" "vm_bravo" { + name = "terraform-multi-vm-bravo" + node_name = "rbmk2" + + clone { + vm_id = 169 + full = true + datastore_id = "local-lvm" + } + + cpu { + sockets = 1 + cores = 2 + } + + memory { + dedicated = 4096 + } + + network_device { + model = "virtio" + bridge = "vmbr0" + } + + initialization { + datastore_id = "local-lvm" + + user_account { + username = "devops" + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyVe1ZhUCVs9imt0UmcCIXRAHpoSKFQ7IH/ekEXohZG dzoni-wolkabout" + ] + } + + ip_config { + ipv4 { + address = var.vm_addresses.bravo + gateway = var.vm_gateway + } + } + } + + agent { + enabled = true + } +} + +resource "proxmox_virtual_environment_vm" "vm_charlie" { + name = "terraform-multi-vm-charlie" + node_name = "rbmk2" + + clone { + vm_id = 169 + full = true + datastore_id = "local-lvm" + } + + cpu { + sockets = 1 + cores = 2 + } + + memory { + dedicated = 4096 + } + + network_device { + model = "virtio" + bridge = "vmbr0" + } + + initialization { + datastore_id = "local-lvm" + + user_account { + username = "devops" + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyVe1ZhUCVs9imt0UmcCIXRAHpoSKFQ7IH/ekEXohZG dzoni-wolkabout" + ] + } + + ip_config { + ipv4 { + address = var.vm_addresses.charlie + gateway = var.vm_gateway + } + } + } + + agent { + enabled = true + } +} + +resource "proxmox_virtual_environment_vm" "vm_delta" { + name = "terraform-multi-vm-delta" + node_name = "rbmk2" + + clone { + vm_id = 169 + full = true + datastore_id = "local-lvm" + } + + cpu { + sockets = 1 + cores = 2 + } + + memory { + dedicated = 4096 + } + + network_device { + model = "virtio" + bridge = "vmbr0" + } + + initialization { + datastore_id = "local-lvm" + + user_account { + username = "devops" + keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyVe1ZhUCVs9imt0UmcCIXRAHpoSKFQ7IH/ekEXohZG dzoni-wolkabout" + ] + } + + ip_config { + ipv4 { + address = var.vm_addresses.delta + gateway = var.vm_gateway + } + } + } + + agent { + enabled = true + } +} diff --git a/terraform/.gitignore b/terraform/.gitignore new file mode 100644 index 0000000..f94faa8 --- /dev/null +++ b/terraform/.gitignore @@ -0,0 +1,8 @@ +.terraform/ +.secrets/ +terraform.tfstate +terraform.tfstate.* +terraform.tfvars +crash.log +crash.*.log + diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..d81c0d3 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/bpg/proxmox" { + version = "0.68.0" + constraints = "0.68.0" + hashes = [ + "h1:4Q+bUZoRz7o2ij/oPS3SsAy1D2CDdIMasegk+ll7oho=", + "zh:012f3fce033a7921335576edba0f2d2dad7dcaec2e5ed3b68ced692845131656", + "zh:1853ddbaef049b14e738bf8531a2c8e45d9ac409676a7f7f997d40ae794db783", + "zh:2a284f49f95bfe022f8b5bfed6ae56df5577f590ff26ae12322767f23e3b6c50", + "zh:491a7d5a3cf47fc3016213ca047fcf20288200901f5c0195314c32925fcd36c0", + "zh:4a198ab0b40b02a35955156d9a195c76a22f92d4078195ce94316b793d0d58d4", + "zh:63f0e62c5805b48893f9a106ed11e628f1a3bc3d34360a2bb31a88cfcc2051dd", + "zh:64cdc6a3bdd56e2285a2d65a17d87ee284fcdbbe69246baed4aeaf465a955007", + "zh:6721eaaa4998795c0caed3225aa2bc8ff796a6de86114431194b9770f98e2600", + "zh:79ef8a813d1b3d5ef69f2a00a3160fde9ca65c541db42c998c69db6dea66558f", + "zh:96aa2d4a6cdac17dcccbb76a1ef0afc15052c3f13fa3bb0f3f44b385272405d4", + "zh:9e1e18b04f228d671e1653294828021e672dab6635a309e72b2da4ba3b9f07e9", + "zh:a91b69c6df914f8f0504d0f0d25af6a870b79befe6ae11d39a1bd8b879871084", + "zh:bc618ee4f85b8c5db0e1494d207d2a6170ca08dad5ce9844866550a94dd56bea", + "zh:ea85f7e5dbbe768e2e15e0cafacee1c94e319d04c1835db1984a6ce79674c8e4", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + ] +} diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..3dd29cb --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,109 @@ +# Wazuh Proxmox Lab (Single VM, reuse VMID/IP) + +Run from: + +`/home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform` + +Target: +- VMID `104` +- IP `10.1.50.125/24` +- Node `rbmk2` +- OS source: Ubuntu 22.04 cloud-init template +- SSH policy target: user `devops`, port `42315`, key-only auth + +## 0) One-time on Proxmox: Ubuntu 22.04 template + +You need one Ubuntu 22.04 cloud-init template in Proxmox first. +After that, Terraform does the rest. + +Example on Proxmox node (adjust storage/bridge if needed): + +```bash +wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img -O /tmp/jammy.img +qm create 9000 --name ubuntu-2204-cloudinit --memory 2048 --cores 2 --net0 virtio,bridge=vmbr0 +qm importdisk 9000 /tmp/jammy.img local-lvm +qm set 9000 --scsihw virtio-scsi-single --scsi0 local-lvm:vm-9000-disk-0 +qm set 9000 --ide2 local-lvm:cloudinit +qm set 9000 --boot c --bootdisk scsi0 +qm set 9000 --serial0 socket --vga serial0 +qm template 9000 +``` + +- pravi Ubuntu 22.04 template VMID `9000` + +## 1) Obrisi postojeci test VM 104 (ako nista ne radi na njemu) + +On Proxmox node: + +```bash +qm stop 104 || true +qm destroy 104 --purge 1 --destroy-unreferenced-disks 1 +``` + +- gasi i brise stari VM 104 + +## 2) Priprema Terraform fajlova + +```bash +cd /home/nikola/codex-cli/projects/wazuh-proxmox-iac/terraform +mkdir -p .secrets +cp terraform.tfvars.example terraform.tfvars +``` + +- ulaz u projekat + vars + secret folder + +```bash +nano terraform.tfvars +``` + +- proveri `vm_id=104`, `vm_ipv4_cidr=10.1.50.125/24`, `proxmox_template_vm_id=9000` + +```bash +nano .secrets/api_token +chmod 600 .secrets/api_token +``` + +- upisi Proxmox API token + +## 3) Podizanje novog Ubuntu VM-a na isto mesto + +```bash +terraform init +terraform fmt -recursive +terraform validate +terraform plan -out tfplan +terraform apply tfplan +terraform output +``` + +- kreira novi VM 104 sa istim IP +- ovaj Terraform ne pokrece Docker/workload automatski; podize clean Ubuntu VM. +- kontrola resursa je kroz `vm_cpu_cores` i `vm_memory_mb` u `terraform.tfvars`. + +## 4) Instalacija Wazuh na novom VM-u + +```bash +chmod +x scripts/company-bootstrap-ubuntu.sh scripts/install-wazuh-aio.sh scripts/verify-wazuh.sh +# ako SSH na 22 nije dostupan, zameni -P22/-p22 sa -P42315/-p42315 +scp -P22 scripts/company-bootstrap-ubuntu.sh devops@10.1.50.125:/tmp/ +ssh devops@10.1.50.125 -p22 "sudo bash /tmp/company-bootstrap-ubuntu.sh devops 42315 \"$(cat ~/.ssh/id_ed25519.pub)\"" +ssh devops@10.1.50.125 -p42315 "echo ssh baseline ok" +scp -P42315 scripts/install-wazuh-aio.sh devops@10.1.50.125:/tmp/ +ssh devops@10.1.50.125 -p42315 "sudo bash /tmp/install-wazuh-aio.sh" +``` + +- primeni company SSH baseline pa instaliraj Wazuh + +## 5) Verifikacija + +```bash +./scripts/verify-wazuh.sh 10.1.50.125 +``` + +- provera dashboard + portovi 1514/1515 + +## Key pravilo (preporuka) + +- Ne bake-uj licni SSH key u template. +- Key ubacuj po VM-u kroz Terraform `vm_ssh_public_key` i/ili bootstrap skriptu. +- Template neka ostane genericki, bez personalnih kljuceva. diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..5db8f9e --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,51 @@ +provider "proxmox" { + endpoint = var.proxmox_endpoint + insecure = var.proxmox_insecure + api_token = trimspace(file(var.proxmox_api_token_file)) +} + +resource "proxmox_virtual_environment_vm" "wazuh" { + name = var.vm_name + vm_id = var.vm_id + node_name = var.proxmox_node_name + + clone { + vm_id = var.proxmox_template_vm_id + full = true + datastore_id = var.proxmox_datastore_id + } + + cpu { + sockets = var.vm_cpu_sockets + cores = var.vm_cpu_cores + } + + memory { + dedicated = var.vm_memory_mb + } + + network_device { + model = "virtio" + bridge = var.proxmox_bridge + } + + initialization { + datastore_id = var.proxmox_datastore_id + + user_account { + username = var.vm_ssh_username + keys = [var.vm_ssh_public_key] + } + + ip_config { + ipv4 { + address = var.vm_ipv4_cidr + gateway = var.vm_gateway + } + } + } + + agent { + enabled = true + } +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..a4b3d0b --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,19 @@ +locals { + vm_ip = split("/", var.vm_ipv4_cidr)[0] +} + +output "vm_name" { + value = proxmox_virtual_environment_vm.wazuh.name +} + +output "vm_ip" { + value = local.vm_ip +} + +output "ssh_command" { + value = "ssh ${var.vm_ssh_username}@${local.vm_ip} -p${var.vm_ssh_port}" +} + +output "wazuh_dashboard_url" { + value = "https://${local.vm_ip}" +} diff --git a/terraform/scripts/company-bootstrap-ubuntu.sh b/terraform/scripts/company-bootstrap-ubuntu.sh new file mode 100755 index 0000000..fcd7c77 --- /dev/null +++ b/terraform/scripts/company-bootstrap-ubuntu.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ "${EUID}" -ne 0 ]]; then + echo "Run as root (sudo)." >&2 + exit 1 +fi + +SSH_USER="${1:-devops}" +SSH_PORT="${2:-42315}" +SSH_PUBKEY="${3:-}" + +if [[ -z "${SSH_PUBKEY}" ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +if ! id -u "${SSH_USER}" >/dev/null 2>&1; then + useradd -m -s /bin/bash "${SSH_USER}" +fi + +usermod -aG sudo "${SSH_USER}" + +install -d -m 700 -o "${SSH_USER}" -g "${SSH_USER}" "/home/${SSH_USER}/.ssh" +touch "/home/${SSH_USER}/.ssh/authorized_keys" +chown "${SSH_USER}:${SSH_USER}" "/home/${SSH_USER}/.ssh/authorized_keys" +chmod 600 "/home/${SSH_USER}/.ssh/authorized_keys" + +if ! grep -Fqx "${SSH_PUBKEY}" "/home/${SSH_USER}/.ssh/authorized_keys"; then + echo "${SSH_PUBKEY}" >>"/home/${SSH_USER}/.ssh/authorized_keys" +fi + +cat >/etc/ssh/sshd_config.d/99-company.conf <&2 + exit 1 +fi + +echo "[1/4] System update and tools" +apt-get update -y +apt-get install -y curl tar + +echo "[2/4] Download Wazuh installer" +cd /root +curl -sSLO https://packages.wazuh.com/4.14/wazuh-install.sh +chmod +x wazuh-install.sh + +echo "[3/4] Install Wazuh all-in-one" +bash ./wazuh-install.sh -a + +echo "[4/4] Installation finished" +echo "Open: https://$(hostname -I | awk '{print $1}')" +echo "Installer output contains generated admin credentials." + diff --git a/terraform/scripts/verify-wazuh.sh b/terraform/scripts/verify-wazuh.sh new file mode 100755 index 0000000..24484a1 --- /dev/null +++ b/terraform/scripts/verify-wazuh.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +TARGET_IP="${1:-}" + +if [[ -z "${TARGET_IP}" ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +echo "[1/3] Dashboard HTTPS check" +curl -kI "https://${TARGET_IP}" | head -n 1 + +echo "[2/3] Enrollment port check" +nc -zv "${TARGET_IP}" 1515 + +echo "[3/3] Agent events port check" +nc -zv "${TARGET_IP}" 1514 + diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example new file mode 100644 index 0000000..a541711 --- /dev/null +++ b/terraform/terraform.tfvars.example @@ -0,0 +1,20 @@ +proxmox_endpoint = "https://10.0.50.110:8006/" +proxmox_insecure = true +proxmox_api_token_file = ".secrets/api_token" +proxmox_node_name = "rbmk2" +# Set this to Ubuntu 22.04 cloud-init template VMID. +proxmox_template_vm_id = 9000 +proxmox_datastore_id = "local-lvm" +proxmox_bridge = "vmbr0" + +vm_name = "terraform-testvm-1" +vm_id = 104 +vm_cpu_sockets = 1 +vm_cpu_cores = 4 +vm_memory_mb = 8192 +vm_ipv4_cidr = "10.1.50.125/24" +vm_gateway = "10.1.50.1" +vm_ssh_username = "devops" +vm_ssh_port = 42315 + +vm_ssh_public_key = "ssh-ed25519 AAAA... your-key-comment" diff --git a/terraform/tfplan b/terraform/tfplan new file mode 100644 index 0000000..e6bf7bc Binary files /dev/null and b/terraform/tfplan differ diff --git a/terraform/tfplan-scale b/terraform/tfplan-scale new file mode 100644 index 0000000..4ddaded Binary files /dev/null and b/terraform/tfplan-scale differ diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..8290263 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,100 @@ +variable "proxmox_endpoint" { + description = "Proxmox API endpoint." + type = string + default = "https://10.0.50.110:8006/" +} + +variable "proxmox_insecure" { + description = "Allow insecure TLS for Proxmox API." + type = bool + default = true +} + +variable "proxmox_api_token_file" { + description = "Path to file containing Proxmox API token." + type = string + default = ".secrets/api_token" +} + +variable "proxmox_node_name" { + description = "Proxmox node where VM will be created." + type = string + default = "rbmk2" +} + +variable "proxmox_template_vm_id" { + description = "Template VM ID used for clone." + type = number + default = 169 +} + +variable "proxmox_datastore_id" { + description = "Datastore used for clone and cloud-init." + type = string + default = "local-lvm" +} + +variable "proxmox_bridge" { + description = "Proxmox bridge name." + type = string + default = "vmbr0" +} + +variable "vm_name" { + description = "Wazuh VM name." + type = string + default = "terraform-testvm-1" +} + +variable "vm_id" { + description = "Proxmox VMID for the Wazuh VM." + type = number + default = 104 +} + +variable "vm_cpu_sockets" { + description = "VM CPU sockets." + type = number + default = 1 +} + +variable "vm_cpu_cores" { + description = "VM CPU cores." + type = number + default = 4 +} + +variable "vm_memory_mb" { + description = "VM memory in MB." + type = number + default = 8192 +} + +variable "vm_ipv4_cidr" { + description = "VM IPv4 address in CIDR format." + type = string + default = "10.1.50.125/24" +} + +variable "vm_gateway" { + description = "VM default gateway." + type = string + default = "10.1.50.1" +} + +variable "vm_ssh_username" { + description = "Cloud-init username for SSH." + type = string + default = "devops" +} + +variable "vm_ssh_port" { + description = "SSH port exposed by company policy." + type = number + default = 42315 +} + +variable "vm_ssh_public_key" { + description = "SSH public key inserted via cloud-init." + type = string +} diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 0000000..30e695a --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.68.0" + } + } +} +