#!/usr/bin/env python2
#
# Author: Jamie Strandboge <jamie@ubuntu.com>
# Copyright (C) 2012 Canonical Ltd.
#
# This script is distributed under the terms and conditions of the GNU General
# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html
# for details.
#
# Outputs a rather gross html dashboard for the security team

import datetime
import optparse
import os
import signal
import subprocess
import sys
import time

def subprocess_setup():
    # Python installs a SIGPIPE handler by default. This is usually not what
    # non-Python subprocesses expect.
    signal.signal(signal.SIGPIPE, signal.SIG_DFL)

def cmd(command, input = None, stderr = subprocess.STDOUT, stdout = subprocess.PIPE, stdin = None, timeout = None):
    '''Try to execute given command (array) and return its stdout, or return
    a textual error if it failed.'''

    try:
        sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=True, preexec_fn=subprocess_setup)
    except OSError, e:
        return [127, str(e)]

    out, outerr = sp.communicate(input)
    # Handle redirection of stdout
    if out == None:
        out = ''
    # Handle redirection of stderr
    if outerr == None:
        outerr = ''
    return [sp.returncode,out+outerr]

def _get_css():
    '''CSS for reports'''
    css = '''
<style type="text/css">
h1, h2, h3, h4, h5 {
 color: #3b2e1e;
}
table {
 border-collapse: collapse;
 border: 0;
 width: 100%;
}
th {
 border: 1px solid #3b2e1e;
 color: #3b2e1e;
 width: 50%;
 text-align: center;
}
/* basic styling */
td {
 width: 50%;
 border: 1px solid #3b2e1e;
 text-align: left;
 vertical-align: top;
 padding-top: 0.1em;
 padding-bottom: 0.1em;
 padding-left: 0.5em;
 padding-right: 0.5em;
 background-color: white;
 font-size: smaller;
}
td.override, th.override {
 border: 0;
}
a img {
 border: 0;
}

div#footer {
 font-size: smaller;
}
</style>
'''
    return css

def get_urls_for_packages(packages):
    urls = ""
    for p in packages.split(','):
        urls += "<a href='http://people.canonical.com/~ubuntu-security/cve/pkg/%s.html'>%s</a>," % (p, p)
    return urls.rstrip(',')

def get_dashboard_html():
    gen_skipped = "linux,webkit,qt4-x11,qtwebkit-source,firefox,thunderbird,oxide-qt"
    todo_gen = get_todo_numbers(skipped=gen_skipped)
    browser_only = "oxide-qt,firefox,thunderbird"
    todo_browser = get_todo_numbers(only=browser_only)
    kernel_only = "linux"
    todo_kernel = get_todo_numbers(only=kernel_only)

    s = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Ubuntu Security Dashboard</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="Canonical Ltd, Jamie Strandboge" />
<meta name="description" content="Ubuntu Security Dashboard" />
<meta name="copyright" content="Canonical Ltd" />
%s
</head>
<body>
<table>
<tr>
<th>Development</th><th>Stable</th>
</tr>
<tr>
<td>
<ul>
<li><a href='https://trello.com/b/HvFhIQpv/security-team'>Security team backlog</a></li>
<li><a href='https://docs.google.com/a/canonical.com/spreadsheets/d/1kAaVTa_0gTMGepR8eeB4usK7FqrSa5JI56iq6TCKi5w/edit# gid=0'>Phone blocking bugs</a></li>

<li>AppArmor
<ul>
<li><a href='https://bugs.launchpad.net/apparmor/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Upstream</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/apparmor/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/linux/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=aa-kernel&field.tags_combinator=ANY'>Ubuntu kernel</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu-rtm/+source/apparmor/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu RTM</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/click-apparmor/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>click-apparmor in Ubuntu</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu-rtm/+source/click-apparmor/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>click-apparmor in Ubuntu RTM</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/apparmor-easyprof-ubuntu/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>apparmor-easyprof-ubuntu in Ubuntu</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu-rtm/+source/apparmor-easyprof-ubuntu/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>apparmor-easyprof-ubuntu in Ubuntu RTM</a> critical and high bugs</li>
</ul>
</li>

<li>Oxide
<ul>
<li><a href='https://bugs.launchpad.net/oxide/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Upstream</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/oxide-qt/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu-rtm/+source/oxide-qt/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu RTM</a> critical and high bugs</li>
</ul>
</li>

<li>eCryptfs
<ul>
<li><a href='https://bugs.launchpad.net/ecryptfs/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Upstream</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/ecryptfs-utils/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu/+source/linux/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=ecryptfs-kernel&field.tags_combinator=ANY'>Ubuntu kernel</a> critical and high bugs</li>
<li><a href='https://bugs.launchpad.net/ubuntu-rtm/+source/ecryptfs-utils/+bugs?field.searchtext=&orderby=-importance&field.importance:list=CRITICAL&field.importance:list=HIGH&field.tag=&field.tags_combinator=ANY'>Ubuntu RTM</a> critical and high bugs</li>
</ul>
</li>

</ul>
</td>
<td>
<ul>
<li>General: %s (<a href='http://people.canonical.com/~ubuntu-security/cve/main.html'>supported</a>)</li>
<li>Kernel: %s (%s)</li>
<li>Browser: %s (%s)</li>
<li>Security team <a href='http://people.canonical.com/~ubuntu-security/metrics/'>metrics</a> and <a href='http://people.canonical.com/~ubuntu-security/graphs/'>graphs</a></li>
<li><a href="http://people.canonical.com/~ubuntu-security/cve/">Ubuntu CVE Tracker</a></li>
<li><a href='http://people.canonical.com/~ubuntu-security/d2u/'>Open CVEs fixed in Debian</a></li>
</ul>
<table>
<tr>
<th class="override">USNs over 12 months</th>
<th class="override">Regressions over 12 months</th>
</tr>
<tr>
<td class="override">
<div><a href="http://www.ubuntu.com/usn/"><img title="USNs over last 12 months" alt="USNs over last 12 months" src="http://people.canonical.com/~ubuntu-security/metrics/USN_all_12.png" height="250" width="300"/></a></div>
</td>
<td class="override">
<div><a href='http://people.canonical.com/~ubuntu-security/metrics/'><img title="Regressions over last 12 months" alt="Regressions over last 12 months" src="http://people.canonical.com/~ubuntu-security/metrics/regression_all_12.png" height="250" width="300"/></a></div>
</td>
</tr>
</table>
</td>
</tr>
</table>

<div id="footer">
Ubuntu Security Dashboard (last updated: %s) - &copy; Canonical Ltd. 2007-%d
</div>
</body>
</html>
''' % (_get_css(),
       todo_gen,
       todo_kernel, get_urls_for_packages(kernel_only),
       todo_browser, get_urls_for_packages(browser_only),
       time.asctime(time.gmtime()), # footer - last updated
       datetime.date.today().year,  # footer - copyright
    )
    return s

def get_todo_numbers(skipped=None, only=None):
    exe = os.path.join(os.path.dirname(sys.argv[0]), 'report-todo-numbers')
    args = ['--show-unique-sources', '--skip-low', '-E']
    if skipped:
        args.append('--skip-packages=%s' % skipped)
    elif only:
        args.append('--only-packages=%s' % only)
    rc, report = cmd([exe] + args + ['--', '-S'])

    s = ""
    for line in report.splitlines():
        if " supported " in line:
            return line.lstrip(' * ')
    return s

#
# main
#
if __name__ == "__main__":
    parser = optparse.OptionParser()
    (opt, args) = parser.parse_args()

    print get_dashboard_html()
