14

I'm new to Ansible. Most VPS provisioning guides I've seen so far do this:

  1. disable root from logging in
  2. create a new user who can only log in with ssh (not password)
  3. add the new user to the wheel group, with passwordless sudo permission

I understand (1) and (2), but not (3).

Surely passwordless sudo is just like logging in as root? I understand the benefit (convenience), but isn't this highly insecure?

I realise that admins run their networks in various ways, and so this could be said to be "subjective", but this is a VERY common practice, it's even shown in various official ansible docs as well as guides published by hosting companies. It goes against common sense. What is the logic behind it?

chicks
  • 3,793
  • 10
  • 27
  • 36
lonix
  • 896
  • 10
  • 23
  • 2
    Ansible is intended for automating administrative tasks, so generally needs top-level (root) level access hence "passwordless sudo". If you only need it to run a subset of the commands available on your system though, you can lock it down to just those commands with a more detailed sudo configuration. Passwordless sudo does not necessarily mean access to *everything* root can do (though this becomes difficult to enforce when you realise the user can potentially modify your sudo config via sudo to give themselves greater control...). – David Spillett Aug 21 '19 at 13:55
  • @DavidSpillett I was wondering about that - i.e. defining which sudo commands to allow in the sudoers file... but I read somewhere that ansible does everything by interpreting via complex python commands, and that that approach would get messy fast. – lonix Aug 21 '19 at 14:08

4 Answers4

20

If the service account can do passwordless sudo, then you have to protect access to that account.

Having the account not have a password, and using only ssh keys to log in to it, accomplishes this, provided you can keep the ssh private key secure as well.

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972
  • 1
    So I'm "sort of" right in feeling perturbed by this convention - and yet, this is the convention for ansible, out of necessity/pragmatism. – lonix Aug 20 '19 at 18:50
  • 1
    So you're saying that I essentially "move" core security from the VPS to my local system, which contains the ansible account's ssh key? In which case, the weak point is not the VPS itself, rather, it's me! And I need to be extra vigilant in protecting that ssh key, in exchange for the convenience that ansible automation gives me. – lonix Aug 20 '19 at 18:57
  • 7
    ssh key, passphrase protected with ssh-agent, is a reasonably good credential. – John Mahowald Aug 20 '19 at 20:14
  • @lonix All secured systems need credentials. Secured systems are at most as secure as the measures you put in securing these credentials, since having those gives 100% access to them. So yes, you cannot expect to secure your VPS if you don't secure properly your SSH key (or root password or whatever). The fact that you configure passwordless sudo means nothing from this point of view, enabling sudo with password doesn't change the fact that it is essential that you secure the SSH key. – Giacomo Alzetta Aug 21 '19 at 12:56
  • @GiacomoAlzetta I know that, what I meant above is that the responsibility is being shifted from the remote to the local machine. Since sudo escalation is done without password, the weak point becomes local. – lonix Aug 21 '19 at 13:02
  • @lonix > "the weak point is not the VPS itself, rather, it's me!" This is true in all cases, anyway. The weakest link in creating a secure system is usually the administrator. But that's a good, empowering statement. As your skills and practices improve, your security improves along with it. The level of security you achieve is directly under your own control. – Jim L. Aug 21 '19 at 17:56
  • @Ionix "The weak point becomes local." Just to elaborate on what Jim and Giacomo said, someone with local access to your machine could just install a keylogger and wait for you to type in an admin password. You might imagine some other scenario where local access is bad for your security, even without the service account. So it's not necessarily an increased risk (for a typical dev's threat model). – Eidolon108 Aug 22 '19 at 01:21
4

The new user created in (2) can only log in with the SSH key, no password. The SSH key gives indirect root access. So this is equivalent to just allowing root login with a key.

As the account doesn't have a password, it is not possible to have sudo ask for a password. Also Ansible needs to be able to execute commands. Having an additional password to provide at the same place as the key would not increase security.

RalfFriedl
  • 3,108
  • 4
  • 13
  • 17
3

The problem is that ansible is for administrators and automation, so if you need to enter a password to run a script is not really the best way. Also it's not secure to store the password for sudo in a file or database and ansible get it every time it run the playbook. So the combination of passwordless sudo and the authentication with ssh Keys is the best method to ensure security and no right problems by running the playbook. Also you an administrator and know what you programming in the playbook. So the playbook can not destroy your servers.

NicoKlaus
  • 31
  • 2
  • Playbooks *can* destroy your systems, but if you use separate test environment only keys, that will not destroy the production hosts. – John Mahowald Aug 20 '19 at 19:55
  • Exactly, this is hopefully a prerequisite when working on productive systems. – NicoKlaus Aug 20 '19 at 20:16
  • 2
    Ansible has 'ansible-vault', and plugins/modules/libraries that permit storing of secrets in many 3rd party secret storage systems like bitwarden, hashicorp vault, keepass,etc. – Zoredache Aug 21 '19 at 00:16
1

In a word, yes. It is not as secure as it could be. If a bad actor gains access to one of your servers and it's possible to sudo without a password, then they can also sudo su and become the root user.

Always have a user password that is required to run escalated privileges

You'd think that this would make automation difficult, having to enter a password each time, but this is where the ansible_become_pass host variable comes in useful.

Create a yaml file somewhere and create a dictionary of hosts to sudo passwords:

sudo_passwords:
  host1.wherever.net: superSeCRETpa$$word
  host2.wherever.net: SUPerDuperSecretpa$$word

There are options where you can keep this file, but here is my strategy. I keep the raw secrets file as a plaintext file in an encrypted volume, then add a symlink to a file in the root of your ansible project. You could also keep this file in the root of the ansible project itself, and use ansible-vault to encrypt/decrypt in place.

# Decrypt when you're using it
ansible-vault decrypt sudo_passwords.yaml

# Encrypt when you're done
ansible-vault encrypt sudo_passwords.yaml

For this part, you will need the encryption password. Think of it like a master password. However, I just symlink, since my encrypted volume is only open when I need to do work.

~/my-ansible-project $ ln -s /path/to/vault/sudo_passwords.yaml

Be sure to keep this file out of version control

Then create a task partial to import the sudo passwords as the ansible_become_pass fact. Save to a file separate from any playbooks, as this can be imported to all playbooks.

---
- name: Import Sudo Password as Fact
  ansible.builtin.set_fact:
    ansible_become_pass: "{{ sudo_passwords[inventory_hostname] }}"
...

Then import this task into any playbooks that require escalated privileges:

- name: Playbook Name
  hosts: all
  gather_facts: true
  vars_files:
    # Point to the passwords file relative to where the playbook file resides
    # In this case, it's the same directory
    - sudo_passwords.yaml  
  tasks:
    - name: Set sudo password
      import_tasks: set-sudo.tasks.yaml

    # Add a directory inside the root user's home for proof of concept
    - name: Create secrets directory
      become: true
      ansible.builtin.file:
        path: /root/.secrets
        state: directory
        mode: 0700
        owner: root 

Note that for simplicity, the playbook, imported task and passwords file all reside in the same directory.

This, I believe is a good balance of ease of automation and security.

mwieczorek
  • 121
  • 3