diff --git a/ansible/roles/test/files/helpers/config_service_acls.sh b/ansible/roles/test/files/helpers/config_service_acls.sh new file mode 100755 index 00000000000..ca1a730689b --- /dev/null +++ b/ansible/roles/test/files/helpers/config_service_acls.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# +# config_service_acls.sh +# +# Configure service ACLs in such a way that should prevent Ansible +# server from connecting to running services. This should cause Ansible +# playbook tasks which remotely connect to thses services to fail (timeout), +# ensuring service ACLs are implemented correctly and actually dropping +# unpermitted traffic. +# + +# Generate an ACL config file which allows only IP address ranges which +# shouldn't contian the IP address of our Ansible server +cat << EOF > /tmp/testacl.json +{ + "acl": { + "acl-sets": { + "acl-set": { + "SNMP-ACL": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_UDP", + "source-ip-address": "1.1.1.1/32" + } + } + } + } + }, + "config": { + "name": "SNMP-ACL" + } + }, + "ssh-only": { + "acl-entries": { + "acl-entry": { + "1": { + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + }, + "config": { + "sequence-id": 1 + }, + "ip": { + "config": { + "protocol": "IP_TCP", + "source-ip-address": "1.1.1.1/32" + } + } + } + } + }, + "config": { + "name": "ssh-only" + } + } + } + } + } +} +EOF + +# Install the new service ACLs +acl-loader update full /tmp/testacl.json + +# Sleep to allow Ansible playbook to attmept to connect and timeout +sleep 30 + +# Delete the test ACL config file +rm -rf /tmp/testacl.json + +# IMPORTANT! Restore original service ACLs, so that we restore SSH connectivity +acl-loader update full /etc/sonic/acl.json diff --git a/ansible/roles/test/tasks/service_acl.yml b/ansible/roles/test/tasks/service_acl.yml new file mode 100644 index 00000000000..119a4f22e4b --- /dev/null +++ b/ansible/roles/test/tasks/service_acl.yml @@ -0,0 +1,75 @@ +- name: Check for existence of /etc/sonic/acl.json (this also ensures we can successfully SSH to the DuT) + become: true + stat: + path: /etc/sonic/acl.json + register: file_stat + failed_when: not file_stat.stat.exists + +# Gather facts with SNMP version 2 +- name: Ensure we can gather basic SNMP facts about the device + snmp_facts: + host: "{{ ansible_host }}" + version: "v2c" + community: "{{ snmp_rocommunity }}" + connection: local + +- name: Copy config_service_acls.sh to the DuT + become: true + copy: + src: roles/test/files/helpers/config_service_acls.sh + dest: /tmp/config_service_acls.sh + mode: 0755 + +# We run the script in the background because if it works +# properly, it will sever our SSH session, but we don't want +# the script to get killed, because it is also responsible +# for resetting the service ACLs back to their previous state +- name: Run config_service_acls.sh in the background on the DuT + become: true + shell: "nohup /tmp/config_service_acls.sh < /dev/null > /dev/null 2>&1 &" + +- name: Sleep for a few seconds to let new ACLs take effect + pause: + seconds: 5 + +- name: Ensure SSH connection to DuT now times out + wait_for: + port: "22" + state: "started" + host: "{{ inventory_hostname }}" + connect_timeout: "5" + timeout: "10" + delegate_to: "localhost" + register: result + failed_when: result.msg != "Timeout when waiting for {{ inventory_hostname }}:22" + +# Gather facts with SNMP version 2 +- name: Ensure attempt to gather basic SNMP facts about the device now times out + snmp_facts: + host: "{{ ansible_host }}" + version: "v2c" + community: "{{ snmp_rocommunity }}" + connection: local + register: result +# failed_when: "'No SNMP response received before timeout' not in result.msg" + failed_when: result.msg != "No SNMP response received before timeout" + +# Adjust the number of seconds we sleep here relative to the number of seconds +# config_service_acls.sh is set to sleep before applying the original service ACLs +- name: Sleep to ensure config_service_acls.sh has reinstated the original service ACLs + pause: + seconds: 30 + +- name: Delete config_service_acls.sh from the DuT (this also tests that we can once again SSH to the DuT) + become: true + file: + state: absent + path: /tmp/config_service_acls.sh + +# Gather facts with SNMP version 2 +- name: Ensure we can gather basic SNMP facts about the device once again + snmp_facts: + host: "{{ ansible_host }}" + version: "v2c" + community: "{{ snmp_rocommunity }}" + connection: local diff --git a/ansible/roles/test/vars/testcases.yml b/ansible/roles/test/vars/testcases.yml index fe168ea209e..288d437f4fc 100644 --- a/ansible/roles/test/vars/testcases.yml +++ b/ansible/roles/test/vars/testcases.yml @@ -146,6 +146,10 @@ testcases: sensors: filename: sensors_check.yml topologies: [t0, t0-64, t0-64-32, t0-116, t1, t1-lag, t1-64-lag, ptf32, ptf64] + + service_acl: + filename: service_acl.yml + topologies: [t0, t0-64, t0-64-32, t0-116, t1, t1-lag, t1-64-lag, ptf32, ptf64] snmp: filename: snmp.yml