# Cisco ACL Idempotency Not Working

**URL:** <https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857>\
**Category:** Get Help\
**Tags:** cisco, playbook\
**Created:** [August 14, 2024, 11:26pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857 "2024-08-14T23:26:26Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 14, 2024, 11:26pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/1 "2024-08-14T23:26:26Z")

</div>

I have a simple ACL for a Cisco router. I cannot figure out how to make the playbook idempotent. It always detects a change.

```auto
- name: Create new vty acl
  cisco.ios.ios_config:
    lines:
    - 5 permit tcp 172.16.0.0 0.15.255.255 any eq 22
    parents: ip access-list extended vty-acl-in
    before: no ip access-list extended vty-acl-in
    match: exact
    replace: block

```

[WARNING]: ansible-pylibssh not installed, falling back to paramiko  
redirecting (type: action) cisco.ios.ios\_config to cisco.ios.ios  
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device  
changed: [rtr2] =\> {“banners”: {}, “changed”: true, “commands”: [“no ip access-list extended vty-acl-in”, “ip access-list extended vty-acl-in”, “5 permit tcp 172.16.0.0 0.15.255.255 any eq 22”], “updates”: [“no ip access-list extended vty-acl-in”, “ip access-list extended vty-acl-in”, “5 permit tcp 172.16.0.0 0.15.255.255 any eq 22”]}

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
rtr2 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

sh ver  
Cisco IOS Software, Linux Software (I86BI\_LINUX-ADVENTERPRISEK9-M), Version 15.4(1)T, DEVELOPMENT TEST SOFTWARE  
Technical Support: [Support - Cisco Support and Downloads – Documentation, Tools, Cases - Cisco](http://www.cisco.com/techsupport)  
Copyright (c) 1986-2013 by Cisco Systems, Inc.  
Compiled Sat 23-Nov-13 03:28 by prod\_rel\_team

ansible --version  
ansible [core 2.16.9]

---

<div class="post-metadata">

**Author:** ![Jonathan](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jonathan/32/4215_2.png) [@Jonathan](https://forum.ansible.com/u/Jonathan)\
**Post date:** [August 15, 2024, 8:40pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/2 "2024-08-15T20:40:17Z")

</div>

Hey asdfnk143,

Something that comes to mind when looking at your playbook snip here is that you are specifying a before action to remove the ACL and then implement it. Ansible may be detecting that as a change, since inherently it is changing something.

Furthermore,

Have you tried to implement this ACL using the cisco.ios.ios\_aclsl module, instead of the cisco.ios.ios\_config module? The ACL module can be found [here](https://docs.ansible.com/ansible/latest/collections/cisco/ios/ios_acls_module.html#ansible-collections-cisco-ios-ios-acls-module).

At the bottom of the module, before the examples section, there is a “state” section, which specifies how ansible should treat implementing it’s config:

 ![image](https://us1.discourse-cdn.com/ansible/original/2X/e/e8d5064646348ac75016139623dd0f26bbea3021.png)

Here is some code from my github I pulled. It’s for a **standard** acl config, but this should give you a good idea of what’s going on 🙂

```auto
    - name: Create new vty acl
      cisco.ios.ios_acls:
        config:
          - afi: ipv4
            acls:
              - name: vty-acl
                acl_type: standard
                aces:
                  - grant: permit
                    sequence: 10
                    source:
                      address: 172.16.0.0
                      wildcard_bits: 0.15.255.255   

```

Let me know if any of that helps, I’m just a network engineer working on rolling out automation to my company , not an Ansible expert (yet 😉 )

---

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 15, 2024, 11:52pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/3 "2024-08-15T23:52:31Z")

</div>

Hey @Jonathan thanks for looking at my issue. I’ve tried the acl module and the config module and still no lucky. I tried your code with the standard acl and it’s still saying changed on subsequent runs of the play. This other forum post said to include the before: no acl format but that doesn’t work for me either? [https://github.com/ansible/ansible/issues/47067](https://github.com/ansible/ansible/issues/47067)

---

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 16, 2024, 12:52am UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/4 "2024-08-16T00:52:42Z")

</div>

This is not idempotent either,

```auto
- name: Create IOS Mgmt ACL
  cisco.ios.ios_acls:
    state: replaced
    config:
    - afi: ipv4
      acls:
      - name: vty-acl-in
        acl_type: extended
        aces:
        - destination:
            any: true
            port_protocol:
              eq: '22'
          grant: permit
          protocol: tcp
          source:
            address: 172.16.0.0
            wildcard_bits: 0.3.255.255
          sequence: 5
  register: acl_result

```

---

<div class="post-metadata">

**Author:** ![Jonathan](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jonathan/32/4215_2.png) [@Jonathan](https://forum.ansible.com/u/Jonathan)\
**Post date:** [August 16, 2024, 2:41am UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/5 "2024-08-16T02:41:58Z")

</div>

So I tried running the apparent “fix” in the github post, and it seemed to make things worse.

Here is the code for reference:

```auto
- name: ACL Playbook to test idempotency

  hosts: LAB
  #serial: 1

  gather_facts: no

  vars:
    Ansible_test:
      - "10 permit 10.10.1.0 0.0.0.255"
      - "15 permit 10.10.80.0 0.0.0.255"
      - "20 deny any log"

  tasks:
   - name: Configure test ACL
     cisco.ios.ios_config:
      lines: "{{ Ansible_test }}"
      parents: ip access-list standard Ansible-test
      match: line
      replace: block
      before: no ip access-list standard Ansible-test
     register: result

```

Before I ran the playbook as written above, the first of my switches in my lab would always come back as “ok” (i.e not changed). Now when running this version of the playbook I get all three switches firing off as “changed”.

I can confirm that when I ran my version, Ansible did register the “before: no ip access-list standard Ansible-test” did register as a change when I viewed the results using very very very very verbose mode -vvvv on my playbook run.

More to follow I’m sure…

This may be related to what version of IOS you/we are running, here is a list of the versions in my lab below:

```auto
C9200L-24P-4G 17.06.04
WS-C2960X-24PS-L 15.2(7)E7
WS-C2960CX-8PC-L 15.2(7)E9

```

My C9200L is the only switch that is behaving with Ansible.

---

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 16, 2024, 3:53pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/6 "2024-08-16T15:53:49Z")

</div>

Just got the github example play to be idempotent with a virtual router IOSv 15.9(3)M6. I am still trying to make it work for extended acls though. The difference being standard acls can have the acl name and rule in one line vs the extended acl declares the acl name then you go into the sub-config of that acl and declare your aces.

```auto
- name: "Ensure access_list mgmt_acl_90"
  ios_config:
    save_when: "modified"
    lines:
    - "access-list 90 permit 172.16.0.0 0.3.255.255"
    match: line
    replace: block
    before: "no access-list 90"
  register: result

```

I tried using the “diff\_ignore\_lines” option with no success,

```auto
diff_ignore_lines: ["no ip access-list extended vty-acl", "ip access-list extended vty-acl"]

```

Extended ACL play with ios\_acls module, not idempotent,

```auto
- name: Create IOS Mgmt ACL
  cisco.ios.ios_acls:
    state: replaced
    config:
    - afi: ipv4
      acls:
      - name: vty-acl-in
        acl_type: extended
        aces:
        - destination:
            any: true
            port_protocol:
              eq: '22'
          grant: permit
          protocol: tcp
          source:
            address: 172.16.0.0
            wildcard_bits: 0.3.255.255
          sequence: 5
  register: acl_result

```

Extended ACL play with config module, not idempotent,

```auto
- name: load new acl into device
  ios_config:
    lines:
    - 10 permit tcp 172.16.0.0 0.3.255.255 any eq 22
    parents: ip access-list extended test
    before: no ip access-list extended test
    match: exact

```

---

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 16, 2024, 4:34pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/7 "2024-08-16T16:34:54Z")

</div>

Tried several permutations of the following to get extended acl to be idempotent,

```auto
- name: load new acl into device
  ios_config:
    lines:
    - 10 permit tcp 172.16.0.0 0.3.255.255 any eq 22
    parents: ip access-list extended test
    before: no ip access-list extended test
    match: line
    diff_ignore_lines: ["no ip access-list extended test"]
    diff_against: running

```

The verbose output seems like it should ignore but it’s not?

```auto
changed: [rtr1] => {
    "banners": {},
    "changed": true,
    "commands": [
        "no ip access-list extended test",
        "ip access-list extended test",
        "10 permit tcp 172.16.0.0 0.3.255.255 any eq 22"
    ],
    "invocation": {
        "module_args": {
            "after": null,
            "backup": false,
            "backup_options": null,
            "before": [
                "no ip access-list extended test"
            ],
            "defaults": false,
            "diff_against": "startup",
            "diff_ignore_lines": [
                "no ip access-list extended test"
            ],
            "intended_config": null,
            "lines": [
                "10 permit tcp 172.16.0.0 0.3.255.255 any eq 22"
            ],
            "match": "line",
            "multiline_delimiter": "@",
            "parents": [
                "ip access-list extended test"
            ],
            "replace": "line",
            "running_config": null,
            "save_when": "never",
            "src": null
        }
    },
    "updates": [
        "no ip access-list extended test",
        "ip access-list extended test",
        "10 permit tcp 172.16.0.0 0.3.255.255 any eq 22"
    ]
}

```

---

<div class="post-metadata">

**Author:** ![asdfnk143](https://avatars.discourse-cdn.com/v4/letter/a/4da419/32.png) [@asdfnk143](https://forum.ansible.com/u/asdfnk143)\
**Post date:** [August 16, 2024, 7:37pm UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/8 "2024-08-16T19:37:44Z")

</div>

I give up on using “ip access-list” standard or extended acl versions. Idempotency seems to only work with “access-list 1” type.

Putting a couple more reference links of what other people have used but none seem to be idempotent.

> **[Adding and Editing ACL on Cisco IOS using Ansible](https://www.networkgalaxy.org/2020/04/adding-and-editing-acl-on-cisco-ios.html)**
>
> A blog about IT Networking, Cloud Computing, Internet of Things, Network Automation, Scripting and much more. Just Networkify Everything..!!!!

> **[Managing Network ACL's With Ansible](https://skyenet.tech/acls-with-ansible/)**
>
> This is a quick glimpse at a production application of Ansible to automate your infrastructure Access-Control-Lists.
> 
> 
> Access-Control-Lists
> 
> Aceess-Control-Lists (ACLs), along with route-maps and prefix-lists, are commonly used to secure a number of...

---

<div class="post-metadata">

**Author:** ![jbroillet](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jbroillet/32/7548_2.png) [@jbroillet](https://forum.ansible.com/u/jbroillet)\
**Post date:** [February 11, 2025, 9:27am UTC](https://forum.ansible.com/t/cisco-acl-idempotency-not-working/7857/9 "2025-02-11T09:27:29Z")

</div>

Hello,

Late reply but maybe still helpful.

Idempotency works with sequence number only on IOS-XE devices because IOS-XE shows the sequence number on the running-config.

IOS devices do not show this sequence number on the running-config. Ansible makes a diff between what is in running-config and what is in your commands.  
Diff is always true because sequence number is missing in running-config.

You can do idempotent playbook by omitting the sequence number.

Regards 🙂
