Merge of RedHatGov/product-demos (#56)

Co-authored-by: MKletz <michael.kletz.27@gmail.com>
Co-authored-by: Ajay Chenampara <ajay.chenampara@gmail.com>
Co-authored-by: dlemons-redhat <69318976+dlemons-redhat@users.noreply.github.com>
Co-authored-by: Nicolas Leiva <nicolasleiva@gmail.com>
Co-authored-by: benblasco <42140583+benblasco@users.noreply.github.com>
Co-authored-by: Benjamin Blasco <bblasco@redhat.com>
Co-authored-by: calvingsmith <4283930+calvingsmith@users.noreply.github.com>
Co-authored-by: Calvin Smith <calvingsmith@users.noreply.github.com>
Co-authored-by: Hicham Mourad <43329991+HichamMourad@users.noreply.github.com>
This commit is contained in:
willtome
2023-03-17 09:07:02 -04:00
committed by GitHub
parent 8acff9c9b1
commit c18a206499
279 changed files with 5191 additions and 4649 deletions

View File

@@ -10,10 +10,10 @@ 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_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"
@@ -21,4 +21,3 @@ aws_env_tag: prod
aws_purpose_tag: ansible_demo
aws_ansiblegroup_tag: cloud
aws_ec2_wait: true

View File

@@ -17,19 +17,19 @@
vpc_id: "{{ aws_vpc.vpc.id }}"
region: "{{ aws_region }}"
tags:
Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-vpc-igw"
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:
amazon.aws.ec2_security_group:
state: present
name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-sec-group"
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
description: Inbound WinRM and RDP, http for demo servers and internal AD ports
rules:
- proto: tcp
- proto: tcp
ports:
- 80 # HTTP
- 443 # HTTPS
@@ -42,7 +42,7 @@
from_port: -1
cidr_ip: 0.0.0.0/0
- proto: tcp
ports:
ports:
- 80 # HTTP
- 5986 # WinRM
- 3389 # RDP
@@ -55,27 +55,27 @@
- 464 # Kerberos Authentication
- 5432 # PostgreSQL
- 636 # LDAPS (LDAP over TLS)
- 873 # Rsync
- 3268-3269 # Global Catalog
- 873 # Rsync
- 3268-3269 # Global Catalog
- 1024-65535 # Ephemeral RPC ports
cidr_ip: 10.0.0.0/16
- proto: udp
ports:
- proto: udp
ports:
- 53 # DNS
- 88 # Kerberos Authentication
- 123 # NTP
- 137-138 # Netlogon
- 389 # LDAP
- 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
- 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"
Name: "{{ aws_vpc_name }}-{{ aws_vpc_prefix }}-sec-group"
owner: "{{ aws_vpc_name }}"
purpose: "{{ aws_purpose_tag }}"
@@ -85,34 +85,34 @@
vpc_id: "{{ aws_vpc.vpc.id }}"
cidr: "{{ aws_subnet_cidr }}"
region: "{{ aws_region }}"
map_public: yes
map_public: true
tags:
Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-subnet"
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
- name: Create a subnet route table
amazon.aws.ec2_vpc_route_table:
state: present
state: present
vpc_id: "{{ aws_vpc.vpc.id }}"
region: "{{ aws_region }}"
subnets:
- "{{ aws_subnet.subnet.id }}"
routes:
- dest: 0.0.0.0/0
- dest: 0.0.0.0/0
gateway_id: "{{ aws_gateway.gateway_id }}"
tags:
Name: "{{ aws_vpc_name }}-{{aws_vpc_prefix }}-vpc-rtbl"
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"
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 }}"
purpose: "{{ aws_purpose_tag }}"

View File

@@ -7,27 +7,27 @@
register: aws_subnet
- name: AWS | CREATE VM | save subnet id
set_fact:
aws_subnet_id: "{{ aws_subnet.subnets|map(attribute='id')| list | last }}"
ansible.builtin.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)}}"
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:
ansible.builtin.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
assign_public_ip: true
key_name: "{{ aws_keypair_name }}"
instance_type: "{{ aws_instance_size }}"
image_id: "{{ aws_instance_ami.image_id }}"
@@ -43,5 +43,5 @@
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
user_data: "{{ lookup('template', aws_userdata_template + '.j2', template_vars=dict(aws_vm_name=vm_name)) }}"
register: aws_vm_output

View File

@@ -4,4 +4,4 @@
state: absent
instance_ids: "{{ instance_id }}"
region: "{{ placement.region }}"
delegate_to: localhost
delegate_to: localhost

View File

@@ -1,17 +0,0 @@
---
##############
# 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

View File

@@ -1,76 +0,0 @@
---
- 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 }}"

View File

@@ -1,28 +0,0 @@
---
- 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 }}"

View File

@@ -1,8 +0,0 @@
---
- 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -0,0 +1,207 @@
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;
}
.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;
}

View File

@@ -1,24 +1,36 @@
- name: create HTML report
- name: Create web directory if it does not exist
ansible.builtin.file:
path: "{{ file_path }}"
state: directory
mode: "0755"
- name: Create HTML report
ansible.builtin.template:
src: report.j2
dest: "{{ file_path }}/network.html"
mode: "0644"
check_mode: false
- name: copy CSS over
- name: Copy CSS over
ansible.builtin.copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
mode: "0775"
check_mode: false
- name: copy logos over
- name: Copy logos over
ansible.builtin.copy:
src: "{{ item }}"
src: "{{ item }}"
dest: "{{ file_path }}"
directory_mode: true
mode: "0644"
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "router.png"
check_mode: false
- name: display link to inventory report
ansible.builtin.debug:
msg: "Please go to http://{{ ansible_host }}/network.html"
# - name: Display link to Linux patch report
# ansible.builtin.debug:
# msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/network.html"

View File

@@ -0,0 +1,41 @@
<!-- INTERNAL TABLE FOR Ansible -->
<div id="accordion">
<div>
<h3>Ansible Automation Info</h3>
<div class="net_content">
<table class="net_info">
<tbody>
<tr>
<td>Ansible user</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_user'] }}</td>
</tr>
<tr>
<td>Transport</td>
<td class="sub_net_info">{% set ansible_connection = hostvars[network_switch]['ansible_net_api'] %}{{ transport[ansible_connection] }}</td>
</tr>
<tr>
<td>Ansible Mgmt IP</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_host'] | default('N/A') }}</td>
</tr>
<tr>
<td>Ansible groups</td>
<td class="sub_net_info">{% for group in hostvars[network_switch]['group_names'] %}{{ group }} {% endfor %}</td>
</tr>
<tr>
<td>Ansible core version</td>
<td class="sub_net_info">{% for group in hostvars[network_switch]['ansible_version']['string']|default("Unknown") %}{{ group }} {% endfor %}</td>
</tr>
<tr>
<td>Ansible Python</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_playbook_python']|default("Unknown") }} </td>
</tr>
<tr>
<td>Python version</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_net_python_version']|default("Unknown") }} </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- END INTERNAL TABLE FOR Ansible -->

View File

@@ -1,25 +1,46 @@
<! INTERNAL TABLE FOR BGP --!>
<!-- INTERNAL TABLE FOR BGP -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">BGP Global Info</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>BGP Global Info</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['bgp_global'] is defined and hostvars[network_switch]['ansible_network_resources']['bgp_global']|length > 0 %}
<table id="subtable">
<thead>
<tr>
<th>ASN</th>
<th>Router ID</th>
</tr>
</thead>
<tbody>
{% for bgpinfo in hostvars[network_switch]['ansible_network_resources']['bgp_global'] %}
<tr>
<td>{{bgpinfo['as_number']}}</td>
<td>{{bgpinfo['router_id']|default("Not Configured")}}</td>
<td>{{ hostvars[network_switch].ansible_network_resources.bgp_global['as_number']|default("Not Configured") }}</td>
<td>{{ hostvars[network_switch].ansible_network_resources.bgp_global.bgp['router_id']['address']|default("Not Configured") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if hostvars[network_switch]['ansible_network_resources']['bgp_global'][
'neighbor'] is defined and hostvars[network_switch]['ansible_network_resources']['bgp_global'][
'neighbor']|length > 0 %}
<p class="internal_label">BGP Neighbors</p>
<table id="subtable">
<thead>
<tr>
<th>Address</th>
<th>Remote AS</th>
</tr>
</thead>
<tbody>
{% for bgp_neighbor in hostvars[network_switch].ansible_network_resources.bgp_global.neighbor %}
<tr>
<td>{{ bgp_neighbor['address']|default("Not Configured") }}</td>
<td>{{ bgp_neighbor['remote_as']|default("Not Configured") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% elif hostvars[network_switch]['ansible_network_resources']['bgp_global'] is defined and hostvars[network_switch]['ansible_network_resources']['bgp_global']|length == 0 %}
BGP is not configured on this device
{% else %}
@@ -28,4 +49,4 @@ No BGP information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR BGP --!>
<!-- END INTERNAL TABLE FOR BGP -->

View File

@@ -0,0 +1,46 @@
<!-- INTERNAL TABLE FOR BGP -->
<div id="accordion">
<div>
<h3>BGP Address Family</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family'] is defined and hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family']|length > 0 %}
{% for address_family in hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family'] %}
<p class="internal_label">Address Family {{ address_family['afi'] }}</p>
<table id="subtable">
<thead>
<tr>
<th>Network</th>
</tr>
</thead>
<tbody>
{% if hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family']['networks'] is defined %}
{% for bgp_network in address_family['networks'] %}
<tr>
<td>{{ bgp_network['prefix']|default("Not Configured") }}</td>
</tr>
{% endfor %}
{% elif hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family']['network'] is defined %}
{% for bgp_network in address_family['network'] %}
<tr>
<td>{{ bgp_network['address']|default("Not Configured") }}</td>
<td>{{ bgp_network['mask']|default("Not Configured") }}</td>
</tr>
{% endfor %}
{% else %}
No BGP networks information available
{% endif %}
</tbody>
</table>
{% endfor %}
{% elif hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family'] is defined and hostvars[network_switch]['ansible_network_resources']['bgp_address_family']['address_family']|length == 0 %}
no BGP address-family is not configured on this device
{% else %}
No BGP information available
{% endif %}
</div>
</div>
</div>
<!-- END INTERNAL TABLE FOR BGP -->

View File

@@ -1,5 +1,3 @@
<div class="wrapper">
<header>
<div class="header-container">
@@ -12,4 +10,4 @@
/>
</a>
</div>
</header>
</header>

View File

@@ -1,10 +1,8 @@
<! INTERNAL TABLE FOR INTERFACES --!>
<!-- INTERNAL TABLE FOR INTERFACES -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">
Interfaces - MTU/Duplex/Speed
</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>Interfaces - MTU/Duplex/Speed</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['interfaces'] is defined and hostvars[network_switch]['ansible_network_resources']['interfaces']|length > 0 %}
<table id="subtable">
<thead>
@@ -23,7 +21,7 @@
<td>{{interface['name']}}</td>
<td>{{interface['description']|default("none")}}</td>
<td>{{interface['duplex']|default("default")}}</td>
<td>{{interface['enabled']}}</td>
<td>{{interface['enabled']|default("N/A")}}</td>
<td>{{interface['mtu']|default("default")}}</td>
<td>{{interface['speed']|default("default")}}</td>
</tr>
@@ -38,4 +36,4 @@ No Interface information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR INTERFACES --!>
<!-- END INTERNAL TABLE FOR INTERFACES -->

View File

@@ -1,8 +1,8 @@
<! INTERNAL TABLE FOR l2_interfaces --!>
<!-- INTERNAL TABLE FOR l2_interfaces -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">L2 Interfaces - Trunk/Access Ports</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>L2 Interfaces - Trunk/Access Ports</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['l2_interfaces'] is defined and hostvars[network_switch]['ansible_network_resources']['l2_interfaces']|length > 0 %}
<table id="subtable">
<thead>
@@ -34,4 +34,4 @@ No L2 information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR l2_interfaces --!>
<!-- END INTERNAL TABLE FOR l2_interfaces -->

View File

@@ -1,8 +1,8 @@
<! INTERNAL TABLE FOR L3_INTERFACES --!>
<!-- INTERNAL TABLE FOR L3_INTERFACES -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">L3 Interfaces - IP Addresses</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>L3 Interfaces - IP Addresses</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['l3_interfaces'] is defined and hostvars[network_switch]['ansible_network_resources']['l3_interfaces']|length > 0 %}
<table id="subtable">
<thead>
@@ -16,15 +16,11 @@
{% for interface in hostvars[network_switch]['ansible_network_resources']['l3_interfaces'] %}
<tr>
<td>{{interface['name']}}</td>
<! INTERNAL IPv4 LOOP FOR L3_INTERFACES --!>
<!-- INTERNAL IPv4 LOOP FOR L3_INTERFACES -->
<td>
{% if interface.ipv4 is defined %}
{% for address in interface.ipv4 %}
{% if address['address'] is defined %}
{{address['address']}}
{% else %}
dhcp
{% endif %}
{{ address['address']|default("Not Configured") }}
{% if address['secondary'] is defined %}
secondary
{% endif %}
@@ -32,17 +28,17 @@ secondary
{% endfor %}
{% endif %}
</td>
<! END IPv4 INTERNAL LOOP FOR L3_INTERFACES --!>
<! INTERNAL IPv6 LOOP FOR L3_INTERFACES --!>
<!-- END IPv4 INTERNAL LOOP FOR L3_INTERFACES -->
<!-- INTERNAL IPv6 LOOP FOR L3_INTERFACES -->
<td>
{% if interface.ipv6 is defined %}
{% for v6address in interface.ipv6 %}
{{v6address['address']}}
{{v6address['address']|default("Not Configured") }}
{% if loop.length > 1 and not loop.last %}<br>{% endif %}
{% endfor %}
{% endif %}
</td>
<! END INTERNAL LOOP FOR L3_INTERFACES --!>
<!-- END INTERNAL LOOP FOR L3_INTERFACES -->
</tr>
{% endfor %}
</tbody>
@@ -55,4 +51,4 @@ No L3 information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR L3_INTERFACES --!>
<!-- END INTERNAL TABLE FOR L3_INTERFACES -->

View File

@@ -1,8 +1,8 @@
<! INTERNAL TABLE FOR LACP --!>
<!-- INTERNAL TABLE FOR LACP -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">LACP</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>LACP</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['lacp'] is defined and hostvars[network_switch]['ansible_network_resources']['lacp'].keys()|length > 0 %}
<table id="subtable">
<thead>
@@ -11,14 +11,14 @@
</tr>
</thead>
<tbody>
{% for property in hostvars[network_switch]['ansible_network_resources']['lacp'] %}
<tr>
{% if hostvars[network_switch]['ansible_network_resources']['lacp']['system'] is defined %}
<td> {{hostvars[network_switch]['ansible_network_resources']['lacp']['system']['priority']}}</td>
{% endif %}
<td>{% if property['system'] is defined %} }{{property['system']['priority']}}{% else %}LACP not configured {% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% elif hostvars[network_switch]['ansible_network_resources']['lacp'] is defined and hostvars[network_switch]['ansible_network_resources']['lacp']|length == 0 %}
{% elif hostvars[network_switch]['ansible_network_resources']['lacp'] is defined and hostvars[network_switch]['ansible_network_resources']['lacp'].keys()|length == 0 %}
LACP is not configured on this device
{% else %}
No LACP information available
@@ -26,4 +26,4 @@ No LACP information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR LACP --!>
<!-- END INTERNAL TABLE FOR LACP -->

View File

@@ -1,9 +1,9 @@
<! INTERNAL TABLE FOR lldp_interfaces --!>
<!-- INTERNAL TABLE FOR lldp_interfaces -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">LLDP Interfaces</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
{% if hostvars[network_switch]['ansible_network_resources']['lldp_interfaces'] is defined and hostvars[network_switch]['ansible_network_resources']['lldp_interfaces']|length > 0 %}
<div>
<h3>LLDP Interfaces</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['lldp_interfaces'] is defined %}
<table id="subtable">
<thead>
<tr>
@@ -22,12 +22,10 @@
{% endfor %}
</tbody>
</table>
{% elif hostvars[network_switch]['ansible_network_resources']['lldp_interfaces'] is defined and hostvars[network_switch]['ansible_network_resources']['lldp_interfaces'].keys()|length == 0 %}
LLDP is not configured on this device
{% else %}
No LLDP information available
{% endif %}
</div>
</div>
</div>
<! END INTERNAL TABLE FOR lldp_interfaces --!>
<!-- END INTERNAL TABLE FOR lldp_interfaces -->

View File

@@ -1,8 +1,8 @@
<! INTERNAL TABLE FOR OSPF --!>
<!-- INTERNAL TABLE FOR OSPF -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">OSPF Global Info</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>OSPF Global Info</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['ospfv2'] is defined and hostvars[network_switch]['ansible_network_resources']['ospfv2']|length > 0 %}
<table id="subtable">
<thead>
@@ -12,10 +12,12 @@
</tr>
</thead>
<tbody>
{% for key,value in hostvars[network_switch]['ansible_network_resources']['ospfv2'].items() %}
<tr>
<td>1</td>
<td>{{ hostvars[network_switch]['ansible_network_resources']['ospfv2']['parameters']['router_id'] }}</td>
<td>{{ value[0].process_id }}</td>
<td>{{ value[0].router_id|default("Not Configured") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% elif hostvars[network_switch]['ansible_network_resources']['ospfv2'] is defined and hostvars[network_switch]['ansible_network_resources']['ospfv2']|length == 0 %}
@@ -26,4 +28,4 @@ No OSPF information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR OSPF --!>
<!-- END INTERNAL TABLE FOR OSPF -->

View File

@@ -1,13 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title> Ansible Network Automation Report </title>
<title>Network Automation Report</title>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="css/new.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="css/main.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function() {
$( "#accordion > div" ).accordion({
@@ -17,55 +16,14 @@ collapsible: true
});
});
</script>
<script>
(function(document) {
'use strict';
var TableFilter = (function(myArray) {
var search_input;
function _onInputSearch(e) {
search_input = e.target;
var tables = document.getElementsByClassName(search_input.getAttribute('data-table'));
myArray.forEach.call(tables, function(table) {
myArray.forEach.call(table.tBodies, function(tbody) {
myArray.forEach.call(tbody.rows, function(row) {
var text_content = row.textContent.toLowerCase();
var search_val = search_input.value.toLowerCase();
row.style.display = text_content.indexOf(search_val) > -1 ? '' : 'none';
});
});
});
}
return {
init: function() {
var inputs = document.getElementsByClassName('search-input');
myArray.forEach.call(inputs, function(input) {
input.oninput = _onInputSearch;
});
}
};
})(Array.prototype);
document.addEventListener('readystatechange', function() {
if (document.readyState === 'complete') {
TableFilter.init();
}
});
})(document);
</script>
</head>
<body>
<div class="wrapper">
{% include 'header.j2' %}
<section>
<center>
<h1>Ansible Network Automation Report</h1>
<h3><input type="search" placeholder="Search..." class="form-control search-input" data-table="main_net_table"/>
<h1>Ansible Network Automation Example Report</h1>
</center>
<table class="table table-striped mt32 main_net_table">
<table class="main_net_table">
<thead>
<tr>
<th>Network Device</th>
@@ -75,35 +33,71 @@ collapsible: true
</tr>
</thead>
<tbody>
{% for network_switch in groups['tag_Router']|sort %}
{% for network_switch in groups['routers']|sort %}
{% if hostvars[network_switch].ansible_facts.network_resources is defined %}
<tr>
<td class="summary_info">
<div id="hostname">
<p class="hostname">
<img class="router_image" src="router.png"> {{ hostvars[network_switch]['ansible_net_hostname'].split('.')[0] }}</p>
</div>
{% include 'summary.j2' %}
</td>
<td>
{% include 'interfaces.j2' %}
</td>
<td>
{% include 'vlans.j2' %}
{% include 'lldp_interfaces.j2' %}
{% include 'l2_interfaces.j2' %}
</td>
<td>
{% include 'l3_interfaces.j2' %}
{% include 'lacp.j2' %}
{% include 'bgp.j2' %}
{% include 'ospf.j2' %}
</td>
<p class="hostname"><img class="router_image" src="router.png" alt="picture of network device">{{ hostvars[network_switch].ansible_net_hostname }}</p>
</div>
<div id="net_info_div">
<table class="net_info">
<tbody>
<tr>
<td>Platform</td>
<td class="sub_net_info">{% set ansible_network_os = hostvars[network_switch]['ansible_net_system'] %}{{ vendor[ansible_network_os]}} {{hostvars[network_switch]['ansible_net_system'] }}</td>
</tr>
<tr>
<td>Code Version</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_net_version'] }}</td>
</tr>
<tr>
<td>Model</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_net_model'] }}</td>
</tr>
<tr>
<td>Serial Number</td>
<td class="sub_net_info">{{ hostvars[network_switch]['ansible_net_serialnum'] | default('N/A') }}</td>
</tr>
</tbody>
</table>
{% include 'ansible.j2' %}
</div>
</td>
<td>
{% include 'interfaces.j2' %}
</td>
<td>
{% include 'vlans.j2' %}
{% include 'lldp_interfaces.j2' %}
{% include 'l2_interfaces.j2' %}
</td>
<td>
{% include 'l3_interfaces.j2' %}
{% include 'lacp.j2' %}
{% include 'static.j2' %}
{% include 'bgp.j2' %}
{% include 'bgp_address_family.j2' %}
{% include 'ospf.j2' %}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<center><p>Created with</p><br><img src="webpage_logo.png" width="300">
<center><p>Created with</p><br><img src="webpage_logo.png" width="300" alt="red hat ansible automation platform logo">
<p>The source code to create this report can be found at <a href="https://github.com/network-automation/toolkit">https://github.com/network-automation/toolkit</a><br><br>
If you are new to Ansible Automation check out the following links:<br>
<a href="https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html">Getting Started</a><br>
<a target="_blank" href="https://ansible.com/workshops">Free hands-on workshops</a><br>
<a href="https://youtube.com/ansibleautomation">Youtube Videos</a><br>
</p>
</center>
</section>
</div>

View File

@@ -0,0 +1,45 @@
<!-- INTERNAL TABLE FOR Static Routes -->
<div id="accordion">
<div>
<h3>Static Routes</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['static_routes'] is defined and hostvars[network_switch]['ansible_network_resources']['static_routes']|length > 0 %}
<table id="subtable">
<thead>
<tr>
<th>VRF</th>
<th>Address-Family</th>
<th>Route</th>
<th>Interface</th>
<th>Next-Hop Address</th>
<th>Global</th>
</tr>
</thead>
<tbody>
{% for net_route in hostvars[network_switch]['ansible_network_resources']['static_routes'] %}
<tr>
<td>{{ net_route['vrf']|default("N/A") }}</td>
{% for address_family in net_route.address_families|default([]) %}
<td>{{ address_family['afi'] }}</td>
{% for routes in address_family['routes'] %}
<td>{{ routes['dest'] }}</td>
{% for next_hops in routes['next_hops'] %}
<td>{{ next_hops['interface']|default("N/A") }}</td>
<td>{{ next_hops['forward_router_address']|default("N/A") }}</td>
<td>{{ next_hops['global']|default("N/A") }}</td>
{% endfor %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% elif hostvars[network_switch]['ansible_network_resources']['static_routes'] is defined and hostvars[network_switch]['ansible_network_resources']['static_routes']|length == 0 %}
Static Routes are not configured on this device
{% else %}
No Static Route information available
{% endif %}
</div>
</div>
</div>
<!-- END INTERNAL TABLE FOR Static Routes -->

View File

@@ -1,25 +0,0 @@
<div id="net_info_div">
<table class="net_info">
<tbody>
<tr>
<td>Platform</td>
<td class="sub_net_info">{{hostvars[network_switch]['ansible_net_system']}}</td>
</tr>
<tr>
<td>Code Version</td>
<td class="sub_net_info">{{hostvars[network_switch]['ansible_net_version']}}</td>
</tr>
<tr>
<td>Model</td>
<td class="sub_net_info">{{hostvars[network_switch]['ansible_net_model']|default("N/A")}}</td>
</tr>
<tr>
<td>Serial Number</td>
<td class="sub_net_info">{{hostvars[network_switch]['ansible_net_serialnum']}}</td>
</tr>
<tr>
<td>Transport</td>
<td class="sub_net_info">{{hostvars[network_switch]['ansible_net_api']}}</td>
</tbody>
</table>
</div>

View File

@@ -1,8 +1,8 @@
<! INTERNAL TABLE FOR VLANS --!>
<!-- INTERNAL TABLE FOR VLANS -->
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">VLANs</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<div>
<h3>VLANs</h3>
<div class="net_content">
{% if hostvars[network_switch]['ansible_network_resources']['vlans'] is defined and hostvars[network_switch]['ansible_network_resources']['vlans']|length > 0 %}
<table id="subtable">
<thead>
@@ -30,4 +30,4 @@ No VLAN information available
</div>
</div>
</div>
<! END INTERNAL TABLE FOR VLANS --!>
<!-- END INTERNAL TABLE FOR VLANS -->

View File

@@ -1 +1,11 @@
file_path: /var/www/html
file_path: "{{ web_path | default('/var/www/html/reports') }}"
vendor:
ios: &my_value 'Cisco'
nxos: *my_value
iosxr: *my_value
junos: "Juniper"
eos: "Arista"
transport:
cliconf: "Network_CLI"
netconf: "NETCONF"
nxapi: "NX-API"

View File

@@ -1,2 +1,2 @@
---
detailedreport: True
detailedreport: true

View File

@@ -1,24 +1,27 @@
- name: create HTML report
- name: Create HTML report
ansible.builtin.template:
src: report.j2
dest: "{{ file_path }}/windows.html"
mode: "0644"
- name: copy CSS over
- name: Copy CSS over
ansible.builtin.copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
mode: "0755"
- name: copy logos over
- name: Copy logos over
ansible.builtin.copy:
src: "{{ item }}"
src: "{{ item }}"
dest: "{{ file_path }}"
directory_mode: true
mode: "0644"
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "server.png"
- name: display link to inventory report
- name: Display link to inventory report
ansible.builtin.debug:
msg: "Please go to http://{{ ansible_host }}/windows.html"
msg: "Please go to http://{{ ansible_host }}/windows.html"

View File

@@ -1 +1 @@
file_path: /var/www/html
file_path: /var/www/html

View File

@@ -1,3 +1,3 @@
EMAIL_FROM: tower@shadowman.dev
email_from: tower@shadowman.dev
to_emails: alex@shadowman.dev,tower@shadowman.dev
EMAIL_TO: "{{ to_emails.split(',') }}"
to_emails_list: "{{ to_emails.split(',') }}"

View File

@@ -2,37 +2,25 @@
ansible.builtin.template:
src: report.j2
dest: "{{ file_path }}/windowspatch.html"
check_mode: no
mode: "0644"
check_mode: false
- name: Copy CSS over
ansible.builtin.copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
mode: "0775"
check_mode: false
- name: Copy logo over
ansible.builtin.copy:
src: "webpage_logo.png"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
mode: "0644"
check_mode: false
- 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

View File

@@ -1 +1 @@
file_path: /var/www/html
file_path: /var/www/html

View File

@@ -1,3 +1,3 @@
---
exclude_packages: []
allow_reboot: true
allow_reboot: true

View File

@@ -1,25 +1,24 @@
---
- name: Scan packages
demo.patching.scan_packages:
os_family: "{{ ansible_os_family }}"
check_mode: no
- name: Get packages
ansible.builtin.package_facts:
check_mode: false
- name: Scan services
demo.patching.scan_services:
check_mode: no
- name: Get services
ansible.builtin.service_facts:
check_mode: false
- name: upgrade packages (yum)
yum:
- name: Upgrade packages (yum)
ansible.builtin.yum:
name: '*'
state: latest
state: latest # noqa: package-latest - Intended to update packages to latest
exclude: "{{ exclude_packages }}"
when: ansible_pkg_mgr == "yum"
register: patchingresult_yum
- name: upgrade packages (dnf)
- name: Upgrade packages (dnf)
ansible.builtin.dnf:
name: '*'
state: latest
state: latest # noqa: package-latest - Intended to update packages to latest
exclude: "{{ exclude_packages }}"
when: ansible_pkg_mgr == "dnf"
register: patchingresult_dnf
@@ -29,10 +28,10 @@
register: result
changed_when: result.rc == 1
failed_when: result.rc > 1
check_mode: no
check_mode: false
- name: Reboot Server if Necessary
ansible.builtin.reboot:
when:
- result.rc == 1
- allow_reboot == true
- result.rc == 1
- allow_reboot

View File

@@ -11,4 +11,4 @@ win_update_categories:
- Tools
- UpdateRollups
- Updates
allow_reboot: true
allow_reboot: true

View File

@@ -1,11 +1,11 @@
---
- name: Scan packages
demo.patching.win_scan_packages:
check_mode: no
check_mode: false
- name: Scan Services
demo.patching.win_scan_services:
check_mode: no
check_mode: false
- name: Install Windows Updates
ansible.windows.win_updates:

View File

@@ -1,2 +1,2 @@
---
detailedreport: True
detailedreport: true

View File

@@ -1,27 +1,30 @@
- name: create HTML report
- name: Create HTML report
ansible.builtin.template:
src: report.j2
dest: "{{ file_path }}/linux.html"
check_mode: no
mode: "0644"
check_mode: false
- name: copy CSS over
- name: Copy CSS over
ansible.builtin.copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
mode: "0775"
check_mode: false
- name: copy logos over
- name: Copy logos over
ansible.builtin.copy:
src: "{{ item }}"
src: "{{ item }}"
dest: "{{ file_path }}"
directory_mode: true
mode: "0644"
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "server.png"
check_mode: no
check_mode: false
- name: display link to inventory report
- name: Display link to inventory report
ansible.builtin.debug:
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/linux.html"

View File

@@ -1 +1 @@
file_path: /var/www/html/reports
file_path: /var/www/html/reports

View File

@@ -1,3 +1,3 @@
EMAIL_FROM: tower@shadowman.dev
email_from: tower@shadowman.dev
to_emails: alex@shadowman.dev,tower@shadowman.dev
EMAIL_TO: "{{ to_emails.split(',') }}"
to_emails_list: "{{ to_emails.split(',') }}"

View File

@@ -2,38 +2,41 @@
ansible.builtin.template:
src: report.j2
dest: "{{ file_path }}/linuxpatch.html"
check_mode: no
mode: "0644"
check_mode: false
- name: Copy CSS over
ansible.builtin.copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
mode: "0775"
check_mode: false
- name: Copy logo over
ansible.builtin.copy:
src: "webpage_logo.png"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
mode: "0644"
check_mode: false
- 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
# - 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

View File

@@ -1 +1 @@
file_path: /var/www/html/reports
file_path: /var/www/html/reports

View File

@@ -29,7 +29,7 @@ p.hostname {
}
a {
color: #ffffff;
color: #000000;
}
p {
@@ -199,4 +199,4 @@ table.net_info {
p.internal_label {
color: #000000;
}
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logos" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="930.2px" height="350px" viewBox="0 0 930.2 350" style="enable-background:new 0 0 930.2 350;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#EE0000;}
</style>
<title>Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB</title>
<path class="st0" d="M383.3,228.5h18.8L446,335.7h-17.5l-12.4-31.4h-48l-12.6,31.4h-16.7L383.3,228.5z M410.9,291l-18.7-47l-18.7,47
H410.9z"/>
<path class="st0" d="M455.2,257.7h15.3v7.8c6.2-6.2,14.7-9.6,23.5-9.3c17.9,0,30.5,12.4,30.5,30.5v49h-15.3v-46.5
c0-12.3-7.5-19.8-19.3-19.8c-7.8-0.3-15.1,3.6-19.3,10.1v56.1h-15.3V257.7z"/>
<path class="st0" d="M543,315.5c8.1,6.4,16.7,9.8,25.4,9.8c11,0,18.7-4.8,18.7-11.7c0-5.5-4-8.7-12.6-10l-14.1-2
c-15.5-2.3-23.3-9.5-23.3-21.6c0-14.1,12.3-23.6,30.5-23.6c11.3-0.1,22.3,3.4,31.5,9.9l-7.8,10.1c-8.6-5.7-16.4-8.1-24.7-8.1
c-9.3,0-15.6,4.3-15.6,10.6c0,5.7,3.7,8.4,12.9,9.8l14.1,2c15.5,2.3,23.6,9.7,23.6,21.7c0,14-14.1,24.5-32.6,24.5
c-13.5,0-25.6-4-34.2-11.5L543,315.5z"/>
<path class="st0" d="M611.6,235.6c0-5.2,4.1-9.4,9.3-9.5c0,0,0,0,0,0c5.2-0.2,9.7,3.9,9.9,9.1c0.2,5.2-3.9,9.7-9.1,9.9
c-0.2,0-0.5,0-0.7,0C615.8,245.1,611.6,240.9,611.6,235.6C611.6,235.7,611.6,235.7,611.6,235.6z M628.6,335.7h-15.3v-78h15.3V335.7z
"/>
<path class="st0" d="M685.5,336.9c-8.5,0-16.8-2.7-23.6-7.8v6.6h-15.2V228.5l15.3-3.4v40c6.6-5.6,15.1-8.7,23.7-8.6
c22.1,0,39.4,17.7,39.4,40.1C725.2,319.1,707.9,336.9,685.5,336.9z M662,279.2v35.2c4.9,5.7,13,9.2,21.8,9.2
c15,0,26.4-11.5,26.4-26.8c0-15.3-11.5-27-26.4-27C674.9,269.8,667.1,273.2,662,279.2z"/>
<path class="st0" d="M755,335.7h-15.3V228.5l15.3-3.4V335.7z"/>
<path class="st0" d="M810.5,337.1c-23,0-40.9-17.7-40.9-40.4c0-22.5,17.2-40.1,39.1-40.1c21.5,0,37.7,17.8,37.7,40.8v4.4h-61.6
c2,13,13.2,22.5,26.4,22.4c7.2,0.2,14.2-2.3,19.8-6.8l9.8,9.7C832.1,333.7,821.5,337.4,810.5,337.1z M784.9,290.2h46.3
c-2.3-11.9-11.5-20.8-22.8-20.8C796.5,269.4,787.2,277.8,784.9,290.2z"/>
<path class="st1" d="M202.8,137.5c18.4,0,45.1-3.8,45.1-25.7c0.1-1.7-0.1-3.4-0.5-5l-11-47.7c-2.5-10.5-4.8-15.2-23.2-24.5
c-14.3-7.3-45.5-19.4-54.7-19.4c-8.6,0-11.1,11.1-21.3,11.1c-9.8,0-17.1-8.3-26.4-8.3c-8.8,0-14.6,6-19,18.4c0,0-12.4,34.9-14,40
c-0.3,0.9-0.4,1.9-0.4,2.9C77.6,92.9,131.1,137.5,202.8,137.5 M250.8,120.7c2.5,12.1,2.5,13.3,2.5,14.9c0,20.6-23.2,32.1-53.7,32.1
c-69,0-129.3-40.3-129.3-67c0-3.7,0.8-7.4,2.2-10.8c-24.8,1.3-56.9,5.7-56.9,34c0,46.4,109.9,103.5,196.9,103.5
c66.7,0,83.5-30.2,83.5-54C296.1,154.6,279.9,133.4,250.8,120.7"/>
<path d="M250.7,120.7c2.5,12.1,2.5,13.3,2.5,14.9c0,20.6-23.2,32.1-53.7,32.1c-69,0-129.3-40.3-129.3-67c0-3.7,0.8-7.4,2.2-10.8
l5.4-13.3c-0.3,0.9-0.4,1.9-0.4,2.8c0,13.6,53.5,58.1,125.2,58.1c18.4,0,45.1-3.8,45.1-25.7c0.1-1.7-0.1-3.4-0.5-5L250.7,120.7z"/>
<path class="st0" d="M869.1,151.2c0,17.5,10.5,26,29.7,26c5.9-0.1,11.8-1,17.5-2.5v-20.3c-3.7,1.2-7.5,1.7-11.3,1.7
c-7.9,0-10.8-2.5-10.8-9.9v-31.1h22.9V94.2h-22.9V67.7l-25,5.4v21.1h-16.6v20.9h16.6L869.1,151.2z M791,151.7
c0-5.4,5.4-8.1,13.6-8.1c5,0,10,0.7,14.9,1.9V156c-4.8,2.6-10.2,3.9-15.6,3.9C795.9,159.9,791.1,156.8,791,151.7 M798.7,177.5
c8.8,0,16-1.9,22.6-6.3v5h24.8v-52.5c0-20-13.5-30.9-35.9-30.9c-12.6,0-25,2.9-38.3,9l9,18.4c9.6-4,17.7-6.5,24.8-6.5
c10.3,0,15.6,4,15.6,12.2v4c-6.1-1.6-12.3-2.4-18.6-2.3c-21.1,0-33.8,8.8-33.8,24.6C768.9,166.6,780.4,177.6,798.7,177.5
M662.5,176.2h26.7v-42.5h44.6v42.5h26.7V67.7h-26.6v41.7h-44.6V67.7h-26.7L662.5,176.2z M561,135.1c0-11.8,9.3-20.8,21.5-20.8
c6.4-0.1,12.6,2.1,17.4,6.4v28.6c-4.7,4.4-10.9,6.7-17.4,6.5C570.5,155.8,561,146.8,561,135.1 M600.2,176.1H625V62.3l-25,5.4v30.8
c-6.4-3.6-13.6-5.5-20.9-5.4c-23.9,0-42.6,18.4-42.6,42c-0.3,23,18.1,41.9,41.1,42.2c0.2,0,0.5,0,0.7,0c7.9,0,15.6-2.5,22-7.1V176.1
z M486.5,113.2c7.9,0,14.6,5.1,17.2,13h-34.2C471.9,118,478.2,113.2,486.5,113.2 M444.2,135.2c0,23.9,19.5,42.5,44.6,42.5
c13.8,0,23.9-3.7,34.3-12.4l-16.6-14.7c-3.9,4-9.6,6.2-16.4,6.2c-8.8,0.2-16.8-4.9-20.2-13h58.4v-6.2c0-26-17.5-44.8-41.4-44.8
c-23.2-0.4-42.4,18.2-42.7,41.5C444.2,134.6,444.2,134.9,444.2,135.2 M400.9,90.5c8.8,0,13.8,5.6,13.8,12.2s-5,12.2-13.8,12.2h-26.3
V90.5H400.9z M347.9,176.2h26.7v-39.5h20.3l20.5,39.5h29.7l-23.9-43.4c12.4-5,20.5-17.1,20.4-30.5c0-19.5-15.3-34.5-38.3-34.5H348
L347.9,176.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -1,20 +1,29 @@
---
- yum:
- name: Inlcude system variables
ansible.builtin.include_vars: "{{ ansible_system }}.yml"
- name: Install httpd package
ansible.builtin.yum:
name: httpd
state: latest
check_mode: no
state: installed
check_mode: false
- file:
path: /var/www/html/reports/
- name: Create reports directory
ansible.builtin.file:
path: "{{ doc_root }}/{{ reports_dir }}"
state: directory
check_mode: no
mode: "0775"
check_mode: false
- copy:
dest: /var/www/html/reports/.htaccess
- name: Copy .htaccess
ansible.builtin.copy:
dest: "{{ doc_root }}/{{ reports_dir }}/.htaccess"
content: Options +Indexes
check_mode: no
mode: "0644"
check_mode: false
- service:
- name: Install httpd service
ansible.builtin.service:
name: httpd
state: started
check_mode: no
check_mode: false

View File

@@ -1,23 +1,26 @@
---
- name: Include system vars
ansible.builtin.include_vars: "{{ ansible_system }}.yml"
- name: Install IIS
ansible.windows.win_feature:
name: Web-Server
state: present
check_mode: no
check_mode: false
- name: Start IIS service
ansible.windows.win_service:
name: W3Svc
state: started
check_mode: no
check_mode: false
- name: Create Directory
ansible.windows.win_file:
path: C:\Inetpub\wwwroot\reports
path: "{{ doc_root }}\\{{ reports_dir }}"
state: directory
check_mode: no
check_mode: false
- 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'"
"Set-WebConfigurationProperty -filter /system.webServer/directoryBrowse -name enabled -value true -PSPath 'IIS:\Sites\Default Web Site\reports'"

View File

@@ -0,0 +1,37 @@
---
- name: Include system vars
ansible.builtin.include_vars: "{{ ansible_system }}.yml"
- name: Get reports
ansible.builtin.find:
paths: "{{ doc_root }}/{{ reports_dir }}"
patterns: '*.html'
register: reports
check_mode: false
- name: Publish landing page
ansible.builtin.template:
src: linux_report.j2
dest: "{{ doc_root }}/index.html"
mode: "0644"
check_mode: false
- name: Copy CSS
ansible.builtin.copy:
src: "css"
dest: "{{ doc_root }}"
directory_mode: true
mode: "0775"
check_mode: false
- name: Copy logos
ansible.builtin.copy:
src: "{{ item }}"
dest: "{{ doc_root }}"
directory_mode: true
mode: "0775"
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "report.png"
check_mode: false

View File

@@ -0,0 +1,8 @@
---
- name: Include Linux tasks
ansible.builtin.include_tasks: apache.yml
when: ansible_system == 'Linux'
- name: Include Windows tasks
ansible.builtin.include_tasks: iis.yml
when: ansible_system == 'Win32NT'

View File

@@ -0,0 +1,34 @@
---
- name: Include system variables
ansible.builtin.include_vars: "{{ ansible_system }}.yml"
- name: Get reports
ansible.windows.win_find:
paths: "{{ doc_root }}/{{ reports_dir }}"
patterns: '*.html'
register: reports
check_mode: false
- name: Publish landing page
ansible.windows.win_template:
src: windows_report.j2
dest: "{{ doc_root }}/index.html"
check_mode: false
- name: Copy CSS
ansible.windows.win_copy:
src: "css"
dest: "{{ doc_root }}"
directory_mode: true
check_mode: false
- name: Copy logos
ansible.windows.win_copy:
src: "{{ item }}"
dest: "{{ doc_root }}"
directory_mode: true
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "report.png"
check_mode: false

View File

@@ -0,0 +1,15 @@
<div class="wrapper">
<header>
<div class="header-container">
<a href="https://ansible.com">
<img
class="header-logo"
src="redhat-ansible-logo.svg"
title="Red Hat Ansible"
alt="Red Hat Ansible"
/>
</a>
</div>
</header>

View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title> Ansible Linux Automation Report </title>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="css/new.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
</head>
<body>
<div class="wrapper">
{% include 'header.j2' %}
<section>
<center>
<h1>Ansible Automation Reports</h1>
<h3><input type="search" placeholder="Search..." class="form-control search-input" data-table="main_net_table"/>
</center>
<table class="table table-striped mt32 main_net_table">
<tbody>
{% for report in reports.files %}
{% set page = report.path.split('/')[-1] %}
<tr>
<td class="summary_info">
<div id="hostname">
<p class="hostname"> <img class="router_image" src="report.png"></p>
</div>
</td>
<td>
<a href="{{ reports_dir }}/{{ page }}"> {{ page }} <a>
</td>
{% endfor %}
</tbody>
</table>
<center><p>Created with</p><br><img src="webpage_logo.png" width="300">
</center>
</section>
</div>
</body>
</html>

View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title> Ansible Linux Automation Report </title>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="css/new.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
</head>
<body>
<div class="wrapper">
{% include 'header.j2' %}
<section>
<center>
<h1>Ansible Automation Reports</h1>
<h3><input type="search" placeholder="Search..." class="form-control search-input" data-table="main_net_table"/>
</center>
<table class="table table-striped mt32 main_net_table">
<tbody>
{% for report in reports.files %}
{% set page = report.path.split('\\')[-1] %}
<tr>
<td class="summary_info">
<div id="hostname">
<p class="hostname"> <img class="router_image" src="report.png"></p>
</div>
</td>
<td>
<a href="{{ reports_dir }}/{{ page }}"> {{ page }} <a>
</td>
{% endfor %}
</tbody>
</table>
<center><p>Created with</p><br><img src="webpage_logo.png" width="300">
</center>
</section>
</div>
</body>
</html>

View File

@@ -0,0 +1,3 @@
---
doc_root: /var/www/html
reports_dir: reports

View File

@@ -0,0 +1,3 @@
---
doc_root: C:\Inetpub\wwwroot
reports_dir: reports

View File

@@ -1,2 +1,2 @@
---
detailedreport: True
detailedreport: true

View File

@@ -1,28 +1,28 @@
---
- name: create HTML report
- name: Create HTML report
ansible.windows.win_template:
src: report.j2
dest: "{{ file_path }}/windows.html"
check_mode: no
check_mode: false
- name: copy CSS over
- name: Copy CSS over
ansible.windows.win_copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
check_mode: false
- name: copy logos over
- name: Copy logos over
ansible.windows.win_copy:
src: "{{ item }}"
src: "{{ item }}"
dest: "{{ file_path }}"
directory_mode: true
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "server.png"
check_mode: no
check_mode: false
#- name: display link to inventory report
# ansible.builtin.debug:
# msg: "Please go to http://{{ host_vars[report_server]['ansible_host'] }}/reports/windows.html"
# - name: display link to inventory report
# ansible.builtin.debug:
# msg: "Please go to http://{{ host_vars[report_server]['ansible_host'] }}/reports/windows.html"

View File

@@ -1 +1,2 @@
file_path: C:\Inetpub\wwwroot\reports
---
file_path: C:\Inetpub\wwwroot\reports

View File

@@ -1,3 +1,4 @@
EMAIL_FROM: tower@shadowman.dev
---
email_from: tower@shadowman.dev
to_emails: alex@shadowman.dev,tower@shadowman.dev
EMAIL_TO: "{{ to_emails.split(',') }}"
to_emails_list: "{{ to_emails.split(',') }}"

View File

@@ -2,22 +2,22 @@
ansible.windows.win_template:
src: report.j2
dest: "{{ file_path }}/windowspatch.html"
check_mode: no
check_mode: false
- name: Copy CSS over
ansible.windows.win_copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
check_mode: false
- name: Copy logo over
ansible.windows.win_copy:
src: "webpage_logo.png"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
check_mode: false
- name: Display link to Patch report
ansible.builtin.debug:
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/windowspatch.html"
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/windowspatch.html"

View File

@@ -1 +1,2 @@
file_path: C:\Inetpub\wwwroot\reports
---
file_path: C:\Inetpub\wwwroot\reports

View File

@@ -0,0 +1,5 @@
---
instance_name: "{{ inventory_hostname | regex_replace('_', '-') }}"
activation_key: "{{ 'RHEL' + ansible_distribution_major_version + '_' + env }}"
rex_user: root # "{{ ansible_user }}"
force_register: true

View File

@@ -0,0 +1,67 @@
---
- name: Verify operating system
ansible.builtin.assert:
that:
- ansible_os_family == 'RedHat'
- (ansible_distribution_major_version == '7') or (ansible_distribution_major_version == '8')
- name: Set hostname
ansible.builtin.hostname:
name: "{{ instance_name }}"
- name: Remove rhui client packages
ansible.builtin.yum:
name:
- google-rhui-client*
- rh-amazon-rhui-client*
state: removed
- name: Get current repos
ansible.builtin.command:
cmd: ls /etc/yum.repos.d/
register: repos
changed_when: false
- name: Remove existing rhui repos
ansible.builtin.file:
path: "/etc/yum.repos.d/{{ item }}"
state: absent
loop: "{{ repos.stdout_lines }}"
- name: Install satellite certificate
ansible.builtin.yum:
name: "{{ satellite_url }}/pub/katello-ca-consumer-latest.noarch.rpm"
state: present
validate_certs: false
disable_gpg_check: true
- name: Register system via subscription-mangler
community.general.redhat_subscription:
state: present
activationkey: "{{ activation_key }}"
consumer_name: "{{ instance_name }}"
org_id: "{{ org_id | default('Default_Organization') }}"
force_register: "{{ force_register }}"
throttle: 1
- name: Include repos
ansible.builtin.include_vars: "vars/{{ ansible_distribution + ansible_distribution_major_version }}.yml"
- name: Enable repos
community.general.rhsm_repository:
name: "{{ rhsm_enabled_repos }}"
state: enabled
- name: Install satellite client
ansible.builtin.yum:
name:
- katello-host-tools
- katello-host-tools-tracer
state: installed
- name: Enable remote execution
ansible.posix.authorized_key:
user: "{{ rex_user }}"
state: present
key: "{{ satellite_url }}:9090/ssh/pubkey"
validate_certs: false

View File

@@ -0,0 +1,4 @@
---
rhsm_enabled_repos:
- rhel-7-server-rpms
# - rhel-7-server-satellite-maintenance-6.11-rpms

View File

@@ -0,0 +1,5 @@
---
rhsm_enabled_repos:
- rhel-8-for-x86_64-baseos-rpms
- rhel-8-for-x86_64-appstream-rpms
- satellite-client-6-for-rhel-8-x86_64-rpms

View File

@@ -0,0 +1,17 @@
# Change Log
All notable changes to this project will be documented in this file.
## [0.0.1] - 20/03/2018 - First Release
### Added
- Install required packages
- Obtain data from satellite API
- Configure crontab and config.yaml
### Changed
### Removed
### Pending
- Allow a list of policies to be applied (only one is allowed at the moment)
- Get schedule from the policy instead of configure it using parameters
- Configure URI tasks to ask capsule instead of Satellite (for hosts without network access to the satellite api)
- Add tests to vars to be correctly formatted

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 morenod
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,45 @@
# Openscap client configuration Role
## About
Role created to configure a client to execute openscap policies based on the information obtained from a Red Hat Satellite/Foreman Host.
Steps and configuration changes obtained from the [foreman_scap_client puppet module](https://github.com/theforeman/puppet-foreman_scap_client)
The role has to be executed with root permission, using the root user or via sudo because it will modify system parameters.
## Ansible Requirements
RPM Repositories have to be enabled and containing required packages.
## Configuration parameters
### Required vars to be overwritten
- `satellite_server`: Used to obtain policy parameters
- `satellite_username`: Used to obtain policy parameters
- `satellite_password`: Used to obtain policy parameters
- `capsule_server`: Used to configure openscap client config.yaml file
- `capsule_port`: Used to configure openscap client config.yaml file
- `policy_name`: Name of the SCAP Policy to be configured
## Example playbook
```yml
---
- name: openscap client
hosts: <<host list>>
remote_user: <<user>>
gather_facts: true
become: yes
become_user: root
become_method: sudo
vars:
satellite_server: satellite.example.com
satellite_username`: admin
satellite_password`: verycomplexpassword
capsule_server`: capsule.example.com
policy_name`: 'rhel7-pci'
roles:
- ansible-ipaRegister
```

View File

@@ -0,0 +1,12 @@
foreman_server_url: "{{ lookup('env', 'SATELLITE_SERVER') }}"
foreman_username: "{{ lookup('env', 'SATELLITE_USERNAME') }}"
foreman_password: "{{ lookup('env', 'SATELLITE_PASSWORD') }}"
foreman_validate_certs: "{{ lookup('env', 'FOREMAN_VALIDATE_CERTS') | default(true) }}"
capsule_server: "{{ foreman_server_url }}"
capsule_port: '9090'
policy_name: 'all'
policy_scan: "{{ policy_name }}"
crontab_hour: 2
crontab_minute: 0
crontab_weekdays: 0
foreman_operations_scap_client_secure_logging: true

View File

@@ -0,0 +1,85 @@
---
- name: Install openscap client packages
ansible.builtin.yum:
name:
- openscap-scanner
- rubygem-foreman_scap_client
state: present
- name: Get Policy parameters
ansible.builtin.uri:
url: "{{ foreman_server_url }}/api/v2/compliance/policies"
method: GET
user: "{{ foreman_username }}"
password: "{{ foreman_password }}"
force_basic_auth: true
body_format: json
validate_certs: false
register: policies
no_log: "{{ foreman_operations_scap_client_secure_logging }}"
- name: Build policy {{ policy_name }}
ansible.builtin.set_fact:
policy: "{{ policy | default([]) }} + {{ [item] }}"
loop: "{{ policies.json.results }}"
when: item.name in policy_name or policy_name == 'all'
- name: Fail if no policy found with required name
ansible.builtin.fail:
when: policy is not defined
- name: Get scap content information
ansible.builtin.uri:
url: "{{ foreman_server_url }}/api/v2/compliance/scap_contents/{{ item.scap_content_id }}"
method: GET
user: "{{ foreman_username }}"
password: "{{ foreman_password }}"
force_basic_auth: false
body_format: json
validate_certs: false
register: scapcontents
loop: "{{ policy }}"
no_log: "{{ foreman_operations_scap_client_secure_logging }}"
- name: Get tailoring content information
ansible.builtin.uri:
url: "{{ foreman_server_url }}/api/v2/compliance/tailoring_files/{{ item.tailoring_file_id }}"
method: GET
user: "{{ foreman_username }}"
password: "{{ foreman_password }}"
force_basic_auth: false
body_format: json
validate_certs: false
register: tailoringfiles
when: item.tailoring_file_id | int > 0 | d(False)
loop: "{{ policy }}"
no_log: "{{ foreman_operations_scap_client_secure_logging }}"
- name: Build scap content parameters
ansible.builtin.set_fact:
scap_content: "{{ scap_content | default({}) | combine({item.json.id: item.json}) }}"
loop: "{{ scapcontents.results }}"
- name: Build tailoring content parameters
ansible.builtin.set_fact:
tailoring_files: "{{ tailoring_files | default({}) | combine({item.json.id: item.json}) }}"
when: item.json is defined
loop: "{{ tailoringfiles.results }}"
- name: Apply openscap client configuration template
ansible.builtin.template:
src: openscap_client_config.yaml.j2
dest: /etc/foreman_scap_client/config.yaml
mode: "0644"
owner: root
group: root
# - name: Configure execution crontab
# cron:
# name: "Openscap Execution"
# cron_file: 'foreman_openscap_client'
# job: '/usr/bin/foreman_scap_client {{policy.id}} > /dev/null'
# weekday: "{{crontab_weekdays}}"
# hour: "{{crontab_hour}}"
# minute: "{{crontab_minute}}"
# user: root

View File

@@ -0,0 +1,47 @@
# Foreman proxy to which reports should be uploaded
:server: {{ capsule_server | urlsplit('hostname') }}
:port: {{ capsule_port }}
## SSL specific options ##
# Client CA file.
# It could be Puppet CA certificate (e.g., '/var/lib/puppet/ssl/certs/ca.pem')
# Or (recommended for client reporting to Katello) subscription manager CA file, (e.g., '/etc/rhsm/ca/katello-server-ca.pem')
:ca_file: '/etc/rhsm/ca/katello-server-ca.pem'
# Client host certificate.
# It could be Puppet agent host certificate (e.g., '/var/lib/puppet/ssl/certs/myhost.example.com.pem')
# Or (recommended for client reporting to Katello) consumer certificate (e.g., '/etc/pki/consumer/cert.pem')
:host_certificate: '/etc/pki/consumer/cert.pem'
#
# Client private key
# It could be Puppet agent private key (e.g., '/var/lib/puppet/ssl/private_keys/myhost.example.com.pem')
# Or (recommended for client reporting to Katello) consumer private key (e.g., '/etc/pki/consumer/key.pem')
:host_private_key: '/etc/pki/consumer/key.pem'
# policy (key is id as in Foreman)
{% for item in policy %}
{{ item.id }}:
{% if item.tailoring_file_id | int > 0 | d(False) %}
{% for profile in tailoring_files[item.tailoring_file_id].tailoring_file_profiles %}
{% if profile.id == item.tailoring_file_profile_id %}
:profile: {{profile.profile_id}}
{% endif%}
{% endfor %}
:content_path: '/var/lib/openscap/content/{{scap_content[item.scap_content_id].digest}}.xml'
# Download path
# A path to download SCAP content from proxy
:download_path: '/compliance/policies/{{item.id}}/content/{{scap_content[item.scap_content_id].digest}}'
:tailoring_path: '/var/lib/openscap/content/{{tailoring_files[item.tailoring_file_id].digest}}.xml'
:tailoring_download_path: '/compliance/policies/{{item.id}}/tailoring/{{tailoring_files[item.tailoring_file_id].digest}}'
{% else %}
{% for profile in scap_content[item.scap_content_id].scap_content_profiles %}
{% if profile.id == item.scap_content_profile_id %}
:profile: {{profile.profile_id}}
{% endif%}
{% endfor %}
:content_path: '/var/lib/openscap/content/{{scap_content[item.scap_content_id].digest}}.xml'
# Download path
# A path to download SCAP content from proxy
:download_path: '/compliance/policies/{{item.id}}/content/{{scap_content[item.scap_content_id].digest}}'
:tailoring_path: ''
:tailoring_download_path: ''
{% endif %}
{% endfor %}

View File

@@ -0,0 +1,37 @@
---
collections:
- name: ansible.controller
version: 4.3.0
- name: redhat_cop.controller_configuration
version: 2.2.5
# linux
- name: redhat.insights
version: 1.0.7
- name: redhat.rhel_system_roles
version: 1.20.0
- name: community.general
version: 6.3.0
- name: containers.podman
# windows
- name: chocolatey.chocolatey
- name: community.windows
version: 1.12.0
- name: ansible.windows
version: 1.13.0
# cloud
- name: azure.azcollection
version: 1.14.0
- name: amazon.aws
version: 5.2.0
# satellite
- name: redhat.satellite
version: 3.8.0
# network
- name: cisco.ios
version: 4.4.0
- name: cisco.nxos
version: 4.1.0
- name: cisco.iosxr
version: 5.0.0
- name: ansible.netcommon
version: 5.0.0

View File

@@ -1,23 +0,0 @@
---
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