wip: add ansible automation to the mix

This commit is contained in:
surtur 2021-05-17 06:42:03 +02:00
parent 2b5ca96ad3
commit e47d508262
Signed by: wanderer
GPG Key ID: 19CE1EC1D9E0486D
12 changed files with 325 additions and 32 deletions

6
.gitmodules vendored Normal file

@ -0,0 +1,6 @@
[submodule "roles/ansible-gobgp"]
path = roles/ansible-gobgp
url = https://git.dotya.ml/mirre-bt/ansible-gobgp
[submodule "roles/ansible-fprobe"]
path = roles/ansible-fprobe
url = https://git.dotya.ml/mirre-bt/ansible-fprobe

16
Makefile Normal file

@ -0,0 +1,16 @@
ap = ansible-playbook
ausr = ansible
privk = ~/.ssh/tf-ansible
pbdir = playbooks
pbname = lab.yml
.PHONY: ans infra destroy
ans:
$(ap) -u $(ausr) --private-key $(privk) -i hosts $(pbdir)/$(pbname)
infra:
cd vms; make infra
destroy:
cd vms; make destroy

13
ansible.cfg Normal file

@ -0,0 +1,13 @@
[defaults]
inventory = hosts
remote_tmp = $HOME/.ansible/tmp
remote_user = root
nocows = 1
roles_path = roles
retry_files_enabled = False
max_diff_size = 250000
[ssh_connection]
pipelining = True
scp_if_ssh = True
retries = 7

@ -0,0 +1,20 @@
GOBGP_CONF:
global:
config:
as: 65000
router-id: 10.16.7.1
port: 179
neighbors:
- config:
neighbor-address: 10.16.7.2
peer-as: 65001
transport:
config:
remote-port: "179"
add-paths:
config:
send-max: "8"
receive: false
afi-safis:
- config:
afi-safi-name: ipv4-unicast

@ -0,0 +1,20 @@
GOBGP_CONF:
global:
config:
as: 65001
router-id: 10.16.7.2
port: 179
neighbors:
- config:
neighbor-address: 10.16.7.1
peer-as: 65000
transport:
config:
remote-port: "179"
add-paths:
config:
send-max: "8"
receive: true
afi-safis:
- config:
afi-safi-name: ipv4-unicast

28
playbooks/lab.yml Normal file

@ -0,0 +1,28 @@
---
- hosts: defender
user: ansible
become: true
become_user: root
become_method: sudo
roles:
- { role: waitpls }
- { role: ndpi }
- { role: fastnetmon }
- group: router
user: ansible
become: true
become_user: root
become_method: sudo
roles:
- { role: waitpls }
- { role: ansible-gobgp }
- hosts: edge
user: ansible
become: true
become_user: root
become_method: sudo
roles:
- { role: waitpls }
- { role: ansible-fprobe }

1
roles/ansible-fprobe Submodule

@ -0,0 +1 @@
Subproject commit c3d75c837813735a708625949b387b1216ae215d

1
roles/ansible-gobgp Submodule

@ -0,0 +1 @@
Subproject commit d39074a8e65f1d2b5bce155b257ab85abcfde302

@ -1,17 +1,26 @@
#cloud-config #cloud-config
# vim: ft=yaml # vim: ft=yaml
runcmd: bootcmd:
- cat /etc/resolv.conf - cat /etc/resolv.conf
- uname -r - uname -r
- timedatectl set-ntp 1 - timedatectl set-ntp 1
- timedatectl set-timezone Europe/Bratislava - timedatectl set-timezone Europe/Bratislava
- systemctl disable --now dnf-makecache.timer - systemctl disable --now dnf-makecache.timer
- systemctl stop systemd-resolved
- echo "nameserver 8.8.8.8" > /etc/resolv.conf
- dnf config-manager --set-disabled fedora-cisco-openh264
- dnf config-manager --set-enabled updates updates-testing - dnf config-manager --set-enabled updates updates-testing
- sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab
- sleep 10
runcmd:
- cat /etc/resolv.conf
- uname -r
- dnf upgrade --refresh -y - dnf upgrade --refresh -y
- dnf distro-sync -y - dnf distro-sync -y
- dnf clean all - ldconfig
- sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab - touch /.plsgo
write_files: write_files:
- content: | - content: |
@ -25,6 +34,12 @@ write_files:
owner: root:root owner: root:root
permissions: '0644' permissions: '0644'
- content: |
/usr/local/lib
path: /etc/ld.so.conf.d/local.conf
owner: root:root
permissions: '0644'
ssh_pwauth: true ssh_pwauth: true
chpasswd: chpasswd:
list: | list: |
@ -38,6 +53,8 @@ users:
- name: ansible - name: ansible
ssh_authorized_keys: ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL
# the tf-ansible key
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ9JEzfMs+O6I5JYRQ+gHWClvCqaNTdop8ncDeSj+RWs
sudo: ['ALL=(ALL) NOPASSWD:ALL'] sudo: ['ALL=(ALL) NOPASSWD:ALL']
shell: /bin/bash shell: /bin/bash
groups: wheel groups: wheel
@ -58,7 +75,7 @@ power_state:
delay: "+1" delay: "+1"
mode: reboot mode: reboot
condition: true condition: true
timeout: 120 # seconds timeout: 300 # seconds
packages: packages:
- vim - vim
@ -78,6 +95,54 @@ packages:
- tcpdump - tcpdump
- tcpflow - tcpflow
- tcptrack - tcptrack
# fastnetmon/nDPI build requirements
- git
- make
- cmake
- automake
- gcc
- gcc-c++
- libgcc
- libstdc++-devel
- libstdc++-static
- glibc-devel
- binutils
- flex
- bison
- openmpi-devel
- which
- file
- grpc-cli
- grpc-cpp
- grpc-devel
- grpc-plugins
- protobuf-c-devel
- protobuf-c-compiler
- protobuf-compiler
- cppunit
- log4cpp-devel
- json-c-devel
- capnproto-devel
- capnproto-libs
- libpcap-devel
- hiredis-devel
- mongo-c-driver-devel
- mongo-c-driver-libs
- boost-devel
- boost-atomic
- boost-chrono
- boost-date-time
- boost-system
- boost-program-options
- boost-regex
- boost-thread
- libtool
- autoconf
- pkgconf
- ncurses-c++-libs
- ncurses-devel
- ncurses-libs
- ncurses-static
package_upgrade: false package_upgrade: false
package_reboot_if_required: true package_reboot_if_required: true

@ -8,6 +8,8 @@ runcmd:
- timedatectl set-timezone Europe/Bratislava - timedatectl set-timezone Europe/Bratislava
- dnf config-manager --set-enabled updates updates-testing - dnf config-manager --set-enabled updates updates-testing
- sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab - sed -i "s/ext4 * defaults *1 1/ext4 noatime 0 0/" /etc/fstab
- sleep 10
- touch /.plsgo
write_files: write_files:
- content: | - content: |
@ -20,6 +22,12 @@ write_files:
path: /etc/dnf/dnf.conf path: /etc/dnf/dnf.conf
owner: root:root owner: root:root
permissions: '0644' permissions: '0644'
- content: |
net.ipv4.ip_forward = 1
path: /etc/sysctl.conf
owner: root:root
permissions: '0644'
append: true
ssh_pwauth: true ssh_pwauth: true
chpasswd: chpasswd:
@ -34,6 +42,8 @@ users:
- name: ansible - name: ansible
ssh_authorized_keys: ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBtG6NCgdLHX4ztpfvYNRaslKWZcl6KdTc1DehVH4kAL
# the tf-ansible key
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ9JEzfMs+O6I5JYRQ+gHWClvCqaNTdop8ncDeSj+RWs
sudo: ['ALL=(ALL) NOPASSWD:ALL'] sudo: ['ALL=(ALL) NOPASSWD:ALL']
shell: /bin/bash shell: /bin/bash
groups: wheel groups: wheel
@ -54,6 +64,7 @@ power_state:
delay: "+1" delay: "+1"
mode: reboot mode: reboot
condition: true condition: true
timeout: 300
packages: packages:
- vim - vim

@ -52,6 +52,19 @@ variable "category" {
type = string type = string
default = "host" default = "host"
} }
variable "subnets" {
type = list(string)
}
variable "network_names" {
type = list(string)
}
variable "dhcp" {
type = list(bool)
}
variable "ssh_private_key" {
description = "the key to use for ansible stuff"
default = "~/.ssh/tf-ansible"
}
# base OS image # base OS image
resource "libvirt_volume" "baseosimage" { resource "libvirt_volume" "baseosimage" {
@ -94,6 +107,17 @@ resource "libvirt_cloudinit_disk" "commoninit" {
user_data = data.template_file.user_data[each.key].rendered user_data = data.template_file.user_data[each.key].rendered
} }
resource "libvirt_network" "additional_networks" {
count = length(var.subnets)
name = var.network_names[count.index]
bridge = "br_${var.network_names[count.index]}"
mode = "route"
addresses = ["${var.subnets[count.index]}"]
dhcp {
enabled = var.dhcp[count.index]
}
}
# net-lab domains loop # net-lab domains loop
resource "libvirt_domain" "net-lab" { resource "libvirt_domain" "net-lab" {
for_each = var.hosts for_each = var.hosts
@ -110,6 +134,16 @@ resource "libvirt_domain" "net-lab" {
# do not wait for a lease if networkname == "host-bridge" # do not wait for a lease if networkname == "host-bridge"
wait_for_lease = var.networkname == "host-bridge" ? false : true wait_for_lease = var.networkname == "host-bridge" ? false : true
} }
dynamic "network_interface" {
for_each = each.value.network
content {
network_name = network_interface.value["name"]
mac = network_interface.value["mac"]
addresses = network_interface.value["address"]
wait_for_lease = network_interface.value.mode == "bridge" ? false : true
}
}
disk { disk {
volume_id = element(libvirt_volume.qcow2_volume[each.key].*.id, 1) volume_id = element(libvirt_volume.qcow2_volume[each.key].*.id, 1)
@ -117,6 +151,25 @@ resource "libvirt_domain" "net-lab" {
cloudinit = libvirt_cloudinit_disk.commoninit[each.value.name].id cloudinit = libvirt_cloudinit_disk.commoninit[each.value.name].id
provisioner "local-exec" {
command = <<EOF
echo "[defender]" > hosts
echo h_defender >> hosts
echo "[defender:vars]" >> hosts
echo "[router]" >> hosts
echo r_upstream >> hosts
echo r_edge >> hosts
echo "[router:vars]" >> hosts
echo "[attacker]" >> hosts
echo h_attacker >> hosts
echo "[attacker:vars]" >> hosts
echo "[victim]" >> hosts
echo h_victim >> hosts
echo "[victim:vars]" >> hosts
ansible-playbook -u ansible --private-key ${var.ssh_private_key} -i hosts playbooks/lab.yml
EOF
}
} }

@ -14,6 +14,9 @@ baseimagediskpool = "default"
domainname = "local" domainname = "local"
networkname = "default" # default==NAT networkname = "default" # default==NAT
subnets = ["10.16.4.0/24", "10.16.5.0/24", "10.16.6.0/24", "10.16.7.0/30"]
network_names = ["inner", "outer", "dmz", "router"]
dhcp = [true, false, false, false]
# host-specific settings # host-specific settings
# RAM in bytes # RAM in bytes
@ -28,6 +31,14 @@ hosts = {
mac = "00:00:00:13:37:22", mac = "00:00:00:13:37:22",
sourceimage = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2", sourceimage = "https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2",
category = "host-victim", category = "host-victim",
network = {
"inner" = {
name = "inner",
mode = "dhcp",
address = ["10.16.4.7"],
mac = "00:04:00:13:37:22",
},
}
}, },
"h_attacker" = { "h_attacker" = {
name = "h_attacker", name = "h_attacker",
@ -36,8 +47,17 @@ hosts = {
diskpool = "default", diskpool = "default",
disksize = "9370000000", disksize = "9370000000",
mac = "00:00:00:13:37:23", mac = "00:00:00:13:37:23",
sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2",
sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2",
category = "host-attacker", category = "host-attacker",
network = {
"outer" = {
name = "outer",
mode = "route",
address = ["10.16.5.1"],
mac = "00:05:00:13:37:23",
},
}
}, },
"r_edge" = { "r_edge" = {
name = "r_edge", name = "r_edge",
@ -46,8 +66,23 @@ hosts = {
diskpool = "default", diskpool = "default",
disksize = "4300000000", disksize = "4300000000",
mac = "00:00:00:13:37:24", mac = "00:00:00:13:37:24",
sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2",
sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2",
category = "router", category = "router",
network = {
"dmz" = {
name = "dmz",
mode = "route",
address = ["10.16.6.1"],
mac = "00:06:00:13:37:24",
},
"router" = {
name = "router",
mode = "route",
address = ["10.16.7.1"],
mac = "00:07:00:13:37:24",
},
}
}, },
"r_upstream" = { "r_upstream" = {
name = "r_upstream", name = "r_upstream",
@ -56,18 +91,42 @@ hosts = {
diskpool = "default", diskpool = "default",
disksize = "4300000000", disksize = "4300000000",
mac = "00:00:00:13:37:25", mac = "00:00:00:13:37:25",
sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2", # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/33/Cloud/x86_64/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2",
sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-33-1.2.x86_64.qcow2",
category = "router", category = "router",
network = {
"outer" = {
name = "outer",
mode = "route",
address = ["10.16.5.1"],
mac = "00:05:00:13:37:25",
},
"router" = {
name = "router",
mode = "route",
address = ["10.16.7.2"],
mac = "00:07:00:13:37:25",
},
},
}, },
"h_defender" = { "h_defender" = {
name = "h_defender", name = "h_defender",
vcpu = 1, vcpu = 1,
memory = "1024", memory = "2048",
diskpool = "default", diskpool = "default",
disksize = "9370000000", disksize = "9370000000",
mac = "00:00:00:13:37:26", mac = "00:00:00:13:37:26",
sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2", # sourceimage = "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2",
sourceimage = "/var/lib/libvirt/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2",
category = "host-defender", category = "host-defender",
network = {
"dmz" = {
name = "dmz",
mode = "route",
address = ["10.16.6.4"],
mac = "00:06:00:13:37:26",
},
},
}, },
} }