1

It is too easy to run playbooks on the wrong hosts in Ansible

I know the best practice would be to use --limit to make sure you can not select the wrong host. I do not trust --limit to ensure Ansible runs playbooks only on the intended hosts.

Is it a crazy idea to use firewalld to disable communication to all the systems you do not want to update? Is there a more logical way to accomplish the same thing?

1
  • I'm having a hard time understanding how this problem can actually arise. This sounds like an inventory management problem - playbooks target hosts which find themselves in the wrong groups for some reason. Can you please elaborate on what your environment looks like - is it dynamic, how are you tagging hosts, creating groups, etc? Commented Nov 30, 2022 at 7:46

4 Answers 4

1

Q: "Disable communication to all the systems you do not want to update."

A: The only safe way is to physically isolate such environment. A firewall might be an option. But, it's not feasible if you want to keep ssh or other connections that Ansible might use.

On the configuration level, there are many options.

1) Special user

Create a special user for this purpose on the systems you want to update. For example user ansible_update. Depending on your environment configure the DEFAULT_REMOTE_USER to ansible_update. This way you make sure no other systems can be connected by mistake.

In addition to this, you control who can connect to these systems by putting their public keys into the authorized_keys of the user ansible_update at the remote hosts.

To enforce this you have to:

  • monitor users at the remote hosts and their authorized_keys
  • scan your project (playbooks, roles, inventory, configuration) for remote users other than ansible_update

2) Bastion host

A better option is creating a bastion host and making it the only source of the configuration for the environment.

3) ansible-pull

The most flexible option is configuring the remote hosts to pull their updates on their own.

Conclusion: Create special users, create a bastion host, and make the remote hosts pull the updates from it.

0

If you enable firewalld rule for ansible, how you want to disable it? Yeah, there are ways, but hey! we talk here about having some sense in the work.

Where is your environment? I assume it is not dynamic, as for dynamic environment you use dynamic inventory.

First idea - split hosts per environments and corresponding directories. This way you have to provide the correct env and file. It gives the time to think.

Not-very-good-solution - run ansible through script. Makefile, bash, whatever, with confirm action.

The best - use CI/CD. Of course, you can do the mistake there, but... only once ;)

0

If you are really paranoid, generate a custom inventory containing only the hosts you want to update, and pass that.

1
  • This post could use some improvement (like a link/explanation on to how to create a custom inventory).
    – Peter Turner
    Commented Nov 30, 2022 at 22:09
0

I think you might be approaching the problem backwards and are using "hosts: all" instead of specific groups, then limiting with --limit. But if not, here's a solution I've used to target specific hosts (such as those in their maintenance window) within an existing group.

I start running against hosts: all

Then I find some sort of limiting criteria like, use the url module to query my ticketing system to tell me which devices have open changes for patching or something.

Then I use "add_host" to create a temporary subgroup*

- name: Add a host alias that we reach through a tunnel (Ansible 2.0 and newer)
  ansible.builtin.add_host:
    ansible_host: '{{ inventory_hostname }}'
    groups: subgroup


and I run against hosts: subgroup

*warning if you refresh your inventory, this will get hosed

Not the answer you're looking for? Browse other questions tagged or ask your own question.