├── README.md ├── defaults └── main.yml ├── meta └── main.yml ├── na_ots_cluster ├── .DS_Store ├── README.md ├── defaults │ └── main.yml ├── meta │ └── main.yml ├── tasks │ ├── add_credential.yml │ ├── add_vcenter_credential.yml │ ├── check_cluster.yml │ ├── check_network.yml │ ├── configure_node.yml │ ├── configure_node_network.yml │ ├── configure_node_storage.yml │ ├── create_cluster.yml │ ├── deploy_cluster.yml │ ├── get_cluster_id.yml │ ├── get_cluster_state.yml │ ├── get_host_ids.yml │ ├── get_node_ids.yml │ ├── main.yml │ ├── monitor_job.yml │ ├── register_esx_vcenter_host.yml │ ├── register_host.yml │ └── verify.yml └── templates │ ├── host2id.j2 │ ├── host2pwd.j2 │ └── networkcheck.j2 ├── na_ots_deploy ├── README.md ├── defaults │ └── main.yml ├── meta │ └── main.yml └── tasks │ └── main.yml ├── nar_ontap_security_ucd_guide ├── .DS_Store ├── ._.DS_Store ├── ._README.md ├── ._files ├── ._nar_ontap_security_ucd_guide ├── ._templates ├── README.md ├── defaults │ ├── ._main.yml │ └── main.yml ├── handlers │ ├── ._main.yml │ └── main.yml ├── meta │ ├── ._main.yml │ └── main.yml ├── tasks │ ├── ._main.yml │ └── main.yml ├── tests │ ├── ._inventory │ ├── ._test.yml │ ├── inventory │ └── test.yml └── vars │ ├── ._main.yml │ └── main.yml └── tasks └── main.yml /README.md: -------------------------------------------------------------------------------- 1 | # ansible 2 | Repo for Ansible roles developed for NetApp Ansible modules and playbooks 3 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/defaults/main.yml -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: "NetApp" 3 | description: "Roles for NetApp solutions" 4 | company: "NetApp" 5 | license: BSD 6 | min_ansible_version: 2.8 7 | platforms: 8 | galaxy_tags: [netapp, ontap, elementsw] 9 | dependencies: [] 10 | -------------------------------------------------------------------------------- /na_ots_cluster/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/na_ots_cluster/.DS_Store -------------------------------------------------------------------------------- /na_ots_cluster/README.md: -------------------------------------------------------------------------------- 1 | # Role Name 2 | `na_ots_cluster`: Install an ONTAP Select Cluster 3 | # Requirements 4 | This role requires Ansible 2.7 release. 5 | # Role Variables 6 | ```yaml 7 | # ------------------------------------------------------------------- 8 | # Passwords 9 | # - Place these in a separate file and implement encryption if needed 10 | # ------------------------------------------------------------------- 11 | deploy_pwd: "" 12 | vcenter_password: "" 13 | ontap_pwd: "" 14 | host_esx_password: "" 15 | host_kvm_password: "" 16 | ``` 17 | ```yaml 18 | # ---------------------------------------------------------------- 19 | # Configuration Settings 20 | # - Place these variables in a separate .yml file and reference in 21 | # the playbook along with the include_role statement 22 | # ---------------------------------------------------------------- 23 | node_count: 24 | hypervisor: 25 | ``` 26 | ```yaml 27 | # ------------------------------------------------------------------------ 28 | # true = Authenticate through vCenter | false = Authenticate host directly 29 | # if esxi host is managed by vCenter then you MUST use vCenter 30 | # ------------------------------------------------------------------------ 31 | use_vcenter: 32 | ``` 33 | ```yaml 34 | # ------------------------------------------------- 35 | # Different parameters to indicate preferences to monitor a job until "success" or "failure" 36 | # ------------------------------------------------- 37 | monitor_deploy_job: 38 | monitor_deploy_retries: 39 | monitor_deploy_delay: 40 | monitor_netcheck_retries: 41 | monitor_netcheck_delay: 42 | ``` 43 | 44 | ```yaml 45 | # ---------------------------------------------------------------------- 46 | # Network Connectivity Check 47 | # - Set to true to run the network connectivity check 48 | # - Valid modes: quick, extended, cleanup 49 | # - Valid switch types: StandardvSwitch, DistributedvSwitch, OpenvSwitch 50 | # - cluster_nodes referenced so make sure item count = node count !!! 51 | # ---------------------------------------------------------------------- 52 | run_net_check: 53 | net_mode: 54 | net_mtu: 55 | net_switch_type: 56 | ``` 57 | 58 | ```yaml 59 | # ----------- 60 | # Deploy Info 61 | # ----------- 62 | deploy_ip: 63 | ``` 64 | 65 | ```yaml 66 | # ------------ 67 | # vCenter Info 68 | # ------------ 69 | vcenter_login: 70 | vcenter_name: 71 | ``` 72 | 73 | ```yaml 74 | # ----- 75 | # Hosts 76 | # ----- 77 | esxi_hosts: 78 | - host_name: 79 | host_login: 80 | - host_name: 81 | host_login: 82 | 83 | kvm_hosts: 84 | - host_name: 85 | host_login: 86 | - host_name: 87 | host_login: 88 | ``` 89 | 90 | ```yaml 91 | # ------------ 92 | # Cluster Info 93 | # ------------ 94 | cluster_name: 95 | cluster_ip: 96 | cluster_netmask: 97 | cluster_gateway: 98 | cluster_ontap_image: "9.5P1" 99 | cluster_ntp: 100 | - 101 | cluster_dns_ips: 102 | - 103 | cluster_dns_domains: 104 | - 105 | ``` 106 | ```yaml 107 | # -------- 108 | # Networks 109 | # -------- 110 | mgt_network: Management 111 | data_network: Data 112 | internal_network: Internal 113 | ``` 114 | ```yaml 115 | # -------- 116 | # Instance 117 | # -------- 118 | instance_type: 119 | ``` 120 | ```yaml 121 | # -------------------------------------------------- 122 | # Node Info 123 | # - cluster_nodes # of items should equal node_count 124 | # -------------------------------------------------- 125 | cluster_nodes: 126 | - node_name: "{{ cluster_name }}-01" 127 | ipAddress: 128 | storage_pool: 129 | capacityTB: 3 130 | host_name: 131 | - node_name: "{{ cluster_name }}-02" 132 | ipAddress: 133 | storage_pool: 134 | capacityTB: 3 135 | host_name: 136 | ``` 137 | # Dependencies 138 | This role assumes that the `na_ots_deploy` role (or the manual equivalent) has already been run and the deploy VM is running. 139 | 140 | # Example Playbook 141 | ```yaml 142 | --- 143 | - name: Create ONTAP Select cluster (ESXi) 144 | hosts: "localhost" 145 | gather_facts: false 146 | # ------------------- 147 | # Read variable files 148 | # ------------------- 149 | vars_files: 150 | - vars_cluster.yml 151 | - vars_cluster_pwd.yml 152 | roles: 153 | - na_ots_cluster 154 | ``` 155 | I use global files to hold variables. 156 | ```yaml 157 | node_count: 2 158 | monitor_job: true 159 | deploy_api_url: "https://xx.xxx.xx.xx/api/v3" 160 | deploy_login: "admin" 161 | vcenter_login: "yourvclogin@yourlab.local" 162 | vcenter_name: "xx.xxx.xx.xx" 163 | esxi_hosts: 164 | - host_name: xx.xxx.xx.xx 165 | 166 | cluster_name: "onenodecluster" 167 | cluster_ip: "10.193.xx.xx" 168 | cluster_netmask: "255.255.255.0" 169 | cluster_gateway: "10.193.xx.xx" 170 | cluster_ontap_image: "9.5P2X1" 171 | cluster_ntp: 172 | - "ntpxx.your.ntp.com" 173 | cluster_dns_ips: 174 | - "10.193.x.xxx" 175 | cluster_dns_domains: 176 | - "thisis.your.dns.com" 177 | 178 | mgt_network: "your-mgmt-network" 179 | data_network: "your-data-network" 180 | internal_network: "your-select-internal-network" 181 | instance_type: "small" 182 | cluster_nodes: 183 | - node_name: "{{ cluster_name }}-01" 184 | ipAddress: 10.193.xx.xx 185 | storage_pool: yourstopool 186 | capacityTB: 1.2 187 | host_name: 10.193.xx.xx 188 | - node_name: "{{ cluster_name }}-02" 189 | ipAddress: 10.0.10.xx 190 | storage_pool: dsONTAP2 191 | capacityTB: 1.2 192 | ``` 193 | # License 194 | BSD 195 | # Author Information 196 | NetApp 197 | -------------------------------------------------------------------------------- /na_ots_cluster/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------- 2 | # Passwords 3 | # - Place these in a separate file and implement encryption if needed 4 | # ------------------------------------------------------------------- 5 | deploy_pwd: "" 6 | vcenter_password: "" 7 | ontap_pwd: "" 8 | host_esx_password: "" 9 | host_kvm_password: "" 10 | 11 | # ---------------------------------------------------------------- 12 | # Configuration Settings 13 | # - Place these variables in a separate .yml file and reference in 14 | # the playbook along with the include_role statement 15 | # ---------------------------------------------------------------- 16 | 17 | # ------------------------------- 18 | # Number of nodes in the cluster 19 | # ------------------------------- 20 | node_count: 2 21 | 22 | # ------------------------------------------- 23 | # Hypervisor Type - ESX | KVM (case sensitve) 24 | # ------------------------------------------- 25 | hypervisor: ESX 26 | 27 | # ------------------------------------------------------------------------ 28 | # true = Authenticate through vCenter | false = Authenticate host directly 29 | # if esxi host is managed by vCenter then you MUST use vCenter 30 | # ------------------------------------------------------------------------ 31 | use_vcenter: true 32 | 33 | # ------------------------------------------------- 34 | # Monitor a job until "success" or "failure" 35 | # - Host registration jobs will always be monitored 36 | # ------------------------------------------------- 37 | monitor_deploy_job: false 38 | monitor_deploy_retries: 60 39 | monitor_deploy_delay: 120 40 | monitor_host_retries: 10 41 | monitor_host_delay: 15 42 | monitor_netcheck_retries: 30 43 | monitor_netcheck_delay: 60 44 | 45 | # ---------------------------------------------------------------------- 46 | # Network Connectivity Check 47 | # - Set to true to run the network connectivity check 48 | # - Valid modes: quick, extended, cleanup 49 | # - Valid switch types: StandardvSwitch, DistributedvSwitch, OpenvSwitch 50 | # - cluster_nodes referenced so make sure item count = node count !!! 51 | # ---------------------------------------------------------------------- 52 | run_net_check: false 53 | net_mode: quick 54 | net_mtu: 9000 55 | net_switch_type: StandardvSwitch 56 | 57 | # ----------- 58 | # Deploy Info 59 | # ----------- 60 | deploy_ip: 61 | deploy_api_url: "https://{{ deploy_ip }}/api/v3" 62 | deploy_login: admin 63 | 64 | # ------------ 65 | # vCenter Info 66 | # ------------ 67 | vcenter_login: administrator@vsphere.local 68 | vcenter_name: vc.vsphere.local 69 | 70 | # ----- 71 | # Hosts 72 | # ----- 73 | esxi_hosts: 74 | - host_name: 75 | host_login: 76 | - host_name: 77 | host_login: 78 | 79 | kvm_hosts: 80 | - host_name: 81 | host_login: 82 | - host_name: 83 | host_login: 84 | 85 | # ------------ 86 | # Cluster Info 87 | # ------------ 88 | cluster_name: 89 | cluster_ip: 90 | cluster_netmask: 91 | cluster_gateway: 92 | cluster_ontap_image: "9.5P1" 93 | cluster_ntp: 94 | - 95 | cluster_dns_ips: 96 | - 97 | cluster_dns_domains: 98 | - 99 | 100 | # -------- 101 | # Networks 102 | # -------- 103 | mgt_network: Management 104 | data_network: Data 105 | internal_network: Internal 106 | 107 | # -------- 108 | # Instance 109 | # -------- 110 | instance_type: small 111 | 112 | # -------------------------------------------------- 113 | # Node Info 114 | # - cluster_nodes # of items should equal node_count 115 | # -------------------------------------------------- 116 | cluster_nodes: 117 | - node_name: "{{ cluster_name }}-01" 118 | ipAddress: 119 | storage_pool: 120 | capacityTB: 3 121 | host_name: 122 | - node_name: "{{ cluster_name }}-02" 123 | ipAddress: 124 | storage_pool: 125 | capacityTB: 3 126 | host_name: 127 | 128 | # ------------------------------------------ 129 | # Capacity Conversion Values 130 | # Note: 1TB in Bytes = 1099511627776 131 | # 300GB in Bytes = 322122547200 132 | # 2% 1TB in Bytes = 21990232555 133 | # 134 | # Formula used to calculate Storage Capacity 135 | # ( capacityTB * TBinBytes - Overhead ) 136 | # ------------------------------------------ 137 | TBinBytes: 1099511627776 138 | Overhead: 322122547200 139 | TB2Percent: 21990232555 140 | -------------------------------------------------------------------------------- /na_ots_cluster/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: "NetApp" 3 | description: "Role for ONTAP Select Deploy" 4 | company: "NetApp" 5 | license: BSD 6 | min_ansible_version: 2.7 7 | platforms: 8 | galaxy_tags: [netapp, ontap, ontapselect, select, ots] 9 | dependencies: [] 10 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/add_credential.yml: -------------------------------------------------------------------------------- 1 | # ----------------------------------- 2 | # Check for existing credential match 3 | # ----------------------------------- 4 | 5 | - name: .....check credential {{ item.host_login }} - {{ item.host_name }} 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/security/credentials?hostname={{ item.host_name }}" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | 18 | register: get_credential_response 19 | 20 | # -------------------------------- 21 | # Add Credenntial if doesn't exist 22 | # -------------------------------- 23 | 24 | - name: .....add credential {{ item.host_login }} - {{ item.host_name }} 25 | 26 | uri: 27 | url: "{{ deploy_api_url }}/security/credentials" 28 | method: POST 29 | headers: 30 | Content-Type: "application/json" 31 | body: 32 | hostname: "{{ item.host_name }}" 33 | password: "{{ lookup('template', 'host2pwd.j2') | trim }}" 34 | type: "host" 35 | username: "{{ item.host_login }}" 36 | body_format: json 37 | user: "{{ deploy_login }}" 38 | password: "{{ deploy_pwd }}" 39 | status_code: 202 40 | validate_certs: False 41 | when: 42 | - get_credential_response.json.num_records == 0 43 | 44 | register: add_credential_response 45 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/add_vcenter_credential.yml: -------------------------------------------------------------------------------- 1 | # ----------------------------------- 2 | # Check for existing credential match 3 | # ----------------------------------- 4 | 5 | - name: .....check credential {{ vcenter_login }} - {{ vcenter_name }} 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/security/credentials?username={{ vcenter_login }}" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | 18 | register: get_vcenter_response 19 | 20 | # -------------------------------- 21 | # Add Credenntial if doesn't exist 22 | # -------------------------------- 23 | 24 | - name: .....add credential {{ vcenter_login }} - {{ vcenter_name }} 25 | 26 | uri: 27 | url: "{{ deploy_api_url }}/security/credentials" 28 | method: POST 29 | headers: 30 | Content-Type: "application/json" 31 | body: 32 | hostname: "{{ vcenter_name }}" 33 | password: "{{ vcenter_password }}" 34 | type: "vcenter" 35 | username: "{{ vcenter_login }}" 36 | body_format: json 37 | user: "{{ deploy_login }}" 38 | password: "{{ deploy_pwd }}" 39 | status_code: 202 40 | validate_certs: False 41 | when: 42 | - get_vcenter_response.json.num_records == 0 43 | 44 | register: add_vcenter_response 45 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/check_cluster.yml: -------------------------------------------------------------------------------- 1 | # -------------------------- 2 | # Check for existing cluster 3 | # -------------------------- 4 | 5 | - name: .....checking 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/clusters?name={{ cluster_name }}" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | 18 | register: cluster_check_response 19 | 20 | # ---------------------------------------- 21 | # Set default value of true to cluster_new 22 | # ---------------------------------------- 23 | 24 | - name: .....set fact ( cluster_new (true) - no cluster exists ) 25 | 26 | set_fact: 27 | cluster_new: true 28 | when: cluster_check_response.json.num_records == 0 29 | 30 | # -------------------------------------------------------------- 31 | # If a record is returned for the cluster name then set to false 32 | # -------------------------------------------------------------- 33 | 34 | - name: .....set fact ( cluster_new (false) - if cluster exists ) 35 | 36 | set_fact: 37 | cluster_new: false 38 | when: 39 | - cluster_check_response.json.num_records == 1 40 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/check_network.yml: -------------------------------------------------------------------------------- 1 | # ------------- 2 | # Check Network 3 | # ------------- 4 | 5 | # -------------------------------------------------------------- 6 | # Compare the number of cluster nodes specified in cluster_nodes 7 | # to the specified node count. If they do NOT match then do NOT 8 | # run the network test since the host names are pulled 9 | # from cluster_nodes. Don't want to stop the cluster deployment. 10 | # --------------------------------------------------------------- 11 | 12 | - debug: 13 | msg: "The specified node count ({{ node_count }}) does not match the number of provided cluster nodes ({{ cluster_nodes_count }})" 14 | when: 15 | - cluster_nodes_count != actual_nodes_count 16 | 17 | # -------------- 18 | # Start the test 19 | # -------------- 20 | 21 | - name: Network Connectivity Check 22 | 23 | uri: 24 | url: "{{ deploy_api_url }}/network/connectivitychecks" 25 | method: POST 26 | headers: 27 | Content-Type: "application/json" 28 | body: "{{ lookup('template', 'networkcheck.j2') }}" 29 | body_format: json 30 | user: "{{ deploy_login }}" 31 | password: "{{ deploy_pwd }}" 32 | status_code: 202 33 | validate_certs: False 34 | register: check_network_response 35 | when: 36 | - cluster_nodes_count == actual_nodes_count 37 | 38 | # --------------- 39 | # Monitor the job 40 | # --------------- 41 | 42 | - name: .....monitor network connectivity job 43 | 44 | include_tasks: monitor_job.yml 45 | vars: 46 | job_id: "{{ check_network_response.json.job.id }}" 47 | job_retries: "{{ monitor_netcheck_retries }}" 48 | job_delay: "{{ monitor_netcheck_delay }}" 49 | when: 50 | - cluster_nodes_count == actual_nodes_count 51 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/configure_node.yml: -------------------------------------------------------------------------------- 1 | # -------------- 2 | # Configure Node 3 | # -------------- 4 | 5 | # -------------------------------------- 6 | # Initial settings - IP address and host 7 | # -------------------------------------- 8 | 9 | - name: Configure Node - {{ outeritem.node_name }} - {{ outeritem.node_id }} 10 | 11 | uri: 12 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ outeritem.node_id }}" 13 | method: PATCH 14 | headers: 15 | Content-Type: "application/json" 16 | body: 17 | instance_type: "{{ instance_type }}" 18 | host: 19 | id: "{{ lookup('template', 'host2id.j2') | trim }}" 20 | ip: "{{ item.ipAddress }}" 21 | passthrough_disks: false 22 | body_format: json 23 | user: "{{ deploy_login }}" 24 | password: "{{ deploy_pwd }}" 25 | status_code: 200 26 | validate_certs: False 27 | loop: "{{ cluster_nodes }}" 28 | loop_control: 29 | label: "{{ item.node_name }} ({{ item.ipAddress }})" 30 | when: 31 | - outeritem.node_name == item.node_name 32 | 33 | register: configure_node_response 34 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/configure_node_network.yml: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------------------------- 2 | # Configure Node Networks 3 | # -------------------------------------------------------------------------------------------------- 4 | # The order of the networks always comes out in the same order (Management, Data, Internal > 1 node) 5 | # -------------------------------------------------------------------------------------------------- 6 | 7 | - name: Retrieve Node Network IDs 8 | 9 | uri: 10 | url: "{{ deploy_api_url }}//clusters/{{ cluster_id }}/nodes/{{ item.node_id }}/networks" 11 | method: GET 12 | headers: 13 | Content-Type: "application/json" 14 | body_format: json 15 | user: "{{ deploy_login }}" 16 | password: "{{ deploy_pwd }}" 17 | status_code: 200 18 | validate_certs: False 19 | 20 | register: get_network_ids_response 21 | 22 | # ------------------ 23 | # Management Network 24 | # ------------------ 25 | 26 | - name: Node {{ item.node_name }} - Management Network - "{{ mgt_network }}" 27 | 28 | uri: 29 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ item.node_id }}/networks/{{ get_network_ids_response.json.records[0].id }}" 30 | method: PATCH 31 | headers: 32 | Content-Type: "application/json" 33 | body: 34 | name: "{{ mgt_network }}" 35 | body_format: json 36 | user: "{{ deploy_login }}" 37 | password: "{{ deploy_pwd }}" 38 | status_code: 200 39 | validate_certs: False 40 | 41 | register: mgt_network_response 42 | 43 | # ------------ 44 | # Data Network 45 | # ------------ 46 | 47 | - name: Node {{ item.node_name }} - Data Network - "{{ data_network }}" 48 | 49 | uri: 50 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ item.node_id }}/networks/{{ get_network_ids_response.json.records[1].id }}" 51 | method: PATCH 52 | headers: 53 | Content-Type: "application/json" 54 | body: 55 | name: "{{ data_network }}" 56 | body_format: json 57 | user: "{{ deploy_login }}" 58 | password: "{{ deploy_pwd }}" 59 | status_code: 200 60 | validate_certs: False 61 | 62 | register: data_network_response 63 | 64 | # ---------------- 65 | # Internal Network 66 | # ---------------- 67 | 68 | - name: Node {{ item.node_name }} - Internal Network - "{{ internal_network }}" 69 | 70 | uri: 71 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ item.node_id }}/networks/{{ get_network_ids_response.json.records[2].id }}" 72 | method: PATCH 73 | headers: 74 | Content-Type: "application/json" 75 | body: 76 | name: "{{ internal_network }}" 77 | body_format: json 78 | user: "{{ deploy_login }}" 79 | password: "{{ deploy_pwd }}" 80 | status_code: 200 81 | validate_certs: False 82 | when: node_count > 1 83 | 84 | register: internal_network_response 85 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/configure_node_storage.yml: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------------------- 2 | # Configure Node Storage 3 | # -------------------------------------------------------------------------------------------- 4 | # 1. capacityTB is converted to bytes and then 300GB is subtracted to allow for overhead 5 | # (system disk) and an additional 2% free space per TB is reserved 6 | # 2. if the node already has a storage pool assigned from a previously incomplete creation 7 | # process, the task will detach (DELETE) the existing pool then add the specified pool. 8 | # -------------------------------------------------------------------------------------------- 9 | 10 | - name: .....check for existing storage pool 11 | 12 | uri: 13 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ outeritem.node_id }}/storage/pools" 14 | method: GET 15 | headers: 16 | Content-Type: "application/json" 17 | body_format: json 18 | user: "{{ deploy_login }}" 19 | password: "{{ deploy_pwd }}" 20 | status_code: 200 21 | validate_certs: False 22 | 23 | register: check_storage_response 24 | 25 | # --------------------------------------- 26 | # Initialize the storage pool id variable 27 | # --------------------------------------- 28 | 29 | - name: .....clear (sp_id) 30 | set_fact: 31 | sp_id: "" 32 | 33 | # --------------------------------------------- 34 | # Save the current storage pool id IF it exists 35 | # --------------------------------------------- 36 | 37 | - name: .....set fact (sp_id) 38 | set_fact: 39 | sp_id: "{{ check_storage_response.json.records[0].id }}" 40 | when: 41 | - check_storage_response.json.num_records == 1 42 | 43 | # ---------------------------------------------------------------------- 44 | # Detach existing storage pool IF it exists 45 | # - This will only occur if the cluster did not successfully deploy and 46 | # the task is being re-executed 47 | # ---------------------------------------------------------------------- 48 | 49 | - name: .....detach existing storage pool 50 | 51 | uri: 52 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ outeritem.node_id }}/storage/pools/{{ sp_id }}" 53 | method: DELETE 54 | headers: 55 | Content-Type: "application/json" 56 | body_format: json 57 | user: "{{ deploy_login }}" 58 | password: "{{ deploy_pwd }}" 59 | status_code: 200 60 | validate_certs: False 61 | loop: "{{ cluster_nodes }}" 62 | when: 63 | - outeritem.node_name == item.node_name 64 | - check_storage_response.json.num_records == 1 65 | - sp_id is defined 66 | 67 | register: detach_node_storage_response 68 | 69 | # ----------------------- 70 | # Attach the storage pool 71 | # ----------------------- 72 | 73 | - name: .....attach storage pool 74 | 75 | uri: 76 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes/{{ outeritem.node_id }}/storage/pools" 77 | method: POST 78 | headers: 79 | Content-Type: "application/json" 80 | body: '{"pool_array": [{"capacity": {{ ( (item.capacityTB * TBinBytes) - Overhead - (item.capacityTB * TB2Percent) ) | int | abs }},"name": "{{ item.storage_pool }}" }]}' 81 | body_format: json 82 | user: "{{ deploy_login }}" 83 | password: "{{ deploy_pwd }}" 84 | status_code: 201,202 85 | validate_certs: False 86 | loop: "{{ cluster_nodes }}" 87 | loop_control: 88 | label: "{{ item.node_name }} ({{ item.storage_pool }})" 89 | when: 90 | - outeritem.node_name == item.node_name 91 | - check_storage_response.json.num_records == 0 92 | 93 | register: configure_node_storage_response 94 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/create_cluster.yml: -------------------------------------------------------------------------------- 1 | # ------------------ 2 | # Create the cluster 3 | # ------------------ 4 | 5 | # ----------------------------------------------------- 6 | # Verify the node count is a valid settings (1,2,4,6,8) 7 | # ----------------------------------------------------- 8 | 9 | - name: Fail check 10 | fail: 11 | msg: "INVALID NODE COUNT - Must be 1,2,4,6 or 8. Node Count currently set to {{ node_count }}" 12 | when: node_count not in [1,2,4,6,8] 13 | 14 | # ----------------------------------------------------------------- 15 | # Create the initial cluster template for the configure_node* tasks 16 | # ----------------------------------------------------------------- 17 | 18 | - name: .....creating cluster 19 | 20 | uri: 21 | url: "{{ deploy_api_url }}/clusters?node_count={{ node_count }}" 22 | method: POST 23 | headers: 24 | Content-Type: "application/json" 25 | body: 26 | name: "{{ cluster_name }}" 27 | ontap_image_version: "{{ cluster_ontap_image }}" 28 | gateway: "{{ cluster_gateway }}" 29 | ip: "{{ cluster_ip }}" 30 | netmask: "{{ cluster_netmask }}" 31 | ntp_servers: "{{ cluster_ntp }}" 32 | dns_info: 33 | dns_ips: "{{ cluster_dns_ips }}" 34 | domains: "{{ cluster_dns_domains }}" 35 | body_format: json 36 | user: "{{ deploy_login }}" 37 | password: "{{ deploy_pwd }}" 38 | status_code: 201 39 | validate_certs: False 40 | 41 | register: cluster_create_response 42 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/deploy_cluster.yml: -------------------------------------------------------------------------------- 1 | # -------------- 2 | # Deploy Cluster 3 | # -------------- 4 | 5 | # ------------------------------------------------------------------- 6 | # Build the cluster once all the configure_node* tasks have completed 7 | # ------------------------------------------------------------------- 8 | 9 | - name: .....start deployment - {{ cluster_name }} 10 | 11 | uri: 12 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/deploy?inhibit_rollback=false" 13 | method: POST 14 | headers: 15 | Content-Type: "application/json" 16 | body: 17 | ontap_credential: 18 | password: "{{ ontap_pwd }}" 19 | body_format: json 20 | user: "{{ deploy_login }}" 21 | password: "{{ deploy_pwd }}" 22 | status_code: 202 23 | validate_certs: False 24 | 25 | register: cluster_deploy_response 26 | 27 | # -------------------------------------------------------- 28 | # Monitor the deployment job IF specified 29 | # - setting to false will return the prompt for other work 30 | # -------------------------------------------------------- 31 | 32 | - name: .....monitor cluster deploy job 33 | include_tasks: monitor_job.yml 34 | vars: 35 | job_id: "{{ cluster_deploy_response.json.job.id }}" 36 | job_retries: "{{ monitor_deploy_retries }}" 37 | job_delay: "{{ monitor_deploy_delay }}" 38 | when: monitor_deploy_job|bool 39 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/get_cluster_id.yml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | # Retrieve cluster details by cluster name 3 | # ---------------------------------------- 4 | 5 | - name: .....retrieving cluster id 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/clusters?name={{ cluster_name }}" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | 18 | register: cluster_get_response 19 | 20 | # -------------------- 21 | # Store the cluster id 22 | # -------------------- 23 | 24 | - name: .....set fact ( cluster_id ({{ cluster_get_response.json.records.0.id }}) ) 25 | 26 | set_fact: 27 | cluster_id: "{{ cluster_get_response.json.records.0.id }}" 28 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/get_cluster_state.yml: -------------------------------------------------------------------------------- 1 | # ---------------------------------------- 2 | # Retrieve cluster state 3 | # ---------------------------------------- 4 | 5 | - name: .....retrieving cluster state 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}?fields=*" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | 18 | register: cluster_get_response 19 | 20 | # ----------------------- 21 | # Store the cluster state 22 | # ----------------------- 23 | 24 | - name: .....set fact ( cluster_deployed ({{ cluster_get_response.json.record.is_deployed }}) ) 25 | 26 | set_fact: 27 | cluster_deployed: "{{ cluster_get_response.json.record.is_deployed | bool }}" 28 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/get_host_ids.yml: -------------------------------------------------------------------------------- 1 | # ---------------------- 2 | # Build List of Host IDs 3 | # ---------------------- 4 | 5 | # ----------------------------------- 6 | # Retrieve currently registered hosts 7 | # ----------------------------------- 8 | 9 | - name: Get Host IDs 10 | 11 | uri: 12 | url: "{{ deploy_api_url }}/hosts?invalidate_cache=true" 13 | method: GET 14 | headers: 15 | Content-Type: "application/json" 16 | body_format: json 17 | user: "{{ deploy_login }}" 18 | password: "{{ deploy_pwd }}" 19 | status_code: 200 20 | validate_certs: False 21 | 22 | register: get_host_ids_response 23 | 24 | # ----------------------------------------------------------------------------- 25 | # Add host name and id to list 26 | # - Clear the list since this task is called before AND after host registration 27 | # - The list is used to inject the host ID into any tasks needing the value 28 | # - A template (host2id.j2) does the lookup 29 | # ----------------------------------------------------------------------------- 30 | 31 | - name: .....clear list 32 | 33 | set_fact: 34 | host_id_list: [] 35 | 36 | - name: .....build list of host IDs 37 | 38 | set_fact: 39 | host_id_list: "{{ host_id_list|default([]) + [ {'host_name': item.name, 'host_id': item.id} ] }}" 40 | loop: "{{ get_host_ids_response.json.records }}" 41 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/get_node_ids.yml: -------------------------------------------------------------------------------- 1 | # ------------ 2 | # Get Node IDs 3 | # ------------ 4 | 5 | - name: .....retrieving node IDs 6 | 7 | uri: 8 | url: "{{ deploy_api_url }}/clusters/{{ cluster_id }}/nodes?order_by=name%20asc" 9 | method: GET 10 | headers: 11 | Content-Type: "application/json" 12 | body_format: json 13 | user: "{{ deploy_login }}" 14 | password: "{{ deploy_pwd }}" 15 | status_code: 200 16 | validate_certs: False 17 | register: get_node_ids_response 18 | 19 | # ---------------------------- 20 | # Add node name and id to list 21 | # ---------------------------- 22 | 23 | - name: .....build list of node IDs 24 | 25 | set_fact: 26 | node_id_list: "{{ node_id_list|default([]) + [ {'node_name': item.name, 'node_id': item.id} ] }}" 27 | loop: "{{ get_node_ids_response.json.records }}" 28 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # --------------------------------------------------------------------------------------- 3 | - name: Verify settings 4 | include_tasks: verify.yml 5 | # --------------------------------------------------------------------------------------- 6 | - name: Add Vcenter credentials 7 | include_tasks: add_vcenter_credential.yml 8 | when: 9 | - use_vcenter 10 | - hypervisor == "ESX" 11 | # --------------------------------------------------------------------------------------- 12 | - name: Add ESXi host credentials (no vCenter ) 13 | include_tasks: add_credential.yml 14 | with_items: "{{ esxi_hosts }}" 15 | when: 16 | - not use_vcenter 17 | - hypervisor == "ESX" 18 | - esxi_hosts != none 19 | # --------------------------------------------------------------------------------------- 20 | - name: Add KVM host credentials 21 | include_tasks: add_credential.yml 22 | with_items: "{{ kvm_hosts }}" 23 | when: 24 | - hypervisor == "KVM" 25 | - kvm_hosts != none 26 | # --------------------------------------------------------------------------------------- 27 | - name: Get existing host IDs 28 | include_tasks: get_host_ids.yml 29 | # --------------------------------------------------------------------------------------- 30 | - name: Register ESXi hosts (vCenter) 31 | include_tasks: register_esx_vcenter_host.yml 32 | with_items: "{{ esxi_hosts }}" 33 | when: 34 | - hypervisor == "ESX" 35 | - use_vcenter 36 | - esxi_hosts != none 37 | # --------------------------------------------------------------------------------------- 38 | - name: Register ESXi hosts (no vCenter) 39 | include_tasks: register_host.yml 40 | with_items: "{{ esxi_hosts }}" 41 | when: 42 | - hypervisor == "ESX" 43 | - not use_vcenter 44 | - esxi_hosts != none 45 | # --------------------------------------------------------------------------------------- 46 | - name: Register KVM hosts 47 | include_tasks: register_host.yml 48 | with_items: "{{ kvm_hosts }}" 49 | when: 50 | - hypervisor == "KVM" 51 | - kvm_hosts != none 52 | # --------------------------------------------------------------------------------------- 53 | - name: Update host IDs list 54 | include_tasks: get_host_ids.yml 55 | # --------------------------------------------------------------------------------------- 56 | - name: Validate internal network 57 | include_tasks: check_network.yml 58 | when: 59 | - run_net_check 60 | - node_count != 1 61 | # --------------------------------------------------------------------------------------- 62 | - name: Check for existing cluster 63 | include_tasks: check_cluster.yml 64 | # --------------------------------------------------------------------------------------- 65 | - name: Create cluster - {{ cluster_name }} x {{ node_count }} nodes 66 | include_tasks: create_cluster.yml 67 | when: 68 | - cluster_new 69 | # --------------------------------------------------------------------------------------- 70 | - name: Get cluster ID - {{ cluster_name }} 71 | include_tasks: get_cluster_id.yml 72 | # --------------------------------------------------------------------------------------- 73 | - name: Get cluster state - {{ cluster_name }} 74 | include_tasks: get_cluster_state.yml 75 | # --------------------------------------------------------------------------------------- 76 | - name: Get node IDs 77 | include_tasks: get_node_ids.yml 78 | when: 79 | - not cluster_deployed 80 | # --------------------------------------------------------------------------------------- 81 | - name: Configure nodes 82 | include_tasks: configure_node.yml 83 | loop: "{{ node_id_list }}" 84 | loop_control: 85 | loop_var: outeritem 86 | when: 87 | - not cluster_deployed 88 | # --------------------------------------------------------------------------------------- 89 | - name: Configure networks 90 | include_tasks: configure_node_network.yml 91 | loop: "{{ node_id_list }}" 92 | when: 93 | - not cluster_deployed 94 | # --------------------------------------------------------------------------------------- 95 | - name: Configure storage pool 96 | include_tasks: configure_node_storage.yml 97 | loop: "{{ node_id_list }}" 98 | loop_control: 99 | loop_var: outeritem 100 | when: 101 | - not cluster_deployed 102 | # --------------------------------------------------------------------------------------- 103 | - name: Deploy cluster 104 | include_tasks: deploy_cluster.yml 105 | when: 106 | - not cluster_deployed 107 | # --------------------------------------------------------------------------------------- 108 | # END PLAYBOOK 109 | # --------------------------------------------------------------------------------------- 110 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/monitor_job.yml: -------------------------------------------------------------------------------- 1 | # ----------------------- 2 | # Monitor Deploymnent Job 3 | # ----------------------- 4 | 5 | # ---------------------------------------------------------- 6 | # Used by any REST call that returns 202 (long running job) 7 | # Set job_id, job_retries, and job_delay in the calling task 8 | # ---------------------------------------------------------- 9 | 10 | - name: .....monitor job ({{ job_id }}) until "success" or "failure" 11 | 12 | uri: 13 | url: "{{ deploy_api_url }}/jobs/{{ job_id }}" 14 | method: GET 15 | headers: 16 | Content-Type: "application/json" 17 | body_format: json 18 | user: "{{ deploy_login }}" 19 | password: "{{ deploy_pwd }}" 20 | status_code: 200 21 | validate_certs: False 22 | register: job_response 23 | until: job_response.json.record.state == "success" or job_response.json.record.state == "failure" 24 | retries: "{{ job_retries }}" 25 | delay: "{{ job_delay }}" 26 | 27 | - name: Fail check 28 | fail: 29 | msg: "{{ job_response.json.record }}" 30 | when: 31 | - job_response.json.record.state == "failure" 32 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/register_esx_vcenter_host.yml: -------------------------------------------------------------------------------- 1 | # ------------------------------------ 2 | # Register ESX host managed by vCenter 3 | # ------------------------------------ 4 | 5 | # ------------------------------------------------------ 6 | # Check the host_id_list for existing registered hosts 7 | # If the specified host is not in the list than register 8 | # - host_id_list is created by get_host_ids task 9 | # ------------------------------------------------------ 10 | 11 | - name: Register new ESXi Host - {{ item.host_name }} 12 | 13 | uri: 14 | url: "{{ deploy_api_url }}/hosts" 15 | method: POST 16 | headers: 17 | Content-Type: "application/json" 18 | body: '{"hosts": [{"hypervisor_type": "ESX","management_server":"{{ vcenter_name }}", "name": "{{ item.host_name }}"}]}' 19 | body_format: json 20 | user: "{{ deploy_login }}" 21 | password: "{{ deploy_pwd }}" 22 | status_code: 202 23 | validate_certs: False 24 | register: host_register_response 25 | when: 26 | - item.host_name not in ( host_id_list | map(attribute='host_name') ) 27 | 28 | # ---------------------------- 29 | # Monitor the registration job 30 | # ---------------------------- 31 | 32 | - name: .....monitor host registration job 33 | 34 | include_tasks: monitor_job.yml 35 | vars: 36 | job_id: "{{ host_register_response.json.job.id }}" 37 | job_retries: "{{ monitor_host_retries }}" 38 | job_delay: "{{ monitor_host_delay }}" 39 | when: 40 | - item.host_name not in ( host_id_list | map(attribute='host_name') ) 41 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/register_host.yml: -------------------------------------------------------------------------------- 1 | # ---------------------------------- 2 | # Register Host 3 | # - ESXi host NOT managed by vCenter 4 | # - KVM host 5 | # ---------------------------------- 6 | 7 | # ------------------------------------------------------ 8 | # Check the host_id_list for existing registered hosts 9 | # If the specified host is not in the list than register 10 | # - host_id_list is created by get_host_ids task 11 | # ------------------------------------------------------ 12 | 13 | - name: Register Host - {{ item.host_name }} 14 | 15 | uri: 16 | url: "{{ deploy_api_url }}/hosts" 17 | method: POST 18 | headers: 19 | Content-Type: "application/json" 20 | body: '{"hosts": [{"hypervisor_type": "{{ hypervisor }}","name": "{{ item.host_name }}"}]}' 21 | body_format: json 22 | user: "{{ deploy_login }}" 23 | password: "{{ deploy_pwd }}" 24 | status_code: 202 25 | validate_certs: False 26 | register: host_register_response 27 | when: item.host_name not in ( host_id_list | map(attribute='host_name') ) 28 | 29 | # ---------------------------- 30 | # Monitor the registration job 31 | # ---------------------------- 32 | 33 | - name: .....monitor host registration job 34 | 35 | include_tasks: monitor_job.yml 36 | vars: 37 | job_id: "{{ host_register_response.json.job.id }}" 38 | job_retries: "{{ monitor_host_retries }}" 39 | job_delay: "{{ monitor_host_delay }}" 40 | when: 41 | - item.host_name not in ( host_id_list | map(attribute='host_name') ) 42 | -------------------------------------------------------------------------------- /na_ots_cluster/tasks/verify.yml: -------------------------------------------------------------------------------- 1 | # --------------- 2 | # Verify Settings 3 | # --------------- 4 | 5 | # -------------------------------------------------------------- 6 | # Compare the number of cluster nodes specified in cluster_nodes 7 | # to the node count. If node count is greater than the number of 8 | # cluster_nodes stop the task. 9 | # - More cluster nodes than node count will still work since 10 | # additional cluster_nodes are skipped - the loop is driven 11 | # by the node_id_list (not the cluster_nodes) 12 | # --------------------------------------------------------------- 13 | 14 | - name: .....set fact (cluster_nodes_count) 15 | 16 | set_fact: 17 | cluster_nodes_count: "{{ cluster_nodes | length }}" 18 | 19 | - name: .....set fact (actual_nodes_count) 20 | 21 | set_fact: 22 | actual_nodes_count: "{{ node_count | string }}" 23 | 24 | - name: ....compare node_count to cluster_nodes count 25 | 26 | fail: 27 | msg: "The specified node count ({{ node_count }}) is greater than the number of provided cluster nodes ({{ cluster_nodes_count }})" 28 | when: 29 | - actual_nodes_count > cluster_nodes_count 30 | 31 | # ------------ 32 | # Verify Image 33 | # ------------ 34 | 35 | - name: .....verify image 36 | 37 | uri: 38 | url: "{{ deploy_api_url }}/images?id={{ cluster_ontap_image }}" 39 | method: GET 40 | headers: 41 | Content-Type: "application/json" 42 | body_format: json 43 | user: "{{ deploy_login }}" 44 | password: "{{ deploy_pwd }}" 45 | status_code: 200 46 | validate_certs: False 47 | 48 | register: verify_image_response 49 | 50 | # ---------------------------------------------- 51 | # If a record is not returned then fail playbook 52 | # ---------------------------------------------- 53 | 54 | - name: .....stop task if ONTAP image is not available 55 | 56 | fail: 57 | msg: "Requested ONTAP Image Not Found in Deploy - {{ cluster_ontap_image }}" 58 | when: 59 | - verify_image_response.json.num_records == 0 60 | -------------------------------------------------------------------------------- /na_ots_cluster/templates/host2id.j2: -------------------------------------------------------------------------------- 1 | {% for j2item in host_id_list %} 2 | 3 | {% if j2item.host_name == item.host_name %} 4 | 5 | {{ j2item.host_id }} 6 | 7 | {% endif %} 8 | 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /na_ots_cluster/templates/host2pwd.j2: -------------------------------------------------------------------------------- 1 | {% if hypervisor == "ESX" %} 2 | 3 | {{ host_esx_password }} 4 | 5 | {% else %} 6 | 7 | {{ host_kvm_password }} 8 | 9 | {% endif %} 10 | -------------------------------------------------------------------------------- /na_ots_cluster/templates/networkcheck.j2: -------------------------------------------------------------------------------- 1 | { 2 | "debug": false, 3 | "host_networks": [ 4 | {%for nodeinfo in cluster_nodes %} 5 | { 6 | "host_name": "{{nodeinfo.host_name}}", 7 | "network_name": "{{internal_network}}" 8 | }{% if not loop.last %}, {%endif%}{%endfor%} 9 | ], 10 | "mode": "{{net_mode}}", 11 | "mtu": {{net_mtu}}, 12 | "vswitch_type": "{{net_switch_type}}" 13 | } -------------------------------------------------------------------------------- /na_ots_deploy/README.md: -------------------------------------------------------------------------------- 1 | # Role Name 2 | `na_ots_deploy`: Create, configure and run the OTS deploy VM. 3 | 4 | # Requirements 5 | The Server that will host the deploy VM should be prepared according to ONTAP Select specifications withing the appropriate virtualization environment and storage and networking configured as required. 6 | Ansible 2.7 or greater is needed to run this role. 7 | 8 | # Role Variables 9 | ```yaml 10 | target_vcenter_or_esxi_host: 11 | host_login: 12 | ovf_path: 13 | datacenter_name: 14 | esx_cluster_name: 15 | datastore_name: 16 | mgt_network: 17 | deploy_name: 18 | deploy_ipAddress: 19 | deploy_gateway: 20 | deploy_proxy_url: 21 | deploy_netMask: 22 | deploy_primaryDNS: 23 | deploy_secondaryDNS: 24 | deploy_searchDomains: 25 | ``` 26 | # Example Playbook 27 | ```yaml 28 | --- 29 | - name: Create ONTAP Select Deploy VM from OVA (ESXi) 30 | hosts: "{{ target_vcenter_or_esxi_host }}" # Entry in Ansible 'hosts' file 31 | gather_facts: false 32 | connection: 'local' 33 | vars_files: 34 | - vars_deploy.yml # All Variables 35 | - vars_deploy_pwd.yml # host_password & deploy_password 36 | roles: 37 | - na_ots_deploy 38 | ``` 39 | # Example Global file 40 | Using a global file for variables helps. Sample below: 41 | ```yaml 42 | target_vcenter_or_esxi_host: "10.xxx.xx.xx" 43 | host_login: "yourlogin@yourlab.local" 44 | ovf_path: "/run/deploy/ovapath/ONTAPdeploy.ova" 45 | datacenter_name: "your-Lab" 46 | esx_cluster_name: "your Cluster" 47 | datastore_name: "your-select-dt" 48 | mgt_network: "your-mgmt-network" 49 | deploy_name: "test-deploy-vm" 50 | deploy_ipAddress: "10.xxx.xx.xx" 51 | deploy_gateway: "10.xxx.xx.1" 52 | deploy_proxy_url: "" 53 | deploy_netMask: "255.255.255.0" 54 | deploy_product_company: "NetApp" 55 | deploy_primaryDNS: "10.xxx.xx.xx" 56 | deploy_secondaryDNS: "" 57 | deploy_searchDomains: "your.search.domain.com" 58 | ``` 59 | # License 60 | BSD 61 | # Author Information 62 | NetApp 63 | -------------------------------------------------------------------------------- /na_ots_deploy/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ############################################################################ 3 | # defaults file for ots_deploy 4 | ##### Define these here or provide vars_files in your playbook ##### 5 | ############################################################################ 6 | target_vcenter_or_esxi_host: "" 7 | host_login: "" 8 | ovf_path: "" 9 | datacenter_name: "" 10 | esx_cluster_name: "" 11 | datastore_name: "" 12 | mgt_network: "" 13 | deploy_name: "" 14 | deploy_ipAddress: "" 15 | deploy_gateway: "" 16 | deploy_proxy_url: "" 17 | deploy_netMask: "" 18 | deploy_product_company: "" 19 | deploy_primaryDNS: "" 20 | deploy_secondaryDNS: "" 21 | deploy_searchDomains: "" 22 | -------------------------------------------------------------------------------- /na_ots_deploy/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: "NetApp" 3 | description: "Role for ONTAP Select Deploy OVA" 4 | company: "NetApp" 5 | license: BSD 6 | min_ansible_version: 2.7 7 | platforms: 8 | galaxy_tags: [netapp, ontap, ontapselect, select, ots] 9 | dependencies: [] 10 | -------------------------------------------------------------------------------- /na_ots_deploy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # tasks file for ots_deploy 2 | - name: Import Deploy OVA - {{ ovf_path }} 3 | vmware_deploy_ovf: 4 | hostname: "{{ target_vcenter_or_esxi_host }}" 5 | username: "{{ host_login }}" 6 | password: "{{ host_password }}" 7 | validate_certs: no 8 | ovf: "{{ ovf_path }}" 9 | networks: 10 | "ONTAP Select Deploy VM Network": "{{ mgt_network }}" 11 | cluster: "{{ esx_cluster_name }}" 12 | datacenter: "{{ datacenter_name }}" 13 | datastore: "{{ datastore_name }}" 14 | name: "{{ deploy_name }}" 15 | properties: 16 | gateway: "{{ deploy_gateway }}" 17 | proxy_url: "{{ deploy_proxy_url }}" 18 | netMask: "{{ deploy_netMask }}" 19 | password: "{{ deploy_password }}" 20 | product_company: "{{ deploy_product_company }}" 21 | ipAddress: "{{ deploy_ipAddress }}" 22 | primaryDNS: "{{ deploy_primaryDNS }}" 23 | secondaryDNS: "{{ deploy_secondaryDNS }}" 24 | hostName: "{{ deploy_name }}" 25 | searchDomains: "{{ deploy_searchDomains }}" 26 | power_on: yes 27 | wait_for_ip_address: true 28 | allow_duplicates: no 29 | delegate_to: localhost 30 | - name: wait for connectivity 31 | wait_for_connection: 32 | delay: 60 33 | timeout: 300 34 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/.DS_Store -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/._.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/._.DS_Store -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/._README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/._README.md -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/._files: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/._files -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/._nar_ontap_security_ucd_guide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/._nar_ontap_security_ucd_guide -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/._templates: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/._templates -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/README.md: -------------------------------------------------------------------------------- 1 | nar_ontap_security_ucd_guide 2 | ========= 3 | 4 | Configures and hardens the ONTAP cluster to the specifications detailed in the NetApp DoD Unified Capabilities (UC) Deployment Guide (NetApp TR-4754). 5 | Use extreme caution when utilizing this role. If used incorrectly it's possible to lock yourself ouf of the ONTAP system where you are unable to gain access. 6 | Reviewing TR-4754 prior to deploying this is highly recommended. 7 | 8 | Requirements 9 | ------------ 10 | 11 | -Since this uses the NetApp ONTAP modules it will require the python library netapp-lib as well as the Ansible 2.8 or later release. 12 | -NetApp ONTAP 9.6 or later. 13 | -The cluster will be deployed with the built-in default cluster admin account, but once complete the final procedure disables the admin account, and no further access through that account is possible. 14 | 15 | Role Variables 16 | -------------- 17 | ``` 18 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. 19 | 20 | hostname: 21 | username: admin 22 | password: 23 | node01_name: 24 | node02_name: 25 | admin_vserver: 26 | 27 | fw_dns_allow_ip: 0.0.0.0/0 28 | # The allowed dns IP’s can be changed, but the recommendation is to keep 0.0.0.0/0 29 | 30 | fw_ssh_allow_ip: 0.0.0.0/0 31 | # The allowed ssh IP’s can be changed, but the recommendation is to keep 0.0.0.0/0 32 | 33 | fw_ntp_allow_ip: 0.0.0.0/0 34 | # The allowed ntp IP’s can be changed, but the recommendation is to keep 0.0.0.0/0 35 | 36 | core_mgmt_allow_ip: 0.0.0.0/0 37 | # The allowed IP's for LIF Services core_mgmt can be changed, but the recommendation is to keep 0.0.0.0/0 38 | 39 | data_core_cifs_allow_ip: 0.0.0.0/0 40 | # Necessary for the domain access vserver to join the domain, the allowed IP's for LIF Services data_core_cifs can be changed, but the recommendation is to keep 0.0.0.0/0 41 | 42 | node01_mgmt_lif_name: 43 | node02_mgmt_lif_name: 44 | 45 | domain_access_vserver: 46 | # The name of the vserver used for domain accounts that will administer the cluster with domain access rights 47 | 48 | da_root_vol_name: 49 | # The name of the root_volume for the domain access vserver 50 | 51 | da_root_vol_aggr_name: 52 | # The name of the data aggregate that will contain the domain access vserver svm root volume 53 | 54 | node01_da_failover_target_port: 55 | node02_da_failover_target_port: 56 | node01_da_lif_home_port: 57 | lif_da_ip: 58 | lif_da_mask: 59 | 60 | da_dns_domain_name: 61 | # Typically in Active Directory environments this is the AD DNS servers FQDN 62 | 63 | da_dns_ip: 64 | 65 | da_cifs_server_name: 66 | # This is the windows AD machine account name for the CIFS server 67 | 68 | da_ad_domain_user_name: 69 | # A windows account with permissions to join a computer to the domain 70 | 71 | da_ad_domain_passwd: 72 | 73 | da_ad_ou_name: 74 | 75 | ad_da_user_name: 76 | # This will be an Active Directory user account name with permissions to login and manage the SVM 77 | 78 | ntp_server_ip: 79 | syslog_server: 80 | 81 | emergency_user_name: emergency_acct 82 | # This account name can be changed if desired. The account is only used during network outages and only has access through the serial console. 83 | 84 | emergency_user_password: 85 | 86 | allowed_http_ip: 127.0.0.1/32 87 | # The allowed http IP’s can be changed, but the recommendation is to keep only the local host. 88 | 89 | allowed_https_ip: 127.0.0.1/32 90 | # The allowed https IP’s can be changed, but the recommendation is to keep only the local host. 91 | ``` 92 | 93 | Dependencies 94 | ------------ 95 | 96 | The tasks in this role are dependent on information from the na_ontap_gather_facts module. The task for na_ontap_gather_facts can not be excluded 97 | 98 | Example Playbook 99 | ---------------- 100 | ``` 101 | # In this example the variable file used is called ucd_guide_vars.yml 102 | 103 | - hosts: localhost 104 | name: Security Harden 105 | vars_files: 106 | - ucd_guide_vars.yml 107 | vars: 108 | login: &login 109 | hostname: "{{ hostname }}" 110 | username: "{{ username }}" 111 | password: "{{ password }}" 112 | tasks: 113 | - name: Enable IPv6 114 | na_ontap_command: 115 | command: ['network options ipv6 modify -enabled true'] 116 | https: true 117 | validate_certs: false 118 | <<: *login 119 | - name: Disable autosupport 120 | na_ontap_autosupport: 121 | state: absent 122 | node_name: "{{ node01_name }}" 123 | https: true 124 | validate_certs: false 125 | <<: *login 126 | - name: Modify Service Processor Network ipv6 127 | na_ontap_service_processor_network: 128 | state: present 129 | address_type: ipv6 130 | is_enabled: false 131 | dhcp: none 132 | node: "{{ node01_name }}" 133 | ip_address: 0::0 134 | prefix_length: 64 135 | https: true 136 | validate_certs: false 137 | #<<: *login 138 | - name: Modify Service Processor Network ipv4 139 | na_ontap_service_processor_network: 140 | state: present 141 | address_type: ipv4 142 | is_enabled: false 143 | dhcp: none 144 | node: "{{ node01_name }}" 145 | ip_address: 0.0.0.0 146 | netmask: 255.255.255.0 147 | gateway_ip_address: 0.0.0.0 148 | <<: *login 149 | - name: Set SSH Ciphers and Algorithims 150 | na_ontap_command: 151 | command: ['security ssh modify -vserver "{{ admin_vserver }}" -key-exchange-algorithms diffie-hellman-group-exchange-sha256 -ciphers aes256-ctr,aes192-ctr,aes128-ctr,aes128-gcm,aes256-gcm'] 152 | https: true 153 | validate_certs: false 154 | <<: *login 155 | - name: Mgmt Firewall Policy HTTP Deny 156 | na_ontap_firewall_policy: 157 | vserver: "{{ admin_vserver }}" 158 | state: present 159 | node: "{{ node01_name }}" 160 | enable: enable 161 | service: http 162 | allow_list: "127.0.0.1/32,::1/128" 163 | logging: enable 164 | policy: secure_mgmt 165 | https: true 166 | validate_certs: false 167 | <<: *login 168 | - name: Mgmt Firewall Policy DNS Allow CLI 169 | na_ontap_command: 170 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service dns -allow-list "{{ fw_dns_allow_ip }}"'] 171 | https: true 172 | validate_certs: false 173 | <<: *login 174 | - name: Mgmt LIF Services HTTPS Deny CLI 175 | na_ontap_command: 176 | command: ['network interface service-policy create -policy secure_mgmt -allowed-addresses 127.0.0.1/32, ::1/128 -vserver "{{ admin_vserver }}" -services management-https'] 177 | privilege: advanced 178 | https: true 179 | validate_certs: false 180 | <<: *login 181 | - name: Mgmt LIF Services SSH Allow CLI 182 | na_ontap_command: 183 | command: ['network interface service-policy add-service -vserver "{{ admin_vserver }}" -policy secure_mgmt -services management-ssh -allowed-addresses "{{ fw_ssh_allow_ip }}"'] 184 | privilege: advanced 185 | https: true 186 | validate_certs: false 187 | <<: *login 188 | - name: Mgmt LIF Services core-management Allow CLI 189 | na_ontap_command: 190 | command: ['network interface service-policy add-service -vserver "{{ admin_vserver }}" -policy secure_mgmt -services management-core -allowed-addresses "{{ core_mgmt_allow_ip }}"'] 191 | privilege: advanced 192 | https: true 193 | validate_certs: false 194 | <<: *login 195 | - name: Mgmt Firewall Policy NDMP Deny CLI 196 | na_ontap_command: 197 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service ndmp -allow-list 127.0.0.1/32, ::1/128'] 198 | https: true 199 | validate_certs: false 200 | <<: *login 201 | - name: Mgmt Firewall Policy RSH Deny CLI 202 | na_ontap_command: 203 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service rsh -allow-list 127.0.0.1/32, ::1/128'] 204 | https: true 205 | validate_certs: false 206 | <<: *login 207 | - name: Mgmt Firewall Policy SNMP Deny CLI 208 | na_ontap_command: 209 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service snmp -allow-list 127.0.0.1/32, ::1/128'] 210 | https: true 211 | validate_certs: false 212 | <<: *login 213 | - name: Mgmt Firewall Policy TELNET Deny CLI 214 | na_ontap_command: 215 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service telnet -allow-list 127.0.0.1/32, ::1/128'] 216 | https: true 217 | validate_certs: false 218 | <<: *login 219 | - name: Mgmt Firewall Policy NTP Allow CLI 220 | na_ontap_command: 221 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service ntp -allow-list "{{ fw_ntp_allow_ip }}"'] 222 | https: true 223 | validate_certs: false 224 | <<: *login 225 | - name: Assign Secure Mgmt LIF Services Policy to Node 01 Managment CLI 226 | na_ontap_command: 227 | command: ['net interface modify -vserver "{{ admin_vserver }}" -lif "{{ node01_mgmt_lif_name }}" -service-policy secure_mgmt'] 228 | privilege: advanced 229 | https: true 230 | validate_certs: false 231 | <<: *login 232 | - name: Assign Mgmt FW Policy to Node 01 Management 233 | na_ontap_interface: 234 | state: present 235 | interface_name: "{{ node01_mgmt_lif_name }}" 236 | firewall_policy: secure_mgmt 237 | vserver: "{{ admin_vserver }}" 238 | https: true 239 | validate_certs: false 240 | <<: *login 241 | - name: Create Domain Access SVM 242 | na_ontap_svm: 243 | state: present 244 | name: "{{ domain_access_vserver }}" 245 | root_volume: "{{ da_root_vol_name }}" 246 | root_volume_aggregate: "{{ da_root_vol_aggr_name }}" 247 | root_volume_security_style: mixed 248 | https: true 249 | validate_certs: false 250 | <<: *login 251 | - name: AD_DA Firewall Policy HTTP Deny 252 | na_ontap_firewall_policy: 253 | vserver: "{{ domain_access_vserver }}" 254 | enable: enable 255 | node: "{{ node01_name }}" 256 | service: http 257 | allow_list: "127.0.0.1/32,::1/128" 258 | logging: enable 259 | policy: domain_access 260 | https: true 261 | validate_certs: false 262 | state: present 263 | <<: *login 264 | - name: AD_DA Firewall Policy DNS Allow CLI 265 | na_ontap_command: 266 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service dns -allow-list "{{ fw_dns_allow_ip }}"'] 267 | https: true 268 | validate_certs: false 269 | <<: *login 270 | - name: AD_DA LIF Services HTTPS Deny CLI 271 | na_ontap_command: 272 | command: ['network interface service-policy create -policy domain_access -allowed-addresses 127.0.0.1/32, ::1/128 -vserver "{{ domain_access_vserver }}" -services management-https'] 273 | privilege: advanced 274 | https: true 275 | validate_certs: false 276 | <<: *login 277 | - name: AD_DA Firewall Policy NDMP Deny CLI 278 | na_ontap_command: 279 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service ndmp -allow-list 127.0.0.1/32, ::1/128'] 280 | https: true 281 | validate_certs: false 282 | <<: *login 283 | - name: AD_DA Firewall Policy RSH Deny CLI 284 | na_ontap_command: 285 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service rsh -allow-list 127.0.0.1/32, ::1/128'] 286 | https: true 287 | validate_certs: false 288 | <<: *login 289 | - name: AD_DA Firewall Policy SNMP Deny CLI 290 | na_ontap_command: 291 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service snmp -allow-list 127.0.0.1/32, ::1/128'] 292 | https: true 293 | validate_certs: false 294 | <<: *login 295 | - name: AD_DA Firewall Policy TELNET Deny CLI 296 | na_ontap_command: 297 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service telnet -allow-list 127.0.0.1/32, ::1/128'] 298 | https: true 299 | validate_certs: false 300 | <<: *login 301 | - name: AD_DA Firewall Policy NTP Allow CLI 302 | na_ontap_command: 303 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service ntp -allow-list "{{ fw_ntp_allow_ip }}"'] 304 | https: true 305 | validate_certs: false 306 | <<: *login 307 | - name: AD_DA LIF Services SSH Deny CLI 308 | na_ontap_command: 309 | command: ['network interface service-policy add-service -vserver "{{ domain_access_vserver }}" -policy domain_access -service management-ssh -allowed-addresses 127.0.0.1/32, ::1/128'] 310 | privilege: advanced 311 | https: true 312 | validate_certs: false 313 | <<: *login 314 | - name: AD_DA LIF Services data-cifs Allow CLI 315 | na_ontap_command: 316 | command: ['network interface service-policy add-service -vserver "{{ domain_access_vserver }}" -policy domain_access -service data_core -allowed-addresses "{{ data_core_cifs_allow_ip }}"'] 317 | privilege: advanced 318 | https: true 319 | validate_certs: false 320 | <<: *login 321 | - name: Create AD_DA LIF Failover Group Node01 Target CLI 322 | na_ontap_command: 323 | command: ['network interface failover-groups create -vserver "{{ domain_access_vserver }}" -failover-group da_fail_grp1 -targets "{{ node01_da_failover_target_port }}"'] 324 | https: true 325 | validate_certs: false 326 | <<: *login 327 | - name: Create AD_DA LIF Failover Group Node02 Target CLI 328 | na_ontap_command: 329 | command: ['network interface failover-groups create -vserver "{{ domain_access_vserver }}" -failover-group da_fail_grp1 -targets "{{ node02_da_failover_target_port }}"'] 330 | https: true 331 | validate_certs: false 332 | <<: *login 333 | - name: Create AD_DA LIF 334 | na_ontap_interface: 335 | state: present 336 | interface_name: lif_domain_access 337 | role: data 338 | protocols: cifs 339 | home_node: "{{ node01_name }}" 340 | home_port: "{{ node01_da_lif_home_port }}" 341 | address: "{{ lif_da_ip }}" 342 | netmask: "{{ lif_da_mask }}" 343 | admin_status: up 344 | firewall_policy: domain_access 345 | is_auto_revert: true 346 | vserver: "{{ domain_access_vserver }}" 347 | https: true 348 | validate_certs: false 349 | <<: *login 350 | - name: AD_DA LIF Services data-cifs Allow CLI 351 | na_ontap_command: 352 | command: ['network interface service-policy add-service -vserver "{{ domain_access_vserver }}" -policy domain_access -service data_core -allowed-addresses "{{ data_core_cifs_allow_ip }}"'] 353 | privilege: advanced 354 | https: true 355 | validate_certs: false 356 | <<: *login 357 | - name: Add AD_DA LIF to Failover Group da_fail_grp1 CLI 358 | na_ontap_command: 359 | command: ['network interface modify -vserver "{{ domain_access_vserver }}" -lif lif_domain_access -failover-group da_fail_grp1'] 360 | https: true 361 | validate_certs: false 362 | <<: *login 363 | - name: Add AD_DA DNS Name Server IP address 364 | na_ontap_dns: 365 | state: present 366 | vserver: "{{ domain_access_vserver }}" 367 | domains: "{{ da_dns_domain_name }}" 368 | nameservers: "{{ da_dns_ip }}" 369 | https: true 370 | validate_certs: false 371 | <<: *login 372 | - name: Join AD_DA SVM to CIFS Domain 373 | na_ontap_cifs_server: 374 | state: present 375 | cifs_server_name: "{{ da_cifs_server_name }}" 376 | vserver: "{{ domain_access_vserver }}" 377 | admin_password: "{{ da_ad_domain_passwd }}" 378 | admin_user_name: "{{ da_ad_domain_user_name }}" 379 | domain: "{{ da_dns_domain_name }}" 380 | service_state: started 381 | ou: "{{ da_ad_ou_name }}" 382 | https: true 383 | validate_certs: false 384 | <<: *login 385 | - name: Enable Domain Tunnel Login for DA SVM CLI 386 | na_ontap_command: 387 | command: ['security login domain-tunnel create -vserver "{{ domain_access_vserver }}"'] 388 | https: true 389 | validate_certs: false 390 | <<: *login 391 | - name: Create NTP server 392 | na_ontap_ntp: 393 | state: present 394 | version: auto 395 | server_name: "{{ ntp_server_ip }}" 396 | https: true 397 | validate_certs: false 398 | <<: *login 399 | - name: Modify SSH timeouts CLI 400 | na_ontap_command: 401 | command: ['system timeout modify -timeout 10'] 402 | https: true 403 | validate_certs: false 404 | <<: *login 405 | - name: Add Syslog Server CLI 406 | na_ontap_command: 407 | command: ['event destination modify -name allevents -syslog "{{ syslog_server }}"'] 408 | https: true 409 | validate_certs: false 410 | <<: *login 411 | - name: Send all EMS events to Syslog Server CLI 412 | na_ontap_command: 413 | command: ['event route add-destinations -messagename * -destinations allevents'] 414 | https: true 415 | validate_certs: false 416 | <<: *login 417 | - name: Create admin_ssh default 418 | na_ontap_user_role: 419 | state: present 420 | name: admin_ssh 421 | command_directory_name: DEFAULT 422 | access_level: all 423 | vserver: "{{ admin_vserver }}" 424 | https: true 425 | validate_certs: false 426 | <<: *login 427 | - name: Create admin_ssh SP deny 428 | na_ontap_user_role: 429 | state: present 430 | name: admin_ssh 431 | command_directory_name: system node service-processor 432 | access_level: none 433 | vserver: "{{ admin_vserver }}" 434 | https: true 435 | validate_certs: false 436 | <<: *login 437 | - name: Modify Admin SSH role CLI 438 | na_ontap_command: 439 | command: ['security login role config modify -role admin_ssh -vserver "{{ admin_vserver }}" -username-alphanum disabled -passwd-minlength 14 -passwd-alphanum enabled -passwd-min-special-chars 1 -passwd-expirty-time 60 -require-initial-passwd-update enabled -max-failed-login-attempts 3 -lockout-duration 60 -disallwed-reuse 24 -change-delay 1 -username-minlength 4'] 440 | https: true 441 | validate_certs: false 442 | <<: *login 443 | - name: Create Emergency User for Console access 444 | na_ontap_user: 445 | state: present 446 | name: "{{ emergency_user_name }}" 447 | application: console 448 | authentication_method: password 449 | set_password: "{{ emergency_user_password }}" 450 | lock_user: True 451 | role_name: admin 452 | vserver: "{{ admin_vserver }}" 453 | https: true 454 | validate_certs: false 455 | <<: *login 456 | - name: Add Emergency User for SP access 457 | na_ontap_user: 458 | state: present 459 | name: "{{ emergency_user_name }}" 460 | application: service-processor 461 | authentication_method: password 462 | set_password: "{{ emergency_user_password }}" 463 | lock_user: True 464 | role_name: admin 465 | vserver: "{{ admin_vserver }}" 466 | https: true 467 | validate_certs: false 468 | <<: *login 469 | - name: Create AD DA User 470 | na_ontap_user: 471 | state: present 472 | name: "{{ ad_da_user_name }}" 473 | application: ssh 474 | authentication_method: domain 475 | set_password: "{{ emergency_user_password }}" 476 | lock_user: True 477 | role_name: admin_ssh 478 | vserver: "{{ admin_vserver }}" 479 | https: true 480 | validate_certs: false 481 | <<: *login 482 | - name: Disable Web Access 483 | na_ontap_command: 484 | command: ['security login lock -vserver "{{ admin_vserver }}" -username admin'] 485 | https: true 486 | validate_certs: false 487 | <<: *login 488 | ``` 489 | 490 | License 491 | ------- 492 | 493 | GNU v3 494 | 495 | Author Information 496 | ------------------ 497 | 498 | NetApp http://www.netapp.io 499 | 500 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/defaults/._main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/defaults/._main.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for nar_ontap_security_ucd_guide 3 | hostname: 4 | username: 5 | password: 6 | node01_name: 7 | node02_name: 8 | admin_vserver: 9 | fw_dns_allow_ip: 0.0.0.0/0 10 | fw_ssh_allow_ip: 0.0.0.0/0 11 | fw_ntp_allow_ip: 0.0.0.0/0 12 | core_mgmt_allow_ip: 0.0.0.0/0 13 | data_core_cifs_allow_ip: 0.0.0.0/0 14 | node01_mgmt_lif_name: 15 | node02_mgmt_lif_name: 16 | domain_access_vserver: 17 | da_root_vol_name: 18 | da_root_vol_aggr_name: 19 | node01_da_failover_target_port: 20 | node02_da_failover_target_port: 21 | node01_da_lif_home_port: 22 | lif_da_ip: 23 | lif_da_mask: 24 | da_dns_domain_name: 25 | da_dns_ip: 26 | da_cifs_server_name: 27 | da_ad_domain_passwd: 28 | da_ad_domain_user_name: 29 | da_ad_ou_name: 30 | ad_da_user_name: 31 | ntp_server_ip: 32 | syslog_server: 33 | emergency_user_name: 34 | emergency_user_password: 35 | allowed_http_ip: 127.0.0.1/32 36 | allowed_https_ip: 127.0.0.1/32 37 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/handlers/._main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/handlers/._main.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for nar_ontap_security_ucd_guide -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/meta/._main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/meta/._main.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: your name 3 | description: your description 4 | company: your company (optional) 5 | 6 | # If the issue tracker for your role is not on github, uncomment the 7 | # next line and provide a value 8 | # issue_tracker_url: http://example.com/issue/tracker 9 | 10 | # Choose a valid license ID from https://spdx.org - some suggested licenses: 11 | # - BSD-3-Clause (default) 12 | # - MIT 13 | # - GPL-2.0-or-later 14 | # - GPL-3.0-only 15 | # - Apache-2.0 16 | # - CC-BY-4.0 17 | license: license (GPL-2.0-or-later, MIT, etc) 18 | 19 | min_ansible_version: 2.4 20 | 21 | # If this a Container Enabled role, provide the minimum Ansible Container version. 22 | # min_ansible_container_version: 23 | 24 | # 25 | # Provide a list of supported platforms, and for each platform a list of versions. 26 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 27 | # To view available platforms and versions (or releases), visit: 28 | # https://galaxy.ansible.com/api/v1/platforms/ 29 | # 30 | # platforms: 31 | # - name: Fedora 32 | # versions: 33 | # - all 34 | # - 25 35 | # - name: SomePlatform 36 | # versions: 37 | # - all 38 | # - 1.0 39 | # - 7 40 | # - 99.99 41 | 42 | galaxy_tags: [] 43 | # List tags for your role here, one per line. A tag is a keyword that describes 44 | # and categorizes the role. Users find roles by searching for tags. Be sure to 45 | # remove the '[]' above, if you add tags to this list. 46 | # 47 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 48 | # Maximum 20 tags per role. 49 | 50 | dependencies: [] 51 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 52 | # if you add dependencies to this list. 53 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tasks/._main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/tasks/._main.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for nar_ontap_security_ucd_guide 3 | - name: Enable IPv6 4 | na_ontap_command: 5 | command: ['network options ipv6 modify -enabled true'] 6 | hostname: "{{ hostname }}" 7 | username: "{{ username }}" 8 | password: "{{ password }}" 9 | https: true 10 | validate_certs: false 11 | - name: Disable autosupport 12 | na_ontap_autosupport: 13 | state: absent 14 | node_name: "{{ node01_name }}" 15 | hostname: "{{ hostname }}" 16 | username: "{{ username }}" 17 | password: "{{ password }}" 18 | https: true 19 | validate_certs: false 20 | - name: Modify Service Processor Network ipv6 21 | na_ontap_service_processor_network: 22 | state: present 23 | address_type: ipv6 24 | is_enabled: false 25 | dhcp: none 26 | node: "{{ node01_name }}" 27 | ip_address: 0::0 28 | prefix_length: 64 29 | hostname: "{{ hostname }}" 30 | username: "{{ username }}" 31 | password: "{{ password }}" 32 | https: true 33 | validate_certs: false 34 | - name: Modify Service Processor Network ipv4 35 | na_ontap_service_processor_network: 36 | state: present 37 | address_type: ipv4 38 | is_enabled: false 39 | dhcp: none 40 | node: "{{ node01_name }}" 41 | ip_address: 0.0.0.0 42 | netmask: 255.255.255.0 43 | gateway_ip_address: 0.0.0.0 44 | hostname: "{{ hostname }}" 45 | username: "{{ username }}" 46 | password: "{{ password }}" 47 | https: true 48 | validate_certs: false 49 | - name: Set SSH Ciphers and Algorithims 50 | na_ontap_command: 51 | command: ['security ssh modify -vserver "{{ admin_vserver }}" -key-exchange-algorithms diffie-hellman-group-exchange-sha256 -ciphers aes256-ctr,aes192-ctr,aes128-ctr,aes128-gcm,aes256-gcm'] 52 | hostname: "{{ hostname }}" 53 | username: "{{ username }}" 54 | password: "{{ password }}" 55 | https: true 56 | validate_certs: false 57 | - name: Mgmt Firewall Policy HTTP Deny 58 | na_ontap_firewall_policy: 59 | vserver: "{{ admin_vserver }}" 60 | state: present 61 | node: "{{ node01_name }}" 62 | enable: enable 63 | service: http 64 | allow_list: "127.0.0.1/32,::1/128" 65 | logging: enable 66 | policy: secure_mgmt 67 | hostname: "{{ hostname }}" 68 | username: "{{ username }}" 69 | password: "{{ password }}" 70 | https: true 71 | validate_certs: false 72 | - name: Mgmt Firewall Policy DNS Allow CLI 73 | na_ontap_command: 74 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service dns -allow-list "{{ fw_dns_allow_ip }}"'] 75 | hostname: "{{ hostname }}" 76 | username: "{{ username }}" 77 | password: "{{ password }}" 78 | https: true 79 | validate_certs: false 80 | - name: Mgmt LIF Services HTTPS Deny CLI 81 | na_ontap_command: 82 | command: ['network interface service-policy create -policy secure_mgmt -allowed-addresses 127.0.0.1/32, ::1/128 -vserver "{{ admin_vserver }}" -services management-https'] 83 | privilege: advanced 84 | hostname: "{{ hostname }}" 85 | username: "{{ username }}" 86 | password: "{{ password }}" 87 | https: true 88 | validate_certs: false 89 | - name: Mgmt LIF Services SSH Allow CLI 90 | na_ontap_command: 91 | command: ['network interface service-policy add-service -vserver "{{ admin_vserver }}" -policy secure_mgmt -services management-ssh -allowed-addresses "{{ fw_ssh_allow_ip }}"'] 92 | privilege: advanced 93 | hostname: "{{ hostname }}" 94 | username: "{{ username }}" 95 | password: "{{ password }}" 96 | https: true 97 | validate_certs: false 98 | - name: Mgmt LIF Services core-management Allow CLI 99 | na_ontap_command: 100 | command: ['network interface service-policy add-service -vserver "{{ admin_vserver }}" -policy secure_mgmt -services management-core -allowed-addresses "{{ core_mgmt_allow_ip }}"'] 101 | privilege: advanced 102 | hostname: "{{ hostname }}" 103 | username: "{{ username }}" 104 | password: "{{ password }}" 105 | https: true 106 | validate_certs: false 107 | - name: Mgmt Firewall Policy NDMP Deny CLI 108 | na_ontap_command: 109 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service ndmp -allow-list 127.0.0.1/32, ::1/128'] 110 | hostname: "{{ hostname }}" 111 | username: "{{ username }}" 112 | password: "{{ password }}" 113 | https: true 114 | validate_certs: false 115 | - name: Mgmt Firewall Policy RSH Deny CLI 116 | na_ontap_command: 117 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service rsh -allow-list 127.0.0.1/32, ::1/128'] 118 | hostname: "{{ hostname }}" 119 | username: "{{ username }}" 120 | password: "{{ password }}" 121 | https: true 122 | validate_certs: false 123 | - name: Mgmt Firewall Policy SNMP Deny CLI 124 | na_ontap_command: 125 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service snmp -allow-list 127.0.0.1/32, ::1/128'] 126 | hostname: "{{ hostname }}" 127 | username: "{{ username }}" 128 | password: "{{ password }}" 129 | https: true 130 | validate_certs: false 131 | - name: Mgmt Firewall Policy TELNET Deny CLI 132 | na_ontap_command: 133 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service telnet -allow-list 127.0.0.1/32, ::1/128'] 134 | hostname: "{{ hostname }}" 135 | username: "{{ username }}" 136 | password: "{{ password }}" 137 | https: true 138 | validate_certs: false 139 | - name: Mgmt Firewall Policy NTP Allow CLI 140 | na_ontap_command: 141 | command: ['firewall policy create -vserver "{{ admin_vserver }}" -policy secure_mgmt -service ntp -allow-list "{{ fw_ntp_allow_ip }}"'] 142 | hostname: "{{ hostname }}" 143 | username: "{{ username }}" 144 | password: "{{ password }}" 145 | https: true 146 | validate_certs: false 147 | - name: Assign Secure Mgmt LIF Services Policy to Node 01 Managment CLI 148 | na_ontap_command: 149 | command: ['net interface modify -vserver "{{ admin_vserver }}" -lif "{{ node01_mgmt_lif_name }}" -service-policy secure_mgmt'] 150 | privilege: advanced 151 | hostname: "{{ hostname }}" 152 | username: "{{ username }}" 153 | password: "{{ password }}" 154 | https: true 155 | validate_certs: false 156 | - name: Assign Mgmt FW Policy to Node 01 Management 157 | na_ontap_interface: 158 | state: present 159 | interface_name: "{{ node01_mgmt_lif_name }}" 160 | firewall_policy: secure_mgmt 161 | vserver: "{{ admin_vserver }}" 162 | hostname: "{{ hostname }}" 163 | username: "{{ username }}" 164 | password: "{{ password }}" 165 | https: true 166 | validate_certs: false 167 | - name: Create Domain Access SVM 168 | na_ontap_svm: 169 | state: present 170 | name: "{{ domain_access_vserver }}" 171 | root_volume: "{{ da_root_vol_name }}" 172 | root_volume_aggregate: "{{ da_root_vol_aggr_name }}" 173 | root_volume_security_style: mixed 174 | hostname: "{{ hostname }}" 175 | username: "{{ username }}" 176 | password: "{{ password }}" 177 | https: true 178 | validate_certs: false 179 | - name: AD_DA Firewall Policy HTTP Deny 180 | na_ontap_firewall_policy: 181 | vserver: "{{ domain_access_vserver }}" 182 | enable: enable 183 | node: "{{ node01_name }}" 184 | service: http 185 | allow_list: "127.0.0.1/32,::1/128" 186 | logging: enable 187 | policy: domain_access 188 | hostname: "{{ hostname }}" 189 | username: "{{ username }}" 190 | password: "{{ password }}" 191 | https: true 192 | validate_certs: false 193 | state: present 194 | - name: AD_DA Firewall Policy DNS Allow CLI 195 | na_ontap_command: 196 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service dns -allow-list "{{ fw_dns_allow_ip }}"'] 197 | hostname: "{{ hostname }}" 198 | username: "{{ username }}" 199 | password: "{{ password }}" 200 | https: true 201 | validate_certs: false 202 | - name: AD_DA LIF Services HTTPS Deny CLI 203 | na_ontap_command: 204 | command: ['network interface service-policy create -policy domain_access -allowed-addresses 127.0.0.1/32, ::1/128 -vserver "{{ domain_access_vserver }}" -services management-https'] 205 | privilege: advanced 206 | hostname: "{{ hostname }}" 207 | username: "{{ username }}" 208 | password: "{{ password }}" 209 | https: true 210 | validate_certs: false 211 | - name: AD_DA Firewall Policy NDMP Deny CLI 212 | na_ontap_command: 213 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service ndmp -allow-list 127.0.0.1/32, ::1/128'] 214 | hostname: "{{ hostname }}" 215 | username: "{{ username }}" 216 | password: "{{ password }}" 217 | https: true 218 | validate_certs: false 219 | - name: AD_DA Firewall Policy RSH Deny CLI 220 | na_ontap_command: 221 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service rsh -allow-list 127.0.0.1/32, ::1/128'] 222 | hostname: "{{ hostname }}" 223 | username: "{{ username }}" 224 | password: "{{ password }}" 225 | https: true 226 | validate_certs: false 227 | - name: AD_DA Firewall Policy SNMP Deny CLI 228 | na_ontap_command: 229 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service snmp -allow-list 127.0.0.1/32, ::1/128'] 230 | hostname: "{{ hostname }}" 231 | username: "{{ username }}" 232 | password: "{{ password }}" 233 | https: true 234 | validate_certs: false 235 | - name: AD_DA Firewall Policy TELNET Deny CLI 236 | na_ontap_command: 237 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service telnet -allow-list 127.0.0.1/32, ::1/128'] 238 | hostname: "{{ hostname }}" 239 | username: "{{ username }}" 240 | password: "{{ password }}" 241 | https: true 242 | validate_certs: false 243 | - name: AD_DA Firewall Policy NTP Allow CLI 244 | na_ontap_command: 245 | command: ['firewall policy create -vserver "{{ domain_access_vserver }}" -policy domain_access -service ntp -allow-list "{{ fw_ntp_allow_ip }}"'] 246 | hostname: "{{ hostname }}" 247 | username: "{{ username }}" 248 | password: "{{ password }}" 249 | https: true 250 | validate_certs: false 251 | - name: AD_DA LIF Services SSH Deny CLI 252 | na_ontap_command: 253 | command: ['network interface service-policy add-service -vserver "{{ domain_access_vserver }}" -policy domain_access -service management-ssh -allowed-addresses 127.0.0.1/32, ::1/128'] 254 | privilege: advanced 255 | hostname: "{{ hostname }}" 256 | username: "{{ username }}" 257 | password: "{{ password }}" 258 | https: true 259 | validate_certs: false 260 | - name: AD_DA LIF Services data-cifs Allow CLI 261 | na_ontap_command: 262 | command: ['network interface service-policy add-service -vserver "{{ domain_access_vserver }}" -policy domain_access -service data_core -allowed-addresses "{{ data_core_cifs_allow_ip }}"'] 263 | privilege: advanced 264 | hostname: "{{ hostname }}" 265 | username: "{{ username }}" 266 | password: "{{ password }}" 267 | https: true 268 | validate_certs: false 269 | - name: Create AD_DA LIF Failover Group Node01 Target CLI 270 | na_ontap_command: 271 | command: ['network interface failover-groups create -vserver "{{ domain_access_vserver }}" -failover-group da_fail_grp1 -targets "{{ node01_da_failover_target_port }}"'] 272 | hostname: "{{ hostname }}" 273 | username: "{{ username }}" 274 | password: "{{ password }}" 275 | https: true 276 | validate_certs: false 277 | - name: Create AD_DA LIF Failover Group Node02 Target CLI 278 | na_ontap_command: 279 | command: ['network interface failover-groups create -vserver "{{ domain_access_vserver }}" -failover-group da_fail_grp1 -targets "{{ node02_da_failover_target_port }}"'] 280 | hostname: "{{ hostname }}" 281 | username: "{{ username }}" 282 | password: "{{ password }}" 283 | https: true 284 | validate_certs: false 285 | - name: Create AD_DA LIF 286 | na_ontap_interface: 287 | state: present 288 | interface_name: lif_domain_access 289 | role: data 290 | protocols: cifs 291 | home_node: "{{ node01_name }}" 292 | home_port: "{{ node01_da_lif_home_port }}" 293 | address: "{{ lif_da_ip }}" 294 | netmask: "{{ lif_da_mask }}" 295 | admin_status: up 296 | firewall_policy: domain_access 297 | is_auto_revert: true 298 | vserver: "{{ domain_access_vserver }}" 299 | hostname: "{{ hostname }}" 300 | username: "{{ username }}" 301 | password: "{{ password }}" 302 | https: true 303 | validate_certs: false 304 | - name: Assign AD_DA LIF Services Policy to domain access Lif CLI 305 | na_ontap_command: 306 | command: ['net interface modify -vserver "{{ domain_access_vserver }}" -lif lif_domain_access -service-policy domain_access'] 307 | privilege: advanced 308 | hostname: "{{ hostname }}" 309 | username: "{{ username }}" 310 | password: "{{ password }}" 311 | https: true 312 | validate_certs: false 313 | - name: Add AD_DA LIF to Failover Group da_fail_grp1 CLI 314 | na_ontap_command: 315 | command: ['network interface modify -vserver "{{ domain_access_vserver }}" -lif lif_domain_access -failover-group da_fail_grp1'] 316 | hostname: "{{ hostname }}" 317 | username: "{{ username }}" 318 | password: "{{ password }}" 319 | https: true 320 | validate_certs: false 321 | - name: Add AD_DA DNS Name Server IP address 322 | na_ontap_dns: 323 | state: present 324 | vserver: "{{ domain_access_vserver }}" 325 | domains: "{{ da_dns_domain_name }}" 326 | nameservers: "{{ da_dns_ip }}" 327 | hostname: "{{ hostname }}" 328 | username: "{{ username }}" 329 | password: "{{ password }}" 330 | https: true 331 | validate_certs: false 332 | - name: Join AD_DA SVM to CIFS Domain 333 | na_ontap_cifs_server: 334 | state: present 335 | cifs_server_name: "{{ da_cifs_server_name }}" 336 | vserver: "{{ domain_access_vserver }}" 337 | admin_password: "{{ da_ad_domain_passwd }}" 338 | admin_user_name: "{{ da_ad_domain_user_name }}" 339 | domain: "{{ da_dns_domain_name }}" 340 | service_state: started 341 | ou: "{{ da_ad_ou_name }}" 342 | hostname: "{{ hostname }}" 343 | username: "{{ username }}" 344 | password: "{{ password }}" 345 | https: true 346 | validate_certs: false 347 | - name: Enable Domain Tunnel Login for DA SVM CLI 348 | na_ontap_command: 349 | command: ['security login domain-tunnel create -vserver "{{ domain_access_vserver }}"'] 350 | hostname: "{{ hostname }}" 351 | username: "{{ username }}" 352 | password: "{{ password }}" 353 | https: true 354 | validate_certs: false 355 | - name: Create NTP server 356 | na_ontap_ntp: 357 | state: present 358 | version: auto 359 | server_name: "{{ ntp_server_ip }}" 360 | hostname: "{{ hostname }}" 361 | username: "{{ username }}" 362 | password: "{{ password }}" 363 | https: true 364 | validate_certs: false 365 | - name: Modify SSH timeouts CLI 366 | na_ontap_command: 367 | command: ['system timeout modify -timeout 10'] 368 | hostname: "{{ hostname }}" 369 | username: "{{ username }}" 370 | password: "{{ password }}" 371 | https: true 372 | validate_certs: false 373 | - name: Add Syslog Server CLI 374 | na_ontap_command: 375 | command: ['event destination modify -name allevents -syslog "{{ syslog_server }}"'] 376 | hostname: "{{ hostname }}" 377 | username: "{{ username }}" 378 | password: "{{ password }}" 379 | https: true 380 | validate_certs: false 381 | - name: Send all EMS events to Syslog Server CLI 382 | na_ontap_command: 383 | command: ['event route add-destinations -messagename * -destinations allevents'] 384 | hostname: "{{ hostname }}" 385 | username: "{{ username }}" 386 | password: "{{ password }}" 387 | https: true 388 | validate_certs: false 389 | - name: Create admin_ssh default 390 | na_ontap_user_role: 391 | state: present 392 | name: admin_ssh 393 | command_directory_name: DEFAULT 394 | access_level: all 395 | vserver: "{{ admin_vserver }}" 396 | hostname: "{{ hostname }}" 397 | username: "{{ username }}" 398 | password: "{{ password }}" 399 | https: true 400 | validate_certs: false 401 | - name: Create admin_ssh SP deny 402 | na_ontap_user_role: 403 | state: present 404 | name: admin_ssh 405 | command_directory_name: system node service-processor 406 | access_level: none 407 | vserver: "{{ admin_vserver }}" 408 | hostname: "{{ hostname }}" 409 | username: "{{ username }}" 410 | password: "{{ password }}" 411 | https: true 412 | validate_certs: false 413 | - name: Modify Admin SSH role CLI 414 | na_ontap_command: 415 | command: ['security login role config modify -role admin_ssh -vserver "{{ admin_vserver }}" -username-alphanum disabled -passwd-minlength 14 -passwd-alphanum enabled -passwd-min-special-chars 1 -passwd-expirty-time 60 -require-initial-passwd-update enabled -max-failed-login-attempts 3 -lockout-duration 60 -disallwed-reuse 24 -change-delay 1 -username-minlength 4'] 416 | hostname: "{{ hostname }}" 417 | username: "{{ username }}" 418 | password: "{{ password }}" 419 | https: true 420 | validate_certs: false 421 | - name: Create Emergency User for Console access 422 | na_ontap_user: 423 | state: present 424 | name: "{{ emergency_user_name }}" 425 | application: console 426 | authentication_method: password 427 | set_password: "{{ emergency_user_password }}" 428 | lock_user: True 429 | role_name: admin 430 | vserver: "{{ admin_vserver }}" 431 | hostname: "{{ hostname }}" 432 | username: "{{ username }}" 433 | password: "{{ password }}" 434 | https: true 435 | validate_certs: false 436 | - name: Add Emergency User for SP access 437 | na_ontap_user: 438 | state: present 439 | name: "{{ emergency_user_name }}" 440 | application: service-processor 441 | authentication_method: password 442 | set_password: "{{ emergency_user_password }}" 443 | lock_user: True 444 | role_name: admin 445 | vserver: "{{ admin_vserver }}" 446 | hostname: "{{ hostname }}" 447 | username: "{{ username }}" 448 | password: "{{ password }}" 449 | https: true 450 | validate_certs: false 451 | - name: Create AD DA User 452 | na_ontap_user: 453 | state: present 454 | name: "{{ ad_da_user_name }}" 455 | application: ssh 456 | authentication_method: domain 457 | set_password: "{{ emergency_user_password }}" 458 | lock_user: True 459 | role_name: admin_ssh 460 | vserver: "{{ admin_vserver }}" 461 | hostname: "{{ hostname }}" 462 | username: "{{ username }}" 463 | password: "{{ password }}" 464 | https: true 465 | validate_certs: false 466 | - name: Disable Web Access 467 | na_ontap_command: 468 | command: ['security login lock -vserver "{{ admin_vserver }}" -username admin'] 469 | hostname: "{{ hostname }}" 470 | username: "{{ username }}" 471 | password: "{{ password }}" 472 | https: true 473 | validate_certs: false 474 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tests/._inventory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/tests/._inventory -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tests/._test.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/tests/._test.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tests/inventory: -------------------------------------------------------------------------------- 1 | localhost 2 | 3 | -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | remote_user: root 4 | roles: 5 | - nar_ontap_security_ucd_guide -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/vars/._main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/nar_ontap_security_ucd_guide/vars/._main.yml -------------------------------------------------------------------------------- /nar_ontap_security_ucd_guide/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for nar_ontap_security_ucd_guide -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetApp/ansible/8aaf420e732664903e088599db6a970616c2fc10/tasks/main.yml --------------------------------------------------------------------------------