{"id":6943,"date":"2021-12-01T09:20:55","date_gmt":"2021-12-01T15:20:55","guid":{"rendered":"http:\/\/gregsowell.com\/?p=6943"},"modified":"2021-12-01T09:20:55","modified_gmt":"2021-12-01T15:20:55","slug":"ansible-automation-platform-configures-nexus-9k-acls","status":"publish","type":"post","link":"https:\/\/gregsowell.com\/?p=6943","title":{"rendered":"Ansible Automation Platform Configures Nexus 9K ACLs"},"content":{"rendered":"<p><a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1-300x169.jpg\" alt=\"\" width=\"300\" height=\"169\" class=\"aligncenter size-medium wp-image-6944\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1-300x169.jpg 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1-768x432.jpg 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1-1024x576.jpg 1024w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/11\/Untitled-1.jpg 1280w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>There are some newer &#8220;ACLs&#8221; modules available via many AAP collections now that make it soooo simple to work idempotently with Access Lists on networking kit.  I figured I&#8217;d show a quick example of using the <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/collections\/cisco\/nxos\/nxos_acls_module.html\">nxos_acls modules <\/a>against some virtual Nexus 9Ks.<\/p>\n<h2>Video Demo<\/h2>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/XVNdPJsETUI\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<h2>Playbook And Files<\/h2>\n<p>You can find the <a href=\"https:\/\/github.com\/gregsowell\/ansible-nexus-acl\">GitHub repo here<\/a> containing all of the files.<\/p>\n<p>I&#8217;m using a template file to specify what the ACL should look like.  The idea is that if I ever want to make an update to this ACL, I don&#8217;t connect to the switch and make adjustments, I simply edit this template file and then use my automation to push the changes.  I can remove or add lines, and the automation will make the ACL on the switch match.<br \/>\nTemplate files looks like this(nexus-acl-template):<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">ip access-list test\r\n  10 permit ip 1.1.1.1\/32 2.2.2.2\/32\r\n  20 permit ip 1.1.1.3\/32 2.2.2.4\/32\r\n  22 permit ip 1.2.3.4\/32 4.3.3.1\/32\r\n  25 permit ip 1.2.3.5\/32 2.2.2.3\/32<\/code><\/pre>\n<p>Now for the playbook(nexus-acl.yml):<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">---\r\n- name: nxos acl testing\r\n  hosts: nexus9k1\r\n  gather_facts: false\r\n  vars:\r\n#    acl_name: test\r\n\r\n  tasks:\r\n  - name: Parse given config to structured data\r\n    cisco.nxos.nxos_acls:\r\n      running_config: &quot;{{ lookup(&#039;file&#039;, &#039;nexus-acl-template&#039;) }}&quot;\r\n#      running_config: |\r\n#        ip access-list ACL1v4\r\n#          50 deny tcp any lt 55 192.0.2.64 0.0.0.255 ack fin\r\n#        ipv6 access-list ACL1v6\r\n#          10 permit sctp any any\r\n      state: parsed\r\n    register: acl_parsed\r\n \r\n#  - name: debut the acl_parsed variable\r\n#    debug:\r\n#      var: acl_parsed\r\n\r\n  - name: Do reconciliation of parsed ACL\r\n    cisco.nxos.nxos_acls:\r\n      config: &quot;{{ acl_parsed.parsed }}&quot;\r\n      state: replaced\r\n    register: acl_ran\r\n\r\n  - name: Debug when changed\r\n    when: acl_ran.changed == true\r\n    debug:\r\n      var: acl_ran.commands<\/code><\/pre>\n<p>^^^in the above playbook I really only have two tasks.<br \/>\nThe first task is using the nxos_acls module to take my template file, parse it, then save the result to a variable(notice &#8220;state: parsed&#8221;).<br \/>\nThe parsing is required because this module expects ACE entries to be in a key:value pair configuration.  This is easy to use, but would be insanely tedious to have to build and store entries in this fashion.  Not only that, but it is difficult to read when there are a lot of entries.  Here&#8217;s an example of the format expected:<\/p>\n<pre class=\"gs-code\"><code class=\"language-plaintext\">    - afi: ipv4\r\n      acls:\r\n      - name: ACL1v4\r\n        aces:\r\n        - grant: deny\r\n          destination:\r\n            address: 192.0.2.64\r\n            wildcard_bits: 0.0.0.255\r\n          source:\r\n            any: true\r\n            port_protocol:\r\n              lt: 55\r\n          protocol: tcp\r\n          protocol_options:\r\n            tcp:\r\n              ack: true\r\n              fin: true\r\n          sequence: 50<\/code><\/pre>\n<p>^^^not the easiest to read.  So the fact that the module will parse a standard ACL for me is AWESOME!<\/p>\n<p>The last real task takes the parsed variable and applies it to the device with a state of &#8220;replaced&#8221;.  This tells the module to take the variablized data and remove anything that shouldn&#8217;t be there and add anything that doesn&#8217;t already exist.  If the ACE from my template file already exists, it will just ignore it and do nothing.  If, however, the entry doesn&#8217;t exist, then it will go ahead and create it.  <\/p>\n<p>One of the really cool features of the replace command is the resulting informational output from the command. If I save the results to a variable, it will show the exact commands that the module will be pasting in the SSH console for the switch.  That way if I run the playbook in check mode it will show me anything that is in non-compliance!<\/p>\n<h2>Running In Controller<\/h2>\n<p>First, this is what the ACL on the switch currently looks like:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_2.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_2-300x115.jpg\" alt=\"\" width=\"300\" height=\"115\" class=\"aligncenter size-medium wp-image-6947\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_2-300x115.jpg 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_2.jpg 319w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Running the playbook in check mode provides me with the following:<br \/>\n<a href=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_1.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_1-300x152.jpg\" alt=\"\" width=\"300\" height=\"152\" class=\"aligncenter size-medium wp-image-6948\" srcset=\"https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_1-300x152.jpg 300w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_1-768x390.jpg 768w, https:\/\/gregsowell.com\/wp-content\/uploads\/2021\/12\/Screenshot_1.jpg 830w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\nOne entry removed and one entry added.<\/p>\n<h2>Conclusion<\/h2>\n<p>I&#8217;m honestly so stoked about the direction we are going with these idempotent modules that make working with often updated configs like ACLs dead simple.  If you would tweak, tune, or change anything, let me know.  <\/p>\n<p>Thanks and happy automating!  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are some newer &#8220;ACLs&#8221; modules available via many AAP collections now that make it soooo simple to work idempotently with Access Lists on\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49,16,8],"tags":[],"class_list":["post-6943","post","type-post","status-publish","format-standard","hentry","category-ansible","category-cisco","category-networking"],"_links":{"self":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6943"}],"version-history":[{"count":4,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6943\/revisions"}],"predecessor-version":[{"id":6950,"href":"https:\/\/gregsowell.com\/index.php?rest_route=\/wp\/v2\/posts\/6943\/revisions\/6950"}],"wp:attachment":[{"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregsowell.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}