vim /etc/my.cnf
[mysqld]
bind-address=127.0.0.1
* Start/Enable the databasesystemctl enable mariadb
systemctl start mariadb
* Run secure setupmysql_secure_installation
* Prompts for the following:
* Current password for root (should be none, just press enter)
* Set database root password
* Remove anonymous users
* Disallow root logins remotely
* Remove test databases
* Reload privilege tables
* Connect to the databasemysql -u root -p
* Create your project's databasecreate database myprojecthere character set utf8;
* Create a database user that Django will usecreate user appuserhere@localhost identified by 'PASSWORDHERE';
* Grant permissions for the app user on your project's databasegrant all privileges on myprojecthere.* to appuserhere@localhost;
* Flush privilegesflush privileges;
----
====== Django ======
Configuring Django.
* Verify django workspython
>>> import django
>>> print(django.get_version())
>>> exit()
===== Project/App Setup =====
* Create a directory to store the projectmkdir /home/django
cd /home/django
* Create a new Django projectdjango-admin startproject myprojecthere
cd /home/django/myprojecthere
* Create a new Django application inside of the projectpython manage.py startapp myapphere
* Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)# Allowed Referrer Hosts (hostname and any cnames)
ALLOWED_HOSTS = ['djangoserver.mycorps.domain.org','myapp.mycorps.domain.org']
# Application definition (add the application, the rest are built in)
INSTALLED_APPS = [
# APPNAME.apps.APPCLASSNAME -> see ../myapphere/apps.py
'myapphere.apps.MyapphereConfig', # add your application here
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# Static files (CSS, JavaScript, Images)
#https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/static/'
===== Database Setup =====
* Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)# Database Configuration
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myprojecthere',
'USER': 'appuserhere',
'PASSWORD': 'PASSWORDHERE',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}
* Run the initial migrate command to create database tables for built in apps that come with Djangocd /home/django/myprojecthere
python manage.py migrate
* Describe your data models (objects that will be stored in the database) (/home/django/myprojecthere/myapphere/models.py) **EXAMPLE**# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Asset Inventory Example
class AssetEntry(models.Model):
##-- Tuples for Use in Field Choices --##
#asset_type choices
DEVICE_TYPES = (
('Firewalls', 'Firewalls'),
('Routers', 'Routers'),
('Servers', 'Servers'),
('Storage', 'Storage'),
('Switches', 'Switches'),
('Workstations', 'Workstations'),
)
# asset_env choices
ENV_NAMES = (
('Dev', 'Development'),
('Test', 'Testing'),
('Prod', 'Production'),
)
# Linux OS List
OS_NAMES_LINUX = (
('CentOS 6', 'CentOS 6'),
('CentOS 7', 'CentOS 7'),
('RHEL 6', 'Red Hat Enterprise Linux 6'),
('RHEL 7', 'Red Hat Enterprise Linux 7'),
('Ubuntu 16.04', 'Ubuntu 16.04'),
('Ubuntu 18.04', 'Ubuntu 18.04'),
)
# Windows OS List
OS_NAMES_WINDOWS = (
('Win 2008', 'Windows 2008'),
('Win 2012', 'Windows 2012'),
('Win 2016', 'Windows 2016'),
('Win 7', 'Windows 7'),
('Win 10', 'Windows 10'),
)
# Other OS List
OS_NAMES_OTHER = (
('Cisco IOS', 'Cisco IOS'),
('Extreme XOS', 'Extreme XOS'),
('Juniper JunOS', 'Juniper JunOS'),
('NA', 'None'),
('Other', 'Other'),
('VMware ESXi', 'VMware ESXi'),
)
# Combined OS List - for asset_os choices
OS_NAMES = OS_NAMES_LINUX + OS_NAMES_WINDOWS + OS_NAMES_OTHER
# asset_hardware choices
HW_TYPES = (
('Virtual', 'Virtual'),
('Physical', 'Physical'),
)
##-- AssetEntry Fields --##
asset_name = models.CharField('Name', max_length=50)
asset_type = models.CharField('Device Type', max_length=15, choices=DEVICE_TYPES)
asset_description = models.CharField('Description', max_length=100)
asset_env = models.CharField('Environment', max_length=15, choices=ENV_NAMES)
asset_os = models.CharField('OS Name/Version', max_length = 20, choices=OS_NAMES)
asset_hardware = models.CharField('Hardware: Virtual or Physical', max_length = 15, choices=HW_TYPES)
# Object representation
def __str__(self):
return self.asset_name
* Stage changes to the databasecd /home/django/myprojecthere
python manage.py makemigrations myapphere
* Make changes to the databasecd /home/django/myprojecthere
python manage.py migrate
===== Logging Setup =====
* Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)# Logging Configuration
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S",
},
'simple': {
'format': '%(levelname)s %(message)s',
},
},
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/myprojecthere/myapphere.log',
'maxBytes': 500000000, # 500 MB
'backupCount': 10,
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
'myapphere': {
'handlers': ['file'],
'level': 'INFO',
},
},
}
####---- End of Logging Config ----####
* Create logging directory and setup ownership/permissionsmkdir /var/log/myprojecthere
chown :apache /var/log/myprojecthere
chmod g+rwxs /var/log/myprojecthere
===== Admin Interface =====
* Create an admin userpython manage.py createsuperuser
* Make your models/objects available for editing in the admin portal (/home/django/myprojecthere/myapphere/admin.py)# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
# Register your models here.
# Make Class Available in Admin Portal (see /home/django/myprojecthere/myapphere/models.py)
from .models import AssetEntry
admin.site.register(AssetEntry)
----
===== URLs/Views =====
A URL+View will generate a web page.
==== URLs ====
**Project Level URLs File**
* Edit project URLs (/home/django/myprojecthere/myprojecthere/urls.py) # add the "import include" part or you won't be able to refer to app level url files
from django.conf.urls import url, include
from django.contrib import admin
# URL Regex Patterns - Map URIs to App's url file for additional matching
urlpatterns = [
# No URI following site name (default app to use)
url(r'^$', include('myapphere.urls')),
# URI for app's name
url(r'^myapphere/', include('myapphere.urls')),
# Included /admin URI
url(r'^admin/', admin.site.urls),
]
\\
**App Level URLs File**
* Create a new App level URLs file (/home/django/myprojecthere/myapphere/urls.py) **EXAMPLE**# urls.py - App URLs Map to App Views
from django.conf.urls import url
from . import views
urlpatterns = [
# "/myapphere/" beginning is implied because we are in the "myapphere" urls file already
# /myapphere/ - All Devices, All Environments (the index)
url(r'^$', views.index, name='index'),
# /myapphere/stats - All Devices, Statistics
url(r'^stats/$', views.stats, name='stats'),
# /myapphere/env_name - All Devices, Specific Environment
url(r'^(?P(dev|test|prod))/$', views.env, name='env'),
# /myapphere/device_type/ - Specific Device, All Environments
url(r'^(?P(firewalls|routers|servers|storage|switches|workstations))/$', views.asset_type_all_env, name='asset_type_all_env'),
# /myapphere/device_type/env_name - Specific Device, Specific Environment
url(r'^(?P(firewalls|routers|servers|storage|switches|workstations))/(?P(dev|test|prod))/$', views.type_env, name='type_env'),
# /myapphere/ - Physical or Virtual
url(r'^(?P(physical|virtual))/$', views.asset_hardware, name='asset_hardware'),
]
==== Views ====
* Edit the App Views that are loaded depending upon URL match(/home/django/myprojecthere/myapphere/views.py) **EXAMPLE**# views.py - URLs are mapped to views
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# Render http response+templates
from django.shortcuts import render
# Object or 404
from django.shortcuts import get_object_or_404
# HTTP Response
from django.http import HttpResponse
# Logging
import logging
logger = logging.getLogger(__name__)
# Your Apps Model
from .models import AssetEntry
# /myapphere/ - All Devices, All Environments (the index)
def index(request):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# Get number of assets in list
number_assets = len(all_asset_list)
# Map template variable names (1st) to Python variables (2nd) for use in html templates
context = { 'all_asset_list': all_asset_list, 'asset_count': number_assets }
# Logging
logger.info("Rendering index.html - All Devices, All Environments")
# Render the http request, using the template, passing the context
return render(request, 'myapphere/index.html', context)
# /myapphere/stats - All Devices, Statistics
def stats(request):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# Get all asset device types
asset_type_list = [key for key,value in AssetEntry.DEVICE_TYPES]
# Get all os names, Linux only, Windows only
os_list = [key for key,value in AssetEntry.OS_NAMES]
os_list_linux = [key for key,value in AssetEntry.OS_NAMES_LINUX]
os_list_windows = [key for key,value in AssetEntry.OS_NAMES_WINDOWS]
# Log for debug purposes
#for key in os_list:
# logger.info("Field names are: " + key)
#- Build Statistics -#
# Initialize Stats list (will be a list of dictionaries)
stats_list = []
####---- Asset Counts Table: Grand Total Row ----####
sysstats_grand_total = 0
sysstats_grand_physical = 0
sysstats_grand_physical_linux = 0
sysstats_grand_physical_windows = 0
sysstats_grand_physical_other = 0
sysstats_grand_virtual = 0
sysstats_grand_virtual_linux = 0
sysstats_grand_virtual_windows = 0
sysstats_grand_virtual_other = 0
sysstats_grand_vmware = 0
# Calculate stats for each type of device
for device_type in asset_type_list:
# Initialize an empty device stats list
device_stats = []
# Add node to the device_stats list if a node from the all_asset_list matches the current device type
for node in all_asset_list:
if ''.join(node.asset_type.lower().split()) == device_type.lower():
device_stats.append(node)
####---- Asset Counts Table ----####
# Total Count
count_total = len(device_stats)
#- Add to grand total
sysstats_grand_total += count_total
# Physical and Virtual Counts
count_physical = 0
count_physical_linux = 0
count_physical_windows = 0
count_physical_other = 0
count_virtual = 0
count_virtual_linux = 0
count_virtual_windows = 0
count_virtual_other = 0
for node in device_stats:
if node.asset_hardware == "Physical":
count_physical += 1
if node.asset_os in os_list_linux:
# Physical+Linux Count
count_physical_linux += 1
elif node.asset_os in os_list_windows:
# Physical+Windows Count
count_physical_windows += 1
else:
# Physical+Other OS
count_physical_other += 1
elif node.asset_hardware == "Virtual":
# Virtual Count
count_virtual += 1
if node.asset_os in os_list_linux:
# Virtual+Linux Count
count_virtual_linux += 1
elif node.asset_os in os_list_windows:
# Virtual+Windows Count
count_virtual_windows += 1
else:
# Virtual+Other OS
count_virtual_other += 1
#- Add to grand total physical
sysstats_grand_physical += count_physical
sysstats_grand_physical_linux += count_physical_linux
sysstats_grand_physical_windows += count_physical_windows
sysstats_grand_physical_other += count_physical_other
#- Add to grand total virtual
sysstats_grand_virtual += count_virtual
sysstats_grand_virtual_linux += count_virtual_linux
sysstats_grand_virtual_windows += count_virtual_windows
sysstats_grand_virtual_other += count_virtual_other
####---- OS Counts Table ----####
# Initialize a new empty OS Counts List
os_counts = []
# Add all the os names and an initial count of 0
for name in os_list:
os_counts.append({ 'os_name': name, 'count': 0 })
# Check each node in the devices specific stats
for node in device_stats:
# Compare node's OS against each os name in the os_counts list and increment count if a match is found
for os_entry in os_counts:
if os_entry['os_name'] == node.asset_os:
# Increment count value on an os name match
os_entry['count'] += 1
####---- After All Stats Calculations: Add Device Stats to stats_list ----####
# Add device statistics to stats_list
stats_list.append({ 'asset_type': device_type, 'total': count_total, 'physical': count_physical, 'physical_linux': count_physical_linux, 'physical_windows': count_physical_windows, 'physical_other': count_physical_other, 'virtual': count_virtual, 'virtual_linux': count_virtual_linux, 'virtual_windows': count_virtual_windows, 'virtual_other': count_virtual_other, 'os_count_stats': os_counts })
# Grand Total Only: VMware ESXi Host Count
for node in device_stats:
if node.asset_os.startswith("VMware"):
sysstats_grand_vmware += 1
#-- END OF Calculate Device Type Stats loop --#
##-- Calculate OS stats grand totals --##
# Initialize a new empty OS Counts Total List
os_counts_total = []
# Add all the os names and an initial count of 0
for name in os_list:
os_counts_total.append({ 'os_name': name, 'count': 0})
# For each device specific stats entry, add up grand total os counts
for device_entry in stats_list:
# For each device_entry in the stats_list, go through its os_count_stats value, which is a list of os_names and counts
for os_device_entry in device_entry['os_count_stats']:
# Check each os_count_stats os_name against the os_counts_total os_name list
for os_entry_total in os_counts_total:
# If we have an os_name match, add the device's os count to the total os count
if os_entry_total['os_name'] == os_device_entry['os_name']:
os_entry_total['count'] += os_device_entry['count']
####---- Add grand totals to stats_list ----####
stats_list.append({ 'asset_type': 'Total', 'total': sysstats_grand_total, 'physical': sysstats_grand_physical, 'physical_linux': sysstats_grand_physical_linux, 'physical_windows': sysstats_grand_physical_windows, 'physical_other': sysstats_grand_physical_other, 'virtual': sysstats_grand_virtual, 'virtual_linux': sysstats_grand_virtual_linux, 'virtual_windows': sysstats_grand_virtual_windows, 'virtual_other': sysstats_grand_virtual_other, 'os_count_stats': os_counts_total })
#- Other Grand Totals: Calculate -#
sysstats_grand_linux = sysstats_grand_physical_linux + sysstats_grand_virtual_linux
sysstats_grand_windows = sysstats_grand_physical_windows + sysstats_grand_virtual_windows
sysstats_grand_other = sysstats_grand_physical_other + sysstats_grand_virtual_other
# Map template variable names (1st) to the Python variables (2nd) for use in templates
context = {'device_stats': stats_list, 'total_linux': sysstats_grand_linux, 'total_windows': sysstats_grand_windows, 'total_other': sysstats_grand_other, 'total_vmware': sysstats_grand_vmware, 'os_list': os_list}
# Logging
logger.info("Rendering stats.html")
# Render the HTTP request, using the template, passing the context
return render(request, 'myapphere/stats.html', context)
# /myapphere/env_name - All Devices, Specific Environment
def env(request, env_name):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# New List for the asset types in the passed environment only
new_list = []
# Check each asset, add to new list if it matches the requested environment name
for node in all_asset_list:
if ''.join(node.asset_env.lower().split()) == env_name.lower():
new_list.append(node)
# Get number of assets in list
number_assets = len(new_list)
# Map template variable names (1st) to Python variables (2nd) for use in html templates
context = { 'all_asset_list': new_list, 'env': env_name, 'asset_count': number_assets }
# Logging
logger.info("Rendering index.html - All Devices, " + env_name)
# Render the http request, using the template, passing the context
return render(request, 'myapphere/index.html', context)
# /myapphere/device/ - Specific Device, All Environments
def asset_type_all_env(request, device_type):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# New List for specific devices only
new_list = []
# Check each asset, add to new list if it matches the requested device type
for node in all_asset_list:
if ''.join(node.asset_type.lower().split()) == device_type.lower():
new_list.append(node)
# Get number of assets in list
number_assets = len(new_list)
# Map template variable names (1st) to Python variables (2nd) for use in html templates
context = { 'all_asset_list': new_list, 'asset_type': device_type, 'asset_count': number_assets }
# Logging
logger.info("Rendering index.html - Devices: " + device_type + ", All Environments")
# Render the http request, using the template, passing the context
return render(request, 'myapphere/index.html', context)
# /myapphere/device/env_name - Specific Device, Specific Environment
def type_env(request, device_type, env_name):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# New List for specific devices and environment only
new_list = []
# Check each asset, add to new list if it matches the requested device and environment
for node in all_asset_list:
if ''.join(node.asset_type.lower().split()) == device_type.lower():
if ''.join(node.asset_env.lower().split()) == env_name.lower():
new_list.append(node)
# Get number of assets in list
number_assets = len(new_list)
# Map template variable names (1st) to Python variables (2nd) for use in html templates
context = { 'all_asset_list': new_list, 'asset_type': device_type, 'env': env_name, 'asset_count': number_assets }
# Logging
logger.info("Rendering index.html - Devices: " + device_type + ", Env: " + env_name)
# Render the http request, using the template, passing the context
return render(request, 'myapphere/index.html', context)
# /myapphere// - Physical or Virtual
def asset_hardware(request, asset_hardware):
# Get all asset objects
all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
# New List for asset_hardware (physical or virtual)
new_list = []
# Check each asset, add to new list if it matches the requested hardware type
for node in all_asset_list:
if ''.join(node.asset_hardware.lower().split()) == asset_hardware.lower():
new_list.append(node)
# Get number of assets in list
number_assets = len(new_list)
# Map template variable names (1st) to the Python variables (2nd) for use in templates
context = {'all_asset_list': new_list, 'asset_hardware': asset_hardware, 'asset_count': number_assets }
# Logging
logger.info("Rendering index.html - All Devices, " + asset_hardware)
# Render the HTTP request, using the template, passing the context
return render(request, 'myapphere/index.html', context)
----
===== Web Page Templates =====
Creating the web page templates.
* Create directory structuremkdir -p /home/django/myprojecthere/myapphere/templates/myapphere
* Create new pages
* templates/myapphere/index.html
* templates/myapphere/stats.html
==== Page Content: Index ====
Example page content for the index.html page.
/home/django/myprojecthere/myapphere/templates/myapphere/index.html
Asset List
{% load static %}
{% if not asset_type %}
- All Devices
{% else %}
- All Devices
{% endif %}
{% if asset_type == 'firewalls' %}
- Firewalls
{% else %}
- Firewalls
{% endif %}
{% if asset_type == 'routers' %}
- Routers
{% else %}
- Routers
{% endif %}
{% if asset_type == 'servers' %}
- Servers
{% else %}
- Servers
{% endif %}
{% if asset_type == 'storage' %}
- Storage
{% else %}
- Storage
{% endif %}
{% if asset_type == 'switches' %}
- Switches
{% else %}
- Switches
{% endif %}
{% if asset_type == 'workstations' %}
- Workstations
{% else %}
- Workstations
{% endif %}
{% if env == 'dev' %}
{% if asset_type %}
- Dev
- Test
- Prod
{% else %}
- Dev
- Test
- Prod
{% endif %}
{% elif env == 'test' %}
{% if asset_type %}
- Dev
- Test
- Prod
{% else %}
- Dev
- Test
- Prod
{% endif %}
{% elif env == 'prod' %}
{% if asset_type %}
- Dev
- Test
- Prod
{% else %}
- Dev
- Test
- Prod
{% endif %}
{% else %}
{% if asset_type %}
- Dev
- Test
- Prod
{% else %}
- Dev
- Test
- Prod
{% endif %}
{% endif %}
{% if user.is_authenticated %}
Logged in: {{ user.username }}
Logout
{% endif %}
{% if asset_type == 'firewalls' %}
{% if env == 'dev' %}
Asset List - Firewalls - Development Environment
{% elif env == 'test' %}
Asset List - Firewalls - Test Environment
{% elif env == 'prod' %}
Asset List - Firewalls - Production Environment
{% else %}
Asset List - Firewalls - All Environments
{% endif %}
{% elif asset_type == 'routers' %}
{% if env == 'dev' %}
Asset List - Routers - Development Environment
{% elif env == 'test' %}
Asset List - Routers - Test Environment
{% elif env == 'prod' %}
Asset List - Routers - Production Environment
{% else %}
Asset List - Routers - All Environments
{% endif %}
{% elif asset_type == 'servers' %}
{% if env == 'dev' %}
Asset List - Servers - Development Environment
{% elif env == 'test' %}
Asset List - Servers - Test Environment
{% elif env == 'prod' %}
Asset List - Servers - Production Environment
{% else %}
Asset List - Servers - All Environments
{% endif %}
{% elif asset_type == 'storage' %}
{% if env == 'dev' %}
Asset List - Storage - Development Environment
{% elif env == 'test' %}
Asset List - Storage - Test Environment
{% elif env == 'prod' %}
Asset List - Storage - Production Environment
{% else %}
Asset List - Storage - All Environments
{% endif %}
{% elif asset_type == 'switches' %}
{% if env == 'dev' %}
Asset List - Switches - Development Environment
{% elif env == 'test' %}
Asset List - Switches - Test Environment
{% elif env == 'prod' %}
Asset List - Switches - Production Environment
{% else %}
Asset List - Switches - All Environments
{% endif %}
{% elif asset_type == 'workstations' %}
{% if env == 'dev' %}
Asset List - Workstations - Development Environment
{% elif env == 'test' %}
Asset List - Workstations - Test Environment
{% elif env == 'prod' %}
Asset List - Workstations - Production Environment
{% else %}
Asset List - Workstations - All Environments
{% endif %}
{% else %}
{% if env == 'dev' %}
Asset List - All Types - Development Environment
{% elif env == 'test' %}
Asset List - All Types - Test Environment
{% elif env == 'prod' %}
Asset List - All Types - Production Environment
{% else %}
Asset List - All Types - All Environments
{% endif %}
{% endif %}
{% if asset_hardware %}
{% if asset_hardware == 'physical' %}
- Physical -
{% elif asset_hardware == 'virtual' %}
- Virtual -
{% endif %}
{% endif %}
{% if asset_count %}
{% if asset_count == 1 %}
({{ asset_count }} asset)
{% else %}
({{ asset_count }} assets)
{% endif %}
{% else %}
(0 assets)
{% endif %}
Device Type
Name
Description
Environment
OS
Hardware
{{ name.asset_type }}
{{ name.asset_name }}
{{ name.asset_description }}
{{ name.asset_env }}
{{ name.asset_os }}
{{ name.asset_hardware }}
{% endfor %}
==== Page Content: Stats ====
Example page content for the stats.html page.
/home/django/myprojecthere/myapphere/templates/myapphere/stats.html
Asset List - Stats
{% load static %}
{% if user.is_authenticated %}
Logged in: {{ user.username }}
Logout
{% endif %}
Asset List - Statistics - Asset Counts
Device Type
Systems
Physical
Physical Linux
Physical Windows
Physical Other
Virtual
Virtual Linux
Virtual Windows
Virtual Other
{% for asset in device_stats %}
{% if asset.asset_type == 'Total' %}
{{ asset.asset_type }}
{{ asset.total }}
{{ asset.physical }}
{{ asset.physical_linux }}
{{ asset.physical_windows }}
{{ asset.physical_other }}
{{ asset.virtual }}
{{ asset.virtual_linux }}
{{ asset.virtual_windows }}
{{ asset.virtual_other }}
{% else %}
{{ asset.asset_type }}
{{ asset.total }}
{{ asset.physical }}
{{ asset.physical_linux }}
{{ asset.physical_windows }}
{{ asset.physical_other }}
{{ asset.virtual }}
{{ asset.virtual_linux }}
{{ asset.virtual_windows }}
{{ asset.virtual_other }}
{% endif %}
{% endfor %}
Total Linux
{{ total_linux }}
Total Windows
{{ total_windows }}
Total Other
{{ total_other }}
Total VMware ESXi*
{{ total_vmware }}
*Physical Virtual Hosts (VMware ESXi) count is included in Physical Linux/Total Linux counts.
Asset List - Statistics - OS Counts
Device Type
{% for os_name in os_list %}
{{ os_name }}
{% endfor %}
{% for asset in device_stats %}
{% if asset.asset_type == 'Total' %}
{{ asset.asset_type }}
{% for name in asset.os_count_stats %}
{{ name.count }}
{% endfor %}
{% else %}
{{ asset.asset_type }}
{% for name in asset.os_count_stats %}
{{ name.count }}
{% endfor %}
{% endif %}
{% endfor %}
----
===== Static Files/Stylesheets =====
Configuring stylesheets.
* Create directory structuremkdir -p /home/django/myprojecthere/myapphere/static/myapphere
* Create stylesheet (/home/django/myprojecthere/myapphere/static/myapphere/style.css)/* style.css : Styles for html templates */
/* ---- Table Styles ---- */
/* table settings */
table.layout {
border-collapse: collapse;
border-spacing: 0px;
padding: 0px;
}
td.layout {
border-spacing: 0px;
padding: 0px;
}
table.myapphere {
border-collapse: collapse;
}
/* table headers, table definitions */
table.myapphere, th.myapphere, td.myapphere {
border-collapse: collapse;
border: 1px solid #ddd;
padding: 5px;
}
/* th -> table headers */
th.myapphere {
background-color: #4CAF50;
color: white;
}
/* tr -> table rows
* * tr:nth-child -> color every even table row
* * tr:hover -> Mouse hover background color effect */
tr.myapphere:nth-child(even) {background-color: #f2f2f2;}
tr.myapphere:hover {background-color: #ddd;}
td.center {
text-align: center;
}
td.totals {
background-color: #b3b3b3;
font-weight: bold;
}
/* ---- Menu Styles ---- */
ul.asset_type {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width: 671px;
}
ul.env {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width: 163px;
}
ul.stats {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width: 60px;
}
ul.asset_hardware {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width: 163px;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 10px 10px;
text-decoration: none;
}
a:hover:not(.active) {
background-color: #111;
}
.active {
background-color:#4CAF50;
}
/* ---- Non-Menu Styles ---- */
a:link.plain {
background-color: #ffffff;
}
a:visited.plain {
background-color: #ffffff;
}
a:hover.plain {
background-color: #4caf50;
}
----
====== Apache ======
Configuring Apache to pass traffic to the application.
* Configure Apache's mod_wsgi for the application (new file)vim /etc/httpd/conf.d/myapphere.conf
# Asset List Django/WSGI Config
# WSGIScriptAlias: The base URL to serve the application from
WSGIScriptAlias / /home/django/myprojecthere/myprojecthere/wsgi.py
# WSGI Daemon Process Config
WSGIDaemonProcess myapphere python-path=/home/django/myprojecthere
WSGIProcessGroup myapphere
# Location of Django Application and wsgi.py config
Require all granted
# Static files (admin interface and style sheet)
Alias /static/ /var/www/static/
Require all granted
* Configure the virtual host (new file)vim /etc/httpd/conf.d/vhosts.conf
# Virtual Host Config
# Redirect shortname to fully qualified
ServerName djangoserver
Redirect "/" "http://djangoserver.mycorps.domain.org/"
# Redirect all http to https
ServerName djangoserver.mycorps.domain.org
# Redirect all to https
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
# Redirect shortname to fully qualified
ServerName djangoserver
Redirect "/" "https://djangoserver.mycorps.domain.org/"
# Django Application lives here at the root /. See: /etc/httpd/conf.d/myapphere.conf
# Fully qualified server name
ServerName djangoserver.mycorps.domain.org
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
# OPTIONAL: CNAME for website - will only work with SSL if using a wildcard certificate
ServerName myapphere.mycorps.domain.org
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
* Configure SSL Certificatevim /etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/pki/tls/certs/current_crt.crt
SSLCertificateKeyFile /etc/pki/tls/certs/current_key.key
SSLCertificateChainFile /etc/pki/tls/certs/current_ca.crt
* [[linux_wiki:ssl_certificates#create_request|Generate a self signed cert]] if this is just a lab environment.
* Start and Enable Apachesystemctl start httpd
systemctl enable httpd
----
====== Django: Authentication ======
Adding authentication to Django requires basic auth to be setup first, as LDAP auth builds upon it.
===== Basic Authentication =====
Basic authentication uses Django local user accounts.
* Edit Project Settings (/home/django/myprojecthere/myprojecthere/settings.py)# Redirect Successful Logins Here
LOGIN_REDIRECT_URL = '/myapphere/'
# Ensure contrib.auth is added to installed apps:
# Application definition
INSTALLED_APPS = [
'myapphere.apps.MyapphereConfig',
'django.contrib.admin',
'django.contrib.auth', # must exist for basic auth to work
...
]
* Add login and logout URLs to project URLs (/home/django/myprojecthere/myprojecthere/urls.py)# auth views - authentication login/logout module
from django.contrib.auth import views as auth_views
# URL Patterns - Map to Projects Within Django
urlpatterns = [
...
# Login URLs
url(r'^login/$', auth_views.login, {'template_name': 'login.html'}, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/login/'}, name='logout'),
...
]
* Edit the application views (/home/django/myprojecthere/myapphere/views.py)# Require login decorator
from django.contrib.auth.decorators import login_required
# Put login decorator before every function definition that you want to require login to view:
#-> Require login for the view following it <-#
@login_required(login_url="/login/")
def index(request):
* Create a HTML Login Page (/home/django/myprojecthere/myapphere/templates/login.html)
{% block title %}Asset List{% endblock %}
Asset List
{% if user.is_authenticated %}
Greetings, {{ user.username }}.
logout
{% endif %}
Login
===== LDAP Authentication =====
Configuring LDAP authentication.
* Install the python django ldap packagepip install django-auth-ldap
* Edit Project Settings (/home/django/myprojecthere/myprojecthere/settings.py) # LDAP Module Imports
import ldap
from django_auth_ldap.config import LDAPSearch
from django_auth_ldap.config import GroupOfNamesType
from django_auth_ldap.config import LDAPGroupQuery
# Authentication Backends (LDAP and Django Local)
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
)
####- LDAP Server Config -####
AUTH_LDAP_SERVER_URI = "ldap://LDAPSERVER01.mycorps.domain.org ldap://LDAPSERVER02.mycorps.domain.org"
AUTH_LDAP_START_TLS = True
# Bind Info: Use authenticating user to get user and group info
AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True
AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,cn=users,cn=accounts,dc=mycorps,dc=domain,dc=org"
# Cache LDAP Groups for use with permissions
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600
# Group Info Gathering
AUTH_LDAP_GROUP_SEARCH = LDAPSearch
"cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org",
ldap.SCOPE_SUBTREE,
"(objectClass=groupofnames)"
)
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
# Group restrictions - Who can login via LDAP
AUTH_LDAP_REQUIRE_GROUP = (
# Allow login for members of the LDAP group "list_users"
LDAPGroupQuery("cn=list_users,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org") |
# Allow login for members of the LDAP group "admin_group"
LDAPGroupQuery("cn=admin_group,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org")
)
# Use LDAP group membership to calculate group permissions.
AUTH_LDAP_FIND_GROUP_PERMS = True
# Update Django record from LDAP each time user logs in
AUTH_LDAP_ALWAYS_UPDATE_USER = True
# Populate the Django user info from LDAP directory info
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenname",
"last_name": "sn",
"email": "mail"
}
# Set user permission flags by group - set LDAP group "admin_group" as Django Staff Members
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_staff": "cn=admin_group,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org"
}
----
====== Django: Jquery ======
Jquery can be added in order to enable an Export as CSV and/or Excel buttons.
Reference: Export Jquery Buttons: https://github.com/kayalshri/tableExport.jquery.plugin
* From the reference link, download:
* jquery.base64.js
* tableExport.js
* Search the internet for CSV and XLS icons. Download them.
* CSV = save as "csv.png"
* XLS = save as "xls.png"
* Save the Javascript files and small pictures (CSV/XLS) into the same directory as the style sheet/home/django/myprojecthere/myapphere/static/myapphere/
* Install the Django Jquery integrationpip install django-jquery
* Add Jquery to the "INSTALLED_APPS" list (/home/django/myprojecthere/myprojecthere/settings.py)# Application definition
INSTALLED_APPS = [
'jquery',
* Add jquery to HTML templates
----
====== Django: Static Files ======
No matter which steps from above you skip, you absolutely need to collect static files to copy them into the location Apache expects them to be.
This is for Apache's access to javascript, css, etc.
* Collect static filescd /home/django/myprojecthere/
python manage.py collectstatic
----
====== DEBUG: TURN OFF ======
Lastly, when you are not developing/debugging your site, **turn off debug mode** to avoid dumping sensitive information to the screen in the event of an error.
\\
Edit the project settings (/home/django/myprojecthere/myprojecthere/settings.py)# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
----
====== Next Steps =======
[[python_wiki:django_api|Proceed to the Django API]] section.
----