Introduction
Hi everyone ! It’s been a while since I have write something here.
I think that my last post was in 2017 !
So today, I wanted to write you a little article about Ansible
Ansible is one of my favorite tool, I use it for automation in my current job but you can use Ansible to automate a lot of things !
Here are some example of things you can automate with Ansible :
- Automate a new installation of Arch on your new laptop
- Easily deploy a Web server on the cloud
- Create reusable server for hacking
- Create a Red teams infrastructure
- etc …
Install Ansible
Ansible is a tool written in Python, to install ansible you will need to install Python and pip
Debian :
sudo apt install python3 python3-pip
Or Arch :
pacman -S python3 python3-pip
If you have python and pip install you can install Ansible with the following command :
pip3 install --user ansible
When the installation is done, you can test that ansible is correctly installed with the following commands :
ansible -m ping 127.0.0.1
You should have the following output :
ansible -m ping 127.0.0.1
[WARNING]: No inventory was parsed, only implicit localhost is available
127.0.0.1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Great ! You run your first Ansible command.
ansible -m ping 127.0.0.1
will just do a ping to 127.0.0.1
But I can run ping 127.0.0.1 to do that !
Well, it’s time to run more useful module
Ansible ad-hoc command
Ansible have two “mode” :
- ad-hoc command
- playbook
Ansible ad-hoc command can run single module on multiple host
Ansible playbooks are yaml files with multiple tasks that should be executed on a given host or group of hosts
Let’s look at how ansible ad-hoc command work first
Creating an Inventory file
Let’s pretend we want to install an nginx server on 4 Raspberry pi in our network :
We have 4 Raspberry pi
raspberry1: 10.0.0.1
raspberry2: 10.0.0.2
raspberry3: 10.0.0.3
raspberry4: 10.0.0.4
The user to log into our raspberry pi is pi
and we have our ssh key in the authorize_hosts
You can use : ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
to copy your key in the authorized_keys
So let’s create a new file named inventory.ini with the following content :
[Raspberry] # This line is the name we give to our group of host
10.0.0.1 # This is one of our Raspberry Host ip
10.0.0.2
10.0.0.3
10.0.0.4
[Raspberry:vars] # We can assign variable to ansible
ansible_user=pi # Here the username to connect to our raspberry
PS: Inventory file can be written in .ini or .yml, to keep this tutorial simple I have decided to write the inventory in .ini
So now that we have our inventory file we can try to run the last command we used against our Raspberry
group
ansible -m ping -i inventory.ini Raspberry
you will have the following output :
ansible -m ping -i inventory.ini Raspberry
10.0.0.1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Now, we know that we can reach all 4 Raspberry pi, let’s install nginx :
ansible -m apt -a "name=nginx state=present" -i inventory.ini Raspberry --become
So here we use the apt module : https://docs.ansible.com/ansible/latest/modules/apt_module.html
we give extra args to apt
name: is the name of the package we want to install here: nginx
state: is the state of the package, here we want to have nginx present on our raspberry
–become: is use to escalate to root to install nginx
When you run the command for the first time, the output will be
192.168.1.34 | CHANGED => {
...
}
If you run the command multiple time, the output will always be
192.168.1.34 | SUCCESS => {
"cache_update_time": 1586104797,
"cache_updated": false,
"changed": false
}
Because nginx is already install, ansible will not try to reinstall nginx if the package is in the state you set before
if you want to uninstall nginx just replace present by absent.
Ansible playbook
Now that we have run some easy command to install nginx on our raspberry let’s make our first playbook
An Ansible playbook is a set of action use to run automate task, you can use all the module you used before in the ad-hoc command
let’s make a new directory
mkdir my-playbook
Create a new inventory file inside your new folder with the following content :
[localhost]
127.0.0.1
Now, let’s write an ansible playbook to install useful tools for CTF or HackTheBox machine
create a new file : install-hacker-tools.yml
---
- hosts: localhost
connection: local
tasks:
- name: Install hacker tools # Here is the name of our task
apt: # We use Apt module here
name: "{{ item }}" # Here we want to loop on multiple package
state: present # We want all our package present on our system
with_items: # Here is the block use to run loops
- nmap
- golang
- git
- name: Install Gobuster
shell: go get github.com/OJ/gobuster # Here we use shell module to run inline command
This file will install nmap, golang, git and gobuster on your local machine
you can run this playbook with :
ansible-playbook install-hacker-tools.yml -i inventory.ini -b
Now all the tools are installed on your machine
With some modification on the playbook and on your inventory, you can run this playbook on a group of hosts
If we have the following inventory :
[Raspberry]
10.0.0.1
10.0.0.2
[WebServer]
10.20.40.1
10.20.40.5
And the following playbook
---
- hosts: all
tasks:
- name: Install hacker tools
apt:
name: "{{ item }}"
state: present
with_items:
- nmap
- golang
- git
- name: Install Gobuster
shell: go get github.com/OJ/gobuster
We can run the playbook only on our Raspberry group with the following command:
ansible-playbook install-hacker-tools.yml -i inventory.ini -b --limit Raspberry
Now you can play a little bit with ansible and automate cool things !
If you have question about ansible tweet me at L3akM3_0d4y !