PaloAltoNetworks / ansible-pan

Ansible modules for Palo Alto Networks NGFWs
Other
229 stars 161 forks source link

panos_security_rule - pass list var as argument for source_ip, destination_ip, application, service and source_users #147

Closed erics302 closed 6 years ago

erics302 commented 6 years ago

Hello all - It would be great if the panos_security_rule module accepted a list var as input for source_ip, destination_ip, application, service and source_users. It seems to only work if you manually enumerate each value in the argument.

Failing example using list var

Here is one example of trying to pass a list for application which fails because a list var is used as input:

- hosts: PALO
  connection: local
  vars:
    src: 1.1.1.1/32
    dest: 1.1.1.2/32
    app_groups:
    - TCP_00080_HTTP
    - TCP_00443_HTTPS
    - TCP_00022_SSH 

  tasks:
    - name: Add rule
      panos_security_rule:
        ip_address: "{{ ip_address }}"
        api_key: "{{ api_string }}"
        devicegroup: zLAB-Apps
        operation: add
        rule_name: "list var test rule"
        source_ip: ["{{ src }}"]
        destination_ip: ["{{ dest }}"]
        application: ["{{ app_groups }}"]

Error:

fatal: [plpano01]: FAILED! => {"changed": false, "msg": " list var test rule -> application '['TCP_00080_HTTP', 'TCP_00443_HTTPS', 'TCP_00022_SSH']' is not an allowed keyword\n list var test rule -> application '['TCP_00080_HTTP', 'TCP_00443_HTTPS', 'TCP_00022_SSH']' is not a valid reference\n list var test rule -> application is invalid"}
        to retry, use: --limit @/home/eric/repo/ansible-role_aci_fw/panos_sec_rule_list_vars.retry

PLAY RECAP *************************************************************************************************************
plpano01                   : ok=1    changed=0    unreachable=0    failed=1   

Same code enumerating all vars as strings

The code necessary to do this now which is not desirable because I must enumerate the apps as individual vars, and my input from rule requestors allows a variable number of apps (or service, source_ip, destination_ip, source_users and services).

---
- hosts: PALO
  connection: local
  vars:
    src: 1.1.1.1/32
    dest1: 1.1.1.2/32
    dest2: 1.1.1.3/32
    app1: TCP_00080_HTTP
    app2: TCP_00443_HTTPS
    app3: TCP_00022_SSH 

  tasks:
    - name: Add rule
      panos_security_rule:
        ip_address: "{{ ip_address }}"
        api_key: "{{ api_string }}"
        devicegroup: 'zLAB-Apps'
        operation: add
        rule_name: "Individual vars test rule"
        source_ip: ["{{ src }}"]
        destination_ip: ["{{ dest1 }}", "{{ dest2 }}"]
        application: ["{{ app1 }}", "{{ app2 }}", "{{ app3 }}"]
shinmog commented 6 years ago

@erics302

I think this is just a data formatting problem with your playbook.

For params that are expecting a list, just make sure that you define the variable as a list. In a few of your examples above, you're specifying them as strings instead. Second, once you have that list variable, you can use it just like you were initially trying to do, and it should work.

I'm also going to modify this playbook to use the state param instead of operation so its idempotent (new in the Ansible Galaxy 2.0 Palo Alto Networks role), but you can continue to use operation if you want.

So try this instead:

---
- hosts: PALO
  connection: local
  vars:
    src:
      - 1.1.1.1/32
    dest:
      - 1.1.1.2/32
      - 1.1.1.3/32
    app:
      - TCP_00080_HTTP
      - TCP_00443_HTTPS
      - TCP_00022_SSH

  tasks:
    - name: Add rule
      panos_security_rule:
        ip_address: "{{ ip_address }}"
        api_key: "{{ api_string }}"
        devicegroup: 'zLAB-Apps'
        state: 'present'
        rule_name: "Individual vars test rule"
        source_ip: "{{ src }}"
        destination_ip: "{{ dest }}"
        application: "{{ app }}"
erics302 commented 6 years ago

@shinmog Awesome that's all it was, I removed the square [] brackets from the play. Thanks, list works perfect!

On a side note, I just downloaded the new panos_security_rule.py from commit ae407b, using state: present doesn't behaving idempotently; it behaves like the old operation 'update' which is to overwrite the existing rule values.

shinmog commented 6 years ago

@erics302

It should behave like "add it if it isn't present, but if it is present and doesn't match this definition, update it." Is this not what you're seeing?

erics302 commented 6 years ago

Hi @shinmog What I'm seeing is the security rule is configured as the last play that runs against that rule name. I was thinking it would be additive. Here is my example: I want to add an extra app group to an existing rule. My desired end state rule has two application groups, TCP-00443-HTTPS and TCP-00080-HTTP

First play to instantiate the rule

    - name: Add rule
      panos_security_rule:
        ip_address: "{{ ip_address }}"
        api_key: "{{ api_string }}"
        devicegroup: 'zLAB-Apps'
        state: present
        rule_name: "Test rule"
        source_ip: ["1.1.1.7/32"]
        destination_ip: ["1.1.1.3/32"]
        application: ["TCP_00443_HTTPS"]

Rule is as desired, only app group "TCP-00443-HTTPS" for now:

image

Run play a second time with only application group TCP-00080-HTTP

Now I want to go back and add a second port to the existing rule; only the application argument has changed and I run the play again.

    - name: update rule
      panos_security_rule:
        ip_address: "{{ ip_address }}"
        api_key: "{{ api_string }}"
        devicegroup: 'zLAB-Apps'
        state: present
        rule_name: "Test rule"
        source_ip: ["1.1.1.7/32"]
        destination_ip: ["1.1.1.3/32"]
        application: ["TCP_00080_HTTP"]

Result after second play run

The rule is overwritten. In my example the rule matches only the last run of the play. I tried with source_ip, destination_ip and service and get the same result. image

shinmog commented 6 years ago

@erics302

I understand. What you were looking for was "add in this config to what is already present." Unfortunately that's not how state is designed, and not what would be expected from long time Ansible users from state. The expectation is that state behaves as "make sure that this thing exists in the config and looks like what I'm specifying."

erics302 commented 6 years ago

@shinmog Thanks for the explanation. I do appreciate the work you are doing for us. I'm closing this issue since list vars are supported I was using incorrect syntax.