Security Automation with Ansible
Securing your severs manually, command by command, is a great way to understand how all those layers work to protect the host. But the more servers you stand up, the more you will want to automate the process. This not only saves time, but also achieves a consistent security baseline across your environment. Read on to learn how this can be accomplished with Ansible!
If you want to speed through this guide, check out the TLDR version.
Ramping up with Ansible
This is list of a list of technical dependencies and more of a recommended background to have when working with Ansible. Watch and learn, and you may even come up with some use-cases of your own!
-
YouTube - Ansible - Powerful Open Source system management and task automation tooling! bu Awesome Open Source - This video is a great primer for what Ansible does and how to set up playbooks. If you've never touched Ansible before, start here!
-
YouTube - Getting started with Ansible playlist by Learn Linux TV - This playbook give provides a deeper dive into the many capabilities of Ansible and how you can develop more complex orchestrations for your environment.
Basic security with sts_baseline
We have made simple, easily decipherable shell scripts and Ansible playbooks to get you (provisionally) secured and ready to build your server to your needs. Please read through the scripts and playbook files and understand the mechanics and the purpose of each action. This playbook will run the following roles.
- 0_updateubuntu - Updates the OS.
- 1_provisionuser - Sets up non-root user.
- 2_provisionkey - Creates SSH key.
- 3_uploadkey - Uploads SSK key to server.
- 4_installdocker - Installs and configure Docker.
- 5_securessh - Secures the SSH service.
- 6_backups - Sets up backup scripts.
Note: This playbook is based on Debian/Ubuntu Server. It may accommodate dnf-based distributions like Fedora and its derivatives at a later date
1. Download the SovereignTechStack repository
We should be starting with a fresh deployment of Ubuntu Server of Debian on a VPS. You should have root access and the root password. To begin, download the repository from here and cd into the ansible directory.
2. Edit inventory.ini
You will need to populate your Ansible inventory file (inventory.ini) with three peices of information to start:
- The server's IP address.
- The "server tag" of the server. This is just a short nickname for the server. Like "nextcloud" if it's a Nextcloud server or "auth" for an identity provider server.
- The name of the non-root user that will become part of the sudo group.
EDIT
Under the host group baselines, enter the new servers public IP address, a server tag, and a name for the non-root user. In this example, the server tag is nextcloud, and the non-root username is serveradmin, and the server's IP address is 203.0.113.74.
[all:vars]
server_tag=nextcloud
baseline_nonroot_user=serveradmin
[baselines]
203.0.113.74
[local]
localhost ansible_connection=local
3. Add login credential to Ansible Vault
We'll now store important credential strings in an encrypted Ansible Vault. This is a simple password-encrypted file that gets unlocked with you run the playbooks. From the SovereignTechStack/ansible directory, run
nano and you can start entering these credentials as variables.
- the password to your non-root user
- the password used to encrypt the SSH key you will use to authenticate to the server after the playbook is run.
# Baseline Server Details
baseline_nonroot_user_password: <your non-root user password>
sshkey_password: <SSH key password>
As we handle more sensitive strings (like database passwords, installation tokens, etc.) that we will use to deploy our services, we will add them to this Vault file. To make changes to the Vault, run this command...
...enter the Vault password, make your changes, and save and exit.4. Run the playbook - sts_baseline.yml
We're now ready to run the first Ansible playbook. This playbook runs as root since that's generally the first and only user on a fresh VPC. With the three pieces of information entered from above, the playbook does the basic "changing the lock" like you do when you move into a new house.
The playbook will perform the following:
- Update Ubuntu and install preferred packages. (You can edit the list of packages in the file
SovereignTechStack/ansible/roles/0_updateubuntu/tasks/main.yml) - Provision the non-root user account and add it to the sudo group.
- Create an SSH key on your local machine.
- Upload the newly-created SSH public key to the non-root accounts
authorized-keysfile. - Install Docker Community Edition (CE) and Docker Compose, then add the non-root user to the docker group.
- Lock down the SSH on the server to disable password logins (only logins with SSK keys is allowed) and to disallow logins using the root account.
Run this command from the playbook directory.
Explanation:- ansible-playbook - the command
- sts_baseline.yml - the main playbook file
- -u root - run as the root user
- --ask-vault-pass - asks for the password to the Ansible Vault
- --ask-pass - asks for the root password
Note: If Ansible throws an error that says "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host.", simply SSH into the host to add it to your known_hosts file.ssh root@<server IP address>, add to your known and then log back out.
Authenticating to your server post-baseline
After baselining the server, you can authenticate to the server with this command. Replace the items from in the brackets appropriately and run.
ssh -i ~/.ssh/id_ed25519_<server_tag>_<baseline_nonroot_user> -p 22 <baseline_nonroot_user>@<server_ip>
Preparing for the next steps
The sts_baseline playbook changes to the way you can access the server (by removing password and root logins), so you won't be able to run the playbook like you did before. For the next steps, we will have to change the Ansible configuration a bit to accommodate the newly-created SSH key.
5. Edit the Ansible Vault
Create a new entry for this server. Change baseline_nonroot_user_password to <server_tag>_become_pass and move that line to the new section you created. You can also remove the sshkey_password line.
So the text in the Vault will go from this...
# Baseline Server Details
baseline_nonroot_user_password: <your non-root user password>
sshkey_password: <SSH key password>
6. Edit inventory.ini
Delete the server entry under [baselines] and create a new host group. For example, add the host group [nextcloud] and include the following.
- The server's IP address.
ansible_user=<the non-root user you just created>ansible_become_pass="{{ <server tag>_become_pass }}". This part makes Ansible reference the Vault for the non-root user's password.ansible_ssh_private_key_file="~/.ssh/id_ed25519_<server_tag>_<non-root user>". This directs Ansible to use the newlly-created SSH key to authenticate.
Here's an example.
[baselines]
[local]
localhost ansible_connection=local
[nextcloud]
203.0.113.74 ansible_user=serveradmin ansible_become_pass="{{ nextcloud_become_pass }}" ansible_ssh_private_key_file="~/.ssh/id_ed25519_nextcloud_serveradmin"
I ran the baselining playbook already, but made a mistake.
There might be a case where you want to run a single baseline task like installing more default packages or
maybe you forgot the details for the SSH key. Just put the edited server entry back in the [baselines] host group and you can run the playbook with tags like so.
Here are the other supported tags for the sts_baseline playbook that you can run individually after the first run.
updatespackagesprovisionuserprovisionkeyuploadkeysecuresshinstalldockersshkeydetails