diff --git a/.gitignore b/.gitignore index 22bd86f..73bcc10 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ choose_demo_example_azure.yml choose_demo_example_aws.yml .ansible.cfg *.gz + diff --git a/README.md b/README.md index 033ebd6..d490a3b 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,31 @@ This is a centralized location for all Ansible Product Demos going forward. Please push contributions via a pull request following the naming convention of name-of-demo. [![GitHub Super-Linter](https://github.com/ansible/ansible-demos/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) + + +## Using this project + + > This project is tested for compatibility with AAP2 Linux Automation Workshop available to Red Hat Employees and Partners. + +1. First you must create a credential for [Automation Hub](https://console.redhat.com/ansible/automation-hub/) to successfully sync collections used by this project. + + 1. In the Credentials section of the Controller UI, add a new Credential called `Automation Hub` with the type `Ansible Galaxy/Automation Hub API Token` + 2. You can obtain a token [here](https://console.redhat.com/ansible/automation-hub/token). This page will also provide the Server URL and Auth Server URL. + 3. Next, click on Organizations and edit the `Default` organization. Add your `Automation Hub` credential to the `Galaxy Credentials` section. Don't forget to click Save!! + +2. If it has not been created for you, add a Project called `Ansible official demo project` with this repo as a source. NOTE: if you are using a fork, be sure that you have the correct URL. Update the project. +3. Finally, Create a Job Template called `Setup` with the following configuration: + + - Name: Setup + - Inventory: Workshop Inventory + - Exec Env: Control Plane EE + - Playbook: setup_demo.yml + - Credentials: + + - Type: Red Hat Ansible Automation Platform + - Name: Controller Credential + - Extra vars: + + demo: + +4. If you require a Windows Active Directory domain you will need to run the "ACTIVE DIRECTORY / Create Active Directory domain" template after the Windows setup completes. This will create the "ansible.local" domain as well as a few generic users and groups. \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..469af5f --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +collections_paths=./collections diff --git a/azure/setup.yml b/azure/setup.yml new file mode 100644 index 0000000..7e434f7 --- /dev/null +++ b/azure/setup.yml @@ -0,0 +1,109 @@ +--- +user_message: | + Be sure to update the public_key extra_var on the 'Azure RHEL 8 VM' Template + The Azure Infrastructure credential must be updated with your service principal credentials to access Azure API +azure_public_key: undef +controller_components: + - projects + - credentials + - inventories + - inventory_sources + - job_templates + +controller_projects: + - name: Azure Repo + description: Azure Demo Repo + organization: Default + scm_type: git + scm_url: https://github.com/ansible-cloud/azure.git + +controller_credentials: + - name: Azure Infrastructure + credential_type: Microsoft Azure Resource Manager + organization: Default + inputs: + subscription: REPLACEME + +controller_inventories: + - name: Workshop Inventory + organization: Default + +controller_inventory_sources: + - name: Azure Inventory + inventory: Workshop Inventory + source: azure_rm + credential: Azure Infrastructure + overwrite: true + update_on_launch: true + source_vars: + include_vm_resource_groups: + - ansible_test + + hostnames: + - computer_name + - default + + keyed_groups: + - prefix: azure_loc + key: location + - prefix: azure_os + key: os_profile.system + +controller_templates: + - name: "AZURE / RHEL 8 VM" + job_type: run + inventory: "Workshop Inventory" + project: "Azure Repo" + playbook: "project/create_rhel_vm_demo.yml" + credentials: + - "Azure Infrastructure" + extra_vars: + resource_group_name: "ansible_test" + region: "eastus" + vnet_cidr: "10.0.0.0/16" + subnet_cidr: "10.0.1.0/24" + vnet_name: "demo_vnet" + subnet_name: "demo_subnet" + network_sec_group_name: "demo_sec_group" + rhel_admin_user: "azureuser" + rhel_public_ip_name: "rhel_demo_ip" + rhel_nic_name: "rhel_demo_nic" + rhel_vm_name: "RHEL8-ansible" + rhel_vm_size: "Standard_DS1_v2" + rhel_vm_sku: "8_5" + rhel_public_key: "{{ azure_public_key }}" + survey_public_ip: "True" + + - name: "AZURE / Windows VM" + job_type: run + inventory: "Workshop Inventory" + project: "Azure Repo" + playbook: "project/create_windows_vm_demo.yml" + credentials: + - "Azure Infrastructure" + extra_vars: + resource_group_name: "ansible_test" + region: "eastus" + vnet_cidr: "10.0.0.0/16" + subnet_cidr: "10.0.1.0/24" + vnet_name: "demo_vnet" + subnet_name: "demo_subnet" + network_sec_group_name: "demo_sec_group" + win_vm_name: "WIN-ansible" + win_vm_size: "Standard_DS1_v2" + win_vm_sku: "2022-Datacenter" + win_public_ip_name: "win_demo_ip" + win_nic_name: "win_demo_nic" + win_admin_user: "azureuser" + win_admin_password: "AnsibleTest@123" + + - name: "AZURE / Destroy Resource Group" + job_type: run + inventory: "Workshop Inventory" + project: "Azure Repo" + playbook: "project/destroy_resource_group.yml" + credentials: + - "Azure Infrastructure" + extra_vars: + resource_group_name: "ansible_test" + region: "eastus" diff --git a/cloud/README.md b/cloud/README.md new file mode 100644 index 0000000..1c9e9b6 --- /dev/null +++ b/cloud/README.md @@ -0,0 +1,64 @@ +# Cloud Demos + +## Table of Contents +- [Cloud Demos](#cloud-demos) + - [Table of Contents](#table-of-contents) + - [About These Demos](#about-these-demos) + - [Jobs](#jobs) + - [Inventory](#inventory) + - [Post Setup Setup](#post-setup-setup) + - [Configure Credentials](#configure-credentials) + - [Add Workshop Credential Password](#add-workshop-credential-password) + - [Remove Inventory Variables](#remove-inventory-variables) + - [Getting your Puiblic Key for Create Infra Job](#getting-your-puiblic-key-for-create-infra-job) + - [Suggested Usage](#suggested-usage) + - [Known Issues](#known-issues) + +## About These Demos +This category of demos shows examples of multi-cloud provisioning and management with Ansible Automation Platform. The list of demos can be found below. These demos are particularly helpful in building additional infrastructure for other demo categories such as Linux and Windows. See the [Suggested Usage](#suggested-usage) section of this document for recommendations on how to best use these demos. + +### Jobs + +- [**Cloud / Create Infra**](create_infra.yml) - Creates a VPC with required routing and firewall rules for provisioning VMs +- [**Cloud / Create VM**](create_vm.yml) - Create a VM based on a [blueprint](blueprints/) in the selected cloud provider +- [**Cloud / Destroy VM**](destroy_vm.yml) - Destroy a VM that has been created in a cloud provider. VM must be imported into dynamic inventory to be deleted. + +### Inventory + +A dynamic inventory is created to pull inventory hosts from cloud providers. The VM will be added by name therefore provisioning VMs with the same name will cause conflict in the inventory. + +Groups will be created based on the operating system (platform) of the VM provisioned as well as a group called `cloud_`. + +## Post Setup Setup +After running the setup job template, there are a few steps required to make the demos fully functional. See post setup actions below. + + > These steps may differ if you in your environment + +### Configure Credentials + +- Add AWS Access and Secret key to the `AWS` Credential created by the setup job. + +### Add Workshop Credential Password + +1) Add the password used to login to Controller. This allows you to connect to Windows Servers provisioned with Create VM job. Required until [RFE](https://github.com/ansible/workshops/issues/1597]) is complete + +### Remove Inventory Variables + +1) Remove Workshop Inventory variables on the Details page of the inventory. Required until [RFE](https://github.com/ansible/workshops/issues/1597]) is complete + +### Getting your Puiblic Key for Create Infra Job + +1) Connect to the command line of your Controller server. This is easiest to do by opening the VS Code Web Editor from the landing page where you found the Controller login details. +2) Open a Terminal Window in the VS Code Web Editor. +3) SSH to one of your linux nodes (eg. `ssh node1`). This should log you into the node as `ec2-user` +4) `cat .ssh/authorized_keys` and copy the key listed including the `ssh-rsa` prefix + + +## Suggested Usage + +**Cloud / Create Infra** -The Create Infra job builds cloud infrastructure based on the provider definition in the included `demo.cloud` collection. + +**Cloud / Create VM** - The Create VM job builds a VM in the given provider based on the included `demo.cloud` collection. VM [blueprints](blueprints/) define variables for each provider that override the defaults in the collection. When creating VMs it is recommended to follow naming conventions that can be used as host patterns. (eg. VM names: `win1`, `win2`, `win3`. Host Pattern: `win*` ) + +## Known Issues +Azure does not work without a custom execution environment that includes the Azure dependencies. \ No newline at end of file diff --git a/cloud/blueprints/rhel7.yml b/cloud/blueprints/rhel7.yml new file mode 100644 index 0000000..8739d89 --- /dev/null +++ b/cloud/blueprints/rhel7.yml @@ -0,0 +1,7 @@ +--- +vm_providers: + - aws +aws_image_owners: 309956199498 +aws_instance_size: t2.medium +aws_image_architecture: x86_64 +aws_image_filter: 'RHEL-7.9_HVM*' \ No newline at end of file diff --git a/cloud/blueprints/rhel8.yml b/cloud/blueprints/rhel8.yml new file mode 100644 index 0000000..cb94a93 --- /dev/null +++ b/cloud/blueprints/rhel8.yml @@ -0,0 +1,7 @@ +--- +vm_providers: + - aws +aws_image_owners: 309956199498 +aws_instance_size: t3.micro +aws_image_architecture: x86_64 +aws_image_filter: 'RHEL-8*HVM-*Hourly*' \ No newline at end of file diff --git a/cloud/blueprints/windows.yml b/cloud/blueprints/windows.yml new file mode 100644 index 0000000..d70ca69 --- /dev/null +++ b/cloud/blueprints/windows.yml @@ -0,0 +1,14 @@ +--- +vm_blueprint_providers: + - aws + - azure +aws_image_filter: 'Windows_Server-2019-English-Core-Base*' +aws_instance_size: t3.medium +aws_userdata_template: aws_windows_userdata +az_vm_os_type: Windows +az_vm_size: Standard_DS1_v2 +az_vm_image: + offer: WindowsServer + publisher: MicrosoftWindowsServer + sku: 2022-Datacenter + version: latest \ No newline at end of file diff --git a/cloud/blueprints/windows_core.yml b/cloud/blueprints/windows_core.yml new file mode 100644 index 0000000..2c000f5 --- /dev/null +++ b/cloud/blueprints/windows_core.yml @@ -0,0 +1,6 @@ +--- +vm_blueprint_providers: + - aws +aws_image_filter: 'Windows_Server-2019-English-Core-Base*' +aws_instance_size: t3.medium +aws_userdata_template: aws_windows_userdata \ No newline at end of file diff --git a/cloud/blueprints/windows_full.yml b/cloud/blueprints/windows_full.yml new file mode 100644 index 0000000..92546f5 --- /dev/null +++ b/cloud/blueprints/windows_full.yml @@ -0,0 +1,6 @@ +--- +vm_blueprint_providers: + - aws +aws_image_filter: 'Windows_Server-2019-English-Full-Base*' +aws_instance_size: t3.medium +aws_userdata_template: aws_windows_userdata \ No newline at end of file diff --git a/cloud/create_infra.yml b/cloud/create_infra.yml new file mode 100644 index 0000000..1f48725 --- /dev/null +++ b/cloud/create_infra.yml @@ -0,0 +1,11 @@ +--- +- name: Create Cloud Infra + hosts: localhost + gather_facts: no + vars: + infra_provider: undef + aws_public_key: undef + tasks: + - include_role: + name: "demo.cloud.{{ infra_provider }}" + tasks_from: create_infra diff --git a/cloud/create_vm.yml b/cloud/create_vm.yml new file mode 100644 index 0000000..9e1836b --- /dev/null +++ b/cloud/create_vm.yml @@ -0,0 +1,25 @@ +--- +- name: Create Cloud Infra + hosts: localhost + gather_facts: no + vars: + vm_name: undef + vm_owner: undef + vm_provider: undef + vm_blueprint: undef + + tasks: + - name: "Importing {{ vm_blueprint | upper }} Blueprint" + include_vars: + file: "blueprints/{{ vm_blueprint }}.yml" + + - name: "Check Provider Compatibility" + assert: + that: "'{{ vm_provider }}' in {{ vm_blueprint_providers }}" + fail_msg: "{{ vm_blueprint | upper }} is not available for {{ vm_provider | upper }}" + when: "vm_blueprint_providers is defined" + + - name: "Building {{ vm_blueprint | upper }} in {{ vm_provider | upper }}" + include_role: + name: "demo.cloud.{{ vm_provider }}" + tasks_from: create_vm \ No newline at end of file diff --git a/cloud/destroy_vm.yml b/cloud/destroy_vm.yml new file mode 100644 index 0000000..fe73c58 --- /dev/null +++ b/cloud/destroy_vm.yml @@ -0,0 +1,19 @@ +--- +- hosts: "{{ HOSTS }}" + gather_facts: no + + tasks: + - name: list systems to be destroyed + debug: + msg: "{{ inventory_hostname }}" + + - name: pause for review... + pause: + seconds: 30 + prompt: "Systems listed above will be DESTROYED in 30 seconds. Cancel the job to Abort." + + - name: destroy vm + include_role: + name: "demo.cloud.aws" + tasks_from: destroy_vm + when: "'cloud_aws' in group_names or 'cloud_azure' in group_names" diff --git a/cloud/setup.yml b/cloud/setup.yml new file mode 100644 index 0000000..dc61b61 --- /dev/null +++ b/cloud/setup.yml @@ -0,0 +1,155 @@ +--- +user_message: + - Update AWS credential with Access and Secret key + - Update Workshop Credential with password used to login to Controller + +controller_components: + - credentials + - inventory_sources + - job_templates + +controller_credentials: + - name: AWS + credential_type: Amazon Web Services + organization: Default + update_secrets: false + inputs: + username: REPLACEME + password: REPLACEME + + #- name: Azure + # credential_type: Microsoft Azure Resource Manager + # organization: Default + # update_secrets: false + # inputs: + # subscription: REPLACEME + +controller_inventory_sources: + - name: AWS Inventory + organization: Default + source: ec2 + inventory: Workshop Inventory + credential: AWS + overwrite: true + source_vars: + hostnames: + - tag:Name + compose: + ansible_host: public_ip_address + groups: + cloud_aws: true + keyed_groups: + - key: platform + prefix: os + + #- name: Azure Inventory + # organization: Default + # source: azure_rm + # inventory: Workshop Inventory + # credential: Azure + # execution_environment: Ansible Engine 2.9 execution environment + # overwrite: true + # source_vars: + # hostnames: + # - tags.Name + # - default + # keyed_groups: + # - key: os_profile.system + # prefix: os + # conditional_groups: + # cloud_azure: true + +controller_templates: + - name: Cloud / Create Infra + job_type: run + organization: Default + credentials: + - AWS + #- Azure + project: Ansible official demo project + playbook: cloud/create_infra.yml + inventory: Workshop Inventory + execution_environment: Default execution environment + survey_enabled: true + extra_vars: + aws_region: us-east-2 + survey: + name: '' + description: '' + spec: + - question_name: Infra Provider + type: multiplechoice + variable: infra_provider + required: true + choices: + - aws + #- azure + - question_name: AWS Public Key (only required for aws provider) + type: textarea + required: false + variable: aws_public_key + - name: Cloud / Create VM + job_type: run + organization: Default + credentials: + - AWS + #- Azure + - Workshop Credential + project: Ansible official demo project + playbook: cloud/create_vm.yml + inventory: Workshop Inventory + execution_environment: Default execution environment + survey_enabled: true + extra_vars: + aws_region: us-east-2 + survey: + name: '' + description: '' + spec: + - question_name: Name + type: text + variable: vm_name + required: true + - question_name: Owner + type: text + variable: vm_owner + required: true + - question_name: Provider + type: multiplechoice + variable: vm_provider + required: true + choices: + - aws + #- azure + - question_name: Blueprint + type: multiplechoice + variable: vm_blueprint + required: true + choices: #"{{ lookup('fileglob', 'blueprints/*.yml') | regex_replace(',','\n') | regex_findall('.*/(.*)(?=.yml)') | list }}" + - windows_core + - windows_full + - rhel8 + - rhel7 + - name: Cloud / Destroy VM + job_type: run + organization: Default + credentials: + - AWS + #- Azure + - Workshop Credential + project: Ansible official demo project + playbook: cloud/destroy_vm.yml + inventory: Workshop Inventory + execution_environment: Default execution environment + survey_enabled: true + extra_vars: + aws_region: us-east-2 + survey: + name: '' + description: '' + spec: + - question_name: Name or Pattern + type: text + variable: HOSTS + required: true + diff --git a/collections/ansible_collections/demo/cloud/README.md b/collections/ansible_collections/demo/cloud/README.md new file mode 100644 index 0000000..e69de29 diff --git a/collections/ansible_collections/demo/cloud/roles/aws/defaults/main.yml b/collections/ansible_collections/demo/cloud/roles/aws/defaults/main.yml new file mode 100644 index 0000000..997346e --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/aws/defaults/main.yml @@ -0,0 +1,24 @@ +--- +####### +# AWS VARS +####### +aws_vpc_name: ansible +aws_vpc_prefix: demo +aws_vpc_cidr_block: 10.0.0.0/16 +aws_subnet_cidr: 10.0.1.0/24 +aws_region: us-east-1 +aws_vm_name: "{{ vm_name }}" +aws_vm_owner: "{{ vm_owner }}" +aws_blueprint: "{{ vm_blueprint }}" +#aws_image_filter: "{{ omit }}" +#aws_instance_size: "{{ omit }}" +#aws_image_architecture: "{{ omit }}" +#aws_image_owners: "{{ omit }} " +aws_userdata_template: default +aws_keypair_name: "{{ aws_vpc_name }}-{{ aws_vpc_prefix }}-demo-key" +aws_securitygroup_name: "{{ aws_vpc_name }}-{{ aws_vpc_prefix }}-sec-group" +aws_env_tag: prod +aws_purpose_tag: ansible_demo +aws_ansiblegroup_tag: cloud +aws_ec2_wait: true + diff --git a/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_infra.yml b/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_infra.yml new file mode 100644 index 0000000..510aed5 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_infra.yml @@ -0,0 +1,118 @@ +--- +- name: AWS | CREATE INFRA | vpc + amazon.aws.ec2_vpc_net: + state: present + name: "{{ aws_vpc_name }}-{{ aws_vpc_prefix }}-vpc" + cidr_block: "{{ aws_vpc_cidr_block }}" + tenancy: default + region: "{{ aws_region }}" + tags: + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" + register: aws_vpc + +- name: AWS | CREATE INFRA | internet gateway + amazon.aws.ec2_vpc_igw: + state: present + vpc_id: "{{ aws_vpc.vpc.id }}" + region: "{{ aws_region }}" + tags: + Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-vpc-igw" + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" + register: aws_gateway + +- name: Create security group internal + amazon.aws.ec2_group: + state: present + name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-sec-group" + region: "{{ aws_region }}" + description: Inbound WinRM and RDP, http for demo servers and internal AD ports + rules: + - proto: tcp + ports: + - 80 # HTTP + - 443 # HTTPS + - 22 # SSH + - 5986 # WinRM + - 3389 # RDP + cidr_ip: 0.0.0.0/0 + - proto: icmp + to_port: -1 + from_port: -1 + cidr_ip: 0.0.0.0/0 + - proto: tcp + ports: + - 80 # HTTP + - 5986 # WinRM + - 3389 # RDP + - 53 # DNS + - 88 # Kerberos Authentication + - 135 # RPC + - 139 # Netlogon + - 389 # LDAP + - 445 # SMB + - 464 # Kerberos Authentication + - 5432 # PostgreSQL + - 636 # LDAPS (LDAP over TLS) + - 873 # Rsync + - 3268-3269 # Global Catalog + - 1024-65535 # Ephemeral RPC ports + cidr_ip: 10.0.0.0/16 + - proto: udp + ports: + - 53 # DNS + - 88 # Kerberos Authentication + - 123 # NTP + - 137-138 # Netlogon + - 389 # LDAP + - 445 # SMB + - 464 # Kerberos Authentication + - 1024-65535 # Ephemeral RPC ports + cidr_ip: 10.0.0.0/16 + rules_egress: + - proto: -1 + cidr_ip: 0.0.0.0/0 + vpc_id: "{{ aws_vpc.vpc.id }}" + tags: + Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-sec-group" + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" + +- name: Create a subnet on the VPC + amazon.aws.ec2_vpc_subnet: + state: present + vpc_id: "{{ aws_vpc.vpc.id }}" + cidr: "{{ aws_subnet_cidr }}" + region: "{{ aws_region }}" + map_public: yes + tags: + Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-subnet" + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" + register: aws_subnet + +- name: Create a subnet route table + amazon.aws.ec2_vpc_route_table: + state: present + vpc_id: "{{ aws_vpc.vpc.id }}" + region: "{{ aws_region }}" + subnets: + - "{{ aws_subnet.subnet.id }}" + routes: + - dest: 0.0.0.0/0 + gateway_id: "{{ aws_gateway.gateway_id }}" + tags: + Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-vpc-rtbl" + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" + +- name: Create AWS keypair + amazon.aws.ec2_key: + name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-demo-key" + region: "{{ aws_region }}" + key_material: "{{ aws_public_key }}" + state: present + tags: + owner: "{{ aws_vpc_name }}" + purpose: "{{ aws_purpose_tag }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_vm.yml b/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_vm.yml new file mode 100644 index 0000000..9c3a781 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/aws/tasks/create_vm.yml @@ -0,0 +1,47 @@ +--- +- name: AWS | CREATE VM | get subnet info + amazon.aws.ec2_vpc_subnet_info: + region: "{{ aws_region }}" + filters: + "tag:Name": "{{ aws_vpc_name }}-{{ aws_vpc_prefix }}-subnet" + register: aws_subnet + +- name: AWS | CREATE VM | save subnet id + set_fact: + aws_subnet_id: "{{ aws_subnet.subnets|map(attribute='id')| list | last }}" + +- name: AWS| CREATE VM | find ami + amazon.aws.ec2_ami_info: + region: "{{ aws_region }}" + owners: "{{ aws_image_owners | default(omit)}}" + filters: + name: "{{ aws_image_filter }}" + architecture: "{{ aws_image_architecture | default(omit) }}" + register: amis + +- name: AWS| CREATE VM | save ami + set_fact: + aws_instance_ami: > + {{ (amis.images | selectattr('name', 'defined') | sort(attribute='creation_date'))[-2] }} + +- name: AWS| CREATE VM | create instance + amazon.aws.ec2_instance: + network: + assign_public_ip: yes + key_name: "{{ aws_keypair_name }}" + instance_type: "{{ aws_instance_size }}" + image_id: "{{ aws_instance_ami.image_id }}" + region: "{{ aws_region }}" + security_group: "{{ aws_securitygroup_name }}" + tags: + blueprint: "{{ aws_blueprint }}" + purpose: "{{ aws_purpose_tag }}" + env: "{{ aws_env_tag }}" + ansible_group: "{{ aws_ansiblegroup_tag }}" + owner: "{{ aws_vm_owner }}" + info: "This instance was built by Red Hat Product Demos" + Name: "{{ aws_vm_name }}" + wait: "{{ aws_ec2_wait }}" + vpc_subnet_id: "{{ aws_subnet_id }}" + user_data: "{{ lookup('template', aws_userdata_template+'.j2', template_vars=dict(aws_vm_name=vm_name)) }}" + register: aws_vm_output \ No newline at end of file diff --git a/collections/ansible_collections/demo/cloud/roles/aws/tasks/destroy_vm.yml b/collections/ansible_collections/demo/cloud/roles/aws/tasks/destroy_vm.yml new file mode 100644 index 0000000..7b5093b --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/aws/tasks/destroy_vm.yml @@ -0,0 +1,7 @@ +--- +- name: Destroy VM + amazon.aws.ec2_instance: + state: absent + instance_ids: "{{ instance_id }}" + region: "{{ placement.region }}" + delegate_to: localhost \ No newline at end of file diff --git a/collections/ansible_collections/demo/cloud/roles/aws/templates/aws_windows_userdata.j2 b/collections/ansible_collections/demo/cloud/roles/aws/templates/aws_windows_userdata.j2 new file mode 100644 index 0000000..c4671f2 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/aws/templates/aws_windows_userdata.j2 @@ -0,0 +1,29 @@ + +# 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 + +# Remove policies stopping us from enabling WinRM +reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service" /v AllowBasic /f +reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service" /v AllowUnencryptedTraffic /f +reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WinRM\Service" /v DisableRunAs /f + +# 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 + +# add ec2-user +$Password = ConvertTo-SecureString {{ ansible_password }} -AsPlainText -Force +New-LocalUser -Name "ec2-user" -Description "Ansible Service Account" -Password $Password +Add-LocalGroupMember -Group "Administrators" -Member "ec2-user" + +Rename-Computer -NewName {{ aws_vm_name }} -Force -Restart + \ No newline at end of file diff --git a/collections/ansible_collections/demo/cloud/roles/aws/templates/default.j2 b/collections/ansible_collections/demo/cloud/roles/aws/templates/default.j2 new file mode 100644 index 0000000..e69de29 diff --git a/collections/ansible_collections/demo/cloud/roles/azure/defaults/main.yml b/collections/ansible_collections/demo/cloud/roles/azure/defaults/main.yml new file mode 100644 index 0000000..085623d --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/azure/defaults/main.yml @@ -0,0 +1,17 @@ +--- +############## +# Azure Vars +############## +az_region: eastus +az_rg_name: ansible +az_rg_prefix: demo +az_vnet_cidr_block: 10.0.0.0/16 +az_subnet_cidr: 10.0.1.0/24 +az_vm_name: "{{ vm_name }}" +az_vm_owner: "{{ vm_owner }}" +az_blueprint: "{{ vm_blueprint }}" +az_vm_username: "{{ ansible_user }}" +az_vm_password: "{{ ansible_password }}" +az_env_tag: prod +az_purpose_tag: ansible_demo +az_ansiblegroup_tag: cloud diff --git a/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_infra.yml b/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_infra.yml new file mode 100644 index 0000000..c7f5804 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_infra.yml @@ -0,0 +1,76 @@ +--- +- name: AZURE | CREATE INFRA | resource group + azure.azcollection.azure_rm_resourcegroup: + name: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + location: "{{ az_region }}" + +- name: AZURE | CREATE INFRA | virtual network + azure.azcollection.azure_rm_virtualnetwork: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ az_rg_name }}-{{ az_rg_prefix }}-vnet" + address_prefixes: "{{ az_vnet_cidr }}" + +- name: AZURE | CREATE INFRA | subnet + azure.azcollection.azure_rm_subnet: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ az_rg_name }}-{{ az_rg_prefix }}-subnet }}" + address_prefix: "{{ az_subnet_cidr }}" + virtual_network: "{{ az_rg_name }}-{{ az_rg_prefix }}-vnet" + +- name: AZURE | CREATE INFRA | security group + azure.azcollection.azure_rm_securitygroup: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ az_rg_name }}-{{ az_rg_prefix }}-sec-group" + rules: + - name: External + protocol: Tcp + destination_port_range: + - 80 # HTTP + - 443 # HTTPS + - 5986 # WinRM + - 3389 # RDP + access: Allow + priority: 1001 + direction: Inbound + - name: Ping + protocol: Icmp + access: Allow + priority: 1002 + direction: Inbound + - name: Internal TCP + protocol: Tcp + destination_port_range: + - 80 # HTTP + - 5986 # WinRM + - 3389 # RDP + - 53 # DNS + - 88 # Kerberos Authentication + - 135 # RPC + - 139 # Netlogon + - 389 # LDAP + - 445 # SMB + - 464 # Kerberos Authentication + - 5432 # PostgreSQL + - 636 # LDAPS (LDAP over TLS) + - 873 # Rsync + - 3268-3269 # Global Catalog + - 1024-65535 # Ephemeral RPC ports + access: Allow + priority: 1003 + direction: Inbound + source_address_prefix: "{{ az_vnet_cidr_block }}" + - name: Internal UDP + protocol: Udp + destination_port_range: + - 53 # DNS + - 88 # Kerberos Authentication + - 123 # NTP + - 137-138 # Netlogon + - 389 # LDAP + - 445 # SMB + - 464 # Kerberos Authentication + - 1024-65535 # Ephemeral RPC ports + access: Allow + priority: 1004 + direction: Inbound + source_address_prefix: "{{ az_vnet_cidr_block }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_vm.yml b/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_vm.yml new file mode 100644 index 0000000..560bdc2 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/azure/tasks/create_vm.yml @@ -0,0 +1,28 @@ +--- +- name: AZURE | CREATE VM | vnet interface + azure.azcollection.azure_rm_networkinterface: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ az_vm_name }}_nic" + public_ip_name: "{{ az_vm_name }}_ip" + virtual_network: "{{ az_rg_name }}-{{ az_rg_prefix }}-vnet" + subnet: "{{ az_rg_name }}-{{ az_rg_prefix }}-subnet }}" + security_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-sec-group" + +- name: AZURE | CREATE VM | vm + azure.azcollection.azure_rm_virtualmachine: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ az_vm_name }}" + os_type: "{{ az_vm_os_type }}" + vm_size: "{{ az_vm_size }}" + admin_username: "{{ az_vm_username }}" + admin_password: "{{ az_vm_password }}" + network_interfaces: "{{ az_vm_name }}_nic" + image: "{{ az_vm_image }}" + tags: + blueprint: "{{ az_blueprint }}" + purpose: "{{ az_purpose_tag }}" + env: "{{ az_env_tag }}" + ansible_group: "{{ az_ansiblegroup_tag }}" + owner: "{{ az_vm_owner }}" + info: "This instance was built by Red Hat Product Demos" + Name: "{{ az_vm_name }}" diff --git a/collections/ansible_collections/demo/cloud/roles/azure/tasks/destroy_vm.yml b/collections/ansible_collections/demo/cloud/roles/azure/tasks/destroy_vm.yml new file mode 100644 index 0000000..9be4644 --- /dev/null +++ b/collections/ansible_collections/demo/cloud/roles/azure/tasks/destroy_vm.yml @@ -0,0 +1,8 @@ +--- +- name: Destroy VM + azure.azcollection.azure_rm_virtualmachine: + resource_group: "{{ az_rg_name }}-{{ az_rg_prefix }}-rg" + name: "{{ inventory_hostname }}" + state: absent + remove_on_absent: all_autocreated + delegate_to: localhost \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py b/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py new file mode 100644 index 0000000..039e5b2 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/scan_packages.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +from ansible.module_utils.basic import * # noqa + +DOCUMENTATION = ''' +--- +module: scan_packages +short_description: Return installed packages information as fact data +description: + - Return information about installed packages as fact data +''' + +EXAMPLES = ''' +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "packages": [ +# { +# "version": "1.0.6-5", +# "source": "apt", +# "arch": "amd64", +# "name": "libbz2-1.0" +# }, +# { +# "version": "2.7.1-4ubuntu1", +# "source": "apt", +# "arch": "amd64", +# "name": "patch" +# }, +# { +# "version": "4.8.2-19ubuntu1", +# "source": "apt", +# "arch": "amd64", +# "name": "gcc-4.8-base" +# } +# ] +''' + + +def rpm_package_list(): + import rpm + trans_set = rpm.TransactionSet() + installed_packages = [] + for package in trans_set.dbMatch(): + package_details = { + 'name':package[rpm.RPMTAG_NAME], + 'version':package[rpm.RPMTAG_VERSION], + 'release':package[rpm.RPMTAG_RELEASE], + 'epoch':package[rpm.RPMTAG_EPOCH], + 'arch':package[rpm.RPMTAG_ARCH], + 'source':'rpm' } + if installed_packages == []: + installed_packages = [package_details] + else: + installed_packages.append(package_details) + return installed_packages + + +def deb_package_list(): + import apt + apt_cache = apt.Cache() + installed_packages = [] + apt_installed_packages = [pk for pk in apt_cache.keys() if apt_cache[pk].is_installed] + for package in apt_installed_packages: + ac_pkg = apt_cache[package].installed + package_details = { + 'name':package, + 'version':ac_pkg.version, + 'arch':ac_pkg.architecture, + 'source':'apt'} + if installed_packages == []: + installed_packages = [package_details] + else: + installed_packages.append(package_details) + return installed_packages + + +def main(): + module = AnsibleModule( + argument_spec = dict(os_family=dict(required=True)) + ) + ans_os = module.params['os_family'] + if ans_os in ('RedHat', 'Suse', 'openSUSE Leap'): + packages = rpm_package_list() + elif ans_os == 'Debian': + packages = deb_package_list() + else: + packages = None + + if packages is not None: + results = dict(ansible_facts=dict(packages=packages)) + else: + results = dict(skipped=True, msg="Unsupported Distribution") + module.exit_json(**results) + + +main() \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py b/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py new file mode 100644 index 0000000..c4de33c --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/scan_services.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +import re +from ansible.module_utils.basic import * # noqa + +DOCUMENTATION = ''' +--- +module: scan_services +short_description: Return service state information as fact data +description: + - Return service state information as fact data for various service management utilities +''' + +EXAMPLES = ''' +- monit: scan_services +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "services": { +# "network": { +# "source": "sysv", +# "state": "running", +# "name": "network" +# }, +# "arp-ethers.service": { +# "source": "systemd", +# "state": "stopped", +# "name": "arp-ethers.service" +# } +# } +# } +''' + + +class BaseService(object): + + def __init__(self, module): + self.module = module + self.incomplete_warning = False + + +class ServiceScanService(BaseService): + + def gather_services(self): + services = {} + service_path = self.module.get_bin_path("service") + if service_path is None: + return None + initctl_path = self.module.get_bin_path("initctl") + chkconfig_path = self.module.get_bin_path("chkconfig") + + # sysvinit + if service_path is not None and chkconfig_path is None: + rc, stdout, stderr = self.module.run_command("%s --status-all 2>&1 | grep -E \"\\[ (\\+|\\-) \\]\"" % service_path, use_unsafe_shell=True) + for line in stdout.split("\n"): + line_data = line.split() + if len(line_data) < 4: + continue # Skipping because we expected more data + service_name = " ".join(line_data[3:]) + if line_data[1] == "+": + service_state = "running" + else: + service_state = "stopped" + services[service_name] = {"name": service_name, "state": service_state, "source": "sysv"} + + # Upstart + if initctl_path is not None and chkconfig_path is None: + p = re.compile('^\s?(?P.*)\s(?P\w+)\/(?P\w+)(\,\sprocess\s(?P[0-9]+))?\s*$') + rc, stdout, stderr = self.module.run_command("%s list" % initctl_path) + real_stdout = stdout.replace("\r","") + for line in real_stdout.split("\n"): + m = p.match(line) + if not m: + continue + service_name = m.group('name') + service_goal = m.group('goal') + service_state = m.group('state') + if m.group('pid'): + pid = m.group('pid') + else: + pid = None # NOQA + payload = {"name": service_name, "state": service_state, "goal": service_goal, "source": "upstart"} + services[service_name] = payload + + # RH sysvinit + elif chkconfig_path is not None: + #print '%s --status-all | grep -E "is (running|stopped)"' % service_path + p = re.compile( + '(?P.*?)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+' + '[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)\s+[0-9]:(?Pon|off)') + rc, stdout, stderr = self.module.run_command('%s' % chkconfig_path, use_unsafe_shell=True) + # Check for special cases where stdout does not fit pattern + match_any = False + for line in stdout.split('\n'): + if p.match(line): + match_any = True + if not match_any: + p_simple = re.compile('(?P.*?)\s+(?Pon|off)') + match_any = False + for line in stdout.split('\n'): + if p_simple.match(line): + match_any = True + if match_any: + # Try extra flags " -l --allservices" needed for SLES11 + rc, stdout, stderr = self.module.run_command('%s -l --allservices' % chkconfig_path, use_unsafe_shell=True) + elif '--list' in stderr: + # Extra flag needed for RHEL5 + rc, stdout, stderr = self.module.run_command('%s --list' % chkconfig_path, use_unsafe_shell=True) + for line in stdout.split('\n'): + m = p.match(line) + if m: + service_name = m.group('service') + service_state = 'stopped' + if m.group('rl3') == 'on': + rc, stdout, stderr = self.module.run_command('%s %s status' % (service_path, service_name), use_unsafe_shell=True) + service_state = rc + if rc in (0,): + service_state = 'running' + #elif rc in (1,3): + else: + if 'root' in stderr or 'permission' in stderr.lower() or 'not in sudoers' in stderr.lower(): + self.incomplete_warning = True + continue + else: + service_state = 'stopped' + service_data = {"name": service_name, "state": service_state, "source": "sysv"} + services[service_name] = service_data + return services + + +class SystemctlScanService(BaseService): + + def systemd_enabled(self): + # Check if init is the systemd command, using comm as cmdline could be symlink + try: + f = open('/proc/1/comm', 'r') + except IOError: + # If comm doesn't exist, old kernel, no systemd + return False + for line in f: + if 'systemd' in line: + return True + return False + + def gather_services(self): + services = {} + if not self.systemd_enabled(): + return None + systemctl_path = self.module.get_bin_path("systemctl", opt_dirs=["/usr/bin", "/usr/local/bin"]) + if systemctl_path is None: + return None + rc, stdout, stderr = self.module.run_command("%s list-unit-files --type=service | tail -n +2 | head -n -2" % systemctl_path, use_unsafe_shell=True) + for line in stdout.split("\n"): + line_data = line.split() + if len(line_data) != 2: + continue + if line_data[1] == "enabled": + state_val = "running" + else: + state_val = "stopped" + services[line_data[0]] = {"name": line_data[0], "state": state_val, "source": "systemd"} + return services + + +def main(): + module = AnsibleModule(argument_spec = dict()) + service_modules = (ServiceScanService, SystemctlScanService) + all_services = {} + incomplete_warning = False + for svc_module in service_modules: + svcmod = svc_module(module) + svc = svcmod.gather_services() + if svc is not None: + all_services.update(svc) + if svcmod.incomplete_warning: + incomplete_warning = True + if len(all_services) == 0: + results = dict(skipped=True, msg="Failed to find any services. Sometimes this is due to insufficient privileges.") + else: + results = dict(ansible_facts=dict(services=all_services)) + if incomplete_warning: + results['msg'] = "WARNING: Could not find status for all services. Sometimes this is due to insufficient privileges." + module.exit_json(**results) + + +main() \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 new file mode 100644 index 0000000..0062f31 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.ps1 @@ -0,0 +1,66 @@ +#!powershell +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# WANT_JSON +# POWERSHELL_COMMON + +$uninstall_native_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" +$uninstall_wow6432_path = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" + +if ([System.IntPtr]::Size -eq 4) { + + # This is a 32-bit Windows system, so we only check for 32-bit programs, which will be + # at the native registry location. + + [PSObject []]$packages = Get-ChildItem -Path $uninstall_native_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win32" }} | + Where-Object { $_.name } + +} else { + + # This is a 64-bit Windows system, so we check for 64-bit programs in the native + # registry location, and also for 32-bit programs under Wow6432Node. + + [PSObject []]$packages = Get-ChildItem -Path $uninstall_native_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win64" }} | + Where-Object { $_.name } + + $packages += Get-ChildItem -Path $uninstall_wow6432_path | + Get-ItemProperty | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="version"; Expression={$_."DisplayVersion"}}, + @{Name="publisher"; Expression={$_."Publisher"}}, + @{Name="arch"; Expression={ "Win32" }} | + Where-Object { $_.name } + +} + +$result = New-Object psobject @{ + ansible_facts = New-Object psobject @{ + packages = $packages + } + changed = $false +} + +Exit-Json $result; \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py new file mode 100644 index 0000000..3281818 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_packages.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +DOCUMENTATION = ''' +--- +module: win_scan_packages +short_description: Return Package state information as fact data +description: + - Return Package state information as fact data for various Packages +''' + +EXAMPLES = ''' +- monit: win_scan_packages +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "packages": [ + { + "name": "Mozilla Firefox 76.0.1 (x64 en-US)", + "version": "76.0.1", + "publisher": "Mozilla", + "arch": "Win64" + }, + { + "name": "Mozilla Maintenance Service", + "version": "76.0.1", + "publisher": "Mozilla", + "arch": "Win64" + }, +# } +''' \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 new file mode 100644 index 0000000..4a5f840 --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.ps1 @@ -0,0 +1,30 @@ +#!powershell +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# WANT_JSON +# POWERSHELL_COMMON + +$result = New-Object psobject @{ + ansible_facts = New-Object psobject @{ + services = Get-Service | + Select-Object -Property @{Name="name"; Expression={$_."DisplayName"}}, + @{Name="win_svc_name"; Expression={$_."Name"}}, + @{Name="state"; Expression={$_."Status".ToString().ToLower()}} + } + changed = $false +} + +Exit-Json $result; \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py new file mode 100644 index 0000000..caae37d --- /dev/null +++ b/collections/ansible_collections/demo/patching/plugins/modules/win_scan_services.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +DOCUMENTATION = ''' +--- +module: win_scan_services +short_description: Return service state information as fact data +description: + - Return service state information as fact data for various service management utilities +''' + +EXAMPLES = ''' +- monit: win_scan_services +# Example fact output: +# host | success >> { +# "ansible_facts": { +# "services": [ + { + "name": "AllJoyn Router Service", + "win_svc_name": "AJRouter", + "state": "stopped" + }, + { + "name": "Application Layer Gateway Service", + "win_svc_name": "ALG", + "state": "stopped" + }, + { + "name": "Application Host Helper Service", + "win_svc_name": "AppHostSvc", + "state": "running" + }, +# } +''' \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/README.md b/collections/ansible_collections/demo/patching/roles/build_report_network/README.md new file mode 100644 index 0000000..a8b311a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/README.md @@ -0,0 +1,36 @@ +build_report_network +======== + +Installs Apache and creates a report based on facts from network devices + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of network devices + + +``` +--- +- hosts: all + + tasks: + - name: Run Network Report + import_role: + name: shadowman.reports.build_report_network + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png b/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png new file mode 100644 index 0000000..d766491 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/example_results/Ansible Network Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css b/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png b/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png new file mode 100644 index 0000000..1fdc4f0 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/files/router.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_network/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml new file mode 100644 index 0000000..accaeba --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/tasks/main.yml @@ -0,0 +1,24 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/network.html" + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "router.png" + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/network.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 new file mode 100644 index 0000000..d6b0f67 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/bgp.j2 @@ -0,0 +1,31 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 new file mode 100644 index 0000000..bf13414 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/interfaces.j2 @@ -0,0 +1,41 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 new file mode 100644 index 0000000..a170b5d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l2_interfaces.j2 @@ -0,0 +1,37 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 new file mode 100644 index 0000000..deb217c --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/l3_interfaces.j2 @@ -0,0 +1,58 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 new file mode 100644 index 0000000..f53b2f7 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lacp.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 new file mode 100644 index 0000000..3ad0852 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/lldp_interfaces.j2 @@ -0,0 +1,33 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 new file mode 100644 index 0000000..d06ff5b --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/ospf.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 new file mode 100644 index 0000000..f00eac7 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/report.j2 @@ -0,0 +1,111 @@ + + + + Ansible Network Automation Report + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Network Automation Report

+

+

+ + + + + + + + + + +{% for network_switch in groups['tag_Router']|sort %} + + + + + + + +{% endfor %} + +
Network DeviceLayer 1Layer 2Layer 3
+
+

+ {{ hostvars[network_switch]['ansible_net_hostname'].split('.')[0] }}

+
+{% include 'summary.j2' %} +
+{% include 'interfaces.j2' %} + +{% include 'vlans.j2' %} +{% include 'lldp_interfaces.j2' %} +{% include 'l2_interfaces.j2' %} + +{% include 'l3_interfaces.j2' %} +{% include 'lacp.j2' %} +{% include 'bgp.j2' %} +{% include 'ospf.j2' %} +
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 new file mode 100644 index 0000000..5f643e4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/summary.j2 @@ -0,0 +1,25 @@ +
+ + + + + + + + + + + + + + + + + + + + + + +
Platform{{hostvars[network_switch]['ansible_net_system']}}
Code Version{{hostvars[network_switch]['ansible_net_version']}}
Model{{hostvars[network_switch]['ansible_net_model']|default("N/A")}}
Serial Number{{hostvars[network_switch]['ansible_net_serialnum']}}
Transport{{hostvars[network_switch]['ansible_net_api']}}
+
diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 new file mode 100644 index 0000000..044a334 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/templates/vlans.j2 @@ -0,0 +1,33 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_network/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md b/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md new file mode 100644 index 0000000..93d6df4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/README.md @@ -0,0 +1,36 @@ +build_report_windows +======== + +Installs Apache and creates a report based on facts from Windows services and packages modules + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Windows servers about their services and packages installed + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Report + import_role: + name: shadowman.reports.build_report_windows + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml new file mode 100644 index 0000000..1154771 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/defaults/main.yml @@ -0,0 +1,2 @@ +--- +detailedreport: True \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png new file mode 100644 index 0000000..1ead477 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/example_results/Ansible Windows Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png new file mode 100644 index 0000000..9ad96fc Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/server.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml new file mode 100644 index 0000000..f349f23 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/tasks/main.yml @@ -0,0 +1,24 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/windows.html" + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "server.png" + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/windows.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 new file mode 100644 index 0000000..f290897 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/packages.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 new file mode 100644 index 0000000..96b5f3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/report.j2 @@ -0,0 +1,101 @@ + + + + Ansible Windows Automation Report + + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Windows Automation Report

+

+

+ + + + + + + + + +{% for windows_host in groups['tag_Windows']|sort %} + + + + + +{% endfor %} + +
Windows DeviceOperating SystemOperating System Kernel Version
+
+

+ {{ hostvars[windows_host]['inventory_hostname'].split('.')[0] }}

+
+{% if detailedreport == 'True' %} +{% include 'packages.j2' %} +{% include 'services.j2' %} +{% endif %} +
{{hostvars[windows_host]['ansible_os_family']|default("none")}}{{hostvars[windows_host]['ansible_distribution']|default("none")}}
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 new file mode 100644 index 0000000..b443161 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/templates/services.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md new file mode 100644 index 0000000..dec8155 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/README.md @@ -0,0 +1,36 @@ +build_report_windows_patch +======== + +Installs Apache and creates a report based on facts from Windows update job + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html patching report on any number of Linux hosts using any number of Windows servers + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Patch Report + import_role: + name: shadowman.reports.build_report_windows_patch + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml new file mode 100644 index 0000000..aaf5c3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/defaults/main.yml @@ -0,0 +1,3 @@ +EMAIL_FROM: tower@shadowman.dev +to_emails: alex@shadowman.dev,tower@shadowman.dev +EMAIL_TO: "{{ to_emails.split(',') }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png new file mode 100644 index 0000000..615a021 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/example_results/Full_Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css new file mode 100644 index 0000000..dfeb435 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/css/main.css @@ -0,0 +1,111 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + } + + #subtable { + background: #ebebeb; + margin: 0px; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + margin:50px auto; + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + thead { + @include border-radius(5px); + } + + thead th { + font-family: 'Patua One', monospace; + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-family: 'Open Sans', sans-serif; + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png new file mode 100644 index 0000000..3d99673 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml new file mode 100644 index 0000000..12a9a74 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/tasks/main.yml @@ -0,0 +1,38 @@ +- name: Create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/windowspatch.html" + check_mode: no + +- name: Copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Copy logo over + ansible.builtin.copy: + src: "webpage_logo.png" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Display link to Patch report + ansible.builtin.debug: + msg: "Please go to http://{{ ansible_host }}/windowspatch.html" + +- name: Send Report via E-mail + community.general.mail: + host: "{{ EMAIL_HOST }}" + username: "{{ EMAIL_USERNAME }}" + password: "{{ EMAIL_PASSWORD }}" + port: "{{ EMAIL_PORT }}" + subject: "Windows Patching Report" + body: "{{ lookup('template', 'report.j2') }}" + from: "{{ EMAIL_FROM }}" + to: "{{ EMAIL_TO }}" + subtype: html + delegate_to: localhost + become: false + check_mode: no \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 new file mode 100644 index 0000000..058b0db --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/templates/report.j2 @@ -0,0 +1,115 @@ + + + + Windows Patch Report + + +
+

Ansible Windows Patching Report

+ +
+ + +
+
+ + + + + + + + + +{% for windows_host in groups['tag_Windows']|sort %} + + + + + + +{% endfor %} + +
HostnameOperating SystemRequired Updates
{{hostvars[windows_host]['inventory_hostname']}}{{hostvars[windows_host]['ansible_distribution']|default("none")}} +
    + +{% if hostvars[windows_host].patchresult.updates is defined and hostvars[windows_host].patchresult.found_update_count|int > 0 %} +{% for update in hostvars[windows_host].patchresult.updates %} +{% set updatenum = hostvars[windows_host].patchresult.updates[update] %} +
  • {{updatenum.title}}
  • +{% endfor %} +{% else %} +
  • Compliant
  • +{% endif %} +
+
+{% for host in ansible_play_hosts %} +

Created with Ansible on {{hostvars[host].ansible_date_time.iso8601}}

+{% endfor %} + + + \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml new file mode 100644 index 0000000..f09b15e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/build_report_windows_patch/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/patch_linux/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/patch_linux/defaults/main.yml new file mode 100644 index 0000000..04bf772 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/patch_linux/defaults/main.yml @@ -0,0 +1,3 @@ +--- +exclude_packages: [] +allow_reboot: true \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/patch_linux/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/patch_linux/tasks/main.yml new file mode 100644 index 0000000..512a900 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/patch_linux/tasks/main.yml @@ -0,0 +1,38 @@ +--- +- name: Scan packages + demo.patching.scan_packages: + os_family: "{{ ansible_os_family }}" + check_mode: no + +- name: Scan services + demo.patching.scan_services: + check_mode: no + +- name: upgrade packages (yum) + yum: + name: '*' + state: latest + exclude: "{{ exclude_packages }}" + when: ansible_pkg_mgr == "yum" + register: patchingresult_yum + +- name: upgrade packages (dnf) + ansible.builtin.dnf: + name: '*' + state: latest + exclude: "{{ exclude_packages }}" + when: ansible_pkg_mgr == "dnf" + register: patchingresult_dnf + +- name: Check to see if we need a reboot + ansible.builtin.command: needs-restarting -r + register: result + changed_when: result.rc == 1 + failed_when: result.rc > 1 + check_mode: no + +- name: Reboot Server if Necessary + ansible.builtin.reboot: + when: + - result.rc == 1 + - allow_reboot == true \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/patch_windows/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/patch_windows/defaults/main.yml new file mode 100644 index 0000000..f8a73c3 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/patch_windows/defaults/main.yml @@ -0,0 +1,14 @@ +--- +win_update_categories: + - Application + - Connectors + - CriticalUpdates + - DefinitionUpdates + - DeveloperKits + - FeaturePacks Guidance + - SecurityUpdates + - ServicePacks + - Tools + - UpdateRollups + - Updates +allow_reboot: true \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/patch_windows/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/patch_windows/tasks/main.yml new file mode 100644 index 0000000..0518c79 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/patch_windows/tasks/main.yml @@ -0,0 +1,15 @@ +--- +- name: Scan packages + demo.patching.win_scan_packages: + check_mode: no + +- name: Scan Services + demo.patching.win_scan_services: + check_mode: no + +- name: Install Windows Updates + ansible.windows.win_updates: + category_names: "{{ win_update_categories | default(omit) }}" + reboot: "{{ allow_reboot }}" + state: installed + register: patchingresult diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/README.md b/collections/ansible_collections/demo/patching/roles/report_linux/README.md new file mode 100644 index 0000000..88fa95c --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/README.md @@ -0,0 +1,36 @@ +build_report_linux +======== + +Installs Apache and creates a report based on facts from Linux services and packages modules + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Linux servers about their services and packages installed + + +``` +--- +- hosts: all + + tasks: + - name: Run Linux Report + import_role: + name: shadowman.reports.build_report_linux + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux/defaults/main.yml new file mode 100644 index 0000000..1154771 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/defaults/main.yml @@ -0,0 +1,2 @@ +--- +detailedreport: True \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/example_results/Ansible Linux Automation Report.png b/collections/ansible_collections/demo/patching/roles/report_linux/example_results/Ansible Linux Automation Report.png new file mode 100644 index 0000000..3e2287a Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux/example_results/Ansible Linux Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/files/css/new.css b/collections/ansible_collections/demo/patching/roles/report_linux/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/report_linux/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/files/server.png b/collections/ansible_collections/demo/patching/roles/report_linux/files/server.png new file mode 100644 index 0000000..9ad96fc Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux/files/server.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/report_linux/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux/tasks/main.yml new file mode 100644 index 0000000..fede495 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/tasks/main.yml @@ -0,0 +1,27 @@ +- name: create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/linux.html" + check_mode: no + +- name: copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: copy logos over + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "server.png" + check_mode: no + +- name: display link to inventory report + ansible.builtin.debug: + msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/linux.html" diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/report_linux/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/templates/packages.j2 b/collections/ansible_collections/demo/patching/roles/report_linux/templates/packages.j2 new file mode 100644 index 0000000..86a842d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/templates/packages.j2 @@ -0,0 +1,31 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/report_linux/templates/report.j2 new file mode 100644 index 0000000..779740b --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/templates/report.j2 @@ -0,0 +1,105 @@ + + + + Ansible Linux Automation Report + + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Linux Automation Report

+

+

+ + + + + + + + + + + +{% for linux_host in ansible_play_hosts |sort %} + + + + + + + +{% endfor %} + +
Linux DevicePackage ManagerOperating SystemOperating System VersionOperating System Kernel Version
+
+

+ {{ hostvars[linux_host]['inventory_hostname'].split('.')[0] }}

+
+{% if detailedreport == 'True' %} +{% include 'packages.j2' %} +{% include 'services.j2' %} +{% endif %} +
{{hostvars[linux_host]['ansible_pkg_mgr']|default("none")}}{{hostvars[linux_host]['ansible_os_family']|default("none")}}{{hostvars[linux_host]['ansible_distribution_version']|default("none")}}{{hostvars[linux_host]['ansible_kernel']|default("none")}}
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/templates/services.j2 b/collections/ansible_collections/demo/patching/roles/report_linux/templates/services.j2 new file mode 100644 index 0000000..b765b5e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/templates/services.j2 @@ -0,0 +1,30 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux/vars/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux/vars/main.yml new file mode 100644 index 0000000..b91cc7a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html/reports \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/README.md b/collections/ansible_collections/demo/patching/roles/report_linux_patching/README.md new file mode 100644 index 0000000..b7e2fe2 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/README.md @@ -0,0 +1,36 @@ +build_report_linux_patch +======== + +Installs Apache and creates a report based on facts from Linux patching + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Linux servers about their patching results(yum and dnf) + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Report + import_role: + name: shadowman.reports.build_report_linux_patch + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux_patching/defaults/main.yml new file mode 100644 index 0000000..aaf5c3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/defaults/main.yml @@ -0,0 +1,3 @@ +EMAIL_FROM: tower@shadowman.dev +to_emails: alex@shadowman.dev,tower@shadowman.dev +EMAIL_TO: "{{ to_emails.split(',') }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Full_Report.png b/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Full_Report.png new file mode 100644 index 0000000..a7d66a2 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Full_Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Splunk Patching Aggregated RHEL 8.png b/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Splunk Patching Aggregated RHEL 8.png new file mode 100644 index 0000000..4367264 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux_patching/example_results/Splunk Patching Aggregated RHEL 8.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/css/main.css b/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/css/main.css new file mode 100644 index 0000000..dfeb435 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/css/main.css @@ -0,0 +1,111 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + } + + #subtable { + background: #ebebeb; + margin: 0px; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + margin:50px auto; + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + thead { + @include border-radius(5px); + } + + thead th { + font-family: 'Patua One', monospace; + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-family: 'Open Sans', sans-serif; + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/webpage_logo.png new file mode 100644 index 0000000..3d99673 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_linux_patching/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux_patching/tasks/main.yml new file mode 100644 index 0000000..ee42bc6 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/tasks/main.yml @@ -0,0 +1,39 @@ +- name: Create HTML report + ansible.builtin.template: + src: report.j2 + dest: "{{ file_path }}/linuxpatch.html" + check_mode: no + +- name: Copy CSS over + ansible.builtin.copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Copy logo over + ansible.builtin.copy: + src: "webpage_logo.png" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Display link to Linux patch report + ansible.builtin.debug: + msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/linuxpatch.html" + + +#- name: Send Report via E-mail +# community.general.mail: +# host: "{{ EMAIL_HOST }}" +# username: "{{ EMAIL_USERNAME }}" +# password: "{{ EMAIL_PASSWORD }}" +# port: "{{ EMAIL_PORT }}" +# subject: "Linux Patching Report" +# body: "{{ lookup('template', 'report.j2') }}" +# from: "{{ EMAIL_FROM }}" +# to: "{{ EMAIL_TO }}" +# subtype: html +# delegate_to: localhost +# become: false +# check_mode: no \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/report_linux_patching/templates/report.j2 new file mode 100644 index 0000000..01df73b --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/templates/report.j2 @@ -0,0 +1,120 @@ + + + + Linux Patch Report + + +
+

Ansible Linux Patching Report

+ +
+ + +
+
+ + + + + + + + + + +{% for linux_host in ansible_play_hosts |sort %} + + + + + + +{% endfor %} + +
HostnameOperating SystemOperating System VersionRequired Updates
{{hostvars[linux_host]['inventory_hostname']}}{{hostvars[linux_host]['ansible_os_family']|default("none")}}{{hostvars[linux_host]['ansible_distribution_version']|default("none")}} +
    +{% if hostvars[linux_host].patchingresult_yum.changed|default("false",true) == true %} +{% for packagename in hostvars[linux_host].patchingresult_yum.changes.updated|sort %} +
  • {{ packagename[0] }} - {{ packagename[1] }}
  • +{% endfor %} +{% elif hostvars[linux_host].patchingresult_dnf.changed|default("false",true) == true %} +{% for packagename in hostvars[linux_host].patchingresult_dnf.results|sort %} +
  • {{ packagename }}
  • +{% endfor %} +{% elif hostvars[linux_host].patchingresult_dnf.changed is undefined %} +
  • Patching Failed
  • +{% elif hostvars[linux_host].patchingresult_yum.changed is undefined %} +
  • Patching Failed
  • +{% else %} +
  • Compliant
  • +{% endif %} +
+
+

Created with Ansible on {{hostvars[inventory_hostname].ansible_date_time.iso8601}}

+ + + \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_linux_patching/vars/main.yml b/collections/ansible_collections/demo/patching/roles/report_linux_patching/vars/main.yml new file mode 100644 index 0000000..b91cc7a --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_linux_patching/vars/main.yml @@ -0,0 +1 @@ +file_path: /var/www/html/reports \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_server/tasks/apache.yml b/collections/ansible_collections/demo/patching/roles/report_server/tasks/apache.yml new file mode 100644 index 0000000..d8faec4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_server/tasks/apache.yml @@ -0,0 +1,20 @@ +--- +- yum: + name: httpd + state: latest + check_mode: no + +- file: + path: /var/www/html/reports/ + state: directory + check_mode: no + +- copy: + dest: /var/www/html/reports/.htaccess + content: Options +Indexes + check_mode: no + +- service: + name: httpd + state: started + check_mode: no \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_server/tasks/iis.yml b/collections/ansible_collections/demo/patching/roles/report_server/tasks/iis.yml new file mode 100644 index 0000000..74e6ffe --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_server/tasks/iis.yml @@ -0,0 +1,23 @@ +--- +- name: Install IIS + ansible.windows.win_feature: + name: Web-Server + state: present + check_mode: no + +- name: Start IIS service + ansible.windows.win_service: + name: W3Svc + state: started + check_mode: no + +- name: Create Directory + ansible.windows.win_file: + path: C:\Inetpub\wwwroot\reports + state: directory + check_mode: no + +- name: Enable Directory Browsing + ansible.windows.win_powershell: + script: | + "Set-WebConfigurationProperty -filter /system.webServer/directoryBrowse -name enabled -value true -PSPath 'IIS:\Sites\Default Web Site\reports'" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/README.md b/collections/ansible_collections/demo/patching/roles/report_windows/README.md new file mode 100644 index 0000000..93d6df4 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/README.md @@ -0,0 +1,36 @@ +build_report_windows +======== + +Installs Apache and creates a report based on facts from Windows services and packages modules + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html report on any number of Linux hosts using any number of Windows servers about their services and packages installed + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Report + import_role: + name: shadowman.reports.build_report_windows + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows/defaults/main.yml new file mode 100644 index 0000000..1154771 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/defaults/main.yml @@ -0,0 +1,2 @@ +--- +detailedreport: True \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/example_results/Ansible Windows Automation Report.png b/collections/ansible_collections/demo/patching/roles/report_windows/example_results/Ansible Windows Automation Report.png new file mode 100644 index 0000000..1ead477 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_windows/example_results/Ansible Windows Automation Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/files/css/new.css b/collections/ansible_collections/demo/patching/roles/report_windows/files/css/new.css new file mode 100644 index 0000000..f58d18f --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/files/css/new.css @@ -0,0 +1,202 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + margin: auto; + width: 50%; + } + + #subtable { + background: #ebebeb; + margin: 0px; + width: 100%; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + padding: 0px; + margin: 0px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + .main_net_table { + margin:50px auto; + } + + thead { + @include border-radius(5px); + } + + thead th { + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + td { + vertical-align: top; + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } + + header { + width: 100%; + position: initial; + float: initial; + padding: 0; + margin: 0; + border-radius: 0; + height: 88px; + background-color: #171717; + } + + .header-container { + margin: 0 auto; + width: 100%; + height: 100%; + max-width: 1170px; + padding: 0; + float: initial; + display: flex; + align-items: center; + } + + .header-logo { + width: 137px; + border: 0; + margin: 0; + margin-left: 15px; + } + + .header-link { + margin-left: 40px; + text-decoration: none; + cursor: pointer; + text-transform: uppercase; + font-size: 15px; + font-family: 'Red Hat Text'; + font-weight: 500; + } + + .header-link:hover { + text-shadow: 0 0 0.02px white; + text-decoration: none; + } + + table.net_info td { + padding: 5px; +} + +p.expandclass:hover { + text-decoration: underline; + color: #EE0000; + cursor: pointer; +} + +.summary_info { +} + +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover { + border: 1px solid #5F0000; + background: #EE0000; +} + +div#net_content { + padding: 0px; + height: auto !important; +} + +img.router_image { + vertical-align: middle; + padding: 0px 10px 10px 10px; + width: 50px; +} + +table.net_info { + width: 100%; +} + +p.internal_label { + color: #000000; +} \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/files/redhat-ansible-logo.svg b/collections/ansible_collections/demo/patching/roles/report_windows/files/redhat-ansible-logo.svg new file mode 100644 index 0000000..2ecef98 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/files/redhat-ansible-logo.svg @@ -0,0 +1,48 @@ + + + + +Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB + + + + + + + + + + + diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/files/server.png b/collections/ansible_collections/demo/patching/roles/report_windows/files/server.png new file mode 100644 index 0000000..9ad96fc Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_windows/files/server.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/report_windows/files/webpage_logo.png new file mode 100644 index 0000000..65b5836 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_windows/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows/tasks/main.yml new file mode 100644 index 0000000..c2f1479 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/tasks/main.yml @@ -0,0 +1,28 @@ +--- +- name: create HTML report + ansible.windows.win_template: + src: report.j2 + dest: "{{ file_path }}/windows.html" + check_mode: no + +- name: copy CSS over + ansible.windows.win_copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: copy logos over + ansible.windows.win_copy: + src: "{{ item }}" + dest: "{{ file_path }}" + directory_mode: true + loop: + - "webpage_logo.png" + - "redhat-ansible-logo.svg" + - "server.png" + check_mode: no + +#- name: display link to inventory report +# ansible.builtin.debug: +# msg: "Please go to http://{{ host_vars[report_server]['ansible_host'] }}/reports/windows.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/templates/header.j2 b/collections/ansible_collections/demo/patching/roles/report_windows/templates/header.j2 new file mode 100644 index 0000000..6d504d0 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/templates/header.j2 @@ -0,0 +1,15 @@ + + +
+
+
+ + + +
+
\ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/templates/packages.j2 b/collections/ansible_collections/demo/patching/roles/report_windows/templates/packages.j2 new file mode 100644 index 0000000..f290897 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/templates/packages.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/report_windows/templates/report.j2 new file mode 100644 index 0000000..7b9ada5 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/templates/report.j2 @@ -0,0 +1,101 @@ + + + + Ansible Windows Automation Report + + + + + + + + + + + +
+ {% include 'header.j2' %} +
+
+

Ansible Windows Automation Report

+

+

+ + + + + + + + + +{% for windows_host in ansible_play_hosts |sort %} + + + + + +{% endfor %} + +
Windows DeviceOperating SystemOperating System Kernel Version
+
+

+ {{ hostvars[windows_host]['inventory_hostname'].split('.')[0] }}

+
+{% if detailedreport == 'True' %} +{% include 'packages.j2' %} +{% include 'services.j2' %} +{% endif %} +
{{hostvars[windows_host]['ansible_os_family']|default("none")}}{{hostvars[windows_host]['ansible_distribution']|default("none")}}
+

Created with


+
+
+
+ + diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/templates/services.j2 b/collections/ansible_collections/demo/patching/roles/report_windows/templates/services.j2 new file mode 100644 index 0000000..b443161 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/templates/services.j2 @@ -0,0 +1,29 @@ + +
+
+ + +
+
+ \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows/vars/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows/vars/main.yml new file mode 100644 index 0000000..3ec787e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows/vars/main.yml @@ -0,0 +1 @@ +file_path: C:\Inetpub\wwwroot\reports \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/README.md b/collections/ansible_collections/demo/patching/roles/report_windows_patching/README.md new file mode 100644 index 0000000..dec8155 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/README.md @@ -0,0 +1,36 @@ +build_report_windows_patch +======== + +Installs Apache and creates a report based on facts from Windows update job + +Requirements +------------ + +Must run on Apache server + +Role Variables / Configuration +-------------- + +N/A + +Dependencies +------------ + +N/A + +Example Playbook +---------------- + +The role can be used to create an html patching report on any number of Linux hosts using any number of Windows servers + + +``` +--- +- hosts: all + + tasks: + - name: Run Windows Patch Report + import_role: + name: shadowman.reports.build_report_windows_patch + +``` \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/defaults/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows_patching/defaults/main.yml new file mode 100644 index 0000000..aaf5c3d --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/defaults/main.yml @@ -0,0 +1,3 @@ +EMAIL_FROM: tower@shadowman.dev +to_emails: alex@shadowman.dev,tower@shadowman.dev +EMAIL_TO: "{{ to_emails.split(',') }}" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/example_results/Full_Report.png b/collections/ansible_collections/demo/patching/roles/report_windows_patching/example_results/Full_Report.png new file mode 100644 index 0000000..615a021 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_windows_patching/example_results/Full_Report.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/css/main.css b/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/css/main.css new file mode 100644 index 0000000..dfeb435 --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/css/main.css @@ -0,0 +1,111 @@ +p.hostname { + color: #000000; + font-weight: bolder; + font-size: large; + } + + #subtable { + background: #ebebeb; + margin: 0px; + } + + #subtable tbody tr td { + padding: 5px 5px 5px 5px; + } + + #subtable thead th { + padding: 5px; + } + + * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: "Open Sans", "Helvetica"; + + } + + a { + color: #ffffff; + } + + p { + color: #ffffff; + } + h1 { + text-align: center; + color: #ffffff; + } + + body { + background:#353a40; + } + + table { + border-collapse: separate; + background:#fff; + @include border-radius(5px); + margin:50px auto; + @include box-shadow(0px 0px 5px rgba(0,0,0,0.3)); + } + + thead { + @include border-radius(5px); + } + + thead th { + font-family: 'Patua One', monospace; + font-size:16px; + font-weight:400; + color:#fff; + @include text-shadow(1px 1px 0px rgba(0,0,0,0.5)); + text-align:left; + padding:20px; + border-top:1px solid #858d99; + background: #353a40; + + &:first-child { + @include border-top-left-radius(5px); + } + + &:last-child { + @include border-top-right-radius(5px); + } + } + + tbody tr td { + font-family: 'Open Sans', sans-serif; + font-weight:400; + color:#5f6062; + font-size:13px; + padding:20px 20px 20px 20px; + border-bottom:1px solid #e0e0e0; + + } + + tbody tr:nth-child(2n) { + background:#f0f3f5; + } + + tbody tr:last-child td { + border-bottom:none; + &:first-child { + @include border-bottom-left-radius(5px); + } + &:last-child { + @include border-bottom-right-radius(5px); + } + } + + span.highlight { + background-color: yellow; + } + + .expandclass { + color: #5f6062; + } + + .content{ + display:none; + margin: 10px; + } \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/webpage_logo.png b/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/webpage_logo.png new file mode 100644 index 0000000..3d99673 Binary files /dev/null and b/collections/ansible_collections/demo/patching/roles/report_windows_patching/files/webpage_logo.png differ diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/tasks/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows_patching/tasks/main.yml new file mode 100644 index 0000000..83b014c --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/tasks/main.yml @@ -0,0 +1,23 @@ +- name: Create HTML report + ansible.windows.win_template: + src: report.j2 + dest: "{{ file_path }}/windowspatch.html" + check_mode: no + +- name: Copy CSS over + ansible.windows.win_copy: + src: "css" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Copy logo over + ansible.windows.win_copy: + src: "webpage_logo.png" + dest: "{{ file_path }}" + directory_mode: true + check_mode: no + +- name: Display link to Patch report + ansible.builtin.debug: + msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/windowspatch.html" \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/templates/report.j2 b/collections/ansible_collections/demo/patching/roles/report_windows_patching/templates/report.j2 new file mode 100644 index 0000000..3da03ec --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/templates/report.j2 @@ -0,0 +1,113 @@ + + + + Windows Patch Report + + +
+

Ansible Windows Patching Report

+ +
+ + +
+
+ + + + + + + + + +{% for windows_host in ansible_play_hosts |sort %} + + + + + + +{% endfor %} + +
HostnameOperating SystemRequired Updates
{{hostvars[windows_host]['inventory_hostname']}}{{hostvars[windows_host]['ansible_distribution']|default("none")}} +
    + +{% if hostvars[windows_host].patchingresult.updates is defined and hostvars[windows_host].patchingresult.found_update_count|int > 0 %} +{% for update in hostvars[windows_host].patchingresult.updates %} +{% set updatenum = hostvars[windows_host].patchingresult.updates[update] %} +
  • {{updatenum.title}}
  • +{% endfor %} +{% else %} +
  • Compliant
  • +{% endif %} +
+
+

Created with Ansible on {{hostvars[inventory_hostname].ansible_date_time.iso8601}}

+ + + \ No newline at end of file diff --git a/collections/ansible_collections/demo/patching/roles/report_windows_patching/vars/main.yml b/collections/ansible_collections/demo/patching/roles/report_windows_patching/vars/main.yml new file mode 100644 index 0000000..3ec787e --- /dev/null +++ b/collections/ansible_collections/demo/patching/roles/report_windows_patching/vars/main.yml @@ -0,0 +1 @@ +file_path: C:\Inetpub\wwwroot\reports \ No newline at end of file diff --git a/collections/requirements.yml b/collections/requirements.yml new file mode 100644 index 0000000..0d82843 --- /dev/null +++ b/collections/requirements.yml @@ -0,0 +1,23 @@ +--- +collections: + - name: ansible.controller + version: 4.1.1 + - name: redhat_cop.controller_configuration + version: 2.1.1 + #linux + - name: redhat.insights + version: 1.0.7 + - name: redhat.rhel_system_roles + version: 1.16.2 + - community.general + - containers.podman + #windows + - chocolatey.chocolatey + - community.windows + - name: ansible.windows + version: 1.9.0 + #cloud + - name: azure.azcollection + version: 1.13.0 + - name: amazon.aws + version: 3.1.1 diff --git a/docs b/docs deleted file mode 120000 index d75422d..0000000 --- a/docs +++ /dev/null @@ -1 +0,0 @@ -old-demo-repository/docs \ No newline at end of file diff --git a/images b/images deleted file mode 120000 index 3c16ad4..0000000 --- a/images +++ /dev/null @@ -1 +0,0 @@ -old-demo-repository/images \ No newline at end of file diff --git a/linux/ec2_register.yml b/linux/ec2_register.yml new file mode 100644 index 0000000..258c190 --- /dev/null +++ b/linux/ec2_register.yml @@ -0,0 +1,61 @@ +--- +- hosts: "{{ HOSTS }}" + become: yes + + tasks: + - name: set hostname + hostname: + name: "{{ inventory_hostname | regex_replace('_','-')}}" + + - name: remove rhui client packages + yum: + name: rh-amazon-rhui-client* + state: removed + + - name: get current repos + command: + cmd: ls /etc/yum.repos.d/ + register: repos + changed_when: False + + - name: remove existing rhui repos + file: + path: "/etc/yum.repos.d/{{ item }}" + state: absent + loop: "{{ repos.stdout_lines }}" + when: "'rhui' in item" + + - name: install katello package + yum: + name: "https://{{ sat_url }}/pub/katello-ca-consumer-latest.noarch.rpm" + state: present + validate_certs: no + when: sat_url is defined + + - name: manage repos with subscription mangler + ansible.builtin.lineinfile: + path: /etc/rhsm/rhsm.conf + regexp: '^manage_repos' + line: 'manage_repos = 1' + + - name: register subscription mangler + community.general.redhat_subscription: + state: present + activationkey: "{{ activation_key }}" + org_id: "{{ org_id }}" + + - name: disable htb repo + community.general.rhsm_repository: + name: rhel-7-server-htb* + state: disabled + ignore_errors: yes + + - name: configure Red Hat insights + import_role: + name: redhat.insights.insights_client + vars: + insights_display_name: "{{ inventory_hostname }}" + insights_tags: + env: "{{ env }}" + purpose: demo + group: "{{ ansible_group }}" \ No newline at end of file diff --git a/linux/inventory.insights.yml b/linux/inventory.insights.yml new file mode 100644 index 0000000..e9a1ebd --- /dev/null +++ b/linux/inventory.insights.yml @@ -0,0 +1,14 @@ +--- +plugin: redhat.insights.insights +get_patches: yes +groups: + patch_bugs: insights_patching.rhba_count > 0 + patch_enhancements: insights_patching.rhea_count > 0 + patch_security: insights_patching.rhsa_count > 0 +get_tags: yes +selection: none +filter_tags: + - insights-client/purpose=demo +keyed_groups: + - key: insights_tags['insights-client'] + prefix: insights diff --git a/linux/patching.yml b/linux/patching.yml new file mode 100644 index 0000000..3c83a8c --- /dev/null +++ b/linux/patching.yml @@ -0,0 +1,38 @@ +--- +- hosts: "{{ HOSTS }}" + become: yes + vars: + report_server: node1 + + tasks: + - include_role: + name: demo.patching.patch_linux + + - block: + - yum: + name: httpd + state: latest + check_mode: no + + - file: + path: /var/www/html/reports/ + state: directory + check_mode: no + + - copy: + dest: /var/www/html/reports/.htaccess + content: Options +Indexes + check_mode: no + + - service: + name: httpd + state: started + check_mode: no + + - include_role: + name: demo.patching.report_linux + + - include_role: + name: demo.patching.report_linux_patching + delegate_to: "{{ report_server }}" + run_once: yes \ No newline at end of file diff --git a/linux/patching_report.yml b/linux/patching_report.yml new file mode 100644 index 0000000..3c83a8c --- /dev/null +++ b/linux/patching_report.yml @@ -0,0 +1,38 @@ +--- +- hosts: "{{ HOSTS }}" + become: yes + vars: + report_server: node1 + + tasks: + - include_role: + name: demo.patching.patch_linux + + - block: + - yum: + name: httpd + state: latest + check_mode: no + + - file: + path: /var/www/html/reports/ + state: directory + check_mode: no + + - copy: + dest: /var/www/html/reports/.htaccess + content: Options +Indexes + check_mode: no + + - service: + name: httpd + state: started + check_mode: no + + - include_role: + name: demo.patching.report_linux + + - include_role: + name: demo.patching.report_linux_patching + delegate_to: "{{ report_server }}" + run_once: yes \ No newline at end of file diff --git a/linux/podman.yml b/linux/podman.yml new file mode 100644 index 0000000..bb5eca3 --- /dev/null +++ b/linux/podman.yml @@ -0,0 +1,51 @@ +--- +- name: Podman + hosts: "{{ HOSTS }}" + vars: + volume_path: podman + message: undef + + tasks: + - name: Install Podman + ansible.builtin.dnf: + name: podman + state: latest + become: yes + + - name: Create volume dir + ansible.builtin.file: + path: "{{ volume_path }}" + state: directory + + - name: Create index.html + ansible.builtin.copy: + dest: "{{ volume_path }}/index.html" + content: "{{ message }}" + + - name: Run httpd container + containers.podman.podman_container: + name: apache + image: docker.io/httpd + state: started + volume: + - "{{ volume_path }}:/usr/local/apache2/htdocs" + ports: + - "8080:80" + + - name: Check Web Page + ansible.builtin.uri: + url: http://127.0.0.1:8080 + return_content: yes + register: web_output + changed_when: false + + - name: podman ps + shell: podman ps + register: podman_output + changed_when: false + + - name: Output + ansible.builtin.debug: + msg: + - "{{ podman_output.stdout_lines }}" + - "{{ web_output.content }}" \ No newline at end of file diff --git a/linux/run_script.yml b/linux/run_script.yml new file mode 100644 index 0000000..a1c3364 --- /dev/null +++ b/linux/run_script.yml @@ -0,0 +1,15 @@ +--- +- name: Run Shell Script + hosts: "{{ HOSTS }}" + become: yes + gather_facts: no + vars: + shell_script: undef + + tasks: + - name: Run Shell Script + shell: "{{ shell_script }}" + + - debug: + msg: You should really consider converting this script to a playbook! + run_once: yes \ No newline at end of file diff --git a/linux/service_start.yml b/linux/service_start.yml new file mode 100644 index 0000000..81979ea --- /dev/null +++ b/linux/service_start.yml @@ -0,0 +1,14 @@ +--- +- hosts: "{{ HOSTS }}" + vars: + service_name: undef + + tasks: + - name: Check Service + service_facts: + + - name: Start Service + service: + name: "{{ service_name }}" + state: started + when: service_name + '.service' in services diff --git a/linux/service_stop.yml b/linux/service_stop.yml new file mode 100644 index 0000000..4ab01b1 --- /dev/null +++ b/linux/service_stop.yml @@ -0,0 +1,14 @@ +--- +- hosts: "{{ HOSTS }}" + vars: + service_name: undef + + tasks: + - name: Check Service + service_facts: + + - name: Stop Service + service: + name: "{{ service_name }}" + state: stopped + when: service_name + '.service' in services \ No newline at end of file diff --git a/linux/setup.yml b/linux/setup.yml new file mode 100644 index 0000000..bfe30b1 --- /dev/null +++ b/linux/setup.yml @@ -0,0 +1,265 @@ +--- +user_message: | + Be sure to update the 'activation_key' and 'org_id' extra variables for 'LINUX / Register'. https://access.redhat.com/management/activation_keys + + Update Credential for Insights Inventory with Red Hat account. +controller_components: + - projects + - credential_types + - credentials + - inventory_sources + - job_templates + +controller_projects: + - name: Fact Scan + organization: Default + scm_type: git + scm_url: 'https://github.com/ansible/awx-facts-playbooks.git' + +controller_credential_types: + - name: "Insights Collection" + kind: cloud + inputs: + fields: + - id: insights_user + type: string + label: Insights User + - id: insights_password + type: string + label: Insights Password + secret: true + injectors: + env: + INSIGHTS_USER: "{% raw %}{ { insights_user }}{% endraw %}" + INSIGHTS_PASSWORD: "{% raw %}{ { insights_password }}{% endraw %}" + +controller_credentials: + - name: Insights Inventory + credential_type: Insights Collection + organization: Default + inputs: + insights_user: REPLACEME + insights_password: REPLACEME + +controller_inventory_sources: + - name: Insights Inventory + inventory: Workshop Inventory + source: scm + source_project: Ansible official demo project + source_path: linux/inventory.insights.yml + credential: Insights Inventory + + +controller_templates: + - name: "LINUX / Register" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/ec2_register.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + extra_vars: + activation_key: undef + org_id: undef + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: Choose Environment + type: multiplechoice + variable: env + choices: + - Dev + - QA + - Prod + required: true + - question_name: Ansible Group + type: text + variable: ansible_group + required: true + - name: "LINUX / Troubleshoot" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/tshoot.yml" + execution_environment: Default execution environment + use_fact_cache: true + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - name: "LINUX / Temporary Sudo" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/temp_sudo.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: User Name + type: text + variable: sudo_user + required: true + - question_name: How long to grant access in minutes + type: integer + variable: sudo_time + default: 10 + required: true + - name: "LINUX / Patching" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/patching.yml" + execution_environment: Default execution environment + use_fact_cache: true + job_type: check + ask_job_type_on_launch: yes + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - name: "LINUX / Start Service" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/service_start.yml" + execution_environment: Default execution environment + use_fact_cache: true + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: Service Name + type: text + variable: service_name + required: true + - name: "LINUX / Stop Service" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/service_stop.yml" + execution_environment: Default execution environment + use_fact_cache: true + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: Service Name + type: text + variable: service_name + required: true + - name: "LINUX / Run Shell Script" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/run_script.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: Shell Script + type: textarea + variable: shell_script + required: true + - name: "LINUX / Fact Scan" + project: Fact Scan + playbook: scan_facts.yml + inventory: Workshop Inventory + execution_environment: Default execution environment + ask_limit_on_launch: true + use_fact_cache: true + credentials: + - Workshop Credential + - name: "LINUX / Podman Webserver" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/podman.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true + - question_name: Web Page Message + type: textarea + variable: message + required: true + - name: "LINUX / System Roles" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "linux/system_roles.yml" + execution_environment: Default execution environment + diff_mode: yes + ask_job_type_on_launch: yes + extra_vars: + system_roles: undef + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: true \ No newline at end of file diff --git a/linux/system_roles.yml b/linux/system_roles.yml new file mode 100644 index 0000000..7a71cfd --- /dev/null +++ b/linux/system_roles.yml @@ -0,0 +1,13 @@ +--- +- name: Apply RHEL System Roles + hosts: "{{ HOSTS }}" + vars: + system_roles: undef + + tasks: + - name: Apply System Roles + include_role: + name: "redhat.rhel_system_roles.{{ item }}" + loop: "{{ system_roles }}" + when: + - system_roles | d("") | length > 0 \ No newline at end of file diff --git a/linux/temp_sudo.yml b/linux/temp_sudo.yml new file mode 100644 index 0000000..cec7ced --- /dev/null +++ b/linux/temp_sudo.yml @@ -0,0 +1,41 @@ +--- +- name: Temporary Sudo + hosts: "{{ HOSTS }}" + become: yes + gather_facts: no + vars: + sudo_cleanup: true + sudo_user: undef + sudo_time: 10 + sudo_units: minutes + + tasks: + - name: Check if sudo user exists on system + getent: + database: passwd + key: "{{ sudo_user }}" + + - name: Check Cleanup package + yum: + name: at + state: latest + + - name: Check Cleanup Service + service: + name: atd + state: started + + - name: Create Sudo Rule + copy: + dest: "/etc/sudoers.d/{{ sudo_user }}" + owner: root + group: root + mode: 0640 + content: "{{ sudo_user }} ALL=(ALL) NOPASSWD:ALL" + + - name: Set Permission Cleanup + at: + command: "rm /etc/sudoers.d/{{ sudo_user }}" + count: "{{ sudo_time }}" + units: "{{ sudo_units }}" + when: sudo_cleanup|bool diff --git a/linux/tshoot.yml b/linux/tshoot.yml new file mode 100644 index 0000000..51c3499 --- /dev/null +++ b/linux/tshoot.yml @@ -0,0 +1,29 @@ +--- +- name: gather debug info + hosts: "{{ HOSTS }}" + become: yes + + tasks: + - name: Gather recent vmstat info + command: /bin/vmstat 1 5 + register: vmstat + + - name: Gather top CPU hogs + command: ps -eo user,pid,size,pcpu,cmd --sort=-pcpu + register: pscpu + + - name: Gather top memory hogs + command: ps -eo user,pid,size,pcpu,cmd --sort=-size + register: pssize + + - name: Swap + wait states + debug: + var: vmstat.stdout_lines + + - name: Top 3 CPU hogs + debug: + var: pscpu.stdout_lines[:4] + + - name: Top 3 memory hogs + debug: + var: pssize.stdout_lines[:4] \ No newline at end of file diff --git a/meta b/meta deleted file mode 120000 index a20b215..0000000 --- a/meta +++ /dev/null @@ -1 +0,0 @@ -old-demo-repository/meta \ No newline at end of file diff --git a/roles b/roles deleted file mode 120000 index 27351dc..0000000 --- a/roles +++ /dev/null @@ -1 +0,0 @@ -old-demo-repository/roles \ No newline at end of file diff --git a/setup_demo.yml b/setup_demo.yml new file mode 100644 index 0000000..25accf5 --- /dev/null +++ b/setup_demo.yml @@ -0,0 +1,20 @@ +--- +- hosts: localhost + gather_facts: no + vars_files: + - "{{demo}}/setup.yml" + vars: + controller_validate_certs: false + + tasks: + - name: Setup Components + include_role: + name: "redhat_cop.controller_configuration.{{ item }}" + loop: "{{ controller_components }}" + when: + - controller_components | d("") | length > 0 + + - name: Print Message + debug: + msg: "{{ user_message }}" + when: user_message is defined \ No newline at end of file diff --git a/windows/active_directory/create_ad_domain.yml b/windows/active_directory/create_ad_domain.yml new file mode 100644 index 0000000..00ee7d2 --- /dev/null +++ b/windows/active_directory/create_ad_domain.yml @@ -0,0 +1,44 @@ +--- +- name: Create Active Directory domain + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + + tasks: + - name: Create new domain in a new forest on the target host + ansible.windows.win_domain: + dns_domain_name: ansible.local + safe_mode_password: "{{ lookup('community.general.random_string', min_lower=1, min_upper=1, min_special=1, min_numeric=1) }}" + register: new_forest + + - name: Reboot the target host + ansible.windows.win_reboot: + reboot_timeout: 3600 + when: new_forest.reboot_required + + - name: Wait up to 10min for AD web services to start + community.windows.win_wait_for_process: + process_name_exact: Microsoft.ActiveDirectory.WebServices + pre_wait_delay: 60 + state: present + timeout: 600 + sleep: 10 + + - name: Create some groups + community.windows.win_domain_group: + name: "{{ item.name }}" + scope: global + loop: + - { name: "GroupA" } + - { name: "GroupB" } + - { name: "GroupC" } + + - name: Create some users + community.windows.win_domain_user: + name: "{{ item.name }}" + groups: "{{ item.groups }}" + password: "{{ lookup('community.general.random_string', min_lower=1, min_upper=1, min_special=1, min_numeric=1) }}" + update_password: on_create + loop: + - { name: "UserA", groups: "GroupA" } + - { name: "UserB", groups: "GroupB" } + - { name: "UserC", groups: "GroupC" } diff --git a/windows/active_directory/helpdesk_new_user_portal.yml b/windows/active_directory/helpdesk_new_user_portal.yml new file mode 100644 index 0000000..a9d61ba --- /dev/null +++ b/windows/active_directory/helpdesk_new_user_portal.yml @@ -0,0 +1,39 @@ +--- +- name: Helpdesk new user portal + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + + tasks: + - name: Setting host facts using complex arguments + set_fact: + temp_password: "{{ lookup('community.general.random_string', min_lower=1, min_upper=1, min_special=1, min_numeric=1) }}" + # Example result: ['&Qw2|E[-'] + + - name: Create new user + community.windows.win_domain_user: + name: "{{ firstname }} {{ surname }}" + firstname: "{{ firstname }}" + surname: "{{ surname }}" + sam_account_name: "{{ firstname[0] }}{{ surname }}" + company: BobCo + password: "{{ temp_password }}" + state: present + groups: + - "GroupA" + - "GroupB" + street: "{{ street }}" + city: "{{ city }}" + state_province: IN + postal_code: "{{ postal_code }}" + country: US + attributes: + telephoneNumber: "{{ telephone_number }}" + register: new_user + + - name: Display User + debug: + var: new_user + + - name: Show temp password + debug: + var: temp_password diff --git a/windows/arbitrary_powershell.yml b/windows/arbitrary_powershell.yml new file mode 100644 index 0000000..90d608d --- /dev/null +++ b/windows/arbitrary_powershell.yml @@ -0,0 +1,16 @@ +--- +- name: Arbitrary PowerShell + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + vars: + ps_script: undef + + tasks: + - name: Run PowerShell + ansible.windows.win_powershell: + script: | + {{ ps_script }} + register: ps_output + + - debug: + msg: "{{ ps_output.output }}" diff --git a/windows/backup.yml b/windows/backup.yml new file mode 100644 index 0000000..86081b9 --- /dev/null +++ b/windows/backup.yml @@ -0,0 +1,7 @@ +--- +- hosts: windows + name: Rollback playbook + tasks: + - name: "Rollback this step" + debug: + msg: "Rolling back this step" diff --git a/windows/group_vars/os_windows.yml b/windows/group_vars/os_windows.yml new file mode 100644 index 0000000..5cde06e --- /dev/null +++ b/windows/group_vars/os_windows.yml @@ -0,0 +1,5 @@ +--- +ansible_connection: winrm +ansible_winrm_transport: ntlm +ansible_winrm_server_cert_validation: ignore +ansible_port: 5986 \ No newline at end of file diff --git a/windows/install_iis.yml b/windows/install_iis.yml new file mode 100644 index 0000000..2b84612 --- /dev/null +++ b/windows/install_iis.yml @@ -0,0 +1,25 @@ +--- +- name: Install IIS + hosts: "{{ HOSTS | default('windows') }}" + vars: + iis_message: undef + + tasks: + - name: Install IIS + win_feature: + name: Web-Server + state: present + + - name: Start IIS service + win_service: + name: W3Svc + state: started + + - name: Create website index.html + win_copy: + content: "{{ iis_message }}" + dest: C:\Inetpub\wwwroot\index.html + + - name: Show website address + debug: + msg: http://{{ ansible_host }} diff --git a/windows/patching.yml b/windows/patching.yml new file mode 100644 index 0000000..dbab74c --- /dev/null +++ b/windows/patching.yml @@ -0,0 +1,22 @@ +--- +- name: Windows updates + hosts: "{{ HOSTS | default('os_windows') }}" + vars: + report_server: win1 + + tasks: + - include_role: + name: demo.patching.patch_windows + + - block: + - include_role: + name: demo.patching.report_server + tasks_from: iis + + - include_role: + name: demo.patching.report_windows + + - include_role: + name: demo.patching.report_windows_patching + delegate_to: "{{ report_server }}" + run_once: yes \ No newline at end of file diff --git a/windows/powershell_dsc.yml b/windows/powershell_dsc.yml new file mode 100644 index 0000000..7db3657 --- /dev/null +++ b/windows/powershell_dsc.yml @@ -0,0 +1,41 @@ +--- +- name: PowerShell DSC + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + + tasks: + - name: Setup the SecurityPolicyDSC module + community.windows.win_psmodule: + name: SecurityPolicyDSC + module_version: 2.10.0.0 + state: present + + - name: Set password history + ansible.windows.win_dsc: + resource_name: AccountPolicy + Name: Enforce_password_history + Enforce_password_history: 24 + + - name: Set maximum password age + ansible.windows.win_dsc: + resource_name: AccountPolicy + Name: Maximum_Password_Age + Maximum_Password_Age: 60 + + - name: Set minimum password age + ansible.windows.win_dsc: + resource_name: AccountPolicy + Name: Minimum_Password_Age + Maximum_Password_Age: 20 + + - name: Set minimum password length + ansible.windows.win_dsc: + resource_name: AccountPolicy + Name: Minimum_Password_Length + Maximum_Password_Age: 8 + + - name: Set password complexity requirements + ansible.windows.win_dsc: + resource_name: AccountPolicy + Name: Password_must_meet_complexity_requirements + Password_must_meet_complexity_requirements: Enabled diff --git a/windows/powershell_script.yml b/windows/powershell_script.yml new file mode 100644 index 0000000..122e5ff --- /dev/null +++ b/windows/powershell_script.yml @@ -0,0 +1,20 @@ +--- +- name: PowerShell Script + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + vars: + remote_dest: "C:\\sample_script.ps1" + tasks: + - name: Copy script to remote + ansible.windows.win_copy: + src: "{{playbook_dir}}/sample_script.ps1" + dest: "{{ remote_dest }}" + + - name: Run Script + ansible.windows.win_powershell: + script: | + {{ remote_dest }} -ServiceState {{ service_state }} + register: ps_output + + - debug: + var: ps_output diff --git a/windows/sample_script.ps1 b/windows/sample_script.ps1 new file mode 100644 index 0000000..159170a --- /dev/null +++ b/windows/sample_script.ps1 @@ -0,0 +1,7 @@ +Param +( + [Parameter(Mandatory=$true)] + [string]$ServiceState +) +# Sample parameterized script for use with powershell_script.yml +Get-Service | Where-Object -FilterScript {$_.Status -eq $ServiceState} | Select-Object -Property 'Name' diff --git a/windows/setup.yml b/windows/setup.yml new file mode 100644 index 0000000..6b42eda --- /dev/null +++ b/windows/setup.yml @@ -0,0 +1,247 @@ +--- +user_message: | + '' + +controller_components: + - projects + - job_templates + +controller_projects: + - name: Fact Scan + organization: Default + scm_type: git + scm_url: 'https://github.com/ansible/awx-facts-playbooks.git' + +controller_templates: + - name: "WINDOWS / Install IIS" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/install_iis.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + - question_name: web content + type: text + variable: iis_message + required: true + + - name: "WINDOWS / Patching" + use_fact_cache: true + job_type: check + ask_job_type_on_launch: yes + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/patching.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + - question_name: Update categories + type: multiselect + variable: win_update_categories + required: false + default: SecurityUpdates + choices: + - Application + - Connectors + - CriticalUpdates + - DefinitionUpdates + - DeveloperKits + - FeaturePacks Guidance + - SecurityUpdates + - ServicePacks + - Tools + - UpdateRollups + - Updates + - question_name: Reboot after install? + type: multiplechoice + variable: allow_reboot + required: false + default: 'Yes' + choices: + - 'Yes' + - 'No' + + - name: "WINDOWS / Chocolatey install multiple" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/windows_choco_multiple.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + + - name: "WINDOWS / Chocolatey install specific" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/windows_choco_specific.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + - question_name: Package name + type: text + variable: package_name + required: true + - name: "WINDOWS / Arbitrary PowerShell" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/arbitrary_powershell.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + - question_name: PowerShell Script (Default returns random cat fact) + type: textarea + variable: ps_script + default: "(Invoke-RestMethod -Method 'GET' -Uri 'https://catfact.ninja/fact').fact" + required: true + + - name: "WINDOWS / PowerShell Script" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/powershell_script.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + - question_name: Service state to query? + type: multiplechoice + variable: service_state + required: false + default: 'Running' + choices: + - 'Running' + - 'Stopped' + + - name: "WINDOWS / PowerShell DSC configuring password requirements" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/powershell_dsc.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + + - name: "ACTIVE DIRECTORY / Create Active Directory domain" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/active_directory/create_ad_domain.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Server Name or Pattern + type: text + variable: HOSTS + required: false + + - name: "ACTIVE DIRECTORY / Helpdesk new user portal" + job_type: run + inventory: "Workshop Inventory" + project: "Ansible official demo project" + playbook: "windows/active_directory/helpdesk_new_user_portal.yml" + execution_environment: Default execution environment + credentials: + - "Workshop Credential" + survey_enabled: true + survey: + name: '' + description: '' + spec: + - question_name: Firstname + type: text + variable: firstname + required: true + - question_name: Surname + type: text + variable: surname + required: true + - question_name: Street + type: text + variable: street + default: 123 4th St. + required: false + - question_name: City + type: text + variable: city + default: Sometown + required: false + - question_name: Postal code + type: text + variable: postal_code + default: IN + required: false + - question_name: Telephone number + type: text + variable: telephone_number + default: 555-123456 + required: false \ No newline at end of file diff --git a/windows/snow.yml b/windows/snow.yml new file mode 100644 index 0000000..4b1aa1b --- /dev/null +++ b/windows/snow.yml @@ -0,0 +1,32 @@ +--- +- name: open a change request + hosts: student1-ansible-1 + vars: + change_request: + severity: 2 + priority: 2 + description: Automated Provisioning + justification: Ansible Triggered + implementation_plan: Updated by Red Hat AAP + risk_impact_analysis: Changes are made automatically based on approved changes + test_plan: Run synthetic validation tests post-deployment + short_description: Automated Provisioning + tasks: + - name: Create a change request + servicenow.itsm.change_request: + instance: + host: "https://{{ snow_instance }}.service-now.com" + username: "{{ snow_username }}" + password: "{{ snow_password }}" + type: standard + state: new + requested_by: admin + short_description: "{{ change_request.short_description }}" + description: "{{ change_request.description }}" + priority: moderate + risk: low + impact: low + register: new_incident + + - debug: + var: new_incident.record.number diff --git a/windows/windows_choco_multiple.yml b/windows/windows_choco_multiple.yml new file mode 100644 index 0000000..83ea42b --- /dev/null +++ b/windows/windows_choco_multiple.yml @@ -0,0 +1,29 @@ +--- +- name: Chocolatey install multiple + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + vars: + choco_packages: + - name: nodejs + version: 13.0.0 + - name: python + version: 3.6.0 + tasks: + - name: Install specific versions of packages sequentially + win_chocolatey: + name: "{{ item.name }}" + version: "{{ item.version }}" + loop: "{{ choco_packages }}" + + - name: Check python version + win_command: python --version + register: check_python_version + changed_when: false + + - name: Check nodejs version + win_command: node --version + register: check_node_version + changed_when: false + + - debug: + msg: Python Version is {{ check_python_version.stdout_lines[0] }} and NodeJS version is {{ check_node_version.stdout_lines[0] }} diff --git a/windows/windows_choco_specific.yml b/windows/windows_choco_specific.yml new file mode 100644 index 0000000..5f034ec --- /dev/null +++ b/windows/windows_choco_specific.yml @@ -0,0 +1,9 @@ +--- +- name: Chocolatey install specific + hosts: "{{ HOSTS | default('windows') }}" + gather_facts: false + + tasks: + - name: Install choco package with specific version + win_chocolatey: + name: "{{ package_name }}"