diff --git a/.gitignore b/.gitignore index e65cca735..13250fe70 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ demos/servicenow/closed_loop_incident_mgmt/snow_demo2/snow_vars.yaml provisioner/roles/ansible_security.ids_config/ provisioner/roles/ansible_security.ids_install/ provisioner/roles/geerlingguy.repo-epel/ +.pyc +.swp diff --git a/README.md b/README.md index 620023325..3f98ca6aa 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,10 @@ The Red Hat Ansible Automation Workshops project is intended for effectively dem - [Vagrant Demo](vagrant-demo) - Self-paced networking exercises that can be run on your personal laptop +# Demos + + - [Demos](demos) - These demos are intended for effectively demonstrating Ansible capabilities with prescriptive guides on the Ansible Automation Workshop infrastructure. + # DOCUMENTATION: - [How to contribute](docs/contribute.md) diff --git a/_config.yml b/_config.yml index fdf220460..080793927 100644 --- a/_config.yml +++ b/_config.yml @@ -2,7 +2,6 @@ theme: jekyll-theme-dinky include: - "provisioner/README.md" exclude: - - "demos/*" - "provisioner/roles" - "provisioner/group_vars" - "provisioner/inventory" diff --git a/demos/README.md b/demos/README.md new file mode 100644 index 000000000..a56de3d69 --- /dev/null +++ b/demos/README.md @@ -0,0 +1,12 @@ +# Demos + +These demos are built for https://github.com/ansible/workshops. To use the demo it is recommended to run the [provisioner](../provisioner/README.md) for the correct **workshop_type**. By standardizing demos on a Ansible Workshop **workbench** it is easier to test and verify demos are always working. Feel free re-use any component of this demo but this demo is only supported in this fashion. + +| Demo Category | Brief Description | +|---|---| +| [ChatOps](chatops) | The objective of this demo is showcase Ansible integrating with a chat tool like "Slack" as an interface to the managed network devices. | +| [networking](networking) | Various Ansible Network Automation demos for the `workshop_type: networking`. These are meant to show off various network automation features and functions. **Note** There may be other demos that require the `workshop_type: networking` but these are meant to be exclusively "show and tell" for network automation features versus interoperability or integration with another tool. | +| [Ansible + ServiceNow](servicenow) | These demos are intended for effectively demonstrating Ansible + ServiceNow capabilities with prescriptive guides on the Ansible Automation Workshop infrastructure. | + +--- +![Red Hat Ansible Automation](../images/rh-ansible-automation.png) diff --git a/demos/chatops/.gitignore b/demos/chatops/.gitignore deleted file mode 100644 index 63ba7c9c7..000000000 --- a/demos/chatops/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.retry -.pyc -.swp diff --git a/demos/chatops/README.md b/demos/chatops/README.md index f295c11ff..b8b1f0a66 100644 --- a/demos/chatops/README.md +++ b/demos/chatops/README.md @@ -1,14 +1,15 @@ -# CHATOPS DEMO +# CHATOPS DEMO + The objective of this demo is to familiarize the network engineer with integrating a chat tool like "Slack" as an interface to the managed network devices. **AUDIENCE**: Network engineers/systems engineers trying to integrate slack into their day-to-day operations to manage end devices **USE CASE**: The scenario for this demo is as follows :- - 1. Network engineer gets a ticket from her customer requesting to open TCP/UDP/IP traffic from source IP (A) to destination IP (B) on some destination port X. - + 1. Network engineer gets a ticket from her customer requesting to open TCP/UDP/IP traffic from source IP (A) to destination IP (B) on some destination port X. + 2. The first step in the manual process is for the network engineer to crawl through devices in the path between A and B and check whether the traffic is already permitted. - + 3. Allow/Disallow the traffic per IT policy In particular, we will use Ansible and Slack to automate step 2 via this demo. @@ -73,7 +74,7 @@ Add an "interactive component". This is the URI invoked (HTTP POST), when the fo ![](./images/interactive2.png) -Similar to the previous step, add a url that contains the public IP/DNS name of the tower instance provisioned per the pre-requisites. +Similar to the previous step, add a url that contains the public IP/DNS name of the tower instance provisioned per the pre-requisites. >Note 1: The app server is preconfigured to listen on port 8888. Ensure that the URL is constructed with that port number. For example: http://34.207.200.32:8888/interactive or http://student11.mydemo.rhdemo.io:8888/collect-data >Note 2: Use a meaningful URI for the interactive component and make sure to note down the name. We will need this later. @@ -91,7 +92,7 @@ Incoming webhooks allow the tower job to communicate back into the slack channel ### STEP 5: Create the bot -Next create the bot associated with this app. +Next create the bot associated with this app. ![](./images/addbotuser1.png) @@ -99,13 +100,13 @@ Next create the bot associated with this app. ### STEP 6: Add the app to the slack channel created in step 1 -This step is done from within the slack client/browser +This step is done from within the slack client/browser ![](./images/add_app1.png) ![](./images/add_app2.png) -After adding the app, ensure that the slash command is now available (it shows up) +After adding the app, ensure that the slash command is now available (it shows up) ![](./images/add_app3.png) @@ -113,7 +114,7 @@ After adding the app, ensure that the slash command is now available (it shows u Finally, switch back to the app configuration in the browser and collect the App and Bot tokens. -For the App verification token, navigate to the "Basic Information" link +For the App verification token, navigate to the "Basic Information" link ![](./images/token.png) @@ -134,7 +135,7 @@ We will need this for our Python app to communicate with the slack app/bot. [student2@ansible ~]$ cd ~/demos/chatops/demo_setup/ [student2@ansible demo_setup]$ pwd /home/student2/demos/chatops/demo_setup -[student2@ansible demo_setup]$ +[student2@ansible demo_setup]$ ``` 2. Edit/Create a file called `input_vars.yaml` and add the information collected in the previous steps into this file: @@ -189,11 +190,11 @@ ok: [localhost] At this point, the demo should be all set up to work. Test this by going to the slack channel and using the "slash" command you created. -![](./images/demo1.png ) +![](./images/demo1.png ) Enter the following values to test this: -![](./images/demo2.png ) +![](./images/demo2.png ) This fires of an Ansible Tower job for you! @@ -212,5 +213,5 @@ This playbook runs and generates a report that is then sent back to the Slack ch ## Conclusion -Feel free to login to the routers and add additional acls entries and test them via the slack interface. +Feel free to login to the routers and add additional acls entries and test them via the slack interface. This demo shows you how flexible Ansible Tower can be for integrating with modern DevOps tools and interaction tools like Slack, allowing network administrators to literally "Chat" with their managed end points. diff --git a/demos/networking/README.md b/demos/networking/README.md new file mode 100644 index 000000000..3d3b0576f --- /dev/null +++ b/demos/networking/README.md @@ -0,0 +1,3 @@ +# Networking Demos + +For now, please refer to the github link: [https://github.com/ansible/workshops/tree/master/demos/networking](https://github.com/ansible/workshops/tree/master/demos/networking) diff --git a/demos/dmvpn/ios_hub.j2 b/demos/networking/dmvpn/ios_hub.j2 similarity index 100% rename from demos/dmvpn/ios_hub.j2 rename to demos/networking/dmvpn/ios_hub.j2 diff --git a/demos/servicenow/1-config-drift/README.md b/demos/servicenow/1-config-drift/README.md index 5e340cf9d..3899884f4 100644 --- a/demos/servicenow/1-config-drift/README.md +++ b/demos/servicenow/1-config-drift/README.md @@ -1,95 +1,47 @@ -# ServiceNow Demo for Linklight +# Ansible + ServiceNow - Config Drift -## Table of Contents - - [Setup](#setup) - - [Demo 01 - Config Drift](#Demo-01-Config-Drift) - - [Explanation](#explanation) - -## Setup - - - Setup a free account - https://developer.servicenow.com/ - - - Click **Manage** and create an instance - - ![manage](images/manage.png) - - A URL will be provided like ```https://dev66073.service-now.com/``` - - - Login to your WebURL and reset your password. - ![snow](images/snow.png) - - - Record these three pieces of information that will provide authentication. - - | Field | Input | - | -------- |:--------------------| - | username | admin | - | password | ThisIsAFakePassword | - | instance | dev66073 | - - **Tip 1** the instance is part the webURL e.g. https://dev66073.service-now.com/ is `dev66073` - - **Tip 2** the password is **not** the same as your password to login to https://developer.servicenow.com/. To reset it click on **Action** and then **Reset admin password** - - ![reset](images/reset.png) - - - Install pysnow - https://pysnow.readthedocs.io/en/latest/ - - ```$ pip install pysnow``` - - **Tip** When using Tower, use [this guide](https://docs.ansible.com/ansible-tower/latest/html/upgrade-migration-guide/virtualenv.html). Tower uses a virtualenv so the install changes slightly: - - ``` - # source /var/lib/awx/venv/ansible/bin/activate - # umask 0022 - # pip install pysnow - # deactivate - -## Demo 01 - Config Drift - -### Objective +# Objective Demonstrate automatic ticket creation for configuration drift. When the configuration for a Cisco CSR router doesn't match desired config, a ServiceNow ticket with relevant information will be created. -### Guide +- Ansible Playbook will check for desired configuration on rtr1 +- The configuration is missing, which generates a Service Now ticket indicating rtr1 is out of compliance. -#### Preface - -This demo is built for the Linklight workbench. To use the demo it is recommended to run the [provisioner](../../provisioner/README.md) for **networking mode**. By standardizing demos on the Linklight workbench it is easier to test and verify demos are always working. Feel free re-use any component of this demo but this demo is only supported in this fashion. - -#### Overview - -- Playbook will check for desired configuration on rtr1 +## Table of Contents -- The configuration is missing which generates a Service Now ticket indicating rtr1 is out of compliance. +- [Step 1 - Connect to workbench](#step-1---connect-to-workbench) +- [Step 2 - Provide ServiceNow credentials](#step-2---provide-servicenow-credentials) +- [Step 3 - Execute Ansible Playbook](#step-3---execute-ansible-playbook) +- [Step 4 - Show ServiceNow incidents](#step-4---show-servicenow-incidents) +- [Explanation](#explanation) -#### Step 1 +## Step 1 - Connect to workbench -Connect to the Linklight workbench: +Connect to the workshop workbench: ``` -[user@RHEL ~]$ ssh student1@X.X.X.X -student1@X.X.X.X's password: +[user@RHEL ~]$ ssh student1@student1.workshop.rhdemo.io +student1@student1.workshop.rhdemo.io's password: + ``` -Move into the `demos/servicenow` directory. +Move into the `demos/servicenow/1-config-drift` directory. ``` [student1@ansible ~]$ -[student1@ansible ~]$ cd demos/servicenow +[student1@ansible ~]$ cd ~/demos/servicenow/1-config-drift ``` -#### Step 2 +## Step 2 - Provide ServiceNow credentials -Define the login information (username, password and instance) as defined in the [Setup](#setup). Fill this information out in `login_info.yml` with your text editor of choice. +Define the login information (username, password and instance) as defined in the [Common Setup](../README.md). Fill this information out in `login_info.yml` with your text editor of choice. ``` [student1@ansible ~]$ nano login_info.yml ``` -#### Step 3 +## Step 3 - Execute Ansible Playbook Run the `config_drift.yml` playbook: @@ -97,9 +49,9 @@ Run the `config_drift.yml` playbook: [student1@ansible ~]$ ansible-playbook config_drift.yml ``` -![snow](images/snow.gif) +![snow](../images/snow.gif) -#### Step 3 +# Step 4 - Show ServiceNow incidents - Login to the Web URL e.g. `https://dev66073.service-now.com/` @@ -107,9 +59,9 @@ Run the `config_drift.yml` playbook: - The Incident just created will show up at the top of the list, assigned to the `System Administrator` which is the default user for the ServerNow developer instance. - Scroll down to to read the `Short Desription` and the `Additional Comments`. -![snow](images/gui.gif) +![snow](../images/gui.gif) -#### Explanation +## Explanation The Ansible Playbook runs a task to configure a Cisco CSR router. @@ -168,4 +120,7 @@ Here is a snippet of ServiceNow task: The block uses the conditional `when` to only run if the previous task **changed**. This means a ServiceNow ticket is only generated if the task actually reports changed. -# End of Demo +## End of Demo + +--- +![Red Hat Ansible Automation](../../../images/rh-ansible-automation.png) diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/README.md b/demos/servicenow/2-closed_loop_incident_mgmt/README.md index 6eab8e464..c46fe1fcf 100644 --- a/demos/servicenow/2-closed_loop_incident_mgmt/README.md +++ b/demos/servicenow/2-closed_loop_incident_mgmt/README.md @@ -1,106 +1,69 @@ -# ServiceNow Demo for Linklight +# Ansible + ServiceNow - Closed Loop Incident Management -#### Preface +For a short video overview of this demonstration please refer to this YouTube video: [https://youtu.be/TkXRj4w2G2Y](https://youtu.be/TkXRj4w2G2Y) -This demo is built for the Linklight workbench. To use the demo it is recommended to run the [provisioner](../../provisioner/README.md) for **networking mode**. By standardizing demos on the Linklight workbench it is easier to test and verify demos are always working. Feel free re-use any component of this demo but this demo is only supported in this fashion. +# Objective +Demonstrate a closed loop incident management scenario. - -## Demo 02 - Closed Loop Incident Management - -### Objective - -Demonstrate a closed loop incident management scenario. -1. Check devices for compliance. When a device does not meet compliance requirements, a ServiceNow ticket with relevant information will be created. - +1. Check devices for compliance. When a device does not meet compliance requirements, a ServiceNow ticket with relevant information will be created. 2. The ticketing system has business logic to automatically fix bespoke incidents - in this case, a device that is out of compliance should be brought into compliance. ServiceNow will call out to Tower to use automation and fix the incident. +3. The Ansible Tower automation job will bring the device into compliance and then reach out to ServiceNow to resolve and close out the ticket -3. The Tower automation job will bring the device into compliance and then reach out to ServiceNow to resolve and close out the ticket - -Thus a BSS system is able to maintain a statement of record while automatically fixing incidents at the same time. +Thus a BSS (Business Services System) is able to maintain a statement of record while automatically fixing incidents at the same time. -## Setup -#### Step 1 - - Setup a free account - https://developer.servicenow.com/ +## Table of Contents - - Click **Manage** and create an instance +- [Step 1 - Connect to workbench](#step-1---connect-to-workbench) +- [Step 2 - Provide ServiceNow credentials](#step-2---provide-servicenow-credentials) +- [Step 3 - Run demo setup playbook](#step-3---run-demo-setup-playbook) - ![manage](../images/manage.png) +- [Explanation](#explanation) - A URL will be provided like ```https://dev66073.service-now.com/``` +## Step 1 - Connect to workbench - - Login to your WebURL and reset your password. - ![snow](../images/snow.png) +Connect to the workshop workbench: - - Record these three pieces of information that will provide authentication. - - | Field | Input | - | -------- |:--------------------| - | username | admin | - | password | ThisIsAFakePassword | - | instance | dev66073 | +``` +[user@RHEL ~]$ ssh student1@student1.workshop.rhdemo.io +student1@student1.workshop.rhdemo.io's password: - **Tip 1** the instance is part the webURL e.g. https://dev66073.service-now.com/ is `dev66073` +``` - **Tip 2** the password is **not** the same as your password to login to https://developer.servicenow.com/. To reset it click on **Action** and then **Reset admin password** +Move into the `demos/servicenow/1-config-drift` directory. - ![reset](../images/reset.png) - - -#### Step 2 - - Install pysnow on the control node - https://pysnow.readthedocs.io/en/latest/ +``` +[student1@ansible ~]$ +[student1@ansible ~]$ cd ~/demos/servicenow/2-closed_loop_incident_mgmt +``` - ``` - # source /var/lib/awx/venv/ansible/bin/activate - # umask 0022 - # pip install pysnow - # deactivate - ``` -#### Step 3 +## Step 2 - Provide ServiceNow credentials -Navigate to the demo directory (~/demos/servicenow/close_loop_incident_mgmt) and update the following files with the relevant data: +Define the login information (username, password and instance) as defined in the [Common Setup](../README.md). Fill this information out in `login_info.yml` with your text editor of choice. -1. `input_vars.yaml` : Update this with the tower admin username and password for your tower instance -*Example data:* - -```yaml ---- -tower_username: admin -tower_password: ansible ``` - - -2. `./snow_demo2/snow_vars.yaml`: Update this with the details you recorded while creating the instance - -*Example input:* -```yaml ---- -SN_USERNAME: admin -SN_PASSWORD: ThisIsafakepassword -SN_INSTANCE: dev66073 +[student1@ansible ~]$ nano login_info.yml ``` - -#### Step 4 -Run the `demo_setup.yaml` playbook as follows. This will create the necessary job templates for the demo in your tower instance: +## Step 3 - Run demo setup playbook + +Run the `demo_setup.yml` playbook as follows. This will create the necessary job templates for the demo in your tower instance: -``` shell -[student1@ansible closed_loop_incident_mgmt]$ ansible-playbook demo_setup.yaml -e @input_vars.yaml +``` +[student1@ansible closed_loop_incident_mgmt]$ ansible-playbook demo_setup.yml ``` After this step, log into your tower instance and verify that the 2 "SNOW" job templates are present: -![](../images/job_templates.png) +![relevant job template picture](../images/job_templates.png) -#### Step 5 +## Step 5 > *Extremely important: Make sure you use FQDNs that have valid SSL certs for the demo to work* -Navigate to the API URI (api/v2/job_templates/) of your tower instance. For example: https://student1.snow-demo.redhatgov.io/api/v2/job_templates/ and identify the API endpoint for the **SNOW-Demo-Compliance-Fix** job template. +Navigate to the API URI (api/v2/job_templates/) of your tower instance. For example: https://student1.snow-demo.redhatgov.io/api/v2/job_templates/ and identify the API endpoint for the **SNOW-Demo-Compliance-Fix** job template. For example, it is https://student1.snow-demo.redhatgov.io/api/v2/job_templates/8 in my instance. @@ -108,8 +71,8 @@ Adding a "launch" URI will make this template executable remotely. Record this U -#### Step 5 -Now, in your servicenow instance, navigate to **System Web Services >> Outbound >> REST Message** +## Step 5 +Now, in your servicenow instance, navigate to **System Web Services >> Outbound >> REST Message** > You can also use the search bar at the top left and search for "rest message" @@ -118,7 +81,7 @@ Now, in your servicenow instance, navigate to **System Web Services >> Outbound - Click on *New* at the top of the page: ![](../images/newrest.png) - + - Give it a name and set the endpoint to the URL we captured in the previous step. - Under the *Authentication* tab, chose "Basic" Authentication type. - For the Basic auth profile, click on the search bar. This will open yet another window. Click on new and add your Tower instance' login information @@ -138,16 +101,16 @@ Now, in your servicenow instance, navigate to **System Web Services >> Outbound > The extra_vars is how the Service Now API is going to pass the incident number information to the Tower instance - Click on the *Auto-generate variable* link ![](../images/rest_setup6.png) - + - Click the *Preview Script Usage* link at the bottom and copy the contents. ![](../images/rest_setup7.png) - + ```javascript - try { + try { var r = new sn_ws.RESTMessageV2('Tower Job to fix compliance issues', 'Launch compliance fix'); r.setStringParameterNoEscape('INC', ''); -//override authentication profile +//override authentication profile //authentication type ='basic'/ 'oauth2' //r.setAuthentication(authentication type, profile name); @@ -169,11 +132,11 @@ catch(ex) { ``` - + - Click submit - - -#### Step 6 + + +## Step 6 - Navigate to **System Definition >> Business Rules** and click on *New* to add a new business rule ![](../images/business_rule1.png) @@ -181,30 +144,17 @@ catch(ex) { - Click on the *Advanced* checkbox to enable the *Advanced* Tab ![](../images/business_rule2.png) > NOTE: Ensure that the Business rule is run **after** the ticket is inserted into the incidents table (see screencap above for all dropdowns and checkboxes) - - + + ** If you have used the exact naming conventions in this README, you can copy and paste the following into the *Advanced* tab.** -``` javascript +```javascript (function executeRule(current, previous /*null when async*/) { - // Add your code here - try { + try { var r = new sn_ws.RESTMessageV2('Tower Job to fix compliance issues', 'Launch compliance fix'); r.setStringParameterNoEscape('INC', current.number); -//override authentication profile -//authentication type ='basic'/ 'oauth2' -//r.setAuthentication(authentication type, profile name); - -//set a MID server name if one wants to run the message on MID -//r.setMIDServer('MY_MID_SERVER'); - -//if the message is configured to communicate through ECC queue, either -//by setting a MID server or calling executeAsync, one needs to set skip_sensor -//to true. Otherwise, one may get an intermittent error that the response body is null -//r.setEccParameter('skip_sensor', true); - var response = r.execute(); var responseBody = response.getBody(); var httpStatus = response.getStatusCode(); @@ -223,20 +173,18 @@ catch(ex) { - Click "Submit" -## Running the Demo +# Running the Demo -### Animation of the Demo +Reminder, for a short video overview of this demonstration please refer to this YouTube video: [https://youtu.be/TkXRj4w2G2Y](https://youtu.be/TkXRj4w2G2Y) -![](../images/closed_loop_snow.gif) - -#### Step 1 +## Step 1 Ensure that the router does not have a current banner (required condition for the device to be out of compliance: ``` -[student1@ansible closed_loop_incident_mgmt]$ ssh rtr1 +[student1@ansible]$ ssh rtr1 rtr1# @@ -247,7 +195,7 @@ rtr1# > If there is an existing banner you can use the `no banner login` command in config mode to remove it -#### Step 2 +## Step 2 Log into the Tower instance and launch the "SNOW-Demo-Compliance-Check" Template >Observe the following 2 tasks as that template runs @@ -264,20 +212,20 @@ ok: [rtr1] => { ``` -#### Step 3 +## Step 3 Switch over to the ServiceNow instance and see that the ticket number as see in the previous output has been created. ![](../images/incident_1.png) -#### Step 4 +## Step 4 -Switch back to the Ansible Tower Jobs and click on the "SNOW-Demo-Compliance-Fix" Job +Switch back to the Ansible Tower Jobs and click on the "SNOW-Demo-Compliance-Fix" Job >Observe that after sleeping for 180s, the job will fix the issue on the router, resolve and close out the ticket -``` +``` TASK [sleep for 180 seconds and continue with play] **************************** ok: [rtr1 -> localhost] TASK [CONFIGURE THE LOGIN BANNER] ********************************************** @@ -289,7 +237,7 @@ changed: [rtr1] ``` -#### Step 5 +## Step 5 Log back into the router and see that you are greeted with the new banner: @@ -305,13 +253,6 @@ rtr1# ``` -#### Step 6 +## Step 6 Finally log back into servicenow to notice the history of the ticket ![](../images/incident_2.png) - - - - - - - diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/injector.yml b/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/injector.yml new file mode 100644 index 000000000..810e0c3a5 --- /dev/null +++ b/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/injector.yml @@ -0,0 +1,8 @@ +env: + SN_INSTANCE: '{{instance}}' + SN_PASSWORD: '{{password}}' + SN_USERNAME: '{{username}}' +extra_vars: + SN_INSTANCE: '{{instance}}' + SN_PASSWORD: '{{password}}' + SN_USERNAME: '{{username}}' diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/inputs.yml b/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/inputs.yml new file mode 100644 index 000000000..06a4e3cdc --- /dev/null +++ b/demos/servicenow/2-closed_loop_incident_mgmt/custom_cred/inputs.yml @@ -0,0 +1,11 @@ +fields: + - type: string + id: username + label: SN_USERNAME + - secret: true + type: string + id: password + label: SN_PASSWORD + - type: string + id: instance + label: SN_INSTANCE diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yaml deleted file mode 100644 index 08b6bd3a1..000000000 --- a/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yaml +++ /dev/null @@ -1,118 +0,0 @@ ---- -- name: SETUP TOWER FOR CLOSED LOOP INCIDENT MGMT DEMO - hosts: cisco - connection: local - become: yes - gather_facts: no - - tasks: - - - name: MOVE THE PLAYBOOK TO VAR/LIB - copy: - src: ./snow_demo2 - dest: /var/lib/awx/projects/ - become: yes - become_method: sudo - become_user: awx - run_once: true - delegate_to: localhost - - - name: CREATE INVENTORY - tower_inventory: - name: "SNOW_CL Inventory" - organization: Default - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - variables: "{{ lookup('file', './snow_demo2/snow_vars.yaml') }}" - run_once: true - delegate_to: localhost - - - name: ADD HOST INTO TOWER INVENTORY - tower_host: - name: "{{ inventory_hostname }}" - inventory: "SNOW_CL Inventory" - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - variables: - ansible_network_os: "{{ansible_network_os}}" - ansible_host: "{{ansible_host}}" - ansible_user: "{{ansible_user}}" - private_ip: "{{private_ip}}" - - - name: ADD GROUP INTO TOWER INVENTORY - tower_group: - name: "cisco" - inventory: "SNOW_CL Inventory" - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - source: manual - run_once: true - delegate_to: localhost - - - - name: ADD CREDENTIAL INTO TOWER - tower_credential: - name: SNOW_CL Credential - ssh_key_data: "/home/{{ansible_user}}/.ssh/aws-private.pem" - kind: ssh - organization: Default - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - run_once: true - delegate_to: localhost - - - - name: ADD PROJECT TO TOWER - tower_project: - name: SNOW_CL - local_path: snow_demo2 - organization: Default - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - run_once: true - delegate_to: localhost - - - - name: ADD A JOB TEMPLATE - COMPLIANCE CHECK - tower_job_template: - name: "SNOW-Demo-Compliance-Check" - job_type: run - inventory: "SNOW_CL Inventory" - project: "SNOW_CL" - playbook: snow_incident.yaml - credential: "SNOW_CL Credential" - state: "present" - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - run_once: true - delegate_to: localhost - - - name: ADD A JOB TEMPLATE - COMPLIANCE FIX - tower_job_template: - name: "SNOW-Demo-Compliance-Fix" - job_type: run - inventory: "SNOW_CL Inventory" - project: "SNOW_CL" - playbook: fix_banner.yaml - credential: "SNOW_CL Credential" - state: "present" - tower_username: "{{ tower_username }}" - tower_password: "{{ tower_password }}" - tower_host: https://localhost - tower_verify_ssl: no - ask_extra_vars: True - extra_vars_path: ./snow_demo2/extra_vars.yaml - run_once: true - delegate_to: localhost diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yml b/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yml new file mode 100644 index 000000000..c806f6808 --- /dev/null +++ b/demos/servicenow/2-closed_loop_incident_mgmt/demo_setup.yml @@ -0,0 +1,89 @@ +--- +- name: SETUP TOWER FOR CLOSED LOOP INCIDENT MGMT DEMO + hosts: ansible + connection: local + become: yes + gather_facts: no + vars: + tower_username: "admin" + tower_password: "ansible" + + tasks: + - name: import login credentials for servicenow + include_vars: "{{lookup('first_found', login_info)}}" + vars: + login_info: + - 'private.yml' + - 'login_info.yml' + + - name: move playbooks to /var/lib/awx/projects/snow_demo + copy: + src: "{{playbook_dir}}/" + dest: /var/lib/awx/projects/snow_demo/ + become: yes + become_method: sudo + become_user: awx + run_once: true + delegate_to: localhost + + - name: add project to tower + tower_project: + name: SNOW_CL + local_path: snow_demo + organization: Default + tower_username: "{{ tower_username }}" + tower_password: "{{ tower_password }}" + tower_host: https://localhost + tower_verify_ssl: no + run_once: true + delegate_to: localhost + + - name: add servicenow custom cred + tower_credential_type: + name: "SNOW_CL Credential" + description: Credential type for SNOW + inputs: "{{ lookup('file', playbook_dir + '/custom_cred/inputs.yml') | from_yaml }}" + injectors: "{{ lookup('file', playbook_dir + '/custom_cred/injector.yml') | from_yaml }}" + state: present + kind: cloud + tower_username: "{{ tower_username }}" + tower_password: "{{ tower_password }}" + tower_host: https://localhost + validate_certs: false + + - name: Add Custom Credential + command: tower-cli credential create --name="SNOW Credential" --credential-type "SNOW_CL Credential" --inputs "{'username':'{{ username }}','password':'{{ password }}','instance':'{{ instance }}'}" -h https://localhost -u {{ tower_username }} -p {{ tower_password }} --organization Default --insecure + + - name: add job template - compliance check + tower_job_template: + name: "SNOW-Demo-Compliance-Check" + job_type: run + inventory: "Workshop Inventory" + project: "SNOW_CL" + playbook: snow_incident.yml + credential: "Workshop Credential" + state: "present" + tower_username: "{{ tower_username }}" + tower_password: "{{ tower_password }}" + tower_host: https://localhost + tower_verify_ssl: no + + - name: add job template - compliance fix + tower_job_template: + name: "SNOW-Demo-Compliance-Fix" + job_type: run + inventory: "Workshop Inventory" + project: "SNOW_CL" + playbook: fix_banner.yml + credential: "Workshop Credential" + state: "present" + tower_username: "{{ tower_username }}" + tower_password: "{{ tower_password }}" + tower_host: https://localhost + tower_verify_ssl: no + + - name: associate snow cred to check + command: tower-cli job_template associate_credential --job-template 'SNOW-Demo-Compliance-Check' --credential 'SNOW Credential' --insecure -h https://localhost -u {{ tower_username }} -p {{ tower_password }} --insecure + + - name: associate snow cred to check + command: tower-cli job_template associate_credential --job-template 'SNOW-Demo-Compliance-Fix' --credential 'SNOW Credential' --insecure -h https://localhost -u {{ tower_username }} -p {{ tower_password }} --insecure diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/extra_vars.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/extra_vars.yaml similarity index 100% rename from demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/extra_vars.yaml rename to demos/servicenow/2-closed_loop_incident_mgmt/extra_vars.yaml diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/fix_banner.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/fix_banner.yml similarity index 100% rename from demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/fix_banner.yaml rename to demos/servicenow/2-closed_loop_incident_mgmt/fix_banner.yml diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/input_vars.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/input_vars.yaml deleted file mode 100644 index 1888cff3d..000000000 --- a/demos/servicenow/2-closed_loop_incident_mgmt/input_vars.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -tower_username: admin -tower_password: ansible diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/login_info.yml b/demos/servicenow/2-closed_loop_incident_mgmt/login_info.yml new file mode 100644 index 000000000..16749c168 --- /dev/null +++ b/demos/servicenow/2-closed_loop_incident_mgmt/login_info.yml @@ -0,0 +1,3 @@ +username: admin +password: asdf +instance: dev1234 diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/snow_vars.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/snow_vars.yaml deleted file mode 100644 index 8ffa0e991..000000000 --- a/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/snow_vars.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -SN_USERNAME: admin -SN_PASSWORD: wZIVu5odJX1q -SN_INSTANCE: dev56779 diff --git a/demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/snow_incident.yaml b/demos/servicenow/2-closed_loop_incident_mgmt/snow_incident.yml similarity index 100% rename from demos/servicenow/2-closed_loop_incident_mgmt/snow_demo2/snow_incident.yaml rename to demos/servicenow/2-closed_loop_incident_mgmt/snow_incident.yml diff --git a/demos/servicenow/README.md b/demos/servicenow/README.md new file mode 100644 index 000000000..7287bd55a --- /dev/null +++ b/demos/servicenow/README.md @@ -0,0 +1,53 @@ +# Ansible + ServiceNow Demos + +These demos are intended for effectively demonstrating Ansible + ServiceNow capabilities with prescriptive guides on the Ansible Automation Workshop infrastructure. + +# Table of Contents + +- [Demo Catalog](#demo-catalog) +- [Common Setup](#common-setup) + +# Demo Catalog + +| Demo Name | Brief Description | Workshop Type | Uses Ansible Tower | +|---|---|---|---| +| [Config Drift](1-config-drift) | Demonstrate automatic ticket creation for configuration drift. When the configuration for a Cisco CSR router doesn't match desired config, a ServiceNow ticket with relevant information will be created. | `workshop_type: networking` | ✗ | +| [Closed Loop Incident Mgmt](2-closed-loop-incident-mgmt) | Ansible Tower will find the router that is out of compliance and open an incident in ServiceNow. ServiceNow will use a business rule to identify the newly opened incident, then kick off an Ansible Tower job to fix the issue. | `workshop_type: networking` | | + +## Common Setup + +You must have the following setup to deliver these demos: + +1. [A ServiceNow instance setup](#servicenow_setup) +2. The correct Ansible Workshop type provisioned (e.g. `workshop_type: networking`). Please refer to the table above for the corresponding `workshop_type`. + +## ServiceNow Setup + + - Setup a free account + https://developer.servicenow.com/ + + - Click **Manage** and create an instance + + ![manage](images/manage.png) + + A URL will be provided like ```https://dev66073.service-now.com/``` + + - Login to your WebURL and reset your password. + ![snow](images/snow.png) + + - Record these three pieces of information that will provide authentication. + + | Field | Input | + | -------- |:--------------------| + | username | admin | + | password | ThisIsAFakePassword | + | instance | dev66073 | + + **Tip 1** the instance is part the webURL e.g. https://dev66073.service-now.com/ is `dev66073` + + **Tip 2** the password is **not** the same as your password to login to https://developer.servicenow.com/. To reset it click on **Action** and then **Reset admin password** + + ![reset](images/reset.png) + +--- +![Red Hat Ansible Automation](../../images/rh-ansible-automation.png) diff --git a/demos/servicenow/images/closed_loop_snow.gif b/demos/servicenow/images/closed_loop_snow.gif deleted file mode 100644 index ebc9f8ee0..000000000 Binary files a/demos/servicenow/images/closed_loop_snow.gif and /dev/null differ diff --git a/exercises/ansible_f5/1.1-get-facts/README.md b/exercises/ansible_f5/1.1-get-facts/README.md index c882d3ab5..a5b645401 100644 --- a/exercises/ansible_f5/1.1-get-facts/README.md +++ b/exercises/ansible_f5/1.1-get-facts/README.md @@ -70,11 +70,12 @@ Next, add the first `task`. This task will use the `bigip_device_facts` module t bigip_device_facts: gather_subset: - system-info - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: 8443 - validate_certs: no + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no register: device_facts ``` {% endraw %} @@ -84,6 +85,7 @@ Next, add the first `task`. This task will use the `bigip_device_facts` module t - `name: COLLECT BIG-IP FACTS` is a user defined description that will display in the terminal output. - `bigip_device_facts:` tells the task which module to use. Everything except `register` is a module parameter defined on the module documentation page. - The `gather_subset: system_info` parameter tells the module only to grab system level information. +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with @@ -109,12 +111,13 @@ Next, add the second `task`. This task will use the `debug` module to print the bigip_device_facts: gather_subset: - system-info - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: 8443 - validate_certs: no - register: bigip_device_facts + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no + register: device_facts - name: DISPLAY COMPLETE BIG-IP SYSTEM INFORMATION debug: @@ -152,11 +155,12 @@ Finally lets add two more tasks to get more specific info from facts gathered. bigip_device_facts: gather_subset: - system-info - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: 8443 - validate_certs: no + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no register: device_facts - name: DISPLAY COMPLETE BIG-IP SYSTEM INFORMATION diff --git a/exercises/ansible_f5/1.1-get-facts/bigip-facts.yml b/exercises/ansible_f5/1.1-get-facts/bigip-facts.yml index 2d71b5b1c..989b6db7b 100755 --- a/exercises/ansible_f5/1.1-get-facts/bigip-facts.yml +++ b/exercises/ansible_f5/1.1-get-facts/bigip-facts.yml @@ -9,11 +9,12 @@ bigip_device_facts: gather_subset: - system-info - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: 8443 - validate_certs: no + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no register: device_facts - name: DISPLAY COMPLETE BIG-IP SYSTEM INFORMATION diff --git a/exercises/ansible_f5/1.2-add-node/README.md b/exercises/ansible_f5/1.2-add-node/README.md index 8b705cb55..84d21b313 100644 --- a/exercises/ansible_f5/1.2-add-node/README.md +++ b/exercises/ansible_f5/1.2-add-node/README.md @@ -58,13 +58,14 @@ Next, add the first `task`. This task will use the `bigip_node` module configure - name: CREATE NODES bigip_node: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no host: "{{hostvars[item].ansible_host}}" name: "{{hostvars[item].inventory_hostname}}" - validate_certs: "no" loop: "{{ groups['webservers'] }}" ``` @@ -74,6 +75,7 @@ Next, add the first `task`. This task will use the `bigip_node` module configure - `name: CREATE NODES` is a user defined description that will display in the terminal output. - `bigip_node:` tells the task which module to use. Everything except `loop` is a module parameter defined on the module documentation page. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with diff --git a/exercises/ansible_f5/1.2-add-node/bigip-node.yml b/exercises/ansible_f5/1.2-add-node/bigip-node.yml index fad9b971a..df565fef9 100755 --- a/exercises/ansible_f5/1.2-add-node/bigip-node.yml +++ b/exercises/ansible_f5/1.2-add-node/bigip-node.yml @@ -8,11 +8,12 @@ - name: CREATE NODES bigip_node: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no host: "{{hostvars[item].ansible_host}}" name: "{{hostvars[item].inventory_hostname}}" - validate_certs: "no" loop: "{{ groups['webservers'] }}" diff --git a/exercises/ansible_f5/1.3-add-pool/README.md b/exercises/ansible_f5/1.3-add-pool/README.md index ab8d7d9de..c67ee71cb 100644 --- a/exercises/ansible_f5/1.3-add-pool/README.md +++ b/exercises/ansible_f5/1.3-add-pool/README.md @@ -59,15 +59,16 @@ Next, add the first `task`. This task will use the `bigip_pool` module configure - name: CREATE POOL bigip_pool: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "http_pool" lb_method: "round-robin" monitors: "/Common/http" monitor_type: "and_list" - validate_certs: "no" ``` @@ -75,6 +76,7 @@ Next, add the first `task`. This task will use the `bigip_pool` module configure - `name: CREATE POOL` is a user defined description that will display in the terminal output. - `bigip_pool:` tells the task which module to use. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with diff --git a/exercises/ansible_f5/1.3-add-pool/bigip-pool.yml b/exercises/ansible_f5/1.3-add-pool/bigip-pool.yml index a7180fcf3..3e4bda130 100755 --- a/exercises/ansible_f5/1.3-add-pool/bigip-pool.yml +++ b/exercises/ansible_f5/1.3-add-pool/bigip-pool.yml @@ -8,12 +8,13 @@ - name: CREATE POOL bigip_pool: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "http_pool" lb_method: "round-robin" monitors: "/Common/http" monitor_type: "and_list" - validate_certs: "no" diff --git a/exercises/ansible_f5/1.4-add-pool-members/README.md b/exercises/ansible_f5/1.4-add-pool-members/README.md index bcae8b59a..5e66fa7cf 100644 --- a/exercises/ansible_f5/1.4-add-pool-members/README.md +++ b/exercises/ansible_f5/1.4-add-pool-members/README.md @@ -57,16 +57,17 @@ Next, add the first `task`. This task will use the `bigip_pool_member` module co - name: ADD POOL MEMBERS bigip_pool_member: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no state: "present" name: "{{hostvars[item].inventory_hostname}}" host: "{{hostvars[item].ansible_host}}" port: "80" pool: "http_pool" - validate_certs: "no" loop: "{{ groups['webservers'] }}" ``` {% endraw %} @@ -78,6 +79,7 @@ Explanation of each line within the task: Next we have module parameters - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with diff --git a/exercises/ansible_f5/1.4-add-pool-members/bigip-pool-members.yml b/exercises/ansible_f5/1.4-add-pool-members/bigip-pool-members.yml index b984122f0..a85fe2702 100755 --- a/exercises/ansible_f5/1.4-add-pool-members/bigip-pool-members.yml +++ b/exercises/ansible_f5/1.4-add-pool-members/bigip-pool-members.yml @@ -8,14 +8,15 @@ - name: ADD POOL MEMBERS bigip_pool_member: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no state: "present" name: "{{hostvars[item].inventory_hostname}}" host: "{{hostvars[item].ansible_host}}" port: "80" pool: "http_pool" - validate_certs: "no" loop: "{{ groups['webservers'] }}" diff --git a/exercises/ansible_f5/1.5-add-virtual-server/README.md b/exercises/ansible_f5/1.5-add-virtual-server/README.md index 7cb1a8c42..7c72ddc23 100755 --- a/exercises/ansible_f5/1.5-add-virtual-server/README.md +++ b/exercises/ansible_f5/1.5-add-virtual-server/README.md @@ -61,10 +61,12 @@ Next, add the `task`. This task will use the `bigip-virtual-server` to configure - name: ADD VIRTUAL SERVER bigip_virtual_server: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "vip" destination: "{{private_ip}}" port: "443" @@ -72,7 +74,6 @@ Next, add the `task`. This task will use the `bigip-virtual-server` to configure all_profiles: ['http','clientssl','oneconnect'] pool: "http_pool" snat: "Automap" - validate_certs: "no" ``` @@ -82,6 +83,7 @@ Next, add the `task`. This task will use the `bigip-virtual-server` to configure - `name: ADD VIRTUAL SERVER` is a user defined description that will display in the terminal output. - `bigip_virtual_server:` tells the task which module to use. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with diff --git a/exercises/ansible_f5/1.5-add-virtual-server/bigip-virtual-server.yml b/exercises/ansible_f5/1.5-add-virtual-server/bigip-virtual-server.yml index 7914e06da..0799046ee 100755 --- a/exercises/ansible_f5/1.5-add-virtual-server/bigip-virtual-server.yml +++ b/exercises/ansible_f5/1.5-add-virtual-server/bigip-virtual-server.yml @@ -7,10 +7,12 @@ - name: ADD VIRTUAL SERVER bigip_virtual_server: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "vip" destination: "{{private_ip}}" port: "443" @@ -18,4 +20,3 @@ all_profiles: ['http','clientssl','oneconnect'] pool: "http_pool" snat: "Automap" - validate_certs: "no" diff --git a/exercises/ansible_f5/1.6-add-irules/README.md b/exercises/ansible_f5/1.6-add-irules/README.md index edf92e1d8..388be13d2 100644 --- a/exercises/ansible_f5/1.6-add-irules/README.md +++ b/exercises/ansible_f5/1.6-add-irules/README.md @@ -87,15 +87,16 @@ Next, add the `task`. This task will use the `bigip-irule` to add irules to the - name: ADD iRules bigip_irule: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no module: "ltm" name: "{{item}}" content: "{{lookup('file','{{item}}')}}" - loop: "{{irules}}" + with_items: "{{irules}}" ``` {% endraw %} @@ -106,6 +107,7 @@ Next, add the `task`. This task will use the `bigip-irule` to add irules to the - `name: ADD iRules` is a user defined description that will display in the terminal output. - `bigip_irule:` tells the task which module to use. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The `password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with @@ -134,23 +136,25 @@ Next, add the `task`. This task will use the `bigip_virtual_server` to add attac - name: ADD iRules bigip_irule: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no module: "ltm" name: "{{item}}" content: "{{lookup('file','{{item}}')}}" - loop: "{{irules}}" - - - name: ATTACH iRules TO EXISTING VIRTUAL SERVER + with_items: "{{irules}}" + + - name: ATTACH iRules TO VIRTUAL SERVER bigip_virtual_server: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "vip" irules: "{{irules}}" ``` diff --git a/exercises/ansible_f5/1.6-add-irules/bigip-irule.yml b/exercises/ansible_f5/1.6-add-irules/bigip-irule.yml index df645a65e..1ae7df45c 100644 --- a/exercises/ansible_f5/1.6-add-irules/bigip-irule.yml +++ b/exercises/ansible_f5/1.6-add-irules/bigip-irule.yml @@ -10,11 +10,12 @@ - name: ADD iRules bigip_irule: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no module: "ltm" name: "{{item}}" content: "{{lookup('file','{{item}}')}}" @@ -22,10 +23,11 @@ - name: ATTACH iRules TO VIRTUAL SERVER bigip_virtual_server: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no name: "vip" irules: "{{irules}}" diff --git a/exercises/ansible_f5/1.7-save-running-config/README.md b/exercises/ansible_f5/1.7-save-running-config/README.md index f4ffaf957..14a41953f 100644 --- a/exercises/ansible_f5/1.7-save-running-config/README.md +++ b/exercises/ansible_f5/1.7-save-running-config/README.md @@ -60,11 +60,12 @@ Next, add the `task`. This task will use the `bigip-config` to save the running - name: SAVE RUNNING CONFIG ON BIG-IP bigip_config: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no save: yes ``` {% endraw %} @@ -75,6 +76,7 @@ Next, add the `task`. This task will use the `bigip-config` to save the running - `name: SAVE RUNNING CONFIG ON BIG-IP` is a user defined description that will display in the terminal output. - `bigip_config:` tells the task which module to use. - The `server: "{{private_ip}}"` parameter tells the module to connect to the F5 BIG-IP IP address, which is stored as a variable `private_ip` in inventory +- The `provider:` parameter is a group of connection details for the BIG-IP. - The `user: "{{ansible_user}}"` parameter tells the module the username to login to the F5 BIG-IP device with - The`password: "{{ansible_ssh_pass}}"` parameter tells the module the password to login to the F5 BIG-IP device with - The `server_port: 8443` parameter tells the module the port to connect to the F5 BIG-IP device with diff --git a/exercises/ansible_f5/1.7-save-running-config/bigip-config.yml b/exercises/ansible_f5/1.7-save-running-config/bigip-config.yml index 4a18ca8ce..f35a2b4dd 100644 --- a/exercises/ansible_f5/1.7-save-running-config/bigip-config.yml +++ b/exercises/ansible_f5/1.7-save-running-config/bigip-config.yml @@ -7,9 +7,10 @@ - name: SAVE RUNNING CONFIG ON BIG-IP bigip_config: - server: "{{private_ip}}" - user: "{{ansible_user}}" - password: "{{ansible_ssh_pass}}" - server_port: "8443" - validate_certs: "no" + provider: + server: "{{private_ip}}" + user: "{{ansible_user}}" + password: "{{ansible_ssh_pass}}" + server_port: 8443 + validate_certs: no save: yes diff --git a/exercises/ansible_network/6-tower-job-template/README.md b/exercises/ansible_network/6-tower-job-template/README.md index 7037df920..b8ed1b362 100644 --- a/exercises/ansible_network/6-tower-job-template/README.md +++ b/exercises/ansible_network/6-tower-job-template/README.md @@ -13,7 +13,7 @@ # Objective -Demonstrate a network backup configuration job template for Red Hat Ansible Tower. This job template will save the running configuration from all four routers and store them under /tmp/backup on the control node with a timestamp. +Demonstrate a network backup configuration job template for Red Hat Ansible Tower. This job template will save the running configuration from all four routers and store them under /backup on the control node with a timestamp. To run an Ansible Playbook in Ansible Tower we need to create a **Job Template**. A **Job Template** requires: - An **Inventory** to run the job against @@ -110,10 +110,10 @@ Any **Job Template** that has been run or is currently running will show up unde ## Step 5: Verify the backups were created -1. On the Ansible control node command line `ls /tmp/backup` to view the time stamped folder (or folders if you created multiple backups) +1. On the Ansible control node command line `ls /backup` to view the time stamped folder (or folders if you created multiple backups) ``` - [student1@ansible ~]$ ls /tmp/backup + [student1@ansible ~]$ ls /backup 2019-07-09-18-42 2019-07-09-19-18 ``` @@ -122,7 +122,7 @@ Any **Job Template** that has been run or is currently running will show up unde 2. Use the `cat` command to view the contents of one of the time stamped network devices ``` - [student1@ansible ~]$ cat /tmp/backup/2019-07-09-18-42/rtr1 + [student1@ansible ~]$ cat /backup/2019-07-09-18-42/rtr1 Current configuration : 5625 bytes ! diff --git a/exercises/ansible_network/7-tower-survey/README.md b/exercises/ansible_network/7-tower-survey/README.md index 3697d3844..529898973 100644 --- a/exercises/ansible_network/7-tower-survey/README.md +++ b/exercises/ansible_network/7-tower-survey/README.md @@ -63,10 +63,12 @@ Here is what the `network_banner.yml` Ansible Playbook looks like: The role **banner** has a very simple `main.yml` file: + ```yml - name: configure banner include_tasks: "{{ ansible_network_os }}.yml" ``` + The `ansible_network_os` variable is being used to parameterize the network OS and create a vendor neutral playbook. diff --git a/exercises/ansible_rhel/2.1-intro/README.ja.md b/exercises/ansible_rhel/2.1-intro/README.ja.md index 364b3fb1b..f1fcff38b 100644 --- a/exercises/ansible_rhel/2.1-intro/README.ja.md +++ b/exercises/ansible_rhel/2.1-intro/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.1 - Tower の紹介 +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + ## Ansible Tower の価値 Ansible Towerは、IT自動化のためのエンタープライズソリューションを提供するWebベースのUIです。 diff --git a/exercises/ansible_rhel/2.1-intro/README.md b/exercises/ansible_rhel/2.1-intro/README.md index 30faabfe3..e6cd97584 100644 --- a/exercises/ansible_rhel/2.1-intro/README.md +++ b/exercises/ansible_rhel/2.1-intro/README.md @@ -1,5 +1,7 @@ # Exercise 2.1 - Introduction to Tower +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + ## Why Ansible Tower? Ansible Tower is a web-based UI that provides an enterprise solution for IT automation. It @@ -31,7 +33,9 @@ The Ansible Tower provided in this lab is individually setup for you. Make sure ## Dashboard -When logged in to Ansible Tower using the web UI, the administrator can view a graph that shows +Let's have a first look at the Tower: Point your browser to the URL you were given, similar to `https://student.workshopname.rhdemo.io` (replace `` with your student number and `workshopname` with the name of your current workshop) and log in as `admin`. The password will be provided by the instructor. + +The web UI of Ansible Tower greets you with a dashboard with a graph showing: - recent job activity @@ -45,7 +49,7 @@ The dashboard also displays real time data about the execution of tasks complete ## Concepts -To start using Ansible Tower, you should get familiar with some concepts and naming conventions. +Before we dive further into using Ansible Tower for your automation, you should get familiar with some concepts and naming conventions. **Projects** diff --git a/exercises/ansible_rhel/2.2-cred/README.ja.md b/exercises/ansible_rhel/2.2-cred/README.ja.md index a615319fc..b3a674bd5 100644 --- a/exercises/ansible_rhel/2.2-cred/README.ja.md +++ b/exercises/ansible_rhel/2.2-cred/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.2 - インベントリー、認証情報、アドホックコマンド +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + ## インベントリーの作成 まず必要なのは、管理対象ホストの一覧です。これは Ansible Engine のインベントリーファイルに相当します。インベントリーにはダイナミックインベントリーなど、高度なものもありますが、まずは基本的なところから始めてみましょう。 diff --git a/exercises/ansible_rhel/2.2-cred/README.md b/exercises/ansible_rhel/2.2-cred/README.md index 41934fe56..a7723e4a2 100644 --- a/exercises/ansible_rhel/2.2-cred/README.md +++ b/exercises/ansible_rhel/2.2-cred/README.md @@ -1,5 +1,7 @@ # Exercise 2.2 - Inventories, credentials and ad hoc commands +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + ## Create an Inventory Let’s get started with: The first thing we need is an inventory of your managed hosts. This is the equivalent of an inventory file in Ansible Engine. There is a lot more to it (like dynamic inventories) but let’s start with the basics. diff --git a/exercises/ansible_rhel/2.3-projects/README.ja.md b/exercises/ansible_rhel/2.3-projects/README.ja.md index 74e6d55e1..bb596a2a4 100644 --- a/exercises/ansible_rhel/2.3-projects/README.ja.md +++ b/exercises/ansible_rhel/2.3-projects/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.3 - プロジェクトとジョブテンプレート +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + Tower の **プロジェクト** は、 Git、Subversion、Mercurial、ローカルホルダなど、Playbook の置き場所を定義する仕組みを提供します。 Tower ではサポートとされるソースコード管理(SCM)と連携して Playbook を管理することが可能です。 Playbook は SCM など、バージョン管理の仕組みの下に置いておくべきです。このラボでは、 Git リポジトリに保存されている Playbook を利用します。 diff --git a/exercises/ansible_rhel/2.3-projects/README.md b/exercises/ansible_rhel/2.3-projects/README.md index 9829eb919..cfe919aaf 100644 --- a/exercises/ansible_rhel/2.3-projects/README.md +++ b/exercises/ansible_rhel/2.3-projects/README.md @@ -1,5 +1,7 @@ # Exercise 2.3 - Projects & job templates +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + A Tower **Project** is a logical collection of Ansible Playbooks. You can manage your playbooks by placingthem into a source code management (SCM) system supported by Tower, including Git, Subversion, and Mercurial. You should definitely keep your Playbooks under version control. In this lab we’ll use Playbooks kept in a Git repository. diff --git a/exercises/ansible_rhel/2.4-surveys/README.ja.md b/exercises/ansible_rhel/2.4-surveys/README.ja.md index dac55b391..20cb45af3 100644 --- a/exercises/ansible_rhel/2.4-surveys/README.ja.md +++ b/exercises/ansible_rhel/2.4-surveys/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.4 - Survey 機能 +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + テンプレート構成ビューの **SURVEYの追加** ボタンに気付いたかもしれません。Survey は、**テンプレート**が**ジョブ**として起動した時に利用する変数の値を入力する簡単なフォームです。 先ほどの演習で、全てのホストに Apache をインストールしました。次にこれを拡張します。 diff --git a/exercises/ansible_rhel/2.4-surveys/README.md b/exercises/ansible_rhel/2.4-surveys/README.md index 9f02ef199..3abe910e7 100644 --- a/exercises/ansible_rhel/2.4-surveys/README.md +++ b/exercises/ansible_rhel/2.4-surveys/README.md @@ -1,5 +1,7 @@ # Exercise 2.4 - Surveys +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + You might have noticed the **ADD SURVEY** button in the **Template** configuration view. A survey is a way to create a simple form to ask for parameters that get used as variables when a **Template** is launched as a **Job**. You have installed Apache on all hosts in the job you just run. Now we’re going to extend on this: diff --git a/exercises/ansible_rhel/2.5-rbac/README.ja.md b/exercises/ansible_rhel/2.5-rbac/README.ja.md index fba56b583..85b545ff1 100644 --- a/exercises/ansible_rhel/2.5-rbac/README.ja.md +++ b/exercises/ansible_rhel/2.5-rbac/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.5 - ロールベースのアクセス制御 +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + Ansible Tower の優れた機能として、認証情報を Tower 内部で適切に管理する方法を学びました。Ansible Tower のもう1つの利点は、ユーザーとグループの権限管理です。 ## Ansible Tower ユーザー diff --git a/exercises/ansible_rhel/2.5-rbac/README.md b/exercises/ansible_rhel/2.5-rbac/README.md index 7acd78e4c..d9e9a946f 100644 --- a/exercises/ansible_rhel/2.5-rbac/README.md +++ b/exercises/ansible_rhel/2.5-rbac/README.md @@ -1,5 +1,7 @@ # Exercise 2.5 - Role based access control +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + You have already learned how Tower separates credentials from users. Another advantage of Ansible Tower is the user and group rights management. ## Ansible Tower Users diff --git a/exercises/ansible_rhel/2.6-workflows/README.ja.md b/exercises/ansible_rhel/2.6-workflows/README.ja.md index 554ee3b70..32e9105ff 100644 --- a/exercises/ansible_rhel/2.6-workflows/README.ja.md +++ b/exercises/ansible_rhel/2.6-workflows/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.6 - ワークフロー +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + # Ansible Tower ワークフロー Ansible Tower の主要な新機能としてバージョン 3.1 からワークフローが導入されました。ワークフローの基本的な考え方は、複数のジョブテンプレートをリンクし実行できることです。各ジョブテンプレートの実行は、例えば以下の様な実行条件を付与することができます。 diff --git a/exercises/ansible_rhel/2.6-workflows/README.md b/exercises/ansible_rhel/2.6-workflows/README.md index b829c2730..0e8d0a467 100644 --- a/exercises/ansible_rhel/2.6-workflows/README.md +++ b/exercises/ansible_rhel/2.6-workflows/README.md @@ -1,5 +1,7 @@ # Exercise 2.6 - Workflows +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + # Ansible Tower Workflows Workflows were introduced as a major new feature in Ansible Tower 3.1. The basic idea of a workflow is to link multiple Job Templates together. They may or may not share inventory, Playbooks or even permissions. The links can be conditional: diff --git a/exercises/ansible_rhel/2.7-wrap/README.ja.md b/exercises/ansible_rhel/2.7-wrap/README.ja.md index 49c10ebd1..91ef9bd6a 100644 --- a/exercises/ansible_rhel/2.7-wrap/README.ja.md +++ b/exercises/ansible_rhel/2.7-wrap/README.ja.md @@ -1,5 +1,7 @@ # 演習 2.7 - まとめ +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + # 最終チャレンジとまとめ 今までに学んだことを踏まえて以下の課題を実施してみましょう。 diff --git a/exercises/ansible_rhel/2.7-wrap/README.md b/exercises/ansible_rhel/2.7-wrap/README.md index 49dbd52a6..0013b569e 100644 --- a/exercises/ansible_rhel/2.7-wrap/README.md +++ b/exercises/ansible_rhel/2.7-wrap/README.md @@ -1,5 +1,7 @@ # Exercise 2.7 - Wrap up +**Read this in other languages**: ![uk](../../../images/uk.png) [English](README.md), ![japan](../../../images/japan.png) [日本語](README.ja.md). + # Final Challenge or Putting it all Together This is the final challenge where we try to put most of what you have learned together. diff --git a/exercises/ansible_rhel/README.md b/exercises/ansible_rhel/README.md index d219f0ac0..eeb67fdb4 100644 --- a/exercises/ansible_rhel/README.md +++ b/exercises/ansible_rhel/README.md @@ -12,12 +12,22 @@ After finishing this lab you are ready to start using Ansible for your automatio ## Presentations -Want the Presentation Deck? Its right here: +The exercises are self explanatory and guide the particpants through the entire lab. All concepts are explained when they are introduces. + +There is an optional presentation available to support the workshops and explain Automation, the basics of Ansible and the topics of the exercises in more detail: [Red Hat Ansible Automation Technical Deck](../../decks/ansible_technical.pdf) Also have a look at our Ansible Best Practices Deck: [Ansible Best Practices](../../decks/ansible_best_practices.pdf) +## Time planning + +The time required to do the workshops strongly depends on multiple factors: the number of participants, how familiar those are with Linux in general and how much discussions are done in between. + +Having said that, the exercises themselves should take roughly 4-5 hours. The first section is slightly longer than the second one. The accompanying presentation itself adds another hour. + +If your experience is different in schedulung those workshops, please let us know and fill an issue. + ## Section 1 - Ansible Engine Exercises - [Exercise 1.1 - Check the Prerequisites](1.1-setup) diff --git a/exercises/ansible_security/0.0-support-docs/editor_intro.md b/exercises/ansible_security/0.0-support-docs/editor_intro.md new file mode 100644 index 000000000..a38dac90c --- /dev/null +++ b/exercises/ansible_security/0.0-support-docs/editor_intro.md @@ -0,0 +1,111 @@ +# Editor Alternatives + +If you don’t like **Vim** as an editor feel free to use **Nano** or **Midnight Commander** (**mc**) in the SSH terminal. Here is a quick introduction to both. And no, I’ll refuse to talk about Emacs…​ ;-) + +## Midnight Commander (mc) + +Mc is more then an editor, it’s a file manager. And it has this nice nineties feel about it…​ anyway we’ll focus on editing files here. + +To open **mc** at the commandline prompt type: + + # mc + +### Basic Editing + +Mc is controlled mainly through the function keys. This can pose all kinds of issues when run in a terminal session, e.g. **F10** is most times caught as a shortcut by the terminal window. + +To work around this: + + - Try the combination **ESC** **0** to get **F10**. Don’t hold **ESC**\! + + - Use the mouse, all **mc** keys should be clickable, even if they don’t look it. + +To create a new file: + + - Type `touch filename` in the command field to create an empty file + + - Navigate with the **arrow keys** in one of the panes to the new file + + - Hit (or click) **F4** to start editing the file + +To save a file: + + - Hit (or click) **F2** and confirm with **Enter** + +To exit edit mode with or without saving: + + - Hit **ESC** **0** or click **F10** + + - If you did any changes you will be asked "Save before Close?". + + - Choose one of the options "Yes, No, Cancel" by moving with the **arrow** or **Tab** keys (or click) + +Copy text internally: + + - Position the cursor where you want to start to copy + + - Hit (or click) **F3** to start selecting + + - Move the cursor to highlight/select the text you want to copy + + - Hit (or click) **F3** again to stop selecting + +Paste text internally: + + - Position the cursor where you want to paste the text + + - Hit (or click) **F5** to paste a copy of the text + + - Hit (or select) **F6** to cut the text and paste it here + +Copy text from external source: + + - mark the text with the mouse, e.g. from the lab guide + + - **right-click → Copy** + +Paste text from external source: + + - Click **Edit → Paste** in the terminal menu at the top + +## Short Intro to the Nano Editor + +If you don’t like **Vim** and you feel too young for **Midnight Commander** use **Nano**, a simple to use command line editor. + +### Basic Commands + +> **Tip** +> +> **Ctrl-\** or **Alt-\** means press and hold the Control or Alt key and then press the character after the dash. + +To create a new file or open an existing file: + + # nano playbook.yml + +> **Tip** +> +> When Nano asks for confirmation, it expects a **y** for yes or **n** for no. + +To save the current file in Nano: + + - Type **Ctrl-o** + +> **Tip** +> +> Depending if the file was changed or not Nano will ask for confirmation and the file name. + +To leave Nano without saving the file (if something went wrong while editing and you just want out without changing anything): + + - Type **Ctrl-x** **n** **Enter** + +Copy and paste external text: + + - mark the text with the mouse, e.g. from the lab guide + + - **right-click → Copy** + + - **right-click** into the Nano terminal window, then click **Paste** + +---- + +[Click here to return to the Ansible for Red Hat Enterprise Linux Workshop](../README.md#section-1---ansible-engine-exercises) diff --git a/exercises/ansible_security/1.1-explore/README.md b/exercises/ansible_security/1.1-explore/README.md new file mode 100644 index 000000000..8ad2f08b6 --- /dev/null +++ b/exercises/ansible_security/1.1-explore/README.md @@ -0,0 +1,133 @@ +# Exercise 1.1 - Exploring the lab environment + +## Step 1.1 - Objective + +Explore and understand the lab environment. This exercise will cover + +- The general setup and idea of the lab +- What nodes and services are part of your environment. +- How you access the control node. +- What your inventory is and where you can find it. +- How to edit files. + +## Step 1.2 - General Setup of the lab + +The focus of this lab is to show how automation can help with various security challenges in the day-to-days business of security practitioners. For this we have set up a typical set of security related tools: + +- a Firewall, in this case [CheckPoint Next Generation Firewall](https://www.checkpoint.com/products/next-generation-firewall/) +- a Security Information and Event Management (SIEM), here [https://www.splunk.com/en_us/software/enterprise-security.html](Splunk Enterprise Security) +- a Intrusion Detection & Prevention System, here [Snort](https://www.snort.org) + +The exercises of the first section of this lab guide you through each individual solution mentioned above. You will learn how to access them, what is basically possible with them and how to interact with them using Ansible. + +The exercises of the second section of this lab are focused on typical security operations use cases: situations in which a certain challenge has to be met, usually by interacting not only with one of the mentioned solutions above, but with a mix of them. After setting forth the challenge and explaining what tasks need to be done manually to solve the situation, the lab walks through the steps to automate the tasks with Ansible. + +## Step 1.3 - Nodes and Services + +In this lab you work in a pre-configured lab environment. You will have access to the following hosts and services: + +| Role | Inventory name | +| -----------------------------| ---------------| +| Ansible Control Host | ansible | +| Splunk Enterprise Security | splunk | +| Snort | snort | +| Ceck Point Management Server | checkpoint | +| Ceck Point Gateway | - | +| Windows Workstation | windows-ws | + +## Step 1.4 - Access the Ansible Environment + +Login to your control host via SSH. Open a terminal and type the following command: + +> **Warning** +> +> Replace **11.22.33.44** by your **IP** provided to you, and the **X** in student**X** by the student number provided to you in the following example and in all other cases were examples contain IP addresses. + +```bash +ssh studentX@11.22.33.44 +``` + +The password is **ansible** if not otherwise noted. + +Then become root: + +```bash +[student@ansible ~]$ sudo -i +``` + +Most prerequisite tasks have already been done for you: + + - Ansible software is installed + + - SSH connection and keys are configured + + - `sudo` has been configured on the managed hosts to run commands that require root privileges. + +Log out of the root account again: + +```bash + [root@ansible ~]# exit + logout +``` + +Check Ansible has been installed correctly + +```bash + [student@ansible ~]$ ansible --version + ansible 2.8.2 + [...] +``` + +In all subsequent exercises you should work as the student\ user on the control node if not explicitly told differently. + +> **Note** +> +> Ansible is keeping configuration management simple. Ansible requires no database or running daemons and can run easily on a laptop. On the managed hosts it needs no running agent. + +## Step 1.5 - Your inventory + +The inventory of your environment will be provided in a static, ini-type file. It can be found at `/home/student/lab_inventory/hosts` and looks like the following listing. Please note that the IP addresses provided here are just an example and will be different in your lab environment: + +```ini +[all:vars] +ansible_user=student1 +ansible_ssh_pass=ansible +ansible_port=22 + +[control] +ansible ansible_host=22.33.44.55 ansible_user=ec2-user private_ip=192.168.2.3 + +[siem] +qradar ansible_host=22.44.55.77 ansible_user=admin private_ip=172.16.3.44 ansible_httpapi_pass="Ansible1!" ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=False ansible_network_os=ibm.qradar.qradar + +[ids] +snort ansible_host=33.44.55.66 ansible_user=ec2-user private_ip=192.168.3.4 + +[firewall] +checkpoint ansible_host=44.55.66.77 ansible_user=admin private_ip=192.168.4.5 ansible_network_os=checkpoint ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=no + +[windows] +windows-ws ansible_host=55.66.77.88 ansible_user=Administrator ansible_pass=RedHat19! ansible_port=5986 ansible_connection=winrm ansible_winrm_server_cert_validation=ignore private_ip=192.168.5.6 +``` + +Ansible is already configured to use the inventory specific to your environment. As shown in the example above, the inventory carries more than just the host names and IP addresses. Especially in the case of the Windows workstation, several more parameters are set. + +> **Note** +> +> Not all hosts in your lab can be reached vis SSH. During the exercises, each node type will be explained in detail and the means how to access the resources will be shown step by step. + +## Step 1.6 - Working the Labs + +You might have guessed by now this lab is pretty commandline-centric…​ :-) + + - Don’t type everything manually, use copy & paste from the browser when appropriate. But stop to think and understand. + + - All labs were prepared using **Vim**, but we understand not everybody loves it. Feel free to use alternative editors. In the lab environment we provide **Midnight Commander** (just run **mc**, function keys can be reached via Esc-\ or simply clicked with the mouse) or **Nano** (run **nano**). Here is a short [editor intro](../0.0-support-docs/editor_intro.md). + +> **Tip** +> +> In the lab guide commands you are supposed to run are shown with or without the expected output, whatever makes more sense in the context. + +---- + +[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.1-setup/README.md b/exercises/ansible_security/1.1-setup/README.md deleted file mode 100644 index ed0b3860a..000000000 --- a/exercises/ansible_security/1.1-setup/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# Exercise 1 - Check the Prerequisites - -## Your Lab Environment - -In this lab you work in a pre-configured lab environment. You will have access to the following hosts: - -| Role | Inventory name | -| -----------------------------| ---------------| -| Ansible Control Host | | -| Splunk Enterprise Security | | -| Snort | | -| Ceck Point Management Server | | -| Ceck Point Gateway | | - -## Step 1.1 - Access the Environment - -Login to your control host via SSH: - -> **Warning** -> -> Replace **11.22.33.44** by your **IP** provided to you, and the **X** in student**X** by the student number provided to you. - - ssh studentX@11.22.33.44 - -> **Tip** -> -> The password is **ansible** if not otherwise noted. - -Then become root: - - [student@ansible ~]$ sudo -i - -Most prerequisite tasks have already been done for you: - - - Ansible software is installed - - - SSH connection and keys are configured - - - `sudo` has been configured on the managed hosts to run commands that require root privileges. - -Check Ansible has been installed correctly - - [root@ansible ~]# ansible --version - ansible 2.8.1 - [...] - -> **Note** -> -> Ansible is keeping configuration management simple. Ansible requires no database or running daemons and can run easily on a laptop. On the managed hosts it needs no running agent. - -Log out of the root account again: - - [root@ansible ~]# exit - logout - -> **Note** -> -> In all subsequent exercises you should work as the student\ user on the control node if not explicitly told differently. - -## Step 1.2 - Working the Labs - -You might have guessed by now this lab is pretty commandline-centric. - - - Don’t type everything manually, use copy & paste from the browser when appropriate. But don’t stop to think and understand. - -> **Tip** -> -> In the lab guide commands you are supposed to run are shown with or without the expected output, whatever makes more sense in the context. - ----- - -[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.2-checkpoint/README.md b/exercises/ansible_security/1.2-checkpoint/README.md new file mode 100644 index 000000000..b56839eb9 --- /dev/null +++ b/exercises/ansible_security/1.2-checkpoint/README.md @@ -0,0 +1,297 @@ +# Exercise 1.2 - Executing the first Check Point playbook + +## Step 2.1 - Check Point Next Generation Firewall + +To showcase how to automate the firewall in a security environment, this lab contains a Check Point Next Generaion Firewall (NGFW). + +The NGFW is usually not managed directly, but via a central security management server (MGMT). The MGMT is a central tool to manage multiple NGFWs or other security tools in one spot. + +There are multiple ways to interact with the MGMT. In our lab, two ways are important: + +- API: Ansible mostly works with the API +- Windows client: the user interaction takes place in a Windows client. + +In this lab the playbooks we write will be interacting with the API in the background. All actions will be verified in the Windows client UI. + +## Step 2.2 - Accessing the Check Point MGMT server via a Windows workstation + +Since access to the MGMT server requires a Windows client and we cannot be sure that each and every lab student has access to a Windows environment, we have provisioned a Windows workstation as part of this lab. + +The Windows workstation can be reached via Remote Desktop Protocol (RDP). We recommend to use a native RDP client if available. If not, the Workstation is equipped with an HTML RDP client which enables lab participants to access the workstation via browser. + +Test the access to the MGMT server now by pointing your RDP client to the `windows-ws` IP in your inventory. + +If you do not have a RDP client available or want to test the HTML RDP client, please open the following URL in your browser: `https:///myrtille`. Be sure to replace `` with the IP for the Windows workstation from your inventory. In the login field, only provide the user name and the password: The user name is **Adminimstrator**, the password is **RedHat19!** if not provided otherwise. + +## Step 2.3 - Install SmartConsole + +SmartConsole should already be installed on your system. Please check your desktop for an icon to launch SmartConsole and launch it. If this works, the following tasks are not necessary and you can proceed to **Step 2.4**. + +If for any reason SmartConsole was not installed properly during the deployment of the lab, it is simple to do that yourself: + +- Inside your Windows workstation, open the Chrome browser +- Point the browser to `https://`, where `` is the IP for the checkpoint entry in your inventory +- A warning page will open since Check Point MGMT server is by default installed with a self signed certificate. Accept the certificate by clicking on **Advanced** and afterwards by clicking on the link named **Proceed to 11.22.33.44 (unsafe)**, with your `checkpoint` IP instead of **11.22.33.44** +- Login with user name `admin` and password `admin123` +- Accept the message of the day with a click on the **Ok** button +- On top of the page, click on the green **Download Now!** button +- The download starts immediately, the file is downloaded to the **Downloads** folder of the administrator +- Find the file and launch the installer via double click +- Accept all default values and finish the installation + +## Step 2.4 - Access the SmartConsole UI + +Launch the Check Point SmartConsole via the desktop icon. In the following window, as username use `admin` and as password `admin123` if not instructed otherwise. The IP address to enter is the one from the **checkpoint** entry of your inventory. + +![SmartConsole login window](images/smartconsole-login-window.png) + +Press the **Login** button. Afterwards you need to verify the server fingerprint by clicking the **PROCEED** button. + +> **Note** +> +> In a productive environment, you would first figure out the fingerprint of the server and would only proceed after you confirmed that the fiungerprint shown is identical with the one from the server. In our demo setup with the short lived instances we can assume that the fingerprints are good. + +You are now viewing the Check Point SmartConsole management interface. + +![SmartConsole main window](images/smartconsole-main-window.png) + +## Step 2.5 - First example playbook + +In Ansible, automation is described in playbooks. Playbooks are files which describe the desired configurations or steps to implement on managed hosts. Playbooks can change lengthy, complex administrative tasks into easily repeatable routines with predictable and successful outcomes. + +A playbook is where you can take some of those ad-hoc commands you just ran and put them into a repeatable set of *plays* and *tasks*. + +A playbook can have multiple plays and a play can have one or multiple tasks. In a task a *module* is called, like the modules in the previous chapter. The goal of a *play* is to map a group of hosts. The goal of a *task* is to implement modules against those hosts. + +> **Tip** +> +> Here is a nice analogy: When Ansible modules are the tools in your workshop, the inventory is the materials and the playbooks are the instructions. + +We will now write a playbook to change the configuration of the Check Point setup. We will start with a simple example where we will add a blacklist entry in the firewall configuration. + +The playbook will be written and run on the Ansible control host. Use SSH to access your control host. On there, open an editor of your choice and create a file with the name `fw_blacklist_ip.yml`. + +First, a playbook needs a name and the hosts it should be executed on. So let's add those: + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint +``` + +> **Note** +> +> It is a good practice to make playbooks more reusable by pointing them at `hosts: all` and limit the execution later on the command line or via Tower. But for now we simplify the process by naming hosts in the playbook directly. + +As mentioned, in this a simple example we will add a blacklist entry. A simple blacklist entry consists of a source IP address, a destination IP address and the rule to prevent access between those. + +For this, we add the source and destination IP as variables to the playbook. + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 +``` + +Next, we need to add the tasks where the actual changes on the target machines are done. This happens in three steps: first we create a source object, than a destination object, and finally the access rule between those two. + +Let's start with a task to define the source object: + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 + + tasks: + - name: Create source IP host object + checkpoint_host: + name: "asa-{{ source_ip }}" + ip_address: "{{ source_ip }}" +``` + +As you can see, the task itself has a name - just like the play itself - and references a module, here `checkpoint_hosts`. The module has parameters, here `name` and `ip_address`. Each module has individual parameters, often some of them are required while others are optional. To get more information about a module, you can call the help: + +```bash +[student@ansible ~]$ ansible-doc checkpoint_host +``` + +> **Tip** +> +> In `ansible-doc` leave by pressing the button `q`. Use the `up`/`down` arrows to scroll through the content. + +In the same way we defined the source IP host object, we will now add the destination IP host object: + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 + + tasks: + - name: Create source IP host object + checkpoint_host: + name: "asa-{{ source_ip }}" + ip_address: "{{ source_ip }}" + + - name: Create destination IP host object + checkpoint_host: + name: "asa-{{ destination_ip }}" + ip_address: "{{ destination_ip }}" +``` + +Last, we are defining the actual access rule between those two host objects: + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 + + tasks: + - name: Create source IP host object + checkpoint_host: + name: "asa-{{ source_ip }}" + ip_address: "{{ source_ip }}" + + - name: Create destination IP host object + checkpoint_host: + name: "asa-{{ destination_ip }}" + ip_address: "{{ destination_ip }}" + + - name: Create access rule to deny access from source to destination + checkpoint_access_rule: + layer: Network + position: top + name: "asa-drop-{{ source_ip }}-to-{{ destination_ip }}" + source: "asa-{{ source_ip }}" + destination: "asa-{{ destination_ip }}" + action: drop +``` + +## Step 2.6 - Run the playbook + +Playbooks are executed using the `ansible-playbook` command on the control node. Before you run a new playbook it’s a good idea to check for syntax errors: + +```bash +[student@ansible ansible-files]$ ansible-playbook --syntax-check fw_blacklist_ip.yml +``` + +Now you should be ready to run your playbook: + +```bash +[student@ansible ansible-files]$ ansible-playbook fw_blacklist_ip.yml + +PLAY [Blacklist IP] ******************************************************************* + +TASK [Gathering Facts] **************************************************************** +ok: [checkpoint] + +TASK [Create source IP host object] *************************************************** +changed: [checkpoint] + +TASK [Create destination IP host object] ********************************************** +changed: [checkpoint] + +TASK [Create access rule to deny access from source todestination] ******************** +changed: [checkpoint] + +PLAY RECAP **************************************************************************** +checkpoint : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +## Step 2.7 - Verfiy changes in UI + +Now it's time to check if the changes really did take place, if the actual Check Point MGMT server configuration was really altered. + +Access the Windows workstation and open the SmartConsole interface. On the right side, underneath **Object Categories**, click on **Network Objects**, then pick **Hosts**. It should list both new host entries. + +![SmartConsole Hosts list](images/smartconsole-hosts-list.png) + +Next, on the left side, click on **SECURITY POLICIES** and note the additional access control policy entry in the middle of the field + +![SmartConsole Policiy Entries](images/smartconsole-policy-entry.png) + +## Step 2.8 - Realizing the same task with pre-defined roles + +While it is possible to write a playbook in one file as we did above throughout this workshop, eventually you’ll want to reuse files and start to organize things. + +Ansible Roles are the way we do this. When you create a role, you deconstruct your playbook into parts and those parts sit in a directory structure. + +There are multiple advantages in using roles to write your automation code. The most notable are that the complexity and intelligence behind a set of playbooks is hidden away. Also the roles are usually easy to re-use by others. + +In case of the security automation we created a role which contains the code mentioned above already - together with some more tasks to make sure that the execution runs in no problems in case objects already exist. You can check out the code in the [Github repository acl_manger](https://github.com/ansible-security/acl_manager). The playbook you are familiar with already is in the file (´[tasks/providers/checkpoint/blacklist_ip.yaml](https://github.com/ansible-security/acl_manager/blob/master/tasks/providers/checkpoint/blacklist_ip.yaml). + +If you have a closer look at how the entire role is set up you soon will realize that it is made in a way to support firewall solutions from multiple vendors. That way users of the role do not have to worry where are the differences are between different firewall vendors - that is hidden away in the role. + +In the more advanced steps in the lab we will sometimes re-use the roles. So let's have a look at how our playbook can be rewritten to use the roles directly. For this first we have to get the role onto our control machine. There are different ways how this can be achieved, but a very convenient way is to use the command line tool `ansible-galaxy`. It can install roles directly from archives, Git URLs - and it can also install roles from [Ansible Galaxy](https://galaxy.ansible.com). Ansible Galaxy is a community hub for finding and sharing Ansible content. It provides features like rating, quality testing, proper searching and so on. For example, the role mentioned above can be found in Ansible Galaxy at [ansible_security/acl_manager](https://galaxy.ansible.com/ansible_security/acl_manager). + +On your control host, use the `ansible-galaxy` tool to download and install the above mentioned role with a single command: + +```bash +[student@ansible ~]$ ansible-galaxy install ansible_security.acl_manager +- downloading role 'acl_manager', owned by ansible_security +- downloading role from https://github.com/ansible-security/acl_manager/archive/master.tar.gz +- extracting ansible_security.acl_manager to /home/student/.ansible/roles/ansible_security.acl_manager +- ansible_security.acl_manager (master) was installed successfully +``` + +As you see the role was installed to the roles default path, `~/.ansible/roles/`. It was prefixed by `ansible_security` which is the project writing the security roles used for example in this workshop. + +As we now have the role installed on our control host, let's use it. Open your editor to create a new file, `role-blacklist.yml`, and add the name and target hosts. Also, we immediately add the variables needed to tell the tasks what we are going to do. + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 +``` + +Next, add the tasks. Instead of tasks directly interacting with target machines we just reference the role and what tasks of the role we want to be used: + +```yaml +--- +- name: Blacklist IP + hosts: checkpoint + + vars: + source_ip: 192.168.0.10 + destination_ip: 192.168.0.11 + + tasks: + - include_role: + name: ansible_security.acl_manager + tasks_from: blacklist_ip +``` + +That's it already - the playbook is much shorter than the previous one because a lot of the code already exists in the role! + +Now we can execute the role: + +```bash +[student@ansible ~]$ ansible-playbook role_blacklist.yml +``` + +The output should look fairly familiar to you - some of the tasks executed are just the ones we had in our playbook. Others are new - those are tasks ensuring that everything works fine even if certain objects already exist. + +You are done with the first steps of automating Check Point with Ansible. Head back to the exercise overview and continue with the next step. + +---- + +[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.2-checkpoint/images/smartconsole-hosts-list.png b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-hosts-list.png new file mode 100644 index 000000000..8ecbac125 Binary files /dev/null and b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-hosts-list.png differ diff --git a/exercises/ansible_security/1.2-checkpoint/images/smartconsole-login-window.png b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-login-window.png new file mode 100644 index 000000000..be8a54053 Binary files /dev/null and b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-login-window.png differ diff --git a/exercises/ansible_security/1.2-checkpoint/images/smartconsole-main-window.png b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-main-window.png new file mode 100644 index 000000000..104aeac44 Binary files /dev/null and b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-main-window.png differ diff --git a/exercises/ansible_security/1.2-checkpoint/images/smartconsole-policy-entry.png b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-policy-entry.png new file mode 100644 index 000000000..dd66d452a Binary files /dev/null and b/exercises/ansible_security/1.2-checkpoint/images/smartconsole-policy-entry.png differ diff --git a/exercises/ansible_security/1.2-explore/README.md b/exercises/ansible_security/1.2-explore/README.md deleted file mode 100644 index 9da7052d7..000000000 --- a/exercises/ansible_security/1.2-explore/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Exercise 1.2 - Exploring the lab environment - ----- - -[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.3-checkpoint/README.md b/exercises/ansible_security/1.3-checkpoint/README.md deleted file mode 100644 index e0f31de67..000000000 --- a/exercises/ansible_security/1.3-checkpoint/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Exercise 1.3 - Executing the first Check Point playbook - ----- - -[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.3-snort/README.md b/exercises/ansible_security/1.3-snort/README.md new file mode 100644 index 000000000..5c23d2469 --- /dev/null +++ b/exercises/ansible_security/1.3-snort/README.md @@ -0,0 +1,310 @@ +# Exercise 1.3 - Executing the first Snort playbook + +## Step 3.1 - Snort + +To showcase how to automate a network intrusion detection and intrusion prevention system in a security environment, this lab contains a Snort installation. Used as an intrusion detection system, Snort can analyze network traffic and compare it against given rule sets. + +In this lab, Snort is installed on a Red Hat Enterprise Linux machine. Ansible interacts with Snort via accessing the Linux node via SSH and interacting with the Snort installation on the machine. + +## Step 3.2 - Accessing the Snort server + +The Snort software is installed on a typical Red Hat Enterprise Linux system. Thus access to the server is performed via SSH. On you control host, open your inventory again and find the IP address of you Snort server. This can also be done in one go with a single command: + +```bash +[student@ansible ~]$ grep snort lab_inventory/hosts +snort ansible_host=22.333.44.5 ansible_user=ec2-user private_ip=172.16.1.2 +``` + +> **NOTE** +> +> The IP addresses here are just an example and will be different in your case since you have a dedicated Snort setup in your individual lab environment. + +Knowing this IP address, you can now access the Snort server: + +```bash +[student@ansible ~]$ ssh ec2-user@22.333.44.5 +Warning: Permanently added '22.333.44.5' (ECDSA) to the list of known hosts. +Last login: Mon Aug 26 12:17:48 2019 from h-213.61.244.2.host.de.colt.net +[ec2-user@ip-172-16-1-2 ~]$ +``` + +Verify that snort is installed and configured properly by calling it via sudo and let it output the version: + +```bash +[ec2-user@ip-172-16-1-2 ~]$ sudo snort --version + + ,,_ -*> Snort! <*- + o" )~ Version 2.9.13 GRE (Build 15013) + '''' By Martin Roesch & The Snort Team: http://www.snort.org/contact#team + Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved. + Copyright (C) 1998-2013 Sourcefire, Inc., et al. + Using libpcap version 1.5.3 + Using PCRE version: 8.32 2012-11-30 + Using ZLIB version: 1.2.7 +``` + +Also, check if the service is actively running via `sudo systemctl`: + +```bash +[ec2-user@ip-172-16-1-2 ~]$ sudo systemctl status snort +● snort.service - Snort service + Loaded: loaded (/etc/systemd/system/snort.service; enabled; vendor preset: disabled) + Active: active (running) since Mon 2019-08-26 17:06:10 UTC; 1s ago + Main PID: 17217 (snort) + CGroup: /system.slice/snort.service + └─17217 /usr/sbin/snort -u root -g root -c /etc/snort/snort.conf -i eth0 -p -R 1 --pid-path=/var/run/snort --no-interface-pidfile --nolock-pidfile +[...] +``` + +Exit the Snort server now by pressing `CTRL` and `D`, or by typing `exit` on the command line. All further interaction will be done via Ansible from the Ansible control host. + +## Step 3.3 - Simple Snort rules + +On the most simple level, Snort works by reading rules and acting according to them. We will work with very simple examples of Snort in this lab to highlight how to automate Snort configuration with Ansible. This lab is not meant to dive into the specifics of Snort rules and what can be done with them in complex setups. But it helps to understand the basic structure of a simple Snort rule to better follow how to automate those. + +Basically, a rule consists of a rule header and rule options and is saved in files. + +The Snort rule header breaks down into: + +- an action +- the protocol to look for like TCP +- source information like IP and port +- destination information like IP and port + +The Snort rule options are keywords separated by `;` and can be: + +- messages to output when a rule matches +- SID, a unique identifier of the rule +- content to search for in the packet payload, for example a suspicious string +- or also byte tests to check for binary data +- a revision of the rule +- the severity of the attack, called "priority" +- a pre-defined attack type called "classtype" to better group the rule with other rules +- and others. + +Not all options are mandatory, some also only override existing default values. + +Together a Snort rule outline is: + +``` +[action][protocol][sourceIP][sourceport] -> [destIP][destport] ( [Rule options] ) +``` + +If you want to learn more about Snort rules, check out the [Snort Rule Infographic](https://www.snort.org/documents/snort-rule-infographic) or dive into the [Snort Users Manual (PDF)](https://www.snort.org/documents/snort-users-manual). If you want to have a look at some real Snort rules you can also access your lab Snort installation and look at the content of the `/etc/snort/rules` directory. + +## Step 3.4 - Example playbook + +With this knowledge, now let's automate the Snort rule configuration! As described earlier, in Ansible automation is described in Playbooks, which consist of multiple tasks. Each task uses a module and corresponding parameters to describe the change that needs to be done or the state that is desired. + +In case of Snort, in Ansible 2.8 there are no modules to interact with Snort. So we wrote a set of modules to interact with Snort properly. That way, we can provide value already without the need to wait for a new Ansible release. Also we are able to update our modules faster which is especially important in the early times of a rather newer module. + +The modules are shipped as part of a role to manage Snort modules, [ids_rule](https://github.com/ansible-security/ids_rule). Open the link in the web browser and click on the [library](https://github.com/ansible-security/ids_rule/tree/master/library) link: you will find the module `snort_rule.py` there. + +If you take an even closer look at the role you will realize that it also comes along with a re-usable playbook at [tasks/snort.yml](https://github.com/ansible-security/ids_rule/blob/master/tasks/snort.yml) - just like it was the case with the Check Point role. + +Again, to use the Snort role and the content inside it, we are going to use the command line `ansible-galaxy` to install it. On your control host, use the `ansible-galaxy` tool to download and install the above mentioned role with a single command: + +```bash +[student@ansible ~]$ ansible-galaxy install ansible_security.ids_rule +- downloading role 'ids_rule', owned by ansible_security +- downloading role from https://github.com/ansible-security/ids_rule/archive/master.tar.gz +- extracting ansible_security.ids_rule to /home/student1/.ansible/roles/ansible_security.ids_rule +- ansible_security.ids_rule (master) was installed successfully +``` + +As you see the role was installed to the roles default path, `~/.ansible/roles/`. It was prefixed by `ansible_security` which is the project writing the security roles used for example in this workshop. + +As we now have the role installed on our control host, let's use it. Open your editor to create a new file, `add_snort_rule.yml`. And the name and target hosts, here `snort`. Also, since we need root rights to do changes to Snort, add the `become` flag so that Ansible will do a privilege escalation. + +```yaml +--- +- name: Add Snort rule + hosts: snort + become: yes +``` + +Next we add the variable needed for our rule. The role we downloaded is written in a way that it can work with multiple IDS providers, so we have to set the `ids_provider` to `snort`. + +```yaml +--- +- name: Add Snort rule + hosts: snort + become: yes + + vars: + ids_provider: snort +``` + +Next, we need to add the tasks where the actual changes on the target machines are done. Since we re-use a role, this is just a single step where we include the role to which we add some task-specific variables: + +- the actual rule +- the Snort rules file +- the state of the rule, present or absent + +```yaml +--- +- name: Add Snort rule + hosts: snort + become: yes + + vars: + ids_provider: snort + + tasks: + - name: Add snort password attack rule + include_role: + name: "ansible_security.ids_rule" + vars: + ids_rule: 'alert tcp and any -> any any (msg:"Attempted /etc/passwd Attack"; uricontent:"/etc/passwd"; classtype:attempted-user; sid:99000004; priority:1; rev:1;)' + ids_rules_file: '/etc/snort/rules/local.rules' + ids_rule_state: present +``` + +Let's quickly look at what is actually happening here: the rule header is `alert tcp and any -> any any`, so we create an alert for tcp traffic from any source to any destination. The rule options define the human readable Snort message when the rule matches, and `uriconten` which is a specialized version of `content` making it easier to analyze URIs. The `classtype` is set to `attempted-used` which is the default class for "attempted user privilege gain" and the SID is set to a value high enough for user defined rules. The priority is `1`. Finally since this is the first version of this rule we set the revision to `1`. + +The other variables set the rules file a the user defined location and set that the rule should be created if not there (`present`). + +## Step 3.5 - Run the playbook + +It is now time to execute the playbook. Call `ansible-playbook` with the appropriate arguments! + +```bash +[student1@ansible ~]$ ansible-playbook add_snort_rule.yml + +PLAY [Add Snort rule] ***************************************************************** + +TASK [Gathering Facts] **************************************************************** +ok: [snort] + +TASK [Add snort password attack rule] ************************************************* + +TASK [ansible_security.ids_rule : verify required variable ids_provider is defined] *** +skipping: [snort] + +TASK [ansible_security.ids_rule : ensure ids_provider is valid] *********************** +skipping: [snort] + +TASK [ansible_security.ids_rule : verify required variable ids_rule is defined] ******* +skipping: [snort] + +TASK [ansible_security.ids_rule : verify required variable ids_rule_state is defined] * +skipping: [snort] + +TASK [ansible_security.ids_rule : include ids_provider tasks] ************************* +included: /home/student1/.ansible/roles/ansible_security.ids_rule/tasks/snort.yml for +snort + +TASK [ansible_security.ids_rule : snort_rule] ***************************************** +changed: [snort] + +RUNNING HANDLER [ansible_security.ids_rule : restart snort] *************************** +changed: [snort] + +PLAY RECAP **************************************************************************** +snort : ok=4 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0 +``` + +As you see there are many more tasks executed than just the mere adding of the rules. The role takes care of reloading the Snort service after the rule was added. Other tasks verify that the entered variables are in fact correct. + +This shows again how valuable re-usable roles can be: it is possible to not only make your content re-usable, you can also add verification tasks and other important steps which are neatly hidden inside the role. + +## Step 3.6 - Verfiy changes + +The quick way to see if the rules were properly written is to check the content of the `/etc/snort/rules/local.rules` file on the Snort server. + +Another way is to use Ansible for this: we created an Ansible role to find existing rules in Snort: [ids_rule_facts](https://github.com/ansible-security/ids_rule_facts). Let's use it to verify that the rule is indeed installed on the Snort server. + +First, let's install the role with `ansible-galaxy`: + +```bash +[student@ansible ~]$ ansible-galaxy install ansible_security.ids_rule_facts +- downloading role 'ids_rule_facts', owned by ansible_security +- downloading role from https://github.com/ansible-security/ids_rule_facts/archive/master.tar.gz +- extracting ansible_security.ids_rule_facts to /home/student1/.ansible/roles/ansible_security.ids_rule_facts +- ansible_security.ids_rule_facts (master) was installed successfully +``` + +Now, let's create a playbook, `verify_attack_rule.yml`. The hosts, the IDS provider variable and the `become` flag can be re-used from the playbook above. Only the name needs to change. + +```yaml +--- +- name: Verify Snort rule + hosts: snort + become: yes + + vars: + ids_provider: snort +``` + +Next, we import the role `ids_rule_facts` and provide a search string to identify the rule we are looking for. In our example it makes sense to use the `uricontent` rule option: + +```yaml +--- +- name: Verify Snort rule + hosts: snort + become: yes + + vars: + ids_provider: snort + + tasks: + - name: import ids_rule_facts + import_role: + name: 'ansible_security.ids_rule_facts' + vars: + ids_rule_facts_filter: 'uricontent:"/etc/passwd"' +``` + +Last but not least we want to see what was actually found. The `ids_rule_facts` stores the data it collects about rules as Ansible facts - information individual to each host which can be used in further tasks. So we add another task outputting these facts: + +```yaml +--- +- name: Verify Snort rule + hosts: snort + become: yes + + vars: + ids_provider: snort + + tasks: + - name: import ids_rule_facts + import_role: + name: 'ansible_security.ids_rule_facts' + vars: + ids_rule_facts_filter: 'uricontent:"/etc/passwd"' + + - name: output rules facts + debug: + var: ansible_facts.ids_rules +``` + +Now let's execute the playbook to verify that our rule is indeed part of the Snort installation: + +```bash +[student@ansible ~]$ ansible-playbook verify_attack_rule.yml + +PLAY [Verify Snort rule] ************************************************************** + +TASK [Gathering Facts] **************************************************************** +ok: [snort] + +TASK [ansible_security.ids_rule_facts : collect snort facts] ************************** +ok: [snort] + +TASK [debugoutput rules facts] ******************************************************** +ok: [snort] => + ansible_facts.ids_rules: + - alert tcp and any -> any any (msg:"Attempted /etc/passwd Attack"; + uricontent:"/etc/passwd"; classtype:attempted-user; sid:99000004; priority:1; rev:1;) + +PLAY RECAP **************************************************************************** +snort : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +The last task outputs the actual rule which was found by the role. + +You are done with the first steps of automating Snort with Ansible. Head back to the exercise overview and continue with the next step. + +---- + +[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.4-qradar/README.md b/exercises/ansible_security/1.4-qradar/README.md new file mode 100644 index 000000000..dc7f6bbc8 --- /dev/null +++ b/exercises/ansible_security/1.4-qradar/README.md @@ -0,0 +1,298 @@ +# Exercise 1.4 - Executing the first IBM QRadar + +## Step 4.1 - IBM QRadar + +To showcase how to automate the SIEM in a security environment, this lab contains a [IBM QRadar SIEM, community edition](https://developer.ibm.com/qradar/ce/). + +The SIEM can be accessed via web UI and via REST API. In this lab the playbooks we write will be interacting with the API in the background. All actions will be verified in the web UI. + +## Step 4.1 - Access the web UI + +Have a first look at the SIEM, and verify that it is actualy working. Point your web broswer towards `https://`, where `` is the IP address for the `qradar` entry in your `siem` section of your inventory. Next you will be faced with a warning that the vertificate is unsecure since it is self-signed. Please accept this and proceed. + +> **Note** +> +> In a productive environment, accepting a insecure certificate would not be an option. Since the lab setup is only short lived and solely serves a demo purppose we accept the risk in this case. + +In the login field, provide the username **admin** and the password **Ansible1!** if not provided otherwise. Press the **Login** button. + +You are now viewing the IBM QRadar main web interface. + +![QRadar main window](images/qradar-main-window.png) + +To get an idea of QRadar and the basic concepts, let's have a short look at the interface: in the upper part there is a navigation bar with multiple entry points into the main parts of QRadar. + +- **Dashboard**, providing a central overview +- **Offenses**, messages or events generated through a monitored condition +- **Log Activity**, showing collected events from log sources +- **Network Activity**, network traffic communication between certain hosts +- **Assets**, automatically created profiles of network devices and hosts in your environment +- **Reports**, customized or standard reports to, well, report what happens in your environment + +For the purpose of the demo, we will have a closer look at the **Offenses**: click on the menu item. In the new window, you will see a navigation bar on the left side to filter the offenses. + +![QRadar offense window](images/qradar-offense-window.png) + +> **Note** +> +> Since this is a demo environment, it is likely that the list of offenses is currently empty. + +Offenses are messages or events generated based upon findings for example in log files or network traffic: for example a malicious log line appears somewhere. QRadar triggers offenses based on rules: the rules describe conditions, and when a condition is met, the offense is the result. + +To say it with the words of the official documentation: + +> *Rules, sometimes called correlation rules are applied to events, flows, or offenses to search for or detect anomalies. If all the conditions of a test are met, the rule generates response.* +> *Source: [QRadar documentation](https://www.ibm.com/support/knowledgecenter/en/SS42VS_7.3.2/com.ibm.qradar.doc/c_qradar_rul_mgt.html)* + +In a productive environment it is common to create more and more custom rules over time. But for now, let's have a look at the rules which are already installed on the system: in the **Offenses** window, on the left side in the navigation bar, click on **Rules**. A long list of rules is displayed. In the search bar on top of this list, enter the following search term: `DDoS` Hit enter afterwards to filter the list. + +The list is filtered, and only shows few rules which are related to DDOS. + +![QRadar, filtered rules list](images/qradar-offenses-rules.png) + +Click on the one called **"Potential DDoS Against Single Host (TCP)"**, note that it is enabled. This will be relevant later in this exercise. + +Now that you had a very first glance at QRadar, it is time to look how it can be automated by Ansible. + +## Step 4.2 - QRadar modules and Ansible collections + +On the most basic level, Ansible automation performs tasks. Those tasks execute modules, which usually work on the corresponding targets, like an API endpoint of a special device or program. + +Ansible comes along with a lot of modules included. But as time of writing Ansible does not ship QRadar modules out of the box. Instead, those modules are provided as [Ansible collections](https://docs.ansible.com/ansible/devel/dev_guide/collections_tech_preview.html): + +> *Collections are a distribution format for Ansible content. They can be used to package and distribute playbooks, roles, modules, and plugins. You can publish and use collections through Ansible Galaxy.* + +Collections follow a simple directory structure to provide Ansible content. If you feel reminded of Ansible roles here, this has a reason: Collections are built upon the idea of roles, but extend the concept to general Ansible content management. The collection for IBM QRadar can be found in the [ansible-security project](https://github.com/ansible-security/ibm_qradar). + +As roles, collections also need to be installed first before they can be used. They are installed on the machine executing Ansible, in the case of the lab this is the control host. + +Let's install the collection for QRadar modules on your control host. Use SSH to access your control host, and execute the command `ansible-galaxy collection --help` to verify that the collections function is working properly: + +```bash +[student@ansible ansible-files]$ ansible-galaxy collection --help +usage: ansible-galaxy collection [-h] COLLECTION_ACTION ... + +positional arguments: + COLLECTION_ACTION + init Initialize new collection with the base structure of a + collection. + build Build an Ansible collection artifact that can be publish + to Ansible Galaxy. + publish Publish a collection artifact to Ansible Galaxy. + install Install collection(s) from file(s), URL(s) or Ansible + Galaxy + +optional arguments: + -h, --help show this help message and exit +``` + +With that in mind, we can now install the collection `ibm.qradar`. To make sure that the collection is installed in our user path and not for example system wide, we also need to provide a path. This can be any path - but the Ansible command line tools automatically look for collections at `~/.ansible/collections`, so we install our collection directly there: + +```bash +[student@ansible ansible-files]$ ansible-galaxy collection install ibm.qradar -p ~/.ansible/collections +Process install dependency map +Starting collection install process +Installing 'ibm.qradar:1.2.1' to '/home/rwolters/.ansible/collections/ansible_collections/ibm/qradar' +``` + +Verify that the collection was installed properly: + +```bash +[student@ansible ansible-files]$ ls -1 ~/.ansible/collections/ansible_collections/ibm/qradar +docs +galaxy.yml +LICENSE +plugins +README.md +tests +``` + +All required files are there - especially the `galaxy.yml` file which indicates that this is indeed an ansible collection, and the directory `plugins/modules` which contains the actual modules. + +With the collection in place, we can now start to write our playbook. + +## Step 4.3 - First example playbook + +To write a first example to interface with QRadar we are going to enable/disable a rule. It is a rather small but common change and shows how Ansible and QRadar interact. + +On your control host, open an editor to create a new file, `change_qradar_rule.yml`. Add the name and target hosts, here `qradar`. + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar +``` + +We also want to use the collections we just added. Collections can be referenced at multiple spots, for example at task level as well as play level. We will reference them at play level to be able to write multiple tasks based on them later on. + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar + collections: + - ibm.qradar +``` + +Next we bring in the actual tasks. The REST API of QRadar is worked in a way that we first have to search for a proper rule to find out its ID, and then deactive a rule with the given ID. For the sake of this lab, let's say the rule which creates messages based on a suspected DDoS attack. In the last section we already had a look at the QRadar rules via **Offenses** > **Rules**, and filitered them for the term **DDoS**. In the filtered list, note the first rule shown there, **"Potential DDoS Against Single Host (TCP)"**. We will use this string to search for the role using the module `qradar_rule_info`: + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar + collections: + - ibm.qradar + + tasks: + - name: get info about qradar rule + qradar_rule_info: + name: "DDoS Attack Detected" +``` + +This module returns a lot of information, among those the ID we need to actually disable to role. Let's register the returned information into a variable that we can reuse those with the help of the `register` keyword which is directly used with the actual module. + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar + collections: + - ibm.qradar + + tasks: + - name: get info about qradar rule + qradar_rule_info: + name: "DDoS Attack Detected" + register: rule_info +``` + +So how do the information returned by the module actually look like? How about we just output the variable `rule_info`? For that, add a `debug` task which can be used to output variables during a playbook run: + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar + collections: + - ibm.qradar + + tasks: + - name: get info about qradar rule + qradar_rule_info: + name: "Potential DDoS Against Single Host (TCP)" + register: rule_info + + - name: output returned rule_info + debug: + var: rule_info +``` + +> **Note** +> +> The parameter "var" of the debug module does expect a variable name already - for that reason curly brackets and quotation marks are not needed like usually when you reference a variable. + +Both tasks only collect and output data, they do not change anything. Let's quickly run the playbook to look at the returned data: + +```bash +[student@ansible ansible-files]$ ansible-playbook change_qradar_rule.yml + +PLAY [Change QRadar rule state] *************************************************** + +TASK [Gathering Facts] ************************************************************ +ok: [qradar] + +TASK [get info about qradar rule] ************************************************* +ok: [qradar] + +TASK [output returned rule_info] ************************************************** +ok: [qradar] => { + "rule_info": { + "changed": false, + "failed": false, + "rules": [ + { + "average_capacity": 0, + "base_capacity": 0, + "base_host_id": 0, + "capacity_timestamp": 0, + "creation_date": 1278524200032, + "enabled": true, + "id": 100065, + "identifier": "SYSTEM-1520", + "linked_rule_identifier": null, + "modification_date": 1566928030130, + "name": "Potential DDoS Against Single Host (TCP)", + "origin": "SYSTEM", + "owner": "admin", + "type": "FLOW" + } + ] + } +} + +PLAY RECAP ************************************************************************ +qradar : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +As you see, the debug task `output returned rule_info` shows the content of the variable, and thus the content which was returned by the module `qradar_rule_info`. Note among those return data the key `id`, here with the value `100065`. This is the key we need. + +How do we get the key when it is in this structure? First, it is in the segment `rules` of the variable, which we can access via `rule_info.rules`. Inside of `rules` there is actually a list (note the curly brackets), but with only one entry - so we access it with `rule_info.rules[0]`. And from within the list entry we can access each key individually via its name: `rule_info.rules[0].id`. + +So, let's provide this as a value to the module which can disable the rule, `qradar_rule`. At the same time we can remove the debug entry since it is not needed for the actual execution. + + +```yaml +--- +- name: Change QRadar rule state + hosts: qradar + collections: + - ibm.qradar + + tasks: + - name: get info about qradar rule + qradar_rule_info: + name: "Potential DDoS Against Single Host (TCP)" + register: rule_info + + - name: disable rule by id + qradar_rule: + state: disabled + id: "{{ rule_info.rules[0].id }}" +``` + + +The playbook is now complete: it queries QRadar for the list of rules, and deactives the one we are looking for. + +## Step 4.6 - Run the playbook + +After we completed the playbook, let's execute it: + +```bash +[student@ansible ansible-files]$ ansible-playbook change_qradar_rule.yml + +PLAY [Change QRadar rule state] *************************************************** + +TASK [Gathering Facts] ************************************************************ +ok: [qradar] + +TASK [get info about qradar rule] ************************************************* +ok: [qradar] + +TASK [disable rule by id] ********************************************************* +changed: [qradar] + +PLAY RECAP ************************************************************************ +qradar : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 +``` + +As you can see, the playbook denotes a change: the rule was changed. Run the playbook again - it does not report a change anymore, since the rule is now already disabled. + +## Step 4.7 - Verfiy changes in UI + +To verify that Ansible indeed changed something, we go back to the UI of QRadar. Open the QRadar IP in your web browser. Click on the **Offenses** tab, and from there on the left side click on **Rules**. The long list of rules is displayed. In the search bar on top of this list, enter the following search term: `DDoS` +Hit enter afterwards to filter the list, so that it only shows few rules which are related to DDOS. At the end, note the rule regarding potential DDOS attacks, and check the state in the **Enabled** column: it is set to **False**! + +![QRadar, filtered rules list showing disabled rule](images/qradar-rules-disabled.png) + +You are done with the first steps of automating QRadar with Ansible. Head back to the exercise overview and continue with the next exercise. + +---- + +[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.4-qradar/images/qradar-main-window.png b/exercises/ansible_security/1.4-qradar/images/qradar-main-window.png new file mode 100644 index 000000000..35519bdb6 Binary files /dev/null and b/exercises/ansible_security/1.4-qradar/images/qradar-main-window.png differ diff --git a/exercises/ansible_security/1.4-qradar/images/qradar-offense-window.png b/exercises/ansible_security/1.4-qradar/images/qradar-offense-window.png new file mode 100644 index 000000000..d855a8d67 Binary files /dev/null and b/exercises/ansible_security/1.4-qradar/images/qradar-offense-window.png differ diff --git a/exercises/ansible_security/1.4-qradar/images/qradar-offenses-rules.png b/exercises/ansible_security/1.4-qradar/images/qradar-offenses-rules.png new file mode 100644 index 000000000..f06f89595 Binary files /dev/null and b/exercises/ansible_security/1.4-qradar/images/qradar-offenses-rules.png differ diff --git a/exercises/ansible_security/1.4-qradar/images/qradar-rules-disabled.png b/exercises/ansible_security/1.4-qradar/images/qradar-rules-disabled.png new file mode 100644 index 000000000..2c42dd945 Binary files /dev/null and b/exercises/ansible_security/1.4-qradar/images/qradar-rules-disabled.png differ diff --git a/exercises/ansible_security/1.4-snort/README.md b/exercises/ansible_security/1.4-snort/README.md deleted file mode 100644 index 762f62a35..000000000 --- a/exercises/ansible_security/1.4-snort/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Exercise 1.4 - Executing the first Snort playbook - ----- - -[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/1.5-splunk/README.md b/exercises/ansible_security/1.5-splunk/README.md deleted file mode 100644 index 6e19aaacf..000000000 --- a/exercises/ansible_security/1.5-splunk/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Exercise 1.5 - Executing the first Splunk ES playbook - ----- - -[Click Here to return to the Ansible Security Automation Workshop](../README.md) diff --git a/exercises/ansible_security/README.md b/exercises/ansible_security/README.md index c3f9aa690..121faf1b8 100644 --- a/exercises/ansible_security/README.md +++ b/exercises/ansible_security/README.md @@ -1,6 +1,6 @@ # Ansible Workshop - Ansible Security Automation -Ansible is a simple yet powerful IT automation engine for application deployment, configuration management, and orchestration that you can learn quickly. This workshop shows, step by step, how you can reach this goal using Ansible to orchestrate 3 investigation and response activities involving multiple security tools - an enterprise firewall (CheckPoint Next Generation Firewall), an intrusion detection system (Snort) and a SIEM (Splunk Enterprise Security). +Ansible is a simple yet powerful IT automation engine for application deployment, configuration management, and orchestration that you can learn quickly. This workshop shows, step by step, how you can reach this goal using Ansible to orchestrate 3 investigation and response activities involving multiple security tools - an enterprise firewall (CheckPoint Next Generation Firewall), an intrusion detection system (Snort) and a SIEM (IBM QRadar). Learn and practice how Ansible can be used to automate different security platforms. Understand how Ansible Automation can support security teams to create more efficient and streamlined investigation and remediation processes. @@ -8,11 +8,10 @@ Learn and practice how Ansible can be used to automate different security platfo ## Section 1 - Introduction to Ansible Security Automation Basics - - [Exercise 1.1 - Check the prerequisites](1.1-setup) - - [Exercise 1.2 - Exploring the lab environment](1.2-explore) - - [Exercise 1.3 - Executing the first Check Point playbook](1.3-checkpoint) - - [Exercise 1.4 - Executing the first Snort playbook](1.4-snort) - - [Exercise 1.5 - Executing the first Splunk ES playbook](1.5-splunk) + - [Exercise 1.1 - Exploring the lab environment](1.1-explore) + - [Exercise 1.2 - Executing the first Check Point playbook](1.2-checkpoint) + - [Exercise 1.3 - Executing the first Snort playbook](1.3-snort) + - [Exercise 1.4 - Executing the first IBM QRadar playbook](1.4-qradar) ## Section 2 - Ansible Security Automation Use Cases diff --git a/provisioner/group_vars/all.yml b/provisioner/group_vars/all.yml index 3ee37beff..c89aeb3d5 100644 --- a/provisioner/group_vars/all.yml +++ b/provisioner/group_vars/all.yml @@ -18,3 +18,7 @@ valid_network_types: - arista - juniper - multivendor +security_console: qradar +valid_security_console_types: + - splunk + - qradar diff --git a/provisioner/provision_lab.yml b/provisioner/provision_lab.yml index 1c412f40e..a4c50c7d0 100644 --- a/provisioner/provision_lab.yml +++ b/provisioner/provision_lab.yml @@ -25,6 +25,14 @@ msg: "network_type must be defined and be one of: {{valid_network_types}}" when: workshop_type == "networking" + - name: make sure security_console is set to a correct value + assert: + that: + - security_console is defined + - security_console in valid_security_console_types + msg: "network_type must be defined and be one of: {{valid_security_console_types}}" + when: workshop_type == "security" + - name: run role to check if local environment setup will work with AWS include_role: name: aws_check_setup @@ -63,14 +71,16 @@ - autolicense is defined - autolicense - - name: Install required roles onto THIS machine - shell: "ansible-galaxy install {{item}} -f --force-with-deps -p ./roles/" - loop: - - 'geerlingguy.repo-epel' - - 'ansible_security.ids_config' - - 'ansible_security.ids_install' + - name: Install required roles and collections onto THIS machine when: - workshop_type == "security" + block: + - name: required roles + shell: "ansible-galaxy install {{item}} -f --force-with-deps -p ./roles/" + loop: + - 'geerlingguy.repo-epel' + - 'ansible_security.ids_config' + - 'ansible_security.ids_install' - name: Create lab instances in AWS hosts: localhost diff --git a/provisioner/roles/control_node/files/ansible-stable-29-prerelease-nightly.repo b/provisioner/roles/control_node/files/ansible-stable-29-prerelease-nightly.repo new file mode 100644 index 000000000..06a110dae --- /dev/null +++ b/provisioner/roles/control_node/files/ansible-stable-29-prerelease-nightly.repo @@ -0,0 +1,6 @@ +[ansible-stable-29-prerelease-nightly] +name=ansible-stable-29-prerelease-nightly +baseurl=https://releases.ansible.com/ansible/rpm/nightly/stable-2.9/epel-7-x86_64/ +enabled=yes +gpgcheck=no + diff --git a/provisioner/roles/control_node/tasks/main.yml b/provisioner/roles/control_node/tasks/main.yml index c36ec3f36..ae5d036e4 100644 --- a/provisioner/roles/control_node/tasks/main.yml +++ b/provisioner/roles/control_node/tasks/main.yml @@ -16,6 +16,7 @@ - tmux - python-pip - ansible + - gcc # - https://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/ansible-2.7.0-1.el7.ans.noarch.rpm state: present retries: 10 diff --git a/provisioner/roles/control_node/tasks/networking.yml b/provisioner/roles/control_node/tasks/networking.yml index 04b67c051..e2fcabd98 100644 --- a/provisioner/roles/control_node/tasks/networking.yml +++ b/provisioner/roles/control_node/tasks/networking.yml @@ -1,45 +1,31 @@ -- name: block for f5 workshop (F5 AUTOMATION MODE) - block: - - name: install f5 workshop dependicies - become: yes - pip: - name: - - pip - - setuptools - - pysnow - state: latest - - - name: install f5 workshop dependicies - become: yes - pip: - name: - - f5-sdk - - bigsuds - - netaddr - - jmespath - state: latest - when: workshop_type == "f5" - -- name: install additional packages (NETWORK AUTOMATION MODE) +- name: upgrade pip and setuptools become: yes pip: name: - pip - - netaddr - setuptools state: latest - when: - - workshop_type == 'networking' -- name: install ncclient for juniper devices (NETWORK AUTOMATION MODE) +- name: install f5 workshop dependicies (F5 AUTOMATION MODE) become: yes pip: name: + - f5-sdk + - bigsuds + - netaddr + - jmespath + state: latest + when: workshop_type == "f5" + +- name: install additional packages (NETWORK AUTOMATION MODE) + become: yes + pip: + name: + - netaddr + - pysnow - ncclient state: latest - when: - - workshop_type == 'networking' - - network_type == 'juniper' or network_type == 'multivendor' + when: workshop_type == 'networking' # FIXME: This should probably be refactored to use things like the following # instead of hard coding diff --git a/provisioner/roles/control_node/tasks/security.yml b/provisioner/roles/control_node/tasks/security.yml index b32fdece8..4019663f5 100644 --- a/provisioner/roles/control_node/tasks/security.yml +++ b/provisioner/roles/control_node/tasks/security.yml @@ -1,95 +1,4 @@ -# FIXME: This should probably be refactored to use things like the following -# instead of hard coding -# -# command: cp -r /tmp/linklight/exercises/{{workshop_type}}/ /home/{{ username }}/{{workshop_type}}-workshop/ -# -# That would enable a more generic role/scaffolding - -- name: Clone linklight repo (SECURITY AUTOMATION MODE) - git: - accept_hostkey: yes - clone: yes - dest: /tmp/linklight - repo: https://github.com/network-automation/linklight.git - force: yes - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -# This is waiting on https://github.com/ansible/ansible/pull/41222 -# which will become available on ansible 2.8 -# - name: Move networking workshop folder to correct location (NETWORKING MODE) -# copy: -# src: /tmp/linklight/exercises/ansible_network/ -# dest: /home/{{ username }}/networking-workshop -# remote_src: yes -# when: workshop_type == 'networking' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: Move networking workshop folder to correct location (NETWORKING MODE) -# command: cp -r /tmp/linklight/exercises/ansible_network/ /home/{{ username }}/networking-workshop/ -# when: workshop_type == 'networking' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -# This is waiting on https://github.com/ansible/ansible/pull/41222 -# which will become available on ansible 2.8 -# - name: Create demos folder with demos -# copy: -# src: /tmp/linklight/demos/ -# dest: /home/{{ username }}/demos -# remote_src: yes -# when: workshop_type == 'networking' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: Create demos folder with demos -# command: cp -r /tmp/linklight/demos/ /home/{{ username }}/demos -# when: workshop_type == 'networking' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -# This is waiting on https://github.com/ansible/ansible/pull/41222 -# which will become available on ansible 2.8 -# - name: Move networking workshop folder to correct location (F5 MODE) -# copy: -# src: /{{playbook_dir}}/linklight/exercises/ansible_f5/ -# dest: /home/{{ username }}/networking-workshop -# when: workshop_type == 'f5' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: Move networking workshop folder to correct location (F5 MODE) -# shell: mkdir /home/{{ username }}/networking-workshop; cp -r /tmp/linklight/exercises/ansible_f5/* /home/{{ username }}/networking-workshop -# when: workshop_type == 'f5' - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: fix permissions of networking-workshop (NETWORKING MODE) -# file: -# path: /home/{{ username }}/networking-workshop -# owner: "{{ username }}" -# group: "{{ username }}" -# recurse: yes - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: fix permissions of demos (NETWORKING MODE) -# file: -# path: /home/{{ username }}/demos -# owner: "{{ username }}" -# group: "{{ username }}" -# recurse: yes - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: Create lab inventory directory (NETWORKING MODE) -# file: -# state: directory -# path: /home/{{ username }}/networking-workshop/lab_inventory -# owner: "{{ username }}" -# group: "{{ username }}" - -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE -#- name: Put student inventory in proper spot (NETWORKING MODE) -# copy: -# src: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ username }}-instances.txt" -# dest: "/home/{{ username }}/networking-workshop/lab_inventory/hosts" -# owner: "{{ username }}" -# group: "{{ username }}" -# when: username in inventory_hostname - +--- - name: make sure .ssh is created file: path: "/home/{{username}}/.ssh/" @@ -129,11 +38,36 @@ group: "{{ansible_user}}" mode: 0700 -# FIXME - MAKE A SECURITY AUTOMATION ONE OF THESE - IF NEEDED -# -#- name: setup /etc/hosts file per student -# copy: -# src: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ username }}-etchosts.txt" -# dest: "/etc/hosts" -# owner: "{{ username }}" -# group: "{{ username }}" +- name: Create lab inventory directory + file: + state: directory + path: /home/{{ username }}/lab_inventory + +- name: Put student inventory in proper spot + copy: + src: ./{{ec2_name_prefix}}/{{ username }}-instances.txt + dest: /home/{{ username }}/lab_inventory/hosts + owner: "{{ username }}" + group: "{{ username }}" + when: username in inventory_hostname + +# FIXME: REMOVE THIS ENTIRE BLOCK ONCE ANSIBLE ENGINE 2.9 GOES GA +- name: Install Ansible 2.9 pre-release (if necessary) + block: + - name: Get package facts + package_facts: + manager: rpm + + - name: Enable nightly RPM build Ansible stable-2.9 branch prerelease + copy: + src: 'ansible-stable-29-prerelease-nightly.repo' + dest: '/etc/yum.repos.d/ansible-stable-29-prerelease-nightly.repo' + when: + - ansible_facts['packages']['ansible'][0]['version'] < '2.9.0' + + - name: Install Ansible 2.9 pre-release + yum: + state: latest + name: ansible + when: + - ansible_facts['packages']['ansible'][0]['version'] < '2.9.0' diff --git a/provisioner/roles/control_node/tasks/tower.yml b/provisioner/roles/control_node/tasks/tower.yml index 33b9acb62..ce67131b7 100644 --- a/provisioner/roles/control_node/tasks/tower.yml +++ b/provisioner/roles/control_node/tasks/tower.yml @@ -46,3 +46,33 @@ - name: Display /api/v2/ping results debug: msg: '{{ check2.json }}' + +# This is documented here: https://docs.ansible.com/ansible-tower/latest/html/upgrade-migration-guide/virtualenv.html#preparing-a-new-custom-virtualenv +- name: Create directory for custom venvs + file: + path: /opt/my-envs + state: directory + mode: '0755' + +- name: specify in Tower which directory to look for custom venvs + uri: + url: https://localhost/api/v2/settings/system/ + method: PATCH + user: admin + password: "ansible" + validate_certs: False + force_basic_auth: yes + body_format: json + body: '{"CUSTOM_VENV_PATHS": ["/opt/my-envs/"]}' + status_code: + - 200 + +- name: install ansible development branch to venv + become: yes + pip: + name: + - git+https://github.com/ansible/ansible.git@devel + - psutil + - paramiko + - ncclient + virtualenv: /opt/my-envs/ansible_dev diff --git a/provisioner/roles/control_node/templates/ansible.cfg.j2 b/provisioner/roles/control_node/templates/ansible.cfg.j2 index 52c06122b..cd44f8369 100644 --- a/provisioner/roles/control_node/templates/ansible.cfg.j2 +++ b/provisioner/roles/control_node/templates/ansible.cfg.j2 @@ -5,7 +5,7 @@ timeout = 60 deprecation_warnings = False host_key_checking = False retry_files_enabled = False -{% if workshop_type == 'rhel' %} +{% if (workshop_type == 'rhel') or (workshop_type == 'security') %} inventory = /home/{{username}}/lab_inventory/hosts {% else %} inventory = /home/{{username}}/networking-workshop/lab_inventory/hosts diff --git a/provisioner/roles/cp_setup/tasks/main.yml b/provisioner/roles/cp_setup/tasks/main.yml new file mode 100644 index 000000000..e69de29bb diff --git a/provisioner/roles/f5_setup/tasks/main.yml b/provisioner/roles/f5_setup/tasks/main.yml index 2125f8434..9eb9c45f8 100644 --- a/provisioner/roles/f5_setup/tasks/main.yml +++ b/provisioner/roles/f5_setup/tasks/main.yml @@ -1,13 +1,3 @@ -# not working right now, possible bug or mis-use of module -# - name: Wait for BIG-IP to boot up completely -# bigip_wait: -# provider: -# ssh_keyfile: "{{playbook_dir}}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" -# transport: cli -# user: admin -# validate_certs: false -# server: "{{ ansible_host }}" - - name: Wait for BIG-IP to boot up completely wait_for: host: "{{ ansible_host }}" @@ -23,13 +13,24 @@ server: "{{ ansible_host }}" commands: "modify auth user admin password {{admin_password}}" -# The bigip_iapplx_package requires rpm installed, on macOS use brew rather than pip or it won't work +- name: Wait for API to be Ready + bigip_wait: + timeout: 300 + provider: + validate_certs: "no" + user: admin + password: "{{admin_password}}" + server_port: 8443 + server: "{{ ansible_host }}" + delegate_to: localhost + +# The bigip_lx_package requires rpm installed, on macOS use brew rather than pip or it won't work - name: Install AS3 - bigip_iapplx_package: + bigip_lx_package: package: "{{playbook_dir}}/roles/f5_setup/files/f5-appsvcs-3.4.0-2.noarch.rpm" provider: validate_certs: "no" user: admin password: "{{admin_password}}" - server_port: "8443" + server_port: 8443 server: "{{ ansible_host }}" diff --git a/provisioner/roles/manage_ec2_instances/defaults/main.yml b/provisioner/roles/manage_ec2_instances/defaults/main.yml index 4dbd4b506..ac0d9e2b8 100644 --- a/provisioner/roles/manage_ec2_instances/defaults/main.yml +++ b/provisioner/roles/manage_ec2_instances/defaults/main.yml @@ -44,6 +44,26 @@ ec2_info: ami: "{{arista_ami | default(omit)}}" os: eos username: ec2-user + checkpoint_mgmt: + owners: 679593333241 + filter: 'Check Point CloudGuard IaaS*PAYG-MGMT*R80.20*' + architecture: x86_64 + size: m5.xlarge + ami: "{{ checkpoint_mgmt_ami| default(omit) }}" + username: admin + checkpoint_gw: + owners: 679593333241 + filter: 'Check Point CloudGuard IaaS GW*PAYG-NGTX*R80.20*' + architecture: x86_64 + size: c5.large + ami: "{{ checkpoint_gw_ami| default(omit) }}" + username: admin + windows_ws: + owners: 679593333241 + filter: 'Windows_Server-2016-English-Full-Base*' + size: t3.medium + ami: "{{ windows_ws_ami| default(omit) }}" + username: Administrator # Look for owner 309956199498 to find official Red Hat AMIs rhel7-tower: owners: 309956199498 @@ -77,14 +97,6 @@ ec2_info: architecture: x86_64 filter: 'RHEL-7.6_HVM-20190515-x86_64-0-Access2-GP2' username: ec2-user - checkpoint_firewall: - owners: 309956199498 - size: t2.micro - os_type: linux - disk_space: 10 - architecture: x86_64 - filter: 'RHEL-7.6_HVM-20190515-x86_64-0-Access2-GP2' #FIXME - needs to be something checkpoint - username: ec2-user netapp: owners: 679593333241 size: t2.medium @@ -93,3 +105,11 @@ ec2_info: architecture: x86_64 filter: 'OnCommand_Cloud_Manager_3.7.0_Marketplace*' username: ec2-user + qradar: + owners: 324218975267 + size: t2.2xlarge + os_type: linux + disk_space: 300 + architecture: x86_64 + filter: 'AnsibleSecurity-QRadarCE*' + username: ec2-user diff --git a/provisioner/roles/manage_ec2_instances/tasks/addhost_security.yml b/provisioner/roles/manage_ec2_instances/tasks/addhost_security.yml index efff69b88..f8c090acb 100644 --- a/provisioner/roles/manage_ec2_instances/tasks/addhost_security.yml +++ b/provisioner/roles/manage_ec2_instances/tasks/addhost_security.yml @@ -1,10 +1,54 @@ -- name: grab facts for splunknode (SECURITY MODE) - ec2_instance_facts: - region: "{{ ec2_region }}" - filters: - instance-state-name: running - "tag:Workshop_splunk": "{{ec2_name_prefix}}-splunk" - register: splunk_node_facts +- name: MANAGE SPLUNK EC2 INSTANCES + when: security_console == 'splunk' + block: + - name: grab facts for splunknode (SECURITY MODE) + ec2_instance_facts: + region: "{{ ec2_region }}" + filters: + instance-state-name: running + "tag:Workshop_splunk": "{{ec2_name_prefix}}-splunk" + register: splunk_node_facts + + - name: ADD SPLUNK NODE TO INVENTORY + add_host: + name: "{{ item.tags.Name }}" + short_name: "{{ item.tags.short_name }}" + ansible_host: "{{ item.public_ip_address }}" + username: "{{ item.tags.Student }}" + ansible_user: "{{ item.tags.username }}" + ansible_port: "{{ ssh_port }}" + ansible_ssh_private_key_file: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" + private_ip: "{{item.private_ip_address}}" + groups: + - splunk + - siem + loop: "{{ splunk_node_facts.instances|flatten(levels=1) }}" + +- name: MANAGE QRADAR EC2 INSTANCES + when: security_console == 'qradar' + block: + - name: grab facts for qradarnode (SECURITY MODE) + ec2_instance_facts: + region: "{{ ec2_region }}" + filters: + instance-state-name: running + "tag:Workshop_qradar": "{{ec2_name_prefix}}-qradar" + register: qradar_node_facts + + - name: ADD QRADAR NODE TO INVENTORY + add_host: + name: "{{ item.tags.Name }}" + short_name: "{{ item.tags.short_name }}" + ansible_host: "{{ item.public_ip_address }}" + username: "{{ item.tags.Student }}" + ansible_user: "{{ item.tags.username }}" + ansible_port: "{{ ssh_port }}" + ansible_ssh_private_key_file: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" + private_ip: "{{item.private_ip_address}}" + groups: + - qradar + - siem + loop: "{{ qradar_node_facts.instances|flatten(levels=1) }}" - name: grab facts for snort node (SECURITY MODE) ec2_instance_facts: @@ -14,18 +58,24 @@ "tag:Workshop_snort": "{{ec2_name_prefix}}-snort" register: snort_node_facts -- name: grab facts for checkpoint node (SECURITY MODE) +- name: grab facts for Check Point CloudGuard Security Management (SECURITY MODE) ec2_instance_facts: region: "{{ ec2_region }}" filters: instance-state-name: running - "tag:Workshop_checkpoint": "{{ec2_name_prefix}}-checkpoint" + "tag:Workshop_checkpoint_mgmt": "{{ec2_name_prefix}}-checkpoint" register: checkpoint_node_facts -- debug: - var: splunk_node_facts.instances +- name: grab facts for Windows workstation for Check Point (SECURITY MODE) + ec2_instance_facts: + region: "{{ ec2_region }}" + filters: + instance-state-name: running + "tag:Workshop_windows": "{{ec2_name_prefix}}-windows" + register: windows_node_facts -- name: ADD SPLUNK NODE TO INVENTORY + +- name: ADD SNORT NODE TO INVENTORY add_host: name: "{{ item.tags.Name }}" short_name: "{{ item.tags.short_name }}" @@ -35,15 +85,12 @@ ansible_port: "{{ ssh_port }}" ansible_ssh_private_key_file: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" private_ip: "{{item.private_ip_address}}" - #FIXME - need to add to splunk ec2_info in manage_ec2_instances once we have - # a real splunk deployment for the httpapi backend - #ansible_network_os: "{{item.tags.ansible_network_os}}" groups: - - splunk - - siem - loop: "{{ splunk_node_facts.instances|flatten(levels=1) }}" + - snort + - ids + loop: "{{ snort_node_facts.instances|flatten(levels=1) }}" -- name: ADD SNORT NODE TO INVENTORY +- name: ADD Check Point CloudGuard Security Management TO INVENTORY add_host: name: "{{ item.tags.Name }}" short_name: "{{ item.tags.short_name }}" @@ -54,24 +101,26 @@ ansible_ssh_private_key_file: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" private_ip: "{{item.private_ip_address}}" groups: - - snort - - ids - loop: "{{ snort_node_facts.instances|flatten(levels=1) }}" + - checkpoint + - firewall + loop: "{{ checkpoint_node_facts.instances|flatten(levels=1) }}" -- name: ADD CHECKPOINT NODES TO INVENTORY +- name: ADD WINDOWS WORKSTATION TO INVENTORY add_host: name: "{{ item.tags.Name }}" short_name: "{{ item.tags.short_name }}" ansible_host: "{{ item.public_ip_address }}" + ansible_user: Administrator + ansible_password: RedHat19! + ansible_port: 5986 + ansible_connection: winrm + ansible_winrm_server_cert_validation: ignore username: "{{ item.tags.Student }}" - ansible_user: "{{ item.tags.username }}" - ansible_port: "{{ ssh_port }}" - ansible_ssh_private_key_file: "{{ playbook_dir }}/{{ec2_name_prefix}}/{{ec2_name_prefix}}-private.pem" private_ip: "{{item.private_ip_address}}" groups: - - checkpoint - - firewalls - loop: "{{ checkpoint_node_facts.instances|flatten(levels=1) }}" + - windows + - workstation + loop: "{{ windows_node_facts.instances|flatten(levels=1) }}" - name: Generate student inventories template: diff --git a/provisioner/roles/manage_ec2_instances/tasks/ami_find_security.yml b/provisioner/roles/manage_ec2_instances/tasks/ami_find_security.yml new file mode 100644 index 000000000..86bd9da05 --- /dev/null +++ b/provisioner/roles/manage_ec2_instances/tasks/ami_find_security.yml @@ -0,0 +1,97 @@ +#### CHECK POINT AMI +- name: BLOCK FOR SPLUNK AMI + when: security_console == 'splunk' + block: + - name: find ami for splunk + ec2_ami_facts: + region: "us-east-1" # I don't know why but that seems to be the only place it's available + owners: "{{ ec2_info['splunk_enterprise']['owners'] }}" + filters: + name: "{{ ec2_info['splunk_enterprise']['filter'] }}" + architecture: "{{ ec2_info['splunk_enterprise']['architecture'] }}" + register: splunk_amis + + - name: save ami for splunk + set_fact: + splunk_ami: > + {{ splunk_amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} + + +- name: BLOCK FOR QRADAR AMI + when: security_console == 'qradar' + block: + - name: find ami for qradar + ec2_ami_facts: + region: "us-east-1" # I don't know why but that seems to be the only place it's available + owners: "{{ ec2_info['qradar']['owners'] }}" + filters: + name: "{{ ec2_info['qradar']['filter'] }}" + architecture: "{{ ec2_info['qradar']['architecture'] }}" + register: qradar_amis + + - name: save ami for qradar + set_fact: + qradar_ami: > + {{ qradar_amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} + +- name: BLOCK FOR SNORT AMI + block: + - name: find ami for snort + ec2_ami_facts: + region: "{{ ec2_region }}" + owners: "{{ ec2_info['rhel7']['owners'] }}" + filters: + name: "{{ ec2_info['rhel7']['filter'] }}" + architecture: "{{ ec2_info['rhel7']['architecture'] }}" + register: snort_amis + + - name: save ami for snort + set_fact: + snort_ami: > + {{ snort_amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} + +- name: BLOCK FOR CHECK POINT AMI + block: + - name: find ami for check point management server (SECURITY MODE) + ec2_ami_facts: + region: "{{ ec2_region }}" + owners: "{{ ec2_info['checkpoint_mgmt']['owners'] }}" + filters: + name: "{{ ec2_info['checkpoint_mgmt']['filter'] }}" + architecture: "{{ ec2_info['checkpoint_mgmt']['architecture'] }}" + register: checkpoint_mgmt_ami_list + + - name: save ami for check point management server (SECURITY MODE) + set_fact: + checkpoint_mgmt_ami: > + {{ checkpoint_mgmt_ami_list.images | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} + + - name: find ami for check point gateway (SECURITY MODE) + ec2_ami_facts: + region: "{{ ec2_region }}" + owners: "{{ ec2_info['checkpoint_gw']['owners'] }}" + filters: + name: "{{ ec2_info['checkpoint_gw']['filter'] }}" + architecture: "{{ ec2_info['checkpoint_gw']['architecture'] }}" + register: checkpoint_gw_ami_list + + - name: save ami for check point gw (SECURITY MODE) + set_fact: + checkpoint_gw_ami: > + {{ checkpoint_gw_ami_list.images | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} + + +#### WINDOWS WORKSTATION AMI +- name: BLOCK FOR WINDOWS WORKSTATION AMI + block: + - name: find ami for windows workstation + ec2_ami_facts: + region: "{{ ec2_region }}" + filters: + name: "{{ ec2_info['windows_ws']['filter'] }}" + register: windows_ws_amis + + - name: save ami for windows + set_fact: + windows_ws_ami: > + {{ windows_ws_amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} diff --git a/provisioner/roles/manage_ec2_instances/tasks/instances_security.yml b/provisioner/roles/manage_ec2_instances/tasks/instances_security.yml index 96636682e..f5533d20e 100644 --- a/provisioner/roles/manage_ec2_instances/tasks/instances_security.yml +++ b/provisioner/roles/manage_ec2_instances/tasks/instances_security.yml @@ -1,45 +1,121 @@ -- name: find ami for splunk - ec2_ami_facts: - region: "us-east-1" # I don't know why but that seems to be the only place it's available - owners: "{{ ec2_info['splunk_enterprise']['owners'] }}" - filters: - name: "{{ ec2_info['splunk_enterprise']['filter'] }}" - architecture: "{{ ec2_info['splunk_enterprise']['architecture'] }}" - register: amis +- import_tasks: ami_find_security.yml -- name: save ami for splunk - set_fact: - splunk_ami: > - {{ amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} +- name: EC2 Create Block for splunk + when: security_console == 'splunk' + block: + - name: Create EC2 instances for splunk + ec2: + assign_public_ip: yes + key_name: "{{ ec2_name_prefix }}-key" + group: "{{ ec2_security_group }}" + instance_type: "{{ ec2_info['splunk_enterprise']['size'] }}" + image: "{{ splunk_ami['image_id'] }}" + region: "{{ ec2_region }}" + exact_count: "{{ student_total }}" + count_tag: + Workshop_splunk: "{{ec2_name_prefix}}-splunk" + wait: "{{ ec2_wait }}" + vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" + volumes: + - device_name: /dev/sda1 + volume_type: gp2 + volume_size: "{{ ec2_info['splunk_enterprise']['disk_space'] }}" + delete_on_termination: true + register: splunk_output -- name: Create EC2 instances for splunk + - name: Ensure tags are present for splunk + ec2_tag: + region: "{{ ec2_region }}" + resource: "{{item[1]}}" + state: present + tags: + Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-splunk" + Workshop_splunk: "{{ec2_name_prefix}}-splunk" + Workshop: "{{ec2_name_prefix}}" + Index: "{{ item[0] }}" + Student: "student{{item[0] + 1}}" + AWS_USERNAME: "{{ linklight_user }}" + Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" + Linklight: "This was provisioned through the linklight provisioner" + Students: "{{student_total}}" + short_name: "splunk" + username: '{{ec2_info["rhel7"]["username"]}}' + with_indexed_items: + - "{{ splunk_output['instance_ids'] }}" + when: splunk_output['instance_ids'] is not none + +- name: EC2 Create Block for qradar + when: security_console == 'qradar' + block: + - name: Create EC2 instances for qradar + ec2: + assign_public_ip: yes + key_name: "{{ ec2_name_prefix }}-key" + group: "{{ ec2_security_group }}" + instance_type: "{{ ec2_info['qradar']['size'] }}" + image: "{{ qradar_ami['image_id'] }}" + region: "{{ ec2_region }}" + exact_count: "{{ student_total }}" + count_tag: + Workshop_qradar: "{{ec2_name_prefix}}-qradar" + wait: "{{ ec2_wait }}" + vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" + volumes: + - device_name: /dev/sda1 + volume_type: gp2 + volume_size: "{{ ec2_info['qradar']['disk_space'] }}" + delete_on_termination: true + register: qradar_output + + - name: Ensure tags are present for qradar + ec2_tag: + region: "{{ ec2_region }}" + resource: "{{item[1]}}" + state: present + tags: + Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-qradar" + Workshop_qradar: "{{ec2_name_prefix}}-qradar" + Workshop: "{{ec2_name_prefix}}" + Index: "{{ item[0] }}" + Student: "student{{item[0] + 1}}" + AWS_USERNAME: "{{ linklight_user }}" + Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" + Linklight: "This was provisioned through the linklight provisioner" + Students: "{{student_total}}" + short_name: "qradar" + username: '{{ec2_info["rhel7"]["username"]}}' + with_indexed_items: + - "{{ qradar_output['instance_ids'] }}" + when: qradar_output['instance_ids'] is not none + +- name: Create EC2 instances for snort ec2: assign_public_ip: yes key_name: "{{ ec2_name_prefix }}-key" group: "{{ ec2_security_group }}" - instance_type: "{{ ec2_info['splunk_enterprise']['size'] }}" - image: "{{ splunk_ami['image_id'] }}" + instance_type: "{{ ec2_info['rhel7']['size'] }}" + image: "{{ snort_ami['image_id'] }}" region: "{{ ec2_region }}" exact_count: "{{ student_total }}" count_tag: - Workshop_splunk: "{{ec2_name_prefix}}-splunk" + Workshop_snort: "{{ec2_name_prefix}}-snort" wait: "{{ ec2_wait }}" vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" volumes: - device_name: /dev/sda1 volume_type: gp2 - volume_size: "{{ ec2_info['splunk_enterprise']['disk_space'] }}" + volume_size: "{{ ec2_info['rhel7']['disk_space'] }}" delete_on_termination: true - register: splunk_output + register: snort_output -- name: Ensure tags are present for splunk +- name: Ensure tags are present for snort ec2_tag: region: "{{ ec2_region }}" resource: "{{item[1]}}" state: present tags: - Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-splunk" - Workshop_splunk: "{{ec2_name_prefix}}-splunk" + Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-snort" + Workshop_snort: "{{ec2_name_prefix}}-snort" Workshop: "{{ec2_name_prefix}}" Index: "{{ item[0] }}" Student: "student{{item[0] + 1}}" @@ -47,118 +123,123 @@ Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" Linklight: "This was provisioned through the linklight provisioner" Students: "{{student_total}}" - short_name: "splunk" + short_name: "snort" username: '{{ec2_info["rhel7"]["username"]}}' with_indexed_items: - - "{{ splunk_output['instance_ids'] }}" - when: splunk_output['instance_ids'] is not none + - "{{ snort_output['instance_ids'] }}" + when: snort_output['instance_ids'] is not none -- name: find ami for snort - ec2_ami_facts: +##############Check Point CloudGuard IaaS Security Management############## +- name: Create EC2 instances for Check Point CloudGuard Security Management + ec2: + assign_public_ip: yes + key_name: "{{ ec2_name_prefix }}-key" + group: "{{ ec2_security_group }}" + instance_type: "{{ec2_info.checkpoint_mgmt.size }}" + image: "{{ec2_info.checkpoint_mgmt.ami.image_id}}" region: "{{ ec2_region }}" - owners: "{{ ec2_info['rhel7']['owners'] }}" - filters: - name: "{{ ec2_info['rhel7']['filter'] }}" - architecture: "{{ ec2_info['rhel7']['architecture'] }}" - register: amis + exact_count: "{{ student_total }}" + user_data: "{{ lookup('template', 'gaia-mgmt-ftw-user-data.sh.j2') }}" + count_tag: + Workshop_checkpoint_mgmt: "{{ec2_name_prefix}}-checkpoint" + wait: "{{ ec2_wait }}" + vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" + register: checkpoint_mgmt_output -- name: save ami for snort - set_fact: - snort_ami: > - {{ amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} +- name: Ensure tags are present for Check Point CloudGuard Security Management node (SECURITY MODE) + ec2_tag: + region: "{{ ec2_region }}" + resource: "{{item.1}}" + state: present + tags: + Name: "{{ ec2_name_prefix }}-student{{item.0 + 1}}-checkpoint_mgmt" + Workshop_checkpoint_mgmt: "{{ec2_name_prefix}}-checkpoint" + Workshop: "{{ec2_name_prefix}}" + Index: "{{ item[0] }}" + Student: "student{{item.0 + 1}}" + AWS_USERNAME: "{{ linklight_user }}" + Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" + Linklight: "This was provisioned through the linklight provisioner" + Students: "{{student_total}}" + short_name: "checkpoint_mgmt" + username: "{{ec2_info.checkpoint_mgmt.username}}" + with_indexed_items: + - "{{ checkpoint_mgmt_output.instance_ids }}" + when: checkpoint_mgmt_output.instance_ids is not none -- name: Create EC2 instances for snort +##############Check Point CloudGuard IaaS Gateway ############## +- name: Create EC2 instances for Check Point CloudGuard Gateway ec2: assign_public_ip: yes key_name: "{{ ec2_name_prefix }}-key" group: "{{ ec2_security_group }}" - instance_type: "{{ ec2_info['rhel7']['size'] }}" - image: "{{ snort_ami['image_id'] }}" + instance_type: "{{ec2_info.checkpoint_gw.size }}" + image: "{{ec2_info.checkpoint_gw.ami.image_id}}" region: "{{ ec2_region }}" exact_count: "{{ student_total }}" + user_data: "{{ lookup('template', 'gaia-ftw-user-data.sh.j2') }}" count_tag: - Workshop_snort: "{{ec2_name_prefix}}-snort" + Workshop_checkpoint_gw: "{{ec2_name_prefix}}-checkpoint" wait: "{{ ec2_wait }}" vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" - volumes: - - device_name: /dev/sda1 - volume_type: gp2 - volume_size: "{{ ec2_info['rhel7']['disk_space'] }}" - delete_on_termination: true - register: snort_output + register: checkpoint_gw_output -- name: Ensure tags are present for snort +- name: Ensure tags are present for Check Point CloudGuard Gateway node (SECURITY MODE) ec2_tag: region: "{{ ec2_region }}" - resource: "{{item[1]}}" + resource: "{{item.1}}" state: present tags: - Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-snort" - Workshop_snort: "{{ec2_name_prefix}}-snort" + Name: "{{ ec2_name_prefix }}-student{{item.0 + 1}}-checkpoint_gw" + Workshop_checkpoint_gw: "{{ec2_name_prefix}}-checkpoint" Workshop: "{{ec2_name_prefix}}" Index: "{{ item[0] }}" - Student: "student{{item[0] + 1}}" + Student: "student{{item.0 + 1}}" AWS_USERNAME: "{{ linklight_user }}" Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" Linklight: "This was provisioned through the linklight provisioner" Students: "{{student_total}}" - short_name: "snort" - username: '{{ec2_info["rhel7"]["username"]}}' + short_name: "checkpoint_gw" + username: "{{ec2_info.checkpoint_gw.username}}" with_indexed_items: - - "{{ snort_output['instance_ids'] }}" - when: snort_output['instance_ids'] is not none - -- name: find ami for checkpoint - ec2_ami_facts: - region: "{{ ec2_region }}" - owners: "{{ ec2_info['checkpoint_firewall']['owners'] }}" - filters: - name: "{{ ec2_info['rhel7']['filter'] }}" - architecture: "{{ ec2_info['checkpoint_firewall']['architecture'] }}" - register: amis + - "{{ checkpoint_gw_output.instance_ids }}" + when: checkpoint_gw_output.instance_ids is not none -- name: save ami for checkpoint - set_fact: - checkpoint_ami: > - {{ amis['images'] | selectattr('name', 'defined') | sort(attribute='creation_date') | last }} +############## Windows Workstation ############## -- name: Create EC2 instances for checkpoint +- name: Create EC2 instances for Windows Workstation (SECURITY MODE) ec2: assign_public_ip: yes key_name: "{{ ec2_name_prefix }}-key" group: "{{ ec2_security_group }}" - instance_type: "{{ ec2_info['checkpoint_firewall']['size'] }}" - image: "{{ checkpoint_ami['image_id'] }}" + instance_type: "{{ec2_info.windows_ws.size }}" + image: "{{ec2_info.windows_ws.ami.image_id}}" region: "{{ ec2_region }}" exact_count: "{{ student_total }}" + user_data: "{{ lookup('template', 'windows_userdata.txt.j2') }}" count_tag: - Workshop_checkpoint: "{{ec2_name_prefix}}-checkpoint" + Workshop_windows: "{{ec2_name_prefix}}-windows" wait: "{{ ec2_wait }}" vpc_subnet_id: "{{ ec2_vpc_subnet_id }}" - volumes: - - device_name: /dev/sda1 - volume_type: gp2 - volume_size: "{{ ec2_info['checkpoint_firewall']['disk_space'] }}" - delete_on_termination: true - register: checkpoint_output + register: windows_ws_output -- name: Ensure tags are present for checkpoint +- name: Ensure tags are present for Windows Workstation (SECURITY MODE) ec2_tag: region: "{{ ec2_region }}" - resource: "{{item[1]}}" + resource: "{{item.1}}" state: present tags: - Name: "{{ ec2_name_prefix }}-student{{item[0] + 1}}-checkpoint" - Workshop_checkpoint: "{{ec2_name_prefix}}-checkpoint" + Name: "{{ ec2_name_prefix }}-student{{item.0 + 1}}-windows_ws" + Workshop_windows: "{{ec2_name_prefix}}-windows" Workshop: "{{ec2_name_prefix}}" Index: "{{ item[0] }}" - Student: "student{{item[0] + 1}}" + Student: "student{{item.0 + 1}}" AWS_USERNAME: "{{ linklight_user }}" Info: "AWS_USERNAME that provisioned this-> {{ linklight_user }}" Linklight: "This was provisioned through the linklight provisioner" Students: "{{student_total}}" - short_name: "checkpoint" - username: '{{ec2_info["rhel7"]["username"]}}' + short_name: "windows_ws" + username: "{{ec2_info.windows_ws.username}}" with_indexed_items: - - "{{ checkpoint_output['instance_ids'] }}" - when: checkpoint_output['instance_ids'] is not none + - "{{ windows_ws_output.instance_ids }}" + when: windows_ws_output.instance_ids is not none diff --git a/provisioner/roles/manage_ec2_instances/tasks/resources.yml b/provisioner/roles/manage_ec2_instances/tasks/resources.yml index 981168b45..43037349c 100644 --- a/provisioner/roles/manage_ec2_instances/tasks/resources.yml +++ b/provisioner/roles/manage_ec2_instances/tasks/resources.yml @@ -81,6 +81,91 @@ to_port: 179 from_port: 179 cidr_ip: 0.0.0.0/0 + - proto: tcp + to_port: 256 + from_port: 256 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point fetch policy + - proto: tcp + to_port: 257 + from_port: 257 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point logging + - proto: tcp + to_port: 18183 + from_port: 18183 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point FW1 sam + - proto: tcp + to_port: 18190 + from_port: 18190 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point SmartConsole CPMI + - proto: tcp + to_port: 18191 + from_port: 18191 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point SIC policy inst + - proto: tcp + to_port: 18192 + from_port: 18192 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point SIC get topology + - proto: tcp + to_port: 18194 + from_port: 18194 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point temain + - proto: tcp + to_port: 18202 + from_port: 18202 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point CP RTM + - proto: tcp + to_port: 18208 + from_port: 18208 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point FW1 remote install + - proto: tcp + to_port: 18209 + from_port: 18209 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point + - proto: tcp + to_port: 18210 + from_port: 18210 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point FW ICA pull + - proto: tcp + to_port: 18211 + from_port: 18211 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point SIC ICA push + - proto: tcp + to_port: 18221 + from_port: 18221 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point CP redundant + - proto: tcp + to_port: 18264 + from_port: 18264 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point FW ICA services + - proto: tcp + to_port: 18266 + from_port: 18266 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point seam + - proto: tcp + to_port: 19009 + from_port: 19009 + cidr_ip: 0.0.0.0/0 + rule_desc: Check Point SmartConsole CPMI + - proto: tcp + to_port: 5986 + from_port: 5986 + cidr_ip: 0.0.0.0/0 + rule_desc: WinRM rules_egress: - proto: all cidr_ip: 0.0.0.0/0 diff --git a/provisioner/roles/manage_ec2_instances/templates/gaia-ftw-user-data.sh.j2 b/provisioner/roles/manage_ec2_instances/templates/gaia-ftw-user-data.sh.j2 new file mode 100644 index 000000000..dc73d252a --- /dev/null +++ b/provisioner/roles/manage_ec2_instances/templates/gaia-ftw-user-data.sh.j2 @@ -0,0 +1,36 @@ +#!/bin/bash + +# gaia-ftw-user-data.sh + +# all set to admin123 +SIC_KEY='admin123' +ADMIN_HASH='$6$0rVzHRkDOMwsB9cP$dm60oGLtEfgNGZK.WiiECa4FP3MPBbhob.oG.a33LyoEZvlbfL.5AFRzKmzRB4OQq0rgDF4JymvibXz3hNB2z/' +ADMIN_PW='admin123' + +FTW_LOG=/var/log/ftw.log +BLINK_CONF=/home/admin/blink.conf + +# Gaia first time wizard +if [ -e "/bin/blink_config" ]; then + echo "Configuring Image Using Blink_Config" | tee /dev/console >> $FTW_LOG + blink_config -t $BLINK_CONF + sed -i 's:download_info=".*":download_info="true":g' $BLINK_CONF + sed -i 's:upload_info=".*":upload_info="true":g' $BLINK_CONF + sed -i "s:ftw_sic_key='':ftw_sic_key='$SIC_KEY':g" $BLINK_CONF + sed -i "s:admin_hash='':admin_hash='$ADMIN_HASH':g" $BLINK_CONF + #sed -i "s:admin_password_regular='':admin_password_regular='$ADMIN_PW':g" $BLINK_CONF + echo "##### BLINK CONF #####" >> $FTW_LOG + cat $BLINK_CONF >> $FTW_LOG + echo "##### END BLINK CONF #####" >> $FTW_LOG + blink_config -f $BLINK_CONF --dry-run >> $FTW_LOG 2>&1 + blink_config -f $BLINK_CONF >> $FTW_LOG 2>&1 +else + echo "Configuring Image Using Config_System" | tee /dev/console >> $FTW_LOG + config_system -s "install_security_gw=true&install_ppak=true&gateway_cluster_member=false&install_security_managment=false&ftw_sic_key=$SIC_KEY" >> $FTW_LOG 2>&1 + clish -c "lock database override" + clish -c "set user admin password-hash $ADMIN_PW_HASH" -s +fi + +# more clish customization below +#clish -c "lock database override" +#clish -c "set user admin shell /bin/bash" -s diff --git a/provisioner/roles/manage_ec2_instances/templates/gaia-mgmt-ftw-user-data.sh.j2 b/provisioner/roles/manage_ec2_instances/templates/gaia-mgmt-ftw-user-data.sh.j2 new file mode 100644 index 000000000..478120f49 --- /dev/null +++ b/provisioner/roles/manage_ec2_instances/templates/gaia-mgmt-ftw-user-data.sh.j2 @@ -0,0 +1,99 @@ +#!/bin/bash + +# gaia-mgmt-ftw-user-data.sh + +# all set to admin123 +SIC_KEY='admin123' +ADMIN_HASH='$6$0rVzHRkDOMwsB9cP$dm60oGLtEfgNGZK.WiiECa4FP3MPBbhob.oG.a33LyoEZvlbfL.5AFRzKmzRB4OQq0rgDF4JymvibXz3hNB2z/' +ADMIN_PW='admin123' + +FTW_LOG=/var/log/ftw.log +BLINK_CONF=/home/admin/blink.conf +NEWSYS_CONF=/home/admin/newsys.conf + +# Gaia first time wizard for a management server +if [ -e "/bin/blink_config" ]; then + echo "Configuring Image Using Blink_Config" | tee /dev/console >> $FTW_LOG + echo "TODO: Implement management server configuration via Blink" | tee /dev/console >> $FTW_LOG + #blink_config -t $BLINK_CONF + #sed -i 's:download_info=".*":download_info="true":g' $BLINK_CONF + #sed -i 's:upload_info=".*":upload_info="true":g' $BLINK_CONF + #sed -i "s:ftw_sic_key='':ftw_sic_key='$SIC_KEY':g" $BLINK_CONF + #sed -i "s:admin_hash='':admin_hash='$ADMIN_HASH':g" $BLINK_CONF + #sed -i "s:admin_password_regular='':admin_password_regular='$ADMIN_PW':g" $BLINK_CONF + #echo "##### BLINK CONF #####" >> $FTW_LOG + #cat $BLINK_CONF >> $FTW_LOG + #echo "##### END BLINK CONF #####" >> $FTW_LOG + #blink_config -f $BLINK_CONF --dry-run >> $FTW_LOG 2>&1 + #blink_config -f $BLINK_CONF >> $FTW_LOG 2>&1 +else + echo "Configuring Image Using Config_System" | tee /dev/console >> $FTW_LOG + config_system -t $NEWSYS_CONF + sed -i 's:install_security_gw=:install_security_gw="false":g' $NEWSYS_CONF + # IMPORTANT: There is a typo in the template file so don't change the next line + sed -i 's:install_security_managment=:install_security_managment="true":g' $NEWSYS_CONF + sed -i 's:install_mgmt_primary=:install_mgmt_primary="true":g' $NEWSYS_CONF + sed -i 's:download_info=".*":download_info="true":g' $NEWSYS_CONF + sed -i 's:upload_info=".*":upload_info="true":g' $NEWSYS_CONF + sed -i 's:mgmt_admin_radio=:mgmt_admin_radio="gaia_admin":g' $NEWSYS_CONF + sed -i 's:mgmt_gui_clients_radio=:mgmt_gui_clients_radio="any":g' $NEWSYS_CONF + sed -i "s:admin_hash='':admin_hash='$ADMIN_HASH':g" $NEWSYS_CONF + sed -i 's:reboot_if_required=:reboot_if_required="false":g' $NEWSYS_CONF + echo "##### NEWSYS CONF #####" >> $FTW_LOG + cat $NEWSYS_CONF >> $FTW_LOG + echo "##### END NEWSYS CONF #####" >> $FTW_LOG + config_system -f $NEWSYS_CONF --dry-run >> $FTW_LOG 2>&1 + config_system -f $NEWSYS_CONF >> $FTW_LOG 2>&1 +fi + +# more clish customization below +clish -c "lock database override" +clish -c "set user admin shell /bin/bash" -s + +# allow incoming web API calls from anywhere +if [ ! -d /home/admin/bin ]; then + mkdir /home/admin/bin +fi +cat << 'EOF' > /home/admin/bin/open-web-api.sh +#!/bin/bash + +# open-web-api.sh + +LOG_FILE=/var/log/open-web-api.log + +start_time=$(date) + +echo "$start_time" > $LOG_FILE + +while true; do + api_status=$(api status |grep "Overall API Status" |awk -F ": " '{ print $2 }') + if [ "$api_status" == "Started" ]; then + echo "API has been started" >> $LOG_FILE + api_access=$(api status |grep "Access" |awk -F "ip " '{ print $2 }' |tr -d '[:space:]') + if [ "$api_access" == "127.0.0.1" ]; then + echo "API access set to localhost only" >> $LOG_FILE + mgmt_cli -r true set api-settings accepted-api-calls-from "All IP addresses" --domain 'System Data' --format json >> $LOG_FILE 2>&1 + api restart >> $LOG_FILE 2>&1 + else + api_access=$(api status |grep "Access") + echo "$api_access" >> $LOG_FILE + fi + break + else + echo "API not started" >> $LOG_FILE + sleep 5 + fi +done + +exit 0 +EOF + +chmod +x /home/admin/bin/open-web-api.sh + +cat << 'EOL' >> /etc/rc.local + +# Allow incoming web API calls +/home/admin/bin/open-web-api.sh & +EOL + +shutdown -r now diff --git a/provisioner/roles/manage_ec2_instances/templates/instructor_inventory_security.j2 b/provisioner/roles/manage_ec2_instances/templates/instructor_inventory_security.j2 index 4f7e0faf4..3518d05d1 100644 --- a/provisioner/roles/manage_ec2_instances/templates/instructor_inventory_security.j2 +++ b/provisioner/roles/manage_ec2_instances/templates/instructor_inventory_security.j2 @@ -10,11 +10,20 @@ ansible_port={{ ssh_port }} {{host.tags.Student}}-ansible ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} {% endif %} {% endfor %} +{% if security_console == 'splunk' %} {% for host in splunk_node_facts.instances %} {% if 'student' ~ number == host.tags.Student %} {{host.tags.Student}}-splunk ansible_host={{ host.public_ip_address }} ansible_user=admin {% endif %} {% endfor %} +{% endif %} +{% if security_console == 'qradar' %} +{% for host in qradar_node_facts.instances %} +{% if 'student' ~ number == host.tags.Student %} +{{host.tags.Student}}-qradar ansible_host={{ host.public_ip_address }} ansible_user=admin +{% endif %} +{% endfor %} +{% endif %} {% for host in snort_node_facts.instances %} {% if 'student' ~ number == host.tags.Student %} {{host.tags.Student}}-snort ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} @@ -22,7 +31,12 @@ ansible_port={{ ssh_port }} {% endfor %} {% for host in checkpoint_node_facts.instances %} {% if 'student' ~ number == host.tags.Student %} -{{host.tags.Student}}-checkpoint ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} +{{host.tags.Student}}-checkpoint ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} ansible_password=admin123 ansible_network_os=checkpoint ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=no +{% endif %} +{% endfor %} +{% for host in windows_node_facts.instances %} +{% if 'student' ~ number == host.tags.Student %} +{{host.tags.Student}}-windows-ws ansible_host={{ host.public_ip_address }} ansible_user=Administrator ansible_port=5986 ansible_connection=winrm ansible_winrm_server_cert_validation=ignore {% endif %} {% endfor %} {% endfor %} diff --git a/provisioner/roles/manage_ec2_instances/templates/security_instances.txt.j2 b/provisioner/roles/manage_ec2_instances/templates/security_instances.txt.j2 index c0f02c378..9bff9ac48 100644 --- a/provisioner/roles/manage_ec2_instances/templates/security_instances.txt.j2 +++ b/provisioner/roles/manage_ec2_instances/templates/security_instances.txt.j2 @@ -5,19 +5,28 @@ ansible_ssh_pass={{ admin_password }} ansible_port={{ ssh_port }} {% endif %} +[control] +{% for vm in ansible_node_facts.instances %} +{% if 'student' + item == vm.tags.Student %} +ansible ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username }} private_ip={{ vm.private_ip_address }} +{% endif %} +{% endfor %} + [siem] +{% if security_console == 'splunk' %} {% for vm in splunk_node_facts.instances %} {% if 'student' + item == vm.tags.Student %} -splunk ansible_host={{ vm.public_ip_address }} ansible_user=admin private_ip={{ vm.private_ip_address }} ansible_ssh_pass=admin +splunk ansible_host={{ vm.public_ip_address }} ansible_user=admin private_ip={{ vm.private_ip_address }} ansible_httpapi_pass="Ansible1!" ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=False ansible_network_os=splunk.enterprise_security.splunk {% endif %} {% endfor %} - -[control] -{% for vm in ansible_node_facts.instances %} +{% endif %} +{% if security_console == 'qradar' %} +{% for vm in qradar_node_facts.instances %} {% if 'student' + item == vm.tags.Student %} -ansible ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username }} private_ip={{ vm.private_ip_address }} +qradar ansible_host={{ vm.public_ip_address }} ansible_user=admin private_ip={{ vm.private_ip_address }} ansible_httpapi_pass="Ansible1!" ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=False ansible_network_os=ibm.qradar.qradar {% endif %} {% endfor %} +{% endif %} [ids] {% for vm in snort_node_facts.instances %} @@ -26,9 +35,16 @@ snort ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username } {% endif %} {% endfor %} -[firewalls] +[firewall] {% for vm in checkpoint_node_facts.instances %} {% if 'student' + item == vm.tags.Student %} -checkpoint ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username }} private_ip={{ vm.private_ip_address }} +checkpoint ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username }} ansible_password=admin123 private_ip={{ vm.private_ip_address }} ansible_network_os=checkpoint ansible_connection=httpapi ansible_httpapi_use_ssl=yes ansible_httpapi_validate_certs=no +{% endif %} +{% endfor %} + +[windows] +{% for vm in windows_node_facts.instances %} +{% if 'student' + item == vm.tags.Student %} +windows-ws ansible_host={{ vm.public_ip_address }} ansible_user={{ vm.tags.username }} ansible_pass={{ windows_password}} ansible_port=5986 ansible_connection=winrm ansible_winrm_server_cert_validation=ignore private_ip={{ vm.private_ip_address }} {% endif %} {% endfor %} diff --git a/provisioner/roles/manage_ec2_instances/templates/security_instructor_inventory.j2 b/provisioner/roles/manage_ec2_instances/templates/security_instructor_inventory.j2 deleted file mode 100644 index 8cf967b0d..000000000 --- a/provisioner/roles/manage_ec2_instances/templates/security_instructor_inventory.j2 +++ /dev/null @@ -1,28 +0,0 @@ -[all:vars] -{% if ssh_port is defined %} -ansible_port={{ ssh_port }} -{% endif %} - -{% for number in range(1,student_total + 1) %} -[student{{ number }}] -{% for host in ansible_node_facts.instances %} -{% if 'student' ~ number == host.tags.Student %} -{{ host.tags.Name | regex_replace(ec2_name_prefix ~ '-','') }} ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} -{% endif %} -{% endfor %} -{% for host in splunk_node_facts.instances %} -{% if 'student' ~ number == host.tags.Student %} -{{ host.tags.Name | regex_replace(ec2_name_prefix ~ '-','') }} ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} -{% endif %} -{% endfor %} -{% for host in snort_node_facts.instances %} -{% if 'student' ~ number == host.tags.Student %} -{{ host.tags.Name | regex_replace(ec2_name_prefix ~ '-','') }} ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} -{% endif %} -{% endfor %} -{% for host in checkpoint_node_facts.instances %} -{% if 'student' ~ number == host.tags.Student %} -{{ host.tags.Name | regex_replace(ec2_name_prefix ~ '-','') }} ansible_host={{ host.public_ip_address }} ansible_user={{ host.tags.username }} -{% endif %} -{% endfor %} -{% endfor %} diff --git a/provisioner/roles/manage_ec2_instances/templates/windows_userdata.txt.j2 b/provisioner/roles/manage_ec2_instances/templates/windows_userdata.txt.j2 new file mode 100644 index 000000000..8583eadfd --- /dev/null +++ b/provisioner/roles/manage_ec2_instances/templates/windows_userdata.txt.j2 @@ -0,0 +1,19 @@ + +# Disable .Net Optimization Service +Get-ScheduledTask *ngen* | Disable-ScheduledTask + +# Disable Windows Auto Updates +# https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/troubleshooting-windows-instances.html#high-cpu-issue +reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUOptions /t REG_DWORD /d 1 /f net stop wuauserv net start wuauserv + +# Disable Windows Defender Monitoring +Set-MpPreference -DisableRealtimeMonitoring $true + +# Enable WinRM +Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\ConfigureRemotingForAnsible.ps1 +C:\ConfigureRemotingForAnsible.ps1 -ForceNewSSLCert -EnableCredSSP + +# Set Administrator Password +$admin = [adsi]("WinNT://./administrator, user") +$admin.PSBase.Invoke("SetPassword", "{{ windows_password }}") + diff --git a/provisioner/roles/windows_ws_setup/files/setup.iss b/provisioner/roles/windows_ws_setup/files/setup.iss new file mode 100644 index 000000000..026808fb7 --- /dev/null +++ b/provisioner/roles/windows_ws_setup/files/setup.iss @@ -0,0 +1,60 @@ +[InstallShield Silent] +Version=v7.00 +File=Response File +[File Transfer] +OverwrittenReadOnly=NoToAll +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-DlgOrder] +Dlg0={ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdWelcome-0 +Count=5 +Dlg1={ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdLicense-0 +Dlg2={ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdAskDestPath-0 +Dlg3={ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdComponentTree-0 +Dlg4={ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdFinish-0 +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdWelcome-0] +Result=1 +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdLicense-0] +Result=1 +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdAskDestPath-0] +szDir=C:\Program Files (x86)\CheckPoint\SmartConsole\R80.20 +Result=1 +[Application] +Name=Management Clients +Version=6.5.9 +Company=CheckPoint +Lang=0409 +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdComponentTree-0] +szDir=C:\Program Files (x86)\CheckPoint\SmartConsole\R80.20 +_COMPONENT1-type=string +_COMPONENT1-count=6 +_COMPONENT1-0=_COMPONENT1\SmartDefense +_COMPONENT1-1=_COMPONENT1\SmartMap +_COMPONENT1-2=_COMPONENT1\VPN Manager +_COMPONENT1-3=_COMPONENT1\Policy Manager +_COMPONENT1-4=_COMPONENT1\Users Manager +_COMPONENT1-5=_COMPONENT1\Objects Manager +Component-type=string +Component-count=19 +Component-0=_COMPONENT16 +Component-1=_COMPONENT1 +Component-2=_COMPONENT14 +Component-3=_COMPONENT12 +Component-4=_COMPONENT13 +Component-5=_COMPONENT3 +Component-6=_COMPONENT4 +Component-7=_COMPONENT6 +Component-8=_COMPONENT9 +Component-9=_COMPONENT15 +Component-10=_COMPONENT2 +Component-11=_COMPONENT10 +Component-12=_COMPONENT7 +Component-13=_COMPONENT5 +Component-14=_COMPONENT11 +Component-15=_TARGETDIR +Component-16=_WINSYSDIR +Component-17=_DEF +Component-18=SU +Result=1 +[{ABB7C1A6-F100-45DD-B6C1-622F44B7C00A}-SdFinish-0] +Result=1 +bOpt1=0 +bOpt2=0 diff --git a/provisioner/roles/windows_ws_setup/tasks/chrome.yml b/provisioner/roles/windows_ws_setup/tasks/chrome.yml new file mode 100644 index 000000000..5a0ced9fa --- /dev/null +++ b/provisioner/roles/windows_ws_setup/tasks/chrome.yml @@ -0,0 +1,51 @@ +--- +- name: install Chocolatey + win_chocolatey: + name: chocolatey + state: present + +- name: disable enhanced exit codes + win_chocolatey_feature: + name: useEnhancedExitCodes + state: disabled + when: ansible_version.full is version_compare('2.8', '<') + +- name: Install Chrome + win_chocolatey: + name: "{{ item }}" + ignore_checksums: true + with_items: + - googlechrome + +- name: Set Chrome to default Browser + win_regedit: + path: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\{{ item }}\UserChoice + name: ProgId + data: ChromeHTML + with_items: + - http + - https + +- name: Set Chrome to not ask about default browser + win_regedit: + path: HKLM:\Software\Policies\Google\Chrome + name: DefaultBrowserSettingEnabled + data: 0 + type: dword + +- name: Disable Chrome Welcome Screen + win_regedit: + path: HKLM:\Software\Policies\Google\Chrome + name: "{{ item }}" + data: 0 + type: dword + with_items: + - PromotionalTabsEnabled + - WelcomePageOnOSUpgradeEnabled + +- name: Disable Chrome Syncing + win_regedit: + path: HKLM:\Software\Policies\Google\Chrome + name: SyncDisabled + data: 1 + type: dword diff --git a/provisioner/roles/windows_ws_setup/tasks/main.yml b/provisioner/roles/windows_ws_setup/tasks/main.yml new file mode 100644 index 000000000..53b1936b8 --- /dev/null +++ b/provisioner/roles/windows_ws_setup/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- include_tasks: chrome.yml +- include_tasks: server_mgmt.yml +- include_tasks: myrtille.yml +- include_tasks: smartconsole.yml diff --git a/provisioner/roles/windows_ws_setup/tasks/myrtille.yml b/provisioner/roles/windows_ws_setup/tasks/myrtille.yml new file mode 100644 index 000000000..5b1fdf21d --- /dev/null +++ b/provisioner/roles/windows_ws_setup/tasks/myrtille.yml @@ -0,0 +1,77 @@ +--- +- name: Install IIS and .Net 4.5 on Server + win_feature: + name: + - Web-Server + - NET-Framework-Core +# - Application-Server + - Web-Asp-Net45 + include_management_tools: True + state: present + when: "'Windows 10' not in ansible_distribution" + +- name: Install IIS and .Net 4.5 on Non-Server + win_dsc: + resource_name: WindowsOptionalFeature + Name: "{{ item }}" + Ensure: Enable + when: "'Windows 10' in ansible_distribution" + loop: + - IIS-WebServerRole + - IIS-WebServer + - NetFx4Extended-ASPNET45 + - IIS-NetFxExtensibility45 + - IIS-ISAPIExtensions + - IIS-ISAPIFilter + - IIS-ASPNET45 + +- name: Create temp directory + win_file: + path: C:\Temp\ + state: directory + +- name: Check if Myrtille is downloaded + win_stat: + path: C:\Temp\Myrtille_2.5.5_x86_x64_Setup.exe + register: myrtille + +- name: Download Myrtille to specified path only if modified + win_get_url: + url: https://s3.amazonaws.com/linklight.securityautomation/Myrtille_2.5.5_x86_x64_Setup.exe + dest: C:\Temp\Myrtille_2.5.5_x86_x64_Setup.exe + checksum: e95438ea3ae5f4363b43a6e2134df771c3d2a213 + force: yes + when: not myrtille.stat.exists + register: win_get_myrtille + until: win_get_myrtille is success + retries: 5 + +- name: Extract the binary + win_command: Myrtille_2.5.5_x86_x64_Setup.exe -o "C:\Temp" -y + args: + chdir: C:\Temp\ + creates: C:\Temp\setup.exe + +- name: Install Myrtille + win_package: + path: C:\Temp\setup.exe + arguments: /q + creates_path: C:\Program Files (x86)\Myrtille + +- name: Disable NTLM RDP Authetication requirement + win_regedit: + path: HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp + name: "{{ item }}" + data: 0 + type: dword + with_items: + - SecurityLayer + - UserAuthentication + +- name: Create RDP Application + win_iis_webapplication: + name: rdp + site: Default Web Site + application_pool: MyrtilleAppPool + physical_path: C:\Program Files (x86)\Myrtille\ + state: present diff --git a/provisioner/roles/windows_ws_setup/tasks/server_mgmt.yml b/provisioner/roles/windows_ws_setup/tasks/server_mgmt.yml new file mode 100644 index 000000000..943975e9c --- /dev/null +++ b/provisioner/roles/windows_ws_setup/tasks/server_mgmt.yml @@ -0,0 +1,20 @@ +--- +- name: Disable Server Management at Startup + win_regedit: + path: HKCU:\Software\Microsoft\ServerManager\ + name: DoNotOpenServerManagerAtLogon + data: 1 + type: dword + +- name: Remove EC2 Feedback Icon + win_file: + path: C:\Users\Administrator\Desktop\EC2 Feedback.website + state: absent + +- name: Remove EC2 Website Icon + win_file: + path: C:\Users\Administrator\Desktop\EC2 Microsoft Windows Guide.website + state: absent + +- name: Remove network notice + win_command: netsh advfirewall firewall set rule group="Network Discovery" new enable=No diff --git a/provisioner/roles/windows_ws_setup/tasks/smartconsole.yml b/provisioner/roles/windows_ws_setup/tasks/smartconsole.yml new file mode 100644 index 000000000..ff061dfa7 --- /dev/null +++ b/provisioner/roles/windows_ws_setup/tasks/smartconsole.yml @@ -0,0 +1,44 @@ +--- +- block: + - name: Download Microsoft Visual C++ Redistributable Packages needed for SmartConsole + win_chocolatey: + name: + - vcredist2010 + - vcredist2012 + state: present + + - name: Ensure the required NuGet package provider version is installed + win_shell: Find-PackageProvider -Name Nuget -ForceBootstrap -IncludeDependencies -Force + + - name: Install Pscx needed for unzip step later + win_psmodule: + name: pscx + allow_clobber: true + + - name: Get SmartConsole download link from CheckPoint support page + win_uri: + url: https://supportcenter.checkpoint.com/supportcenter/portal?action=portlets.DCFileAction&eventSubmit_doGetdcdetails=&fileid=94524 + return_content: yes + register: filepage_data + + - name: Download SmartConsole from CheckPoint support page + win_get_url: + url: "{{ filepage_data.content | regex_search('http://([a-z0-9]{1,3}).checkpoint.com/paid/20/([a-z0-9]{1,35})/Check_Point_SmartConsole_R80_20([a-zA-Z0-9_]{1,25})_Win.exe(.)HashKey=([0-9]{1,12})_([a-z0-9]{1,35})(.)xtn=.exe') }}" + dest: C:\Temp\SmartConsole.exe + + - name: Unpack SmartConsole archive + win_unzip: + src: C:\Temp\SmartConsole.exe + dest: C:\Temp\SmartConsole + creates: C:\Temp\SmartConsole\SmartConsole.exe + + - name: Copy installer answer file to appropriate place + win_copy: + src: setup.iss + dest: C:\Temp\SmartConsole\setup.iss + + - name: Execute SmartConsole installer + win_command: C:\Temp\SmartConsole\SmartConsole.exe -s setup.iss + + ignore_errors: yes + diff --git a/provisioner/sample_workshops/sample-security.yml b/provisioner/sample_workshops/sample-security.yml index b9cb4dd0f..43e82e1c6 100644 --- a/provisioner/sample_workshops/sample-security.yml +++ b/provisioner/sample_workshops/sample-security.yml @@ -1,3 +1,4 @@ +--- # region where the nodes will live ec2_region: us-east-1 # name prefix for all the VMs @@ -6,8 +7,10 @@ ec2_name_prefix: TESTWORKSHOP student_total: 2 # workshop is put into isecurity mode workshop_type: 'security' +security_console: 'qradar' ## Optional Variables admin_password: ansible +windows_password: RedHat19! create_login_page: false autolicense: false towerinstall: true diff --git a/provisioner/security.yml b/provisioner/security.yml index b065e65f8..c50005bc2 100644 --- a/provisioner/security.yml +++ b/provisioner/security.yml @@ -1,9 +1,6 @@ -- name: INSTALL AND CONFIGURE SPLUNK ENTERPRISE - hosts: splunk - become: true - gather_facts: no - roles: - - role: splunk_enterprise +- name: include splunk playbook + import_playbook: splunk.yml + when: security_console == 'splunk' - name: INSTALL AND CONFIGURE SNORT hosts: snort @@ -25,3 +22,16 @@ - name: import ids_config role include_role: name: "ansible_security.ids_config" + +- name: SETUP CHECKPOINT ENVIRONMENT + hosts: localhost + become: no + connection: local + gather_facts: no + roles: + - role: cp_setup + +- name: SETUP WINDOWS WORKSTATION + hosts: windows + roles: + - role: windows_ws_setup diff --git a/provisioner/splunk.yml b/provisioner/splunk.yml new file mode 100644 index 000000000..16c3d1f79 --- /dev/null +++ b/provisioner/splunk.yml @@ -0,0 +1,8 @@ +--- +- name: INSTALL AND CONFIGURE SPLUNK ENTERPRISE + hosts: splunk + become: true + gather_facts: yes + roles: + - role: splunk_enterprise + diff --git a/provisioner/tests/pipeline.groovy b/provisioner/tests/pipeline.groovy index e6fe1c0ef..a3cf3d6a3 100644 --- a/provisioner/tests/pipeline.groovy +++ b/provisioner/tests/pipeline.groovy @@ -89,7 +89,7 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=rhel -e ec2_name_prefix=tower-qe-rhel-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee rhel.log" + sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=rhel -e ec2_name_prefix=tower-qe-rhel-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee rhel.log" } } } @@ -102,7 +102,7 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=rhel -e ec2_name_prefix=tower-qe-rhel-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} 2>&1 | tee -a rhel.log" + sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=rhel -e ec2_name_prefix=tower-qe-rhel-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} 2>&1 | tee -a rhel.log" } } archiveArtifacts artifacts: 'rhel.log' @@ -125,7 +125,7 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=networking -e ec2_name_prefix=tower-qe-networking-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee networking.log" + sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=networking -e ec2_name_prefix=tower-qe-networking-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee networking.log" } } } @@ -138,7 +138,7 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=networking -e ec2_name_prefix=tower-qe-networking-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} 2>&1 | tee -a networking.log" + sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=networking -e ec2_name_prefix=tower-qe-networking-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} 2>&1 | tee -a networking.log" } } archiveArtifacts artifacts: 'networking.log' @@ -161,14 +161,14 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=f5 -e ec2_name_prefix=tower-qe-f5-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee f5.log" + sh "ansible-playbook provisioner/provision_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=f5 -e ec2_name_prefix=tower-qe-f5-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} -e tower_installer_url=${tower_installer_url} -e gpgcheck=${gpgcheck} -e aw_repo_url=${aw_repo_url} -e ansible_workshops_url=${ANSIBLE_WORKSHOPS_URL} -e ansible_workshops_version=${params.WORKSHOP_BRANCH} 2>&1 | tee f5.log" } } } } script { stage('F5-exercises') { - sh "cat provisioner/tower-qe-f5-tower-${TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}/student1-instances.txt | grep -A 1 control | tail -n 1 | cut -d' ' -f 2 | cut -d'=' -f2 | tee control_host" + sh "cat provisioner/tower-qe-f5-tower-${TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION}/student1-instances.txt | grep -A 1 control | tail -n 1 | cut -d' ' -f 2 | cut -d'=' -f2 | tee control_host" CONTROL_NODE_HOST = readFile('control_host').trim() RUN_ALL_PLAYBOOKS = 'find . -name "*.yml" -o -name "*.yaml" | grep -v "2.0" | sort | xargs -I {} bash -c "echo {} && ANSIBLE_FORCE_COLOR=true ansible-playbook {}"' sh "sshpass -p 'ansible' ssh -o StrictHostKeyChecking=no student1@${CONTROL_NODE_HOST} 'cd networking-workshop && ${RUN_ALL_PLAYBOOKS}'" @@ -182,7 +182,7 @@ ${AWX_NIGHTLY_REPO_URL}""" "AWS_ACCESS_KEY=${AWS_ACCESS_KEY}", "ANSIBLE_CONFIG=provisioner/ansible.cfg", "ANSIBLE_FORCE_COLOR=true"]) { - sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=f5 -e ec2_name_prefix=tower-qe-f5-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID} 2>&1 | tee -a f5.log" + sh "ansible-playbook provisioner/teardown_lab.yml -e @provisioner/tests/vars.yml -e workshop_type=f5 -e ec2_name_prefix=tower-qe-f5-tower-${params.TOWER_VERSION}-${env.BRANCH_NAME}-${env.BUILD_ID}-${params.ANSIBLE_VERSION} 2>&1 | tee -a f5.log" } } archiveArtifacts artifacts: 'f5.log'