Showing posts with label ansible. Show all posts
Showing posts with label ansible. Show all posts

Thursday, January 25, 2018

Configuring Firewalld on CentOS 7 with Ansible

I've been working on the configuration of a new server with Ansible; this client has CentOS servers, so I'm configuring it for the current release of CentOS 7.x, which comes with Firewalld. All of the existing playbooks are set up for iptables, which was used in earlier versions of CentOS.

I thought about rolling it back to iptables, but I decided to try using firewalld first. I hit some problems:

  • Firewalld port forwarding only supports remote traffic:
    • If I want to run Tomcat and use the firewall to forward from port 80 to the Tomcat port, then accessing http://localhost will not trigger these port forwarding rules.
    • Fortunately, you can work around that with a "direct" rule.
  • The ansible firewalld module seems immature:
    • flagged as 'preview'
    • doesn't support port forwarding
    • doesn't support direct rules
    • You can work around that by invoking `firewall-cmd` using the command module.
  • Not easy to use `firewall-cmd` in an idempotent way.
    • Firewalld is configured with commands, somewhat like iptables. You can run these commands using the command module.
    • It's not that easy to invoke these commands in Ansible in a way that lets you be properly idempotent -- only run this command or mark it changed if something has changed. As a result, these will run every time, and if you have a handler to restart the firewalld service, that will also trigger every time.
What I ended up doing is configuring firewalld with commands, then looking at the configuration files that result and instead of having the ansible playbook trigger these commands, I have the playbook copy these files into place. File copying is something that is easier to do in an idempotent way than command invocation, so I can configure Ansible to copy configuration files into place (/etc/firewall/direct.xml, /etc/firewall/zones/public.xml), and then restart firewalld if the files have changed.

That seems to be reasonably happy.

Sunday, September 18, 2016

Host Key Verification and Ansible

I've been using Ansible to configure some instances on Amazon Web Services with a client, for two reasons:
  • To make it repeatable in the future, if we want to configure an instance again, or another instance.
  • Because I will be repeating it immediately now, making more than one server to live behind a load balancer that are meant to be configured identically.
When you connect to a host for the first time over SSH, you are asked to verify the host key. When you use Ansibleagainst a host for the first time, the same thing happens. If you are connecting to multiple hosts at the same time, bad things happen -- you get multiple prompts to verify the host key and responding to them doesn't seem to work:

$ ansible servergroup -m ping
The authenticity of host '10.0.2.161 ()' can't be established.
ECDSA key fingerprint is SHA256:hEdMy3XKWV/zWobmSuwf+b6oI9xt4cYJzM1eAa2T8Ak.
Are you sure you want to continue connecting (yes/no)? 
The authenticity of host '10.0.1.79 ()' can't be established.
ECDSA key fingerprint is SHA256:N5iv0/+zRHk7UTsIQOUlzn2ZiU9L2xL+Fn153nlZdjs.
Are you sure you want to continue connecting (yes/no)? yes
Please type 'yes' or 'no': yes
Please type 'yes' or 'no': yes
Please type 'yes' or 'no': yes
Please type 'yes' or 'no': yes
Please type 'yes' or 'no': yes
Please type 'yes' or 'no': ^CProcess WorkerProcess-3:
Process WorkerProcess-2:
Traceback (most recent call last):
 [ERROR]: User interrupted execution

 While I was pleased to read the toroid.org post about bugs filed, it doesn't seem to be fixed yet.

Happily, as long as you connect to a single host at at time, everything is fine, and after that you can connect to the group:
$ ansible server-one -m ping
The authenticity of host '10.0.1.79 ()' can't be established.
ECDSA key fingerprint is SHA256:N5iv0/+zRHk7UTsIQOUlzn2ZiU9L2xL+Fn153nlZdjs.
Are you sure you want to continue connecting (yes/no)? yes
server-one | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
That's fine for a couple of servers, but it wouldn't be fun with a large cluster. If there's a better way, I haven't discovered it yet.