Ansible ufw module ERROR: Could not find a profile matching 'xxxxx'
Asked Answered
M

1

6

I'm working to setup UFW rules via Ansible. I'm able to get it installed, start it and deny everything. I then attempt to allow connections from http, https, and ssh. All attempts to add the allow for those items are met with errors that look like:

failed: [lempy1] (item={u'service': u'http'}) => {"failed": true, "item": {"service": "http"}, "msg": "ERROR: Could not find a profile matching 'http'\n"}
failed: [lempy1] (item={u'service': u'https'}) => {"failed": true, "item": {"service": "https"}, "msg": "ERROR: Could not find a profile matching 'https'\n"}
failed: [lempy1] (item={u'service': u'ssh'}) => {"failed": true, "item": {"service": "ssh"}, "msg": "ERROR: Could not find a profile matching 'ssh'\n"}

The entire role looks like this:

tasks/main.yml

     ---
    - name: Install ufw
      apt: name=ufw state=present
      tags:
        - security

    - name: Allow webservery things
      ufw:
        rule: allow
        name: '{{item.service}}'
      with_items:
        - service: http
        - service: https
        - service: ssh
      tags:
        - security

    - name: Start ufw
      ufw: state=enabled policy=deny
      tags:
        - security

Any idea why I wouldn't be able to allow these services? I am able to add the services properly when ssh'ing into the server and running sudo ufw allow http, etc.

Muddler answered 17/5, 2016 at 6:7 Comment(1)
Could it be related to the rule name being transmitted with the single quote? I know YAML force you to quote {{ and }} but you could try to replace '{{item.service}}' with "{{item.service}}" and check the result.Cubiform
D
3

As mentioned in the ufw module docs, the name (or app) parameter uses applications that are registered in /etc/ufw/applications.d which have an INI format and look something like this:

[CUPS]
title=Common UNIX Printing System server
description=CUPS is a printing system with support for IPP, samba, lpd, and other protocols.
ports=631

Normally you can use ufw allow application-profile to allow an application defined either in /etc/ufw/applications.d or /etc/services to open up iptables for things that aren't necessarily defined in /etc/ufw/applications.d.

Unfortunately, Ansible's ufw module instead builds the ufw command in this format instead:

/usr/sbin/ufw allow from any to any app 'application-profile'

Which only uses the /etc/ufw/applications.d list and won't read /etc/services.

In your case you could simply specify the ports as these are well known, potentially using a named variable to further explain your Ansible code:

- name: Allow webservery things
  ufw:
    rule: allow
    port: '{{ item }}'
  with_items:
    - '{{ http_port }}'
    - '{{ https_port }}'
    - '{{ ssh_port }}'
  tags:
    - security

And then define the variables somewhere (such as your role defaults):

http_port: 80
https_port: 443
ssh_port: 22

As an aside, you might want to notice that I simplified your list of dictionaries with a single key into a simpler straight list which tidies up your task a bit.

Alternatively you could easily template the application profiles using Ansible's template module.

Drafty answered 17/5, 2016 at 9:48 Comment(3)
so I still get the Could not find a profile matching '80'. Same for all other ports I try and assign. Error looks like: {"failed": true, "item": 80, "msg": "ERROR: Could not find a profile matching '80'\n"}. Any ideas? My task now looks exactly as you've laid it out here. I'm wondering if a template would be the best thing to do.Muddler
Apologies, that should have been port rather than name. Forgot to edit that when I copied your code into my answerDrafty
Figured that part out fiddling around, thanks again!Muddler

© 2022 - 2024 — McMap. All rights reserved.